From b8bbcd2196b418caec807484be07be50990124ad Mon Sep 17 00:00:00 2001 From: LukeGus Date: Tue, 29 Sep 2026 13:08:39 -0500 Subject: [PATCH] feat: type the plugin host record, move plugin strings out of core and add lint checks --- drizzle/mysql/0064_flippant_killer_shrike.sql | 5 + drizzle/mysql/meta/0064_snapshot.json | 4754 +++++++++++++++++ drizzle/mysql/meta/_journal.json | 7 + drizzle/postgres/0064_sticky_pestilence.sql | 5 + drizzle/postgres/meta/0064_snapshot.json | 4740 ++++++++++++++++ drizzle/postgres/meta/_journal.json | 7 + .../sqlite/0059_adorable_wrecking_crew.sql | 5 + drizzle/sqlite/meta/0059_snapshot.json | 4482 ++++++++++++++++ drizzle/sqlite/meta/_journal.json | 7 + package.json | 2 +- packages/plugin-sdk/src/backend.ts | 117 +- packages/plugin-sdk/src/frontend.ts | 55 +- packages/plugin-sdk/src/testing.ts | 89 +- plugins/ai/locales/en.json | 3 + plugins/ai/locales/translated/af_ZA.json | 3 + plugins/ai/locales/translated/ar_SA.json | 3 + plugins/ai/locales/translated/bg_BG.json | 3 + plugins/ai/locales/translated/bn_BD.json | 3 + plugins/ai/locales/translated/ca_ES.json | 3 + plugins/ai/locales/translated/cs_CZ.json | 3 + plugins/ai/locales/translated/da_DK.json | 3 + plugins/ai/locales/translated/de_DE.json | 3 + plugins/ai/locales/translated/el_GR.json | 3 + plugins/ai/locales/translated/es_ES.json | 3 + plugins/ai/locales/translated/fi_FI.json | 3 + plugins/ai/locales/translated/fr_FR.json | 3 + plugins/ai/locales/translated/he_IL.json | 3 + plugins/ai/locales/translated/hi_IN.json | 3 + plugins/ai/locales/translated/hu_HU.json | 3 + plugins/ai/locales/translated/id_ID.json | 3 + plugins/ai/locales/translated/it_IT.json | 3 + plugins/ai/locales/translated/ja_JP.json | 3 + plugins/ai/locales/translated/ko_KR.json | 3 + plugins/ai/locales/translated/nl_NL.json | 3 + plugins/ai/locales/translated/no_NO.json | 3 + plugins/ai/locales/translated/pl_PL.json | 3 + plugins/ai/locales/translated/pt_BR.json | 3 + plugins/ai/locales/translated/pt_PT.json | 3 + plugins/ai/locales/translated/ro_RO.json | 3 + plugins/ai/locales/translated/ru_RU.json | 3 + plugins/ai/locales/translated/sr_SP.json | 3 + plugins/ai/locales/translated/sv_SE.json | 3 + plugins/ai/locales/translated/th_TH.json | 3 + plugins/ai/locales/translated/tr_TR.json | 3 + plugins/ai/locales/translated/uk_UA.json | 3 + plugins/ai/locales/translated/vi_VN.json | 3 + plugins/ai/locales/translated/zh_CN.json | 3 + plugins/ai/locales/translated/zh_TW.json | 3 + plugins/ai/src/backend/tools/executor.ts | 3 +- plugins/docker/locales/en.json | 12 +- plugins/docker/locales/translated/af_ZA.json | 12 + plugins/docker/locales/translated/ar_SA.json | 12 + plugins/docker/locales/translated/bg_BG.json | 12 + plugins/docker/locales/translated/bn_BD.json | 12 + plugins/docker/locales/translated/ca_ES.json | 12 + plugins/docker/locales/translated/cs_CZ.json | 12 + plugins/docker/locales/translated/da_DK.json | 12 + plugins/docker/locales/translated/de_DE.json | 12 + plugins/docker/locales/translated/el_GR.json | 12 + plugins/docker/locales/translated/es_ES.json | 12 + plugins/docker/locales/translated/fi_FI.json | 12 + plugins/docker/locales/translated/fr_FR.json | 12 + plugins/docker/locales/translated/he_IL.json | 12 + plugins/docker/locales/translated/hi_IN.json | 12 + plugins/docker/locales/translated/hu_HU.json | 12 + plugins/docker/locales/translated/id_ID.json | 12 + plugins/docker/locales/translated/it_IT.json | 12 + plugins/docker/locales/translated/ja_JP.json | 12 + plugins/docker/locales/translated/ko_KR.json | 12 + plugins/docker/locales/translated/nl_NL.json | 12 + plugins/docker/locales/translated/no_NO.json | 12 + plugins/docker/locales/translated/pl_PL.json | 12 + plugins/docker/locales/translated/pt_BR.json | 12 + plugins/docker/locales/translated/pt_PT.json | 12 + plugins/docker/locales/translated/ro_RO.json | 12 + plugins/docker/locales/translated/ru_RU.json | 12 + plugins/docker/locales/translated/sr_SP.json | 12 + plugins/docker/locales/translated/sv_SE.json | 12 + plugins/docker/locales/translated/th_TH.json | 12 + plugins/docker/locales/translated/tr_TR.json | 12 + plugins/docker/locales/translated/uk_UA.json | 12 + plugins/docker/locales/translated/vi_VN.json | 12 + plugins/docker/locales/translated/zh_CN.json | 12 + plugins/docker/locales/translated/zh_TW.json | 12 + plugins/docker/src/frontend/DockerApp.tsx | 6 +- plugins/docker/src/frontend/DockerManager.tsx | 5 +- plugins/docker/src/frontend/DockerWidget.tsx | 2 +- plugins/docker/src/frontend/index.tsx | 4 +- plugins/docker/src/frontend/types.ts | 16 +- plugins/file-manager/locales/en.json | 115 +- .../locales/translated/af_ZA.json | 105 +- .../locales/translated/ar_SA.json | 105 +- .../locales/translated/bg_BG.json | 105 +- .../locales/translated/bn_BD.json | 105 +- .../locales/translated/ca_ES.json | 105 +- .../locales/translated/cs_CZ.json | 105 +- .../locales/translated/da_DK.json | 105 +- .../locales/translated/de_DE.json | 105 +- .../locales/translated/el_GR.json | 105 +- .../locales/translated/es_ES.json | 105 +- .../locales/translated/fi_FI.json | 105 +- .../locales/translated/fr_FR.json | 105 +- .../locales/translated/he_IL.json | 105 +- .../locales/translated/hi_IN.json | 105 +- .../locales/translated/hu_HU.json | 105 +- .../locales/translated/id_ID.json | 105 +- .../locales/translated/it_IT.json | 105 +- .../locales/translated/ja_JP.json | 105 +- .../locales/translated/ko_KR.json | 105 +- .../locales/translated/nl_NL.json | 105 +- .../locales/translated/no_NO.json | 105 +- .../locales/translated/pl_PL.json | 105 +- .../locales/translated/pt_BR.json | 105 +- .../locales/translated/pt_PT.json | 105 +- .../locales/translated/ro_RO.json | 105 +- .../locales/translated/ru_RU.json | 105 +- .../locales/translated/sr_SP.json | 105 +- .../locales/translated/sv_SE.json | 105 +- .../locales/translated/th_TH.json | 105 +- .../locales/translated/tr_TR.json | 105 +- .../locales/translated/uk_UA.json | 105 +- .../locales/translated/vi_VN.json | 105 +- .../locales/translated/zh_CN.json | 105 +- .../locales/translated/zh_TW.json | 105 +- plugins/fleets/locales/en.json | 40 + plugins/fleets/locales/translated/af_ZA.json | 40 + plugins/fleets/locales/translated/ar_SA.json | 40 + plugins/fleets/locales/translated/bg_BG.json | 40 + plugins/fleets/locales/translated/bn_BD.json | 40 + plugins/fleets/locales/translated/ca_ES.json | 40 + plugins/fleets/locales/translated/cs_CZ.json | 40 + plugins/fleets/locales/translated/da_DK.json | 40 + plugins/fleets/locales/translated/de_DE.json | 40 + plugins/fleets/locales/translated/el_GR.json | 40 + plugins/fleets/locales/translated/es_ES.json | 40 + plugins/fleets/locales/translated/fi_FI.json | 40 + plugins/fleets/locales/translated/fr_FR.json | 40 + plugins/fleets/locales/translated/he_IL.json | 40 + plugins/fleets/locales/translated/hi_IN.json | 40 + plugins/fleets/locales/translated/hu_HU.json | 40 + plugins/fleets/locales/translated/id_ID.json | 40 + plugins/fleets/locales/translated/it_IT.json | 40 + plugins/fleets/locales/translated/ja_JP.json | 40 + plugins/fleets/locales/translated/ko_KR.json | 40 + plugins/fleets/locales/translated/nl_NL.json | 40 + plugins/fleets/locales/translated/no_NO.json | 40 + plugins/fleets/locales/translated/pl_PL.json | 40 + plugins/fleets/locales/translated/pt_BR.json | 40 + plugins/fleets/locales/translated/pt_PT.json | 40 + plugins/fleets/locales/translated/ro_RO.json | 40 + plugins/fleets/locales/translated/ru_RU.json | 40 + plugins/fleets/locales/translated/sr_SP.json | 40 + plugins/fleets/locales/translated/sv_SE.json | 40 + plugins/fleets/locales/translated/th_TH.json | 40 + plugins/fleets/locales/translated/tr_TR.json | 40 + plugins/fleets/locales/translated/uk_UA.json | 40 + plugins/fleets/locales/translated/vi_VN.json | 40 + plugins/fleets/locales/translated/zh_CN.json | 40 + plugins/fleets/locales/translated/zh_TW.json | 40 + plugins/network-topology/locales/en.json | 3 + .../locales/translated/af_ZA.json | 3 + .../locales/translated/ar_SA.json | 3 + .../locales/translated/bg_BG.json | 3 + .../locales/translated/bn_BD.json | 3 + .../locales/translated/ca_ES.json | 3 + .../locales/translated/cs_CZ.json | 3 + .../locales/translated/da_DK.json | 3 + .../locales/translated/de_DE.json | 3 + .../locales/translated/el_GR.json | 3 + .../locales/translated/es_ES.json | 3 + .../locales/translated/fi_FI.json | 3 + .../locales/translated/fr_FR.json | 3 + .../locales/translated/he_IL.json | 3 + .../locales/translated/hi_IN.json | 3 + .../locales/translated/hu_HU.json | 3 + .../locales/translated/id_ID.json | 3 + .../locales/translated/it_IT.json | 3 + .../locales/translated/ja_JP.json | 3 + .../locales/translated/ko_KR.json | 3 + .../locales/translated/nl_NL.json | 3 + .../locales/translated/no_NO.json | 3 + .../locales/translated/pl_PL.json | 3 + .../locales/translated/pt_BR.json | 3 + .../locales/translated/pt_PT.json | 3 + .../locales/translated/ro_RO.json | 3 + .../locales/translated/ru_RU.json | 3 + .../locales/translated/sr_SP.json | 3 + .../locales/translated/sv_SE.json | 3 + .../locales/translated/th_TH.json | 3 + .../locales/translated/tr_TR.json | 3 + .../locales/translated/uk_UA.json | 3 + .../locales/translated/vi_VN.json | 3 + .../locales/translated/zh_CN.json | 3 + .../locales/translated/zh_TW.json | 3 + plugins/opkssh/locales/en.json | 3 + plugins/opkssh/locales/translated/af_ZA.json | 3 + plugins/opkssh/locales/translated/ar_SA.json | 3 + plugins/opkssh/locales/translated/bg_BG.json | 3 + plugins/opkssh/locales/translated/bn_BD.json | 3 + plugins/opkssh/locales/translated/ca_ES.json | 3 + plugins/opkssh/locales/translated/cs_CZ.json | 3 + plugins/opkssh/locales/translated/da_DK.json | 3 + plugins/opkssh/locales/translated/de_DE.json | 3 + plugins/opkssh/locales/translated/el_GR.json | 3 + plugins/opkssh/locales/translated/es_ES.json | 3 + plugins/opkssh/locales/translated/fi_FI.json | 3 + plugins/opkssh/locales/translated/fr_FR.json | 3 + plugins/opkssh/locales/translated/he_IL.json | 3 + plugins/opkssh/locales/translated/hi_IN.json | 3 + plugins/opkssh/locales/translated/hu_HU.json | 3 + plugins/opkssh/locales/translated/id_ID.json | 3 + plugins/opkssh/locales/translated/it_IT.json | 3 + plugins/opkssh/locales/translated/ja_JP.json | 3 + plugins/opkssh/locales/translated/ko_KR.json | 3 + plugins/opkssh/locales/translated/nl_NL.json | 3 + plugins/opkssh/locales/translated/no_NO.json | 3 + plugins/opkssh/locales/translated/pl_PL.json | 3 + plugins/opkssh/locales/translated/pt_BR.json | 3 + plugins/opkssh/locales/translated/pt_PT.json | 3 + plugins/opkssh/locales/translated/ro_RO.json | 3 + plugins/opkssh/locales/translated/ru_RU.json | 3 + plugins/opkssh/locales/translated/sr_SP.json | 3 + plugins/opkssh/locales/translated/sv_SE.json | 3 + plugins/opkssh/locales/translated/th_TH.json | 3 + plugins/opkssh/locales/translated/tr_TR.json | 3 + plugins/opkssh/locales/translated/uk_UA.json | 3 + plugins/opkssh/locales/translated/vi_VN.json | 3 + plugins/opkssh/locales/translated/zh_CN.json | 3 + plugins/opkssh/locales/translated/zh_TW.json | 3 + plugins/proxmox/locales/en.json | 13 +- plugins/proxmox/locales/translated/af_ZA.json | 13 +- plugins/proxmox/locales/translated/ar_SA.json | 13 +- plugins/proxmox/locales/translated/bg_BG.json | 13 +- plugins/proxmox/locales/translated/bn_BD.json | 13 +- plugins/proxmox/locales/translated/ca_ES.json | 13 +- plugins/proxmox/locales/translated/cs_CZ.json | 13 +- plugins/proxmox/locales/translated/da_DK.json | 13 +- plugins/proxmox/locales/translated/de_DE.json | 13 +- plugins/proxmox/locales/translated/el_GR.json | 13 +- plugins/proxmox/locales/translated/es_ES.json | 13 +- plugins/proxmox/locales/translated/fi_FI.json | 13 +- plugins/proxmox/locales/translated/fr_FR.json | 13 +- plugins/proxmox/locales/translated/he_IL.json | 13 +- plugins/proxmox/locales/translated/hi_IN.json | 13 +- plugins/proxmox/locales/translated/hu_HU.json | 13 +- plugins/proxmox/locales/translated/id_ID.json | 13 +- plugins/proxmox/locales/translated/it_IT.json | 13 +- plugins/proxmox/locales/translated/ja_JP.json | 13 +- plugins/proxmox/locales/translated/ko_KR.json | 13 +- plugins/proxmox/locales/translated/nl_NL.json | 13 +- plugins/proxmox/locales/translated/no_NO.json | 13 +- plugins/proxmox/locales/translated/pl_PL.json | 13 +- plugins/proxmox/locales/translated/pt_BR.json | 13 +- plugins/proxmox/locales/translated/pt_PT.json | 13 +- plugins/proxmox/locales/translated/ro_RO.json | 13 +- plugins/proxmox/locales/translated/ru_RU.json | 13 +- plugins/proxmox/locales/translated/sr_SP.json | 13 +- plugins/proxmox/locales/translated/sv_SE.json | 13 +- plugins/proxmox/locales/translated/th_TH.json | 13 +- plugins/proxmox/locales/translated/tr_TR.json | 13 +- plugins/proxmox/locales/translated/uk_UA.json | 13 +- plugins/proxmox/locales/translated/vi_VN.json | 13 +- plugins/proxmox/locales/translated/zh_CN.json | 13 +- plugins/proxmox/locales/translated/zh_TW.json | 13 +- plugins/proxmox/src/backend/guest-sync.ts | 12 +- .../proxmox/src/backend/proxmox-jump-hosts.ts | 5 - plugins/proxmox/src/backend/routes.ts | 132 +- .../src/frontend/ProxmoxDiscoverDialog.tsx | 9 +- plugins/proxmox/src/frontend/index.tsx | 15 +- .../tests/backend/proxmox-jump-hosts.test.ts | 24 +- plugins/proxmox/tests/backend/routes.test.ts | 12 + .../proxmox/tests/frontend/activate.test.tsx | 19 + plugins/remote-desktop/locales/en.json | 6 +- .../locales/translated/af_ZA.json | 6 +- .../locales/translated/ar_SA.json | 6 +- .../locales/translated/bg_BG.json | 6 +- .../locales/translated/bn_BD.json | 6 +- .../locales/translated/ca_ES.json | 6 +- .../locales/translated/cs_CZ.json | 6 +- .../locales/translated/da_DK.json | 6 +- .../locales/translated/de_DE.json | 6 +- .../locales/translated/el_GR.json | 6 +- .../locales/translated/es_ES.json | 6 +- .../locales/translated/fi_FI.json | 6 +- .../locales/translated/fr_FR.json | 6 +- .../locales/translated/he_IL.json | 6 +- .../locales/translated/hi_IN.json | 6 +- .../locales/translated/hu_HU.json | 6 +- .../locales/translated/id_ID.json | 6 +- .../locales/translated/it_IT.json | 6 +- .../locales/translated/ja_JP.json | 6 +- .../locales/translated/ko_KR.json | 6 +- .../locales/translated/nl_NL.json | 6 +- .../locales/translated/no_NO.json | 6 +- .../locales/translated/pl_PL.json | 6 +- .../locales/translated/pt_BR.json | 6 +- .../locales/translated/pt_PT.json | 6 +- .../locales/translated/ro_RO.json | 6 +- .../locales/translated/ru_RU.json | 6 +- .../locales/translated/sr_SP.json | 6 +- .../locales/translated/sv_SE.json | 6 +- .../locales/translated/th_TH.json | 6 +- .../locales/translated/tr_TR.json | 6 +- .../locales/translated/uk_UA.json | 6 +- .../locales/translated/vi_VN.json | 6 +- .../locales/translated/zh_CN.json | 6 +- .../locales/translated/zh_TW.json | 6 +- plugins/remote-desktop/src/frontend/index.tsx | 14 +- plugins/session-sharing/locales/en.json | 12 + .../locales/translated/af_ZA.json | 12 + .../locales/translated/ar_SA.json | 12 + .../locales/translated/bg_BG.json | 12 + .../locales/translated/bn_BD.json | 12 + .../locales/translated/ca_ES.json | 12 + .../locales/translated/cs_CZ.json | 12 + .../locales/translated/da_DK.json | 12 + .../locales/translated/de_DE.json | 12 + .../locales/translated/el_GR.json | 12 + .../locales/translated/es_ES.json | 12 + .../locales/translated/fi_FI.json | 12 + .../locales/translated/fr_FR.json | 12 + .../locales/translated/he_IL.json | 12 + .../locales/translated/hi_IN.json | 12 + .../locales/translated/hu_HU.json | 12 + .../locales/translated/id_ID.json | 12 + .../locales/translated/it_IT.json | 12 + .../locales/translated/ja_JP.json | 12 + .../locales/translated/ko_KR.json | 12 + .../locales/translated/nl_NL.json | 12 + .../locales/translated/no_NO.json | 12 + .../locales/translated/pl_PL.json | 12 + .../locales/translated/pt_BR.json | 12 + .../locales/translated/pt_PT.json | 12 + .../locales/translated/ro_RO.json | 12 + .../locales/translated/ru_RU.json | 12 + .../locales/translated/sr_SP.json | 12 + .../locales/translated/sv_SE.json | 12 + .../locales/translated/th_TH.json | 12 + .../locales/translated/tr_TR.json | 12 + .../locales/translated/uk_UA.json | 12 + .../locales/translated/vi_VN.json | 12 + .../locales/translated/zh_CN.json | 12 + .../locales/translated/zh_TW.json | 12 + plugins/ssh-terminal/locales/en.json | 3 + .../locales/translated/af_ZA.json | 3 + .../locales/translated/ar_SA.json | 3 + .../locales/translated/bg_BG.json | 3 + .../locales/translated/bn_BD.json | 3 + .../locales/translated/ca_ES.json | 3 + .../locales/translated/cs_CZ.json | 3 + .../locales/translated/da_DK.json | 3 + .../locales/translated/de_DE.json | 3 + .../locales/translated/el_GR.json | 3 + .../locales/translated/es_ES.json | 3 + .../locales/translated/fi_FI.json | 3 + .../locales/translated/fr_FR.json | 3 + .../locales/translated/he_IL.json | 3 + .../locales/translated/hi_IN.json | 3 + .../locales/translated/hu_HU.json | 3 + .../locales/translated/id_ID.json | 3 + .../locales/translated/it_IT.json | 3 + .../locales/translated/ja_JP.json | 3 + .../locales/translated/ko_KR.json | 3 + .../locales/translated/nl_NL.json | 3 + .../locales/translated/no_NO.json | 3 + .../locales/translated/pl_PL.json | 3 + .../locales/translated/pt_BR.json | 3 + .../locales/translated/pt_PT.json | 3 + .../locales/translated/ro_RO.json | 3 + .../locales/translated/ru_RU.json | 3 + .../locales/translated/sr_SP.json | 3 + .../locales/translated/sv_SE.json | 3 + .../locales/translated/th_TH.json | 3 + .../locales/translated/tr_TR.json | 3 + .../locales/translated/uk_UA.json | 3 + .../locales/translated/vi_VN.json | 3 + .../locales/translated/zh_CN.json | 3 + .../locales/translated/zh_TW.json | 3 + plugins/tailscale/locales/en.json | 11 +- .../tailscale/locales/translated/af_ZA.json | 8 + .../tailscale/locales/translated/ar_SA.json | 8 + .../tailscale/locales/translated/bg_BG.json | 8 + .../tailscale/locales/translated/bn_BD.json | 8 + .../tailscale/locales/translated/ca_ES.json | 8 + .../tailscale/locales/translated/cs_CZ.json | 8 + .../tailscale/locales/translated/da_DK.json | 8 + .../tailscale/locales/translated/de_DE.json | 8 + .../tailscale/locales/translated/el_GR.json | 8 + .../tailscale/locales/translated/es_ES.json | 8 + .../tailscale/locales/translated/fi_FI.json | 8 + .../tailscale/locales/translated/fr_FR.json | 8 + .../tailscale/locales/translated/he_IL.json | 8 + .../tailscale/locales/translated/hi_IN.json | 8 + .../tailscale/locales/translated/hu_HU.json | 8 + .../tailscale/locales/translated/id_ID.json | 8 + .../tailscale/locales/translated/it_IT.json | 8 + .../tailscale/locales/translated/ja_JP.json | 8 + .../tailscale/locales/translated/ko_KR.json | 8 + .../tailscale/locales/translated/nl_NL.json | 8 + .../tailscale/locales/translated/no_NO.json | 8 + .../tailscale/locales/translated/pl_PL.json | 8 + .../tailscale/locales/translated/pt_BR.json | 8 + .../tailscale/locales/translated/pt_PT.json | 8 + .../tailscale/locales/translated/ro_RO.json | 8 + .../tailscale/locales/translated/ru_RU.json | 8 + .../tailscale/locales/translated/sr_SP.json | 8 + .../tailscale/locales/translated/sv_SE.json | 8 + .../tailscale/locales/translated/th_TH.json | 8 + .../tailscale/locales/translated/tr_TR.json | 8 + .../tailscale/locales/translated/uk_UA.json | 8 + .../tailscale/locales/translated/vi_VN.json | 8 + .../tailscale/locales/translated/zh_CN.json | 8 + .../tailscale/locales/translated/zh_TW.json | 8 + plugins/tmux-monitor/locales/en.json | 3 +- .../locales/translated/af_ZA.json | 3 +- .../locales/translated/ar_SA.json | 3 +- .../locales/translated/bg_BG.json | 3 +- .../locales/translated/bn_BD.json | 3 +- .../locales/translated/ca_ES.json | 3 +- .../locales/translated/cs_CZ.json | 3 +- .../locales/translated/da_DK.json | 3 +- .../locales/translated/de_DE.json | 3 +- .../locales/translated/el_GR.json | 3 +- .../locales/translated/es_ES.json | 3 +- .../locales/translated/fi_FI.json | 3 +- .../locales/translated/fr_FR.json | 3 +- .../locales/translated/he_IL.json | 3 +- .../locales/translated/hi_IN.json | 3 +- .../locales/translated/hu_HU.json | 3 +- .../locales/translated/id_ID.json | 3 +- .../locales/translated/it_IT.json | 3 +- .../locales/translated/ja_JP.json | 3 +- .../locales/translated/ko_KR.json | 3 +- .../locales/translated/nl_NL.json | 3 +- .../locales/translated/no_NO.json | 3 +- .../locales/translated/pl_PL.json | 3 +- .../locales/translated/pt_BR.json | 3 +- .../locales/translated/pt_PT.json | 3 +- .../locales/translated/ro_RO.json | 3 +- .../locales/translated/ru_RU.json | 3 +- .../locales/translated/sr_SP.json | 3 +- .../locales/translated/sv_SE.json | 3 +- .../locales/translated/th_TH.json | 3 +- .../locales/translated/tr_TR.json | 3 +- .../locales/translated/uk_UA.json | 3 +- .../locales/translated/vi_VN.json | 3 +- .../locales/translated/zh_CN.json | 3 +- .../locales/translated/zh_TW.json | 3 +- .../tmux-monitor/src/frontend/PanePreview.tsx | 5 +- plugins/tunnels/locales/en.json | 14 +- plugins/tunnels/locales/translated/af_ZA.json | 14 +- plugins/tunnels/locales/translated/ar_SA.json | 14 +- plugins/tunnels/locales/translated/bg_BG.json | 14 +- plugins/tunnels/locales/translated/bn_BD.json | 14 +- plugins/tunnels/locales/translated/ca_ES.json | 14 +- plugins/tunnels/locales/translated/cs_CZ.json | 14 +- plugins/tunnels/locales/translated/da_DK.json | 14 +- plugins/tunnels/locales/translated/de_DE.json | 14 +- plugins/tunnels/locales/translated/el_GR.json | 14 +- plugins/tunnels/locales/translated/es_ES.json | 14 +- plugins/tunnels/locales/translated/fi_FI.json | 14 +- plugins/tunnels/locales/translated/fr_FR.json | 14 +- plugins/tunnels/locales/translated/he_IL.json | 14 +- plugins/tunnels/locales/translated/hi_IN.json | 14 +- plugins/tunnels/locales/translated/hu_HU.json | 14 +- plugins/tunnels/locales/translated/id_ID.json | 14 +- plugins/tunnels/locales/translated/it_IT.json | 14 +- plugins/tunnels/locales/translated/ja_JP.json | 14 +- plugins/tunnels/locales/translated/ko_KR.json | 14 +- plugins/tunnels/locales/translated/nl_NL.json | 14 +- plugins/tunnels/locales/translated/no_NO.json | 14 +- plugins/tunnels/locales/translated/pl_PL.json | 14 +- plugins/tunnels/locales/translated/pt_BR.json | 14 +- plugins/tunnels/locales/translated/pt_PT.json | 14 +- plugins/tunnels/locales/translated/ro_RO.json | 14 +- plugins/tunnels/locales/translated/ru_RU.json | 14 +- plugins/tunnels/locales/translated/sr_SP.json | 14 +- plugins/tunnels/locales/translated/sv_SE.json | 14 +- plugins/tunnels/locales/translated/th_TH.json | 14 +- plugins/tunnels/locales/translated/tr_TR.json | 14 +- plugins/tunnels/locales/translated/uk_UA.json | 14 +- plugins/tunnels/locales/translated/vi_VN.json | 14 +- plugins/tunnels/locales/translated/zh_CN.json | 14 +- plugins/tunnels/locales/translated/zh_TW.json | 14 +- .../wake-on-lan/src/frontend/host-action.ts | 14 +- plugins/wake-on-lan/src/frontend/index.tsx | 2 +- plugins/web-endpoint/locales/en.json | 3 +- .../locales/translated/af_ZA.json | 3 +- .../locales/translated/ar_SA.json | 3 +- .../locales/translated/bg_BG.json | 3 +- .../locales/translated/bn_BD.json | 3 +- .../locales/translated/ca_ES.json | 3 +- .../locales/translated/cs_CZ.json | 3 +- .../locales/translated/da_DK.json | 3 +- .../locales/translated/de_DE.json | 3 +- .../locales/translated/el_GR.json | 3 +- .../locales/translated/es_ES.json | 3 +- .../locales/translated/fi_FI.json | 3 +- .../locales/translated/fr_FR.json | 3 +- .../locales/translated/he_IL.json | 3 +- .../locales/translated/hi_IN.json | 3 +- .../locales/translated/hu_HU.json | 3 +- .../locales/translated/id_ID.json | 3 +- .../locales/translated/it_IT.json | 3 +- .../locales/translated/ja_JP.json | 3 +- .../locales/translated/ko_KR.json | 3 +- .../locales/translated/nl_NL.json | 3 +- .../locales/translated/no_NO.json | 3 +- .../locales/translated/pl_PL.json | 3 +- .../locales/translated/pt_BR.json | 3 +- .../locales/translated/pt_PT.json | 3 +- .../locales/translated/ro_RO.json | 3 +- .../locales/translated/ru_RU.json | 3 +- .../locales/translated/sr_SP.json | 3 +- .../locales/translated/sv_SE.json | 3 +- .../locales/translated/th_TH.json | 3 +- .../locales/translated/tr_TR.json | 3 +- .../locales/translated/uk_UA.json | 3 +- .../locales/translated/vi_VN.json | 3 +- .../locales/translated/zh_CN.json | 3 +- .../locales/translated/zh_TW.json | 3 +- plugins/workspaces/locales/en.json | 3 + .../workspaces/locales/translated/af_ZA.json | 3 + .../workspaces/locales/translated/ar_SA.json | 3 + .../workspaces/locales/translated/bg_BG.json | 3 + .../workspaces/locales/translated/bn_BD.json | 3 + .../workspaces/locales/translated/ca_ES.json | 3 + .../workspaces/locales/translated/cs_CZ.json | 3 + .../workspaces/locales/translated/da_DK.json | 3 + .../workspaces/locales/translated/de_DE.json | 3 + .../workspaces/locales/translated/el_GR.json | 3 + .../workspaces/locales/translated/es_ES.json | 3 + .../workspaces/locales/translated/fi_FI.json | 3 + .../workspaces/locales/translated/fr_FR.json | 3 + .../workspaces/locales/translated/he_IL.json | 3 + .../workspaces/locales/translated/hi_IN.json | 3 + .../workspaces/locales/translated/hu_HU.json | 3 + .../workspaces/locales/translated/id_ID.json | 3 + .../workspaces/locales/translated/it_IT.json | 3 + .../workspaces/locales/translated/ja_JP.json | 3 + .../workspaces/locales/translated/ko_KR.json | 3 + .../workspaces/locales/translated/nl_NL.json | 3 + .../workspaces/locales/translated/no_NO.json | 3 + .../workspaces/locales/translated/pl_PL.json | 3 + .../workspaces/locales/translated/pt_BR.json | 3 + .../workspaces/locales/translated/pt_PT.json | 3 + .../workspaces/locales/translated/ro_RO.json | 3 + .../workspaces/locales/translated/ru_RU.json | 3 + .../workspaces/locales/translated/sr_SP.json | 3 + .../workspaces/locales/translated/sv_SE.json | 3 + .../workspaces/locales/translated/th_TH.json | 3 + .../workspaces/locales/translated/tr_TR.json | 3 + .../workspaces/locales/translated/uk_UA.json | 3 + .../workspaces/locales/translated/vi_VN.json | 3 + .../workspaces/locales/translated/zh_CN.json | 3 + .../workspaces/locales/translated/zh_TW.json | 3 + scripts/check-core-plugin-ids.cjs | 81 +- scripts/check-core-plugin-ids.test.ts | 83 + scripts/check-plugin-locales.cjs | 228 + scripts/check-plugin-locales.test.ts | 127 + scripts/check-sdk-ui-exports.cjs | 281 + scripts/check-sdk-ui-exports.test.ts | 61 + scripts/check-test-locations.cjs | 61 + scripts/check-test-locations.test.ts | 57 + src/backend/database/database.ts | 13 +- src/backend/database/db/index.ts | 9 - src/backend/database/db/schema.mysql.ts | 4 - src/backend/database/db/schema.pg.ts | 4 - src/backend/database/db/schema.ts | 4 - .../database/routes/host-normalizers.ts | 3 - .../database/routes/host-plugin-settings.ts | 48 + src/backend/hosts/host-resolver.ts | 3 - src/backend/plugins/ctx-hosts.ts | 280 +- .../routes/host-plugin-settings.test.ts | 36 + .../tests/fixtures/upgrade/upgrade-mysql.sql | 7 + .../fixtures/upgrade/upgrade-postgres.sql | 7 + src/backend/tests/hosts/host-resolver.test.ts | 4 - src/backend/tests/plugins/ctx-hosts.test.ts | 124 +- .../security/credential-shapes.test.ts | 5 +- .../user-encryption-migration-store.test.ts | 15 +- src/backend/utils/field-crypto.ts | 3 - src/backend/utils/lazy-field-encryption.ts | 15 - src/backend/utils/logger.ts | 3 - .../utils/user-encryption-migration-store.ts | 5 +- src/types/index.ts | 4 - src/ui/locales/en.json | 117 +- src/ui/locales/translated/af_ZA.json | 116 +- src/ui/locales/translated/ar_SA.json | 116 +- src/ui/locales/translated/bg_BG.json | 116 +- src/ui/locales/translated/bn_BD.json | 116 +- src/ui/locales/translated/ca_ES.json | 116 +- src/ui/locales/translated/cs_CZ.json | 116 +- src/ui/locales/translated/da_DK.json | 116 +- src/ui/locales/translated/de_DE.json | 116 +- src/ui/locales/translated/el_GR.json | 116 +- src/ui/locales/translated/es_ES.json | 116 +- src/ui/locales/translated/fi_FI.json | 116 +- src/ui/locales/translated/fr_FR.json | 116 +- src/ui/locales/translated/he_IL.json | 116 +- src/ui/locales/translated/hi_IN.json | 116 +- src/ui/locales/translated/hu_HU.json | 116 +- src/ui/locales/translated/id_ID.json | 116 +- src/ui/locales/translated/it_IT.json | 116 +- src/ui/locales/translated/ja_JP.json | 116 +- src/ui/locales/translated/ko_KR.json | 116 +- src/ui/locales/translated/nl_NL.json | 116 +- src/ui/locales/translated/no_NO.json | 116 +- src/ui/locales/translated/pl_PL.json | 116 +- src/ui/locales/translated/pt_BR.json | 116 +- src/ui/locales/translated/pt_PT.json | 116 +- src/ui/locales/translated/ro_RO.json | 116 +- src/ui/locales/translated/ru_RU.json | 116 +- src/ui/locales/translated/sr_SP.json | 116 +- src/ui/locales/translated/sv_SE.json | 116 +- src/ui/locales/translated/th_TH.json | 116 +- src/ui/locales/translated/tr_TR.json | 116 +- src/ui/locales/translated/uk_UA.json | 116 +- src/ui/locales/translated/vi_VN.json | 116 +- src/ui/locales/translated/zh_CN.json | 116 +- src/ui/locales/translated/zh_TW.json | 116 +- src/ui/plugin-host/bridge.ts | 51 +- src/ui/plugin-host/shell-bridge.ts | 18 +- .../tests/onboarding/onboarding-steps.test.ts | 1 - src/ui/tests/plugin-host/bridge.test.ts | 34 + src/ui/tests/plugin-host/registries.test.tsx | 10 +- src/ui/tests/plugin-host/shell-bridge.test.ts | 52 + 626 files changed, 23884 insertions(+), 4590 deletions(-) create mode 100644 drizzle/mysql/0064_flippant_killer_shrike.sql create mode 100644 drizzle/mysql/meta/0064_snapshot.json create mode 100644 drizzle/postgres/0064_sticky_pestilence.sql create mode 100644 drizzle/postgres/meta/0064_snapshot.json create mode 100644 drizzle/sqlite/0059_adorable_wrecking_crew.sql create mode 100644 drizzle/sqlite/meta/0059_snapshot.json create mode 100644 plugins/proxmox/tests/backend/routes.test.ts create mode 100644 scripts/check-core-plugin-ids.test.ts create mode 100644 scripts/check-plugin-locales.cjs create mode 100644 scripts/check-plugin-locales.test.ts create mode 100644 scripts/check-sdk-ui-exports.cjs create mode 100644 scripts/check-sdk-ui-exports.test.ts create mode 100644 scripts/check-test-locations.cjs create mode 100644 scripts/check-test-locations.test.ts create mode 100644 src/ui/tests/plugin-host/bridge.test.ts create mode 100644 src/ui/tests/plugin-host/shell-bridge.test.ts diff --git a/drizzle/mysql/0064_flippant_killer_shrike.sql b/drizzle/mysql/0064_flippant_killer_shrike.sql new file mode 100644 index 000000000..190356856 --- /dev/null +++ b/drizzle/mysql/0064_flippant_killer_shrike.sql @@ -0,0 +1,5 @@ +-- ssh_data.autostart_password, autostart_key and autostart_key_password held +-- copies of a host's login for 2.8's autostart endpoint, which nothing has read +-- since. They leave the schema but stay in place, unused, until 3.0.0, so no +-- install loses what it stored. +SELECT 1; diff --git a/drizzle/mysql/meta/0064_snapshot.json b/drizzle/mysql/meta/0064_snapshot.json new file mode 100644 index 000000000..729654235 --- /dev/null +++ b/drizzle/mysql/meta/0064_snapshot.json @@ -0,0 +1,4754 @@ +{ + "version": "5", + "dialect": "mysql", + "id": "ddc40beb-f1b7-49d8-959b-59e1870d69cb", + "prevId": "81525cde-2267-463d-8352-2b41916bc2c8", + "tables": { + "api_keys": { + "name": "api_keys", + "columns": { + "id": { + "name": "id", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "user_id": { + "name": "user_id", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "token_hash": { + "name": "token_hash", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "token_prefix": { + "name": "token_prefix", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "created_at": { + "name": "created_at", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "(CURRENT_TIMESTAMP)" + }, + "expires_at": { + "name": "expires_at", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "last_used_at": { + "name": "last_used_at", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "is_active": { + "name": "is_active", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": true + } + }, + "indexes": { + "idx_api_keys_user_id": { + "name": "idx_api_keys_user_id", + "columns": [ + "user_id" + ], + "isUnique": false + } + }, + "foreignKeys": { + "api_keys_user_id_users_id_fk": { + "name": "api_keys_user_id_users_id_fk", + "tableFrom": "api_keys", + "tableTo": "users", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": { + "api_keys_id": { + "name": "api_keys_id", + "columns": [ + "id" + ] + } + }, + "uniqueConstraints": {}, + "checkConstraint": {} + }, + "audit_logs": { + "name": "audit_logs", + "columns": { + "id": { + "name": "id", + "type": "int", + "primaryKey": false, + "notNull": true, + "autoincrement": true + }, + "user_id": { + "name": "user_id", + "type": "varchar(255)", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "username": { + "name": "username", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "action": { + "name": "action", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "resource_type": { + "name": "resource_type", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "resource_id": { + "name": "resource_id", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "resource_name": { + "name": "resource_name", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "details": { + "name": "details", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "ip_address": { + "name": "ip_address", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "user_agent": { + "name": "user_agent", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "success": { + "name": "success", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "error_message": { + "name": "error_message", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "timestamp": { + "name": "timestamp", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "(CURRENT_TIMESTAMP)" + } + }, + "indexes": { + "idx_audit_logs_timestamp": { + "name": "idx_audit_logs_timestamp", + "columns": [ + "timestamp" + ], + "isUnique": false + }, + "idx_audit_logs_user_ts": { + "name": "idx_audit_logs_user_ts", + "columns": [ + "user_id", + "timestamp" + ], + "isUnique": false + }, + "idx_audit_logs_action_ts": { + "name": "idx_audit_logs_action_ts", + "columns": [ + "action", + "timestamp" + ], + "isUnique": false + }, + "idx_audit_logs_resource_ts": { + "name": "idx_audit_logs_resource_ts", + "columns": [ + "resource_type", + "timestamp" + ], + "isUnique": false + } + }, + "foreignKeys": { + "audit_logs_user_id_users_id_fk": { + "name": "audit_logs_user_id_users_id_fk", + "tableFrom": "audit_logs", + "tableTo": "users", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": { + "audit_logs_id": { + "name": "audit_logs_id", + "columns": [ + "id" + ] + } + }, + "uniqueConstraints": {}, + "checkConstraint": {} + }, + "credential_access": { + "name": "credential_access", + "columns": { + "id": { + "name": "id", + "type": "int", + "primaryKey": false, + "notNull": true, + "autoincrement": true + }, + "credential_id": { + "name": "credential_id", + "type": "int", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "user_id": { + "name": "user_id", + "type": "varchar(255)", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "role_id": { + "name": "role_id", + "type": "int", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "granted_by": { + "name": "granted_by", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "permission_level": { + "name": "permission_level", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "('use')" + }, + "expires_at": { + "name": "expires_at", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "created_at": { + "name": "created_at", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "(CURRENT_TIMESTAMP)" + } + }, + "indexes": { + "idx_credential_access_user_id": { + "name": "idx_credential_access_user_id", + "columns": [ + "user_id" + ], + "isUnique": false + }, + "idx_credential_access_role_id": { + "name": "idx_credential_access_role_id", + "columns": [ + "role_id" + ], + "isUnique": false + }, + "idx_credential_access_credential_id": { + "name": "idx_credential_access_credential_id", + "columns": [ + "credential_id" + ], + "isUnique": false + } + }, + "foreignKeys": { + "credential_access_credential_id_ssh_credentials_id_fk": { + "name": "credential_access_credential_id_ssh_credentials_id_fk", + "tableFrom": "credential_access", + "tableTo": "ssh_credentials", + "columnsFrom": [ + "credential_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "credential_access_user_id_users_id_fk": { + "name": "credential_access_user_id_users_id_fk", + "tableFrom": "credential_access", + "tableTo": "users", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "credential_access_role_id_roles_id_fk": { + "name": "credential_access_role_id_roles_id_fk", + "tableFrom": "credential_access", + "tableTo": "roles", + "columnsFrom": [ + "role_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "credential_access_granted_by_users_id_fk": { + "name": "credential_access_granted_by_users_id_fk", + "tableFrom": "credential_access", + "tableTo": "users", + "columnsFrom": [ + "granted_by" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": { + "credential_access_id": { + "name": "credential_access_id", + "columns": [ + "id" + ] + } + }, + "uniqueConstraints": {}, + "checkConstraint": {} + }, + "credential_sidebar_preferences": { + "name": "credential_sidebar_preferences", + "columns": { + "user_id": { + "name": "user_id", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "data": { + "name": "data", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "updated_at": { + "name": "updated_at", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "(CURRENT_TIMESTAMP)" + } + }, + "indexes": {}, + "foreignKeys": { + "credential_sidebar_preferences_user_id_users_id_fk": { + "name": "credential_sidebar_preferences_user_id_users_id_fk", + "tableFrom": "credential_sidebar_preferences", + "tableTo": "users", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": { + "credential_sidebar_preferences_user_id": { + "name": "credential_sidebar_preferences_user_id", + "columns": [ + "user_id" + ] + } + }, + "uniqueConstraints": {}, + "checkConstraint": {} + }, + "folder_access": { + "name": "folder_access", + "columns": { + "id": { + "name": "id", + "type": "int", + "primaryKey": false, + "notNull": true, + "autoincrement": true + }, + "owner_user_id": { + "name": "owner_user_id", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "folder": { + "name": "folder", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "user_id": { + "name": "user_id", + "type": "varchar(255)", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "role_id": { + "name": "role_id", + "type": "int", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "granted_by": { + "name": "granted_by", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "permission_level": { + "name": "permission_level", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "('connect')" + }, + "expires_at": { + "name": "expires_at", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "created_at": { + "name": "created_at", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "(CURRENT_TIMESTAMP)" + } + }, + "indexes": { + "idx_folder_access_owner_folder": { + "name": "idx_folder_access_owner_folder", + "columns": [ + "owner_user_id", + "folder" + ], + "isUnique": false + } + }, + "foreignKeys": { + "folder_access_owner_user_id_users_id_fk": { + "name": "folder_access_owner_user_id_users_id_fk", + "tableFrom": "folder_access", + "tableTo": "users", + "columnsFrom": [ + "owner_user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "folder_access_user_id_users_id_fk": { + "name": "folder_access_user_id_users_id_fk", + "tableFrom": "folder_access", + "tableTo": "users", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "folder_access_role_id_roles_id_fk": { + "name": "folder_access_role_id_roles_id_fk", + "tableFrom": "folder_access", + "tableTo": "roles", + "columnsFrom": [ + "role_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "folder_access_granted_by_users_id_fk": { + "name": "folder_access_granted_by_users_id_fk", + "tableFrom": "folder_access", + "tableTo": "users", + "columnsFrom": [ + "granted_by" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": { + "folder_access_id": { + "name": "folder_access_id", + "columns": [ + "id" + ] + } + }, + "uniqueConstraints": {}, + "checkConstraint": {} + }, + "host_access": { + "name": "host_access", + "columns": { + "id": { + "name": "id", + "type": "int", + "primaryKey": false, + "notNull": true, + "autoincrement": true + }, + "host_id": { + "name": "host_id", + "type": "int", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "user_id": { + "name": "user_id", + "type": "varchar(255)", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "role_id": { + "name": "role_id", + "type": "int", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "granted_by": { + "name": "granted_by", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "permission_level": { + "name": "permission_level", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "('connect')" + }, + "expires_at": { + "name": "expires_at", + "type": "varchar(255)", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "created_at": { + "name": "created_at", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "(CURRENT_TIMESTAMP)" + }, + "last_accessed_at": { + "name": "last_accessed_at", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "access_count": { + "name": "access_count", + "type": "int", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": 0 + } + }, + "indexes": { + "idx_host_access_user_id": { + "name": "idx_host_access_user_id", + "columns": [ + "user_id" + ], + "isUnique": false + }, + "idx_host_access_role_id": { + "name": "idx_host_access_role_id", + "columns": [ + "role_id" + ], + "isUnique": false + }, + "idx_host_access_host_id": { + "name": "idx_host_access_host_id", + "columns": [ + "host_id" + ], + "isUnique": false + }, + "idx_host_access_expires_at": { + "name": "idx_host_access_expires_at", + "columns": [ + "expires_at" + ], + "isUnique": false + } + }, + "foreignKeys": { + "host_access_host_id_ssh_data_id_fk": { + "name": "host_access_host_id_ssh_data_id_fk", + "tableFrom": "host_access", + "tableTo": "ssh_data", + "columnsFrom": [ + "host_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "host_access_user_id_users_id_fk": { + "name": "host_access_user_id_users_id_fk", + "tableFrom": "host_access", + "tableTo": "users", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "host_access_role_id_roles_id_fk": { + "name": "host_access_role_id_roles_id_fk", + "tableFrom": "host_access", + "tableTo": "roles", + "columnsFrom": [ + "role_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "host_access_granted_by_users_id_fk": { + "name": "host_access_granted_by_users_id_fk", + "tableFrom": "host_access", + "tableTo": "users", + "columnsFrom": [ + "granted_by" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": { + "host_access_id": { + "name": "host_access_id", + "columns": [ + "id" + ] + } + }, + "uniqueConstraints": {}, + "checkConstraint": {} + }, + "host_protocol_auth": { + "name": "host_protocol_auth", + "columns": { + "id": { + "name": "id", + "type": "int", + "primaryKey": false, + "notNull": true, + "autoincrement": true + }, + "host_id": { + "name": "host_id", + "type": "int", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "user_id": { + "name": "user_id", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "protocol": { + "name": "protocol", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "auth_type": { + "name": "auth_type", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "('direct')" + }, + "credential_id": { + "name": "credential_id", + "type": "int", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "username": { + "name": "username", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "password": { + "name": "password", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "fields": { + "name": "fields", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "secret_fields": { + "name": "secret_fields", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "created_at": { + "name": "created_at", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "(CURRENT_TIMESTAMP)" + }, + "updated_at": { + "name": "updated_at", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "(CURRENT_TIMESTAMP)" + } + }, + "indexes": { + "idx_host_protocol_auth_host_protocol": { + "name": "idx_host_protocol_auth_host_protocol", + "columns": [ + "host_id", + "protocol" + ], + "isUnique": true + }, + "idx_host_protocol_auth_user": { + "name": "idx_host_protocol_auth_user", + "columns": [ + "user_id" + ], + "isUnique": false + }, + "idx_host_protocol_auth_credential": { + "name": "idx_host_protocol_auth_credential", + "columns": [ + "credential_id" + ], + "isUnique": false + } + }, + "foreignKeys": { + "host_protocol_auth_host_id_ssh_data_id_fk": { + "name": "host_protocol_auth_host_id_ssh_data_id_fk", + "tableFrom": "host_protocol_auth", + "tableTo": "ssh_data", + "columnsFrom": [ + "host_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "host_protocol_auth_user_id_users_id_fk": { + "name": "host_protocol_auth_user_id_users_id_fk", + "tableFrom": "host_protocol_auth", + "tableTo": "users", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "host_protocol_auth_credential_id_ssh_credentials_id_fk": { + "name": "host_protocol_auth_credential_id_ssh_credentials_id_fk", + "tableFrom": "host_protocol_auth", + "tableTo": "ssh_credentials", + "columnsFrom": [ + "credential_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": { + "host_protocol_auth_id": { + "name": "host_protocol_auth_id", + "columns": [ + "id" + ] + } + }, + "uniqueConstraints": {}, + "checkConstraint": {} + }, + "host_sidebar_preferences": { + "name": "host_sidebar_preferences", + "columns": { + "user_id": { + "name": "user_id", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "data": { + "name": "data", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "updated_at": { + "name": "updated_at", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "(CURRENT_TIMESTAMP)" + } + }, + "indexes": {}, + "foreignKeys": { + "host_sidebar_preferences_user_id_users_id_fk": { + "name": "host_sidebar_preferences_user_id_users_id_fk", + "tableFrom": "host_sidebar_preferences", + "tableTo": "users", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": { + "host_sidebar_preferences_user_id": { + "name": "host_sidebar_preferences_user_id", + "columns": [ + "user_id" + ] + } + }, + "uniqueConstraints": {}, + "checkConstraint": {} + }, + "ssh_data": { + "name": "ssh_data", + "columns": { + "id": { + "name": "id", + "type": "int", + "primaryKey": false, + "notNull": true, + "autoincrement": true + }, + "user_id": { + "name": "user_id", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "connection_type": { + "name": "connection_type", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "('ssh')" + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "ip": { + "name": "ip", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "port": { + "name": "port", + "type": "int", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "username": { + "name": "username", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "folder": { + "name": "folder", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "parent_host_id": { + "name": "parent_host_id", + "type": "int", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "tags": { + "name": "tags", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "pin": { + "name": "pin", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": false + }, + "sort_order": { + "name": "sort_order", + "type": "int", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "auth_type": { + "name": "auth_type", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "share_ssh_auth": { + "name": "share_ssh_auth", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": false + }, + "force_keyboard_interactive": { + "name": "force_keyboard_interactive", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "password": { + "name": "password", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "key": { + "name": "key", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "key_password": { + "name": "key_password", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "key_type": { + "name": "key_type", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "sudo_password": { + "name": "sudo_password", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "credential_id": { + "name": "credential_id", + "type": "int", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "override_credential_username": { + "name": "override_credential_username", + "type": "boolean", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "jump_hosts": { + "name": "jump_hosts", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "status_check_enabled": { + "name": "status_check_enabled", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": true + }, + "status_check_interval": { + "name": "status_check_interval", + "type": "int", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "terminal_config": { + "name": "terminal_config", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "ssh_options": { + "name": "ssh_options", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "quick_actions": { + "name": "quick_actions", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "notes": { + "name": "notes", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "enable_ssh": { + "name": "enable_ssh", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": true + }, + "ssh_port": { + "name": "ssh_port", + "type": "int", + "primaryKey": false, + "notNull": false, + "autoincrement": false, + "default": 22 + }, + "use_socks5": { + "name": "use_socks5", + "type": "boolean", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "socks5_host": { + "name": "socks5_host", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "socks5_port": { + "name": "socks5_port", + "type": "int", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "socks5_username": { + "name": "socks5_username", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "socks5_password": { + "name": "socks5_password", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "socks5_proxy_chain": { + "name": "socks5_proxy_chain", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "connection_origin": { + "name": "connection_origin", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "port_knock_sequence": { + "name": "port_knock_sequence", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "host_key_fingerprint": { + "name": "host_key_fingerprint", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "host_key_type": { + "name": "host_key_type", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "host_key_algorithm": { + "name": "host_key_algorithm", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false, + "default": "('sha256')" + }, + "host_key_first_seen": { + "name": "host_key_first_seen", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "host_key_last_verified": { + "name": "host_key_last_verified", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "host_key_changed_count": { + "name": "host_key_changed_count", + "type": "int", + "primaryKey": false, + "notNull": false, + "autoincrement": false, + "default": 0 + }, + "sync_id": { + "name": "sync_id", + "type": "varchar(255)", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "local_only": { + "name": "local_only", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": false + }, + "shared_source": { + "name": "shared_source", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "created_at": { + "name": "created_at", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "(CURRENT_TIMESTAMP)" + }, + "updated_at": { + "name": "updated_at", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "(CURRENT_TIMESTAMP)" + } + }, + "indexes": { + "idx_ssh_data_user_id": { + "name": "idx_ssh_data_user_id", + "columns": [ + "user_id" + ], + "isUnique": false + }, + "idx_ssh_data_parent_host": { + "name": "idx_ssh_data_parent_host", + "columns": [ + "parent_host_id" + ], + "isUnique": false + }, + "idx_ssh_data_credential": { + "name": "idx_ssh_data_credential", + "columns": [ + "credential_id" + ], + "isUnique": false + } + }, + "foreignKeys": { + "ssh_data_user_id_users_id_fk": { + "name": "ssh_data_user_id_users_id_fk", + "tableFrom": "ssh_data", + "tableTo": "users", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "ssh_data_parent_host_id_ssh_data_id_fk": { + "name": "ssh_data_parent_host_id_ssh_data_id_fk", + "tableFrom": "ssh_data", + "tableTo": "ssh_data", + "columnsFrom": [ + "parent_host_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + }, + "ssh_data_credential_id_ssh_credentials_id_fk": { + "name": "ssh_data_credential_id_ssh_credentials_id_fk", + "tableFrom": "ssh_data", + "tableTo": "ssh_credentials", + "columnsFrom": [ + "credential_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": { + "ssh_data_id": { + "name": "ssh_data_id", + "columns": [ + "id" + ] + } + }, + "uniqueConstraints": { + "ssh_data_sync_id_unique": { + "name": "ssh_data_sync_id_unique", + "columns": [ + "sync_id" + ] + } + }, + "checkConstraint": {} + }, + "plugin_install_counts": { + "name": "plugin_install_counts", + "columns": { + "id": { + "name": "id", + "type": "int", + "primaryKey": false, + "notNull": true, + "autoincrement": true + }, + "plugin_id": { + "name": "plugin_id", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "registry_id": { + "name": "registry_id", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "count": { + "name": "count", + "type": "int", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": 0 + }, + "source": { + "name": "source", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "('aggregate-telemetry')" + }, + "updated_at": { + "name": "updated_at", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "(CURRENT_TIMESTAMP)" + } + }, + "indexes": { + "idx_plugin_install_counts_plugin_registry": { + "name": "idx_plugin_install_counts_plugin_registry", + "columns": [ + "plugin_id", + "registry_id" + ], + "isUnique": true + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": { + "plugin_install_counts_id": { + "name": "plugin_install_counts_id", + "columns": [ + "id" + ] + } + }, + "uniqueConstraints": {}, + "checkConstraint": {} + }, + "plugin_migrations": { + "name": "plugin_migrations", + "columns": { + "id": { + "name": "id", + "type": "int", + "primaryKey": false, + "notNull": true, + "autoincrement": true + }, + "plugin_id": { + "name": "plugin_id", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "migration_id": { + "name": "migration_id", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "checksum": { + "name": "checksum", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "applied_at": { + "name": "applied_at", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "(CURRENT_TIMESTAMP)" + } + }, + "indexes": { + "idx_plugin_migrations_plugin_migration": { + "name": "idx_plugin_migrations_plugin_migration", + "columns": [ + "plugin_id", + "migration_id" + ], + "isUnique": true + } + }, + "foreignKeys": { + "plugin_migrations_plugin_id_plugins_id_fk": { + "name": "plugin_migrations_plugin_id_plugins_id_fk", + "tableFrom": "plugin_migrations", + "tableTo": "plugins", + "columnsFrom": [ + "plugin_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": { + "plugin_migrations_id": { + "name": "plugin_migrations_id", + "columns": [ + "id" + ] + } + }, + "uniqueConstraints": {}, + "checkConstraint": {} + }, + "plugin_permission_grants": { + "name": "plugin_permission_grants", + "columns": { + "id": { + "name": "id", + "type": "int", + "primaryKey": false, + "notNull": true, + "autoincrement": true + }, + "plugin_id": { + "name": "plugin_id", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "capability": { + "name": "capability", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "granted_at": { + "name": "granted_at", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "(CURRENT_TIMESTAMP)" + }, + "granted_by": { + "name": "granted_by", + "type": "varchar(255)", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "source": { + "name": "source", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "('admin')" + } + }, + "indexes": { + "idx_plugin_permission_grants_plugin_capability": { + "name": "idx_plugin_permission_grants_plugin_capability", + "columns": [ + "plugin_id", + "capability" + ], + "isUnique": true + } + }, + "foreignKeys": { + "plugin_permission_grants_plugin_id_plugins_id_fk": { + "name": "plugin_permission_grants_plugin_id_plugins_id_fk", + "tableFrom": "plugin_permission_grants", + "tableTo": "plugins", + "columnsFrom": [ + "plugin_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "plugin_permission_grants_granted_by_users_id_fk": { + "name": "plugin_permission_grants_granted_by_users_id_fk", + "tableFrom": "plugin_permission_grants", + "tableTo": "users", + "columnsFrom": [ + "granted_by" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": { + "plugin_permission_grants_id": { + "name": "plugin_permission_grants_id", + "columns": [ + "id" + ] + } + }, + "uniqueConstraints": {}, + "checkConstraint": {} + }, + "plugin_registries": { + "name": "plugin_registries", + "columns": { + "id": { + "name": "id", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "url": { + "name": "url", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "kind": { + "name": "kind", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "('community')" + }, + "enabled": { + "name": "enabled", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": true + }, + "signing_key": { + "name": "signing_key", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "last_checked_at": { + "name": "last_checked_at", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "last_index_hash": { + "name": "last_index_hash", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": { + "plugin_registries_id": { + "name": "plugin_registries_id", + "columns": [ + "id" + ] + } + }, + "uniqueConstraints": {}, + "checkConstraint": {} + }, + "plugin_settings": { + "name": "plugin_settings", + "columns": { + "id": { + "name": "id", + "type": "int", + "primaryKey": false, + "notNull": true, + "autoincrement": true + }, + "plugin_id": { + "name": "plugin_id", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "scope": { + "name": "scope", + "type": "enum('admin','user','host','secret')", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "scope_id": { + "name": "scope_id", + "type": "varchar(255)", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "key": { + "name": "key", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "value": { + "name": "value", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "encrypted": { + "name": "encrypted", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": false + }, + "updated_at": { + "name": "updated_at", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "(CURRENT_TIMESTAMP)" + } + }, + "indexes": { + "idx_plugin_settings_scope_key": { + "name": "idx_plugin_settings_scope_key", + "columns": [ + "plugin_id", + "scope", + "scope_id", + "key" + ], + "isUnique": true + }, + "idx_plugin_settings_plugin_scope": { + "name": "idx_plugin_settings_plugin_scope", + "columns": [ + "plugin_id", + "scope" + ], + "isUnique": false + } + }, + "foreignKeys": { + "plugin_settings_plugin_id_plugins_id_fk": { + "name": "plugin_settings_plugin_id_plugins_id_fk", + "tableFrom": "plugin_settings", + "tableTo": "plugins", + "columnsFrom": [ + "plugin_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": { + "plugin_settings_id": { + "name": "plugin_settings_id", + "columns": [ + "id" + ] + } + }, + "uniqueConstraints": {}, + "checkConstraint": {} + }, + "plugin_storage": { + "name": "plugin_storage", + "columns": { + "id": { + "name": "id", + "type": "int", + "primaryKey": false, + "notNull": true, + "autoincrement": true + }, + "plugin_id": { + "name": "plugin_id", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "key": { + "name": "key", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "value": { + "name": "value", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "updated_at": { + "name": "updated_at", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "(CURRENT_TIMESTAMP)" + } + }, + "indexes": { + "idx_plugin_storage_plugin_key": { + "name": "idx_plugin_storage_plugin_key", + "columns": [ + "plugin_id", + "key" + ], + "isUnique": true + } + }, + "foreignKeys": { + "plugin_storage_plugin_id_plugins_id_fk": { + "name": "plugin_storage_plugin_id_plugins_id_fk", + "tableFrom": "plugin_storage", + "tableTo": "plugins", + "columnsFrom": [ + "plugin_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": { + "plugin_storage_id": { + "name": "plugin_storage_id", + "columns": [ + "id" + ] + } + }, + "uniqueConstraints": {}, + "checkConstraint": {} + }, + "plugins": { + "name": "plugins", + "columns": { + "id": { + "name": "id", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "version": { + "name": "version", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "tier": { + "name": "tier", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "('available')" + }, + "source": { + "name": "source", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "('community')" + }, + "registry_id": { + "name": "registry_id", + "type": "varchar(255)", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "state": { + "name": "state", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "('disabled')" + }, + "last_error": { + "name": "last_error", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "installed_at": { + "name": "installed_at", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "(CURRENT_TIMESTAMP)" + }, + "updated_at": { + "name": "updated_at", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "(CURRENT_TIMESTAMP)" + }, + "auto_update": { + "name": "auto_update", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": false + }, + "manifest_json": { + "name": "manifest_json", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + } + }, + "indexes": { + "idx_plugins_registry_id": { + "name": "idx_plugins_registry_id", + "columns": [ + "registry_id" + ], + "isUnique": false + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": { + "plugins_id": { + "name": "plugins_id", + "columns": [ + "id" + ] + } + }, + "uniqueConstraints": {}, + "checkConstraint": {} + }, + "rbac_applied_defaults": { + "name": "rbac_applied_defaults", + "columns": { + "id": { + "name": "id", + "type": "int", + "primaryKey": false, + "notNull": true, + "autoincrement": true + }, + "role_name": { + "name": "role_name", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "permission": { + "name": "permission", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "applied_at": { + "name": "applied_at", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "(CURRENT_TIMESTAMP)" + } + }, + "indexes": { + "idx_rbac_applied_defaults_role_permission": { + "name": "idx_rbac_applied_defaults_role_permission", + "columns": [ + "role_name", + "permission" + ], + "isUnique": true + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": { + "rbac_applied_defaults_id": { + "name": "rbac_applied_defaults_id", + "columns": [ + "id" + ] + } + }, + "uniqueConstraints": {}, + "checkConstraint": {} + }, + "rbac_known_permissions": { + "name": "rbac_known_permissions", + "columns": { + "id": { + "name": "id", + "type": "int", + "primaryKey": false, + "notNull": true, + "autoincrement": true + }, + "permission": { + "name": "permission", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "plugin_id": { + "name": "plugin_id", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "first_seen_at": { + "name": "first_seen_at", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "(CURRENT_TIMESTAMP)" + } + }, + "indexes": { + "idx_rbac_known_permissions_permission": { + "name": "idx_rbac_known_permissions_permission", + "columns": [ + "permission" + ], + "isUnique": true + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": { + "rbac_known_permissions_id": { + "name": "rbac_known_permissions_id", + "columns": [ + "id" + ] + } + }, + "uniqueConstraints": {}, + "checkConstraint": {} + }, + "recent_activity": { + "name": "recent_activity", + "columns": { + "id": { + "name": "id", + "type": "int", + "primaryKey": false, + "notNull": true, + "autoincrement": true + }, + "user_id": { + "name": "user_id", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "type": { + "name": "type", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "host_id": { + "name": "host_id", + "type": "int", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "host_name": { + "name": "host_name", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "timestamp": { + "name": "timestamp", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "(CURRENT_TIMESTAMP)" + } + }, + "indexes": { + "idx_recent_activity_user_ts": { + "name": "idx_recent_activity_user_ts", + "columns": [ + "user_id", + "timestamp" + ], + "isUnique": false + } + }, + "foreignKeys": { + "recent_activity_user_id_users_id_fk": { + "name": "recent_activity_user_id_users_id_fk", + "tableFrom": "recent_activity", + "tableTo": "users", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "recent_activity_host_id_ssh_data_id_fk": { + "name": "recent_activity_host_id_ssh_data_id_fk", + "tableFrom": "recent_activity", + "tableTo": "ssh_data", + "columnsFrom": [ + "host_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": { + "recent_activity_id": { + "name": "recent_activity_id", + "columns": [ + "id" + ] + } + }, + "uniqueConstraints": {}, + "checkConstraint": {} + }, + "roles": { + "name": "roles", + "columns": { + "id": { + "name": "id", + "type": "int", + "primaryKey": false, + "notNull": true, + "autoincrement": true + }, + "name": { + "name": "name", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "display_name": { + "name": "display_name", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "description": { + "name": "description", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "is_system": { + "name": "is_system", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": false + }, + "permissions": { + "name": "permissions", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "created_at": { + "name": "created_at", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "(CURRENT_TIMESTAMP)" + }, + "updated_at": { + "name": "updated_at", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "(CURRENT_TIMESTAMP)" + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": { + "roles_id": { + "name": "roles_id", + "columns": [ + "id" + ] + } + }, + "uniqueConstraints": { + "roles_name_unique": { + "name": "roles_name_unique", + "columns": [ + "name" + ] + } + }, + "checkConstraint": {} + }, + "sessions": { + "name": "sessions", + "columns": { + "id": { + "name": "id", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "user_id": { + "name": "user_id", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "jwt_token": { + "name": "jwt_token", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "device_type": { + "name": "device_type", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "device_info": { + "name": "device_info", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "oidc_sub": { + "name": "oidc_sub", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "oidc_sid": { + "name": "oidc_sid", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "sso_provider_id": { + "name": "sso_provider_id", + "type": "int", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "created_at": { + "name": "created_at", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "(CURRENT_TIMESTAMP)" + }, + "expires_at": { + "name": "expires_at", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "last_active_at": { + "name": "last_active_at", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "(CURRENT_TIMESTAMP)" + } + }, + "indexes": { + "idx_sessions_user_id": { + "name": "idx_sessions_user_id", + "columns": [ + "user_id" + ], + "isUnique": false + }, + "idx_sessions_expires_at": { + "name": "idx_sessions_expires_at", + "columns": [ + "expires_at" + ], + "isUnique": false + } + }, + "foreignKeys": { + "sessions_user_id_users_id_fk": { + "name": "sessions_user_id_users_id_fk", + "tableFrom": "sessions", + "tableTo": "users", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": { + "sessions_id": { + "name": "sessions_id", + "columns": [ + "id" + ] + } + }, + "uniqueConstraints": {}, + "checkConstraint": {} + }, + "settings": { + "name": "settings", + "columns": { + "key": { + "name": "key", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "value": { + "name": "value", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": { + "settings_key": { + "name": "settings_key", + "columns": [ + "key" + ] + } + }, + "uniqueConstraints": {}, + "checkConstraint": {} + }, + "shared_credential_secrets": { + "name": "shared_credential_secrets", + "columns": { + "id": { + "name": "id", + "type": "int", + "primaryKey": false, + "notNull": true, + "autoincrement": true + }, + "credential_access_id": { + "name": "credential_access_id", + "type": "int", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "target_user_id": { + "name": "target_user_id", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "credential_id": { + "name": "credential_id", + "type": "int", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "encrypted_username": { + "name": "encrypted_username", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "auth_type": { + "name": "auth_type", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "('password')" + }, + "encrypted_password": { + "name": "encrypted_password", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "encrypted_key": { + "name": "encrypted_key", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "encrypted_key_password": { + "name": "encrypted_key_password", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "key_type": { + "name": "key_type", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "public_key": { + "name": "public_key", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "cert_public_key": { + "name": "cert_public_key", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "created_at": { + "name": "created_at", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "(CURRENT_TIMESTAMP)" + }, + "updated_at": { + "name": "updated_at", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "(CURRENT_TIMESTAMP)" + } + }, + "indexes": { + "idx_shared_credential_secrets_scope": { + "name": "idx_shared_credential_secrets_scope", + "columns": [ + "credential_access_id", + "target_user_id" + ], + "isUnique": true + }, + "idx_shared_credential_secrets_target": { + "name": "idx_shared_credential_secrets_target", + "columns": [ + "target_user_id", + "credential_id" + ], + "isUnique": false + } + }, + "foreignKeys": { + "shared_credential_secrets_target_user_id_users_id_fk": { + "name": "shared_credential_secrets_target_user_id_users_id_fk", + "tableFrom": "shared_credential_secrets", + "tableTo": "users", + "columnsFrom": [ + "target_user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "shared_credential_secrets_credential_id_ssh_credentials_id_fk": { + "name": "shared_credential_secrets_credential_id_ssh_credentials_id_fk", + "tableFrom": "shared_credential_secrets", + "tableTo": "ssh_credentials", + "columnsFrom": [ + "credential_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "shared_cred_secrets_access_id_fk": { + "name": "shared_cred_secrets_access_id_fk", + "tableFrom": "shared_credential_secrets", + "tableTo": "credential_access", + "columnsFrom": [ + "credential_access_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": { + "shared_credential_secrets_id": { + "name": "shared_credential_secrets_id", + "columns": [ + "id" + ] + } + }, + "uniqueConstraints": {}, + "checkConstraint": {} + }, + "shared_host_auth_overrides": { + "name": "shared_host_auth_overrides", + "columns": { + "id": { + "name": "id", + "type": "int", + "primaryKey": false, + "notNull": true, + "autoincrement": true + }, + "host_id": { + "name": "host_id", + "type": "int", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "user_id": { + "name": "user_id", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "protocol": { + "name": "protocol", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "'ssh'" + }, + "credential_id": { + "name": "credential_id", + "type": "int", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "created_at": { + "name": "created_at", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "(CURRENT_TIMESTAMP)" + }, + "updated_at": { + "name": "updated_at", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "(CURRENT_TIMESTAMP)" + } + }, + "indexes": { + "shared_host_auth_overrides_host_user_protocol_unique": { + "name": "shared_host_auth_overrides_host_user_protocol_unique", + "columns": [ + "host_id", + "user_id", + "protocol" + ], + "isUnique": true + } + }, + "foreignKeys": { + "shared_host_auth_overrides_host_id_ssh_data_id_fk": { + "name": "shared_host_auth_overrides_host_id_ssh_data_id_fk", + "tableFrom": "shared_host_auth_overrides", + "tableTo": "ssh_data", + "columnsFrom": [ + "host_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "shared_host_auth_overrides_user_id_users_id_fk": { + "name": "shared_host_auth_overrides_user_id_users_id_fk", + "tableFrom": "shared_host_auth_overrides", + "tableTo": "users", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "shared_host_auth_overrides_credential_id_ssh_credentials_id_fk": { + "name": "shared_host_auth_overrides_credential_id_ssh_credentials_id_fk", + "tableFrom": "shared_host_auth_overrides", + "tableTo": "ssh_credentials", + "columnsFrom": [ + "credential_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": { + "shared_host_auth_overrides_id": { + "name": "shared_host_auth_overrides_id", + "columns": [ + "id" + ] + } + }, + "uniqueConstraints": {}, + "checkConstraint": {} + }, + "shared_host_secrets": { + "name": "shared_host_secrets", + "columns": { + "id": { + "name": "id", + "type": "int", + "primaryKey": false, + "notNull": true, + "autoincrement": true + }, + "host_access_id": { + "name": "host_access_id", + "type": "int", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "target_user_id": { + "name": "target_user_id", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "protocol": { + "name": "protocol", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "'ssh'" + }, + "source_type": { + "name": "source_type", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "('credential')" + }, + "original_credential_id": { + "name": "original_credential_id", + "type": "int", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "encrypted_username": { + "name": "encrypted_username", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "encrypted_auth_type": { + "name": "encrypted_auth_type", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "encrypted_password": { + "name": "encrypted_password", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "encrypted_key": { + "name": "encrypted_key", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "encrypted_key_password": { + "name": "encrypted_key_password", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "encrypted_key_type": { + "name": "encrypted_key_type", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "encrypted_domain": { + "name": "encrypted_domain", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "encrypted_fields": { + "name": "encrypted_fields", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "created_at": { + "name": "created_at", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "(CURRENT_TIMESTAMP)" + }, + "updated_at": { + "name": "updated_at", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "(CURRENT_TIMESTAMP)" + } + }, + "indexes": { + "idx_shared_host_secrets_scope": { + "name": "idx_shared_host_secrets_scope", + "columns": [ + "host_access_id", + "target_user_id", + "protocol" + ], + "isUnique": true + } + }, + "foreignKeys": { + "shared_host_secrets_host_access_id_host_access_id_fk": { + "name": "shared_host_secrets_host_access_id_host_access_id_fk", + "tableFrom": "shared_host_secrets", + "tableTo": "host_access", + "columnsFrom": [ + "host_access_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "shared_host_secrets_target_user_id_users_id_fk": { + "name": "shared_host_secrets_target_user_id_users_id_fk", + "tableFrom": "shared_host_secrets", + "tableTo": "users", + "columnsFrom": [ + "target_user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "shared_host_secrets_original_credential_id_ssh_credentials_id_fk": { + "name": "shared_host_secrets_original_credential_id_ssh_credentials_id_fk", + "tableFrom": "shared_host_secrets", + "tableTo": "ssh_credentials", + "columnsFrom": [ + "original_credential_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": { + "shared_host_secrets_id": { + "name": "shared_host_secrets_id", + "columns": [ + "id" + ] + } + }, + "uniqueConstraints": {}, + "checkConstraint": {} + }, + "ssh_credential_usage": { + "name": "ssh_credential_usage", + "columns": { + "id": { + "name": "id", + "type": "int", + "primaryKey": false, + "notNull": true, + "autoincrement": true + }, + "credential_id": { + "name": "credential_id", + "type": "int", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "host_id": { + "name": "host_id", + "type": "int", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "user_id": { + "name": "user_id", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "used_at": { + "name": "used_at", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "(CURRENT_TIMESTAMP)" + } + }, + "indexes": { + "idx_ssh_credential_usage_credential": { + "name": "idx_ssh_credential_usage_credential", + "columns": [ + "credential_id" + ], + "isUnique": false + }, + "idx_ssh_credential_usage_user": { + "name": "idx_ssh_credential_usage_user", + "columns": [ + "user_id" + ], + "isUnique": false + } + }, + "foreignKeys": { + "ssh_credential_usage_credential_id_ssh_credentials_id_fk": { + "name": "ssh_credential_usage_credential_id_ssh_credentials_id_fk", + "tableFrom": "ssh_credential_usage", + "tableTo": "ssh_credentials", + "columnsFrom": [ + "credential_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "ssh_credential_usage_host_id_ssh_data_id_fk": { + "name": "ssh_credential_usage_host_id_ssh_data_id_fk", + "tableFrom": "ssh_credential_usage", + "tableTo": "ssh_data", + "columnsFrom": [ + "host_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "ssh_credential_usage_user_id_users_id_fk": { + "name": "ssh_credential_usage_user_id_users_id_fk", + "tableFrom": "ssh_credential_usage", + "tableTo": "users", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": { + "ssh_credential_usage_id": { + "name": "ssh_credential_usage_id", + "columns": [ + "id" + ] + } + }, + "uniqueConstraints": {}, + "checkConstraint": {} + }, + "ssh_credentials": { + "name": "ssh_credentials", + "columns": { + "id": { + "name": "id", + "type": "int", + "primaryKey": false, + "notNull": true, + "autoincrement": true + }, + "user_id": { + "name": "user_id", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "description": { + "name": "description", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "folder": { + "name": "folder", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "tags": { + "name": "tags", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "pin": { + "name": "pin", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": false + }, + "sort_order": { + "name": "sort_order", + "type": "int", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "auth_type": { + "name": "auth_type", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "username": { + "name": "username", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "password": { + "name": "password", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "key": { + "name": "key", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "private_key": { + "name": "private_key", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "public_key": { + "name": "public_key", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "key_password": { + "name": "key_password", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "key_type": { + "name": "key_type", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "detected_key_type": { + "name": "detected_key_type", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "cert_public_key": { + "name": "cert_public_key", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "usage_count": { + "name": "usage_count", + "type": "int", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": 0 + }, + "last_used": { + "name": "last_used", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "sync_id": { + "name": "sync_id", + "type": "varchar(255)", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "shared_source": { + "name": "shared_source", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "created_at": { + "name": "created_at", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "(CURRENT_TIMESTAMP)" + }, + "updated_at": { + "name": "updated_at", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "(CURRENT_TIMESTAMP)" + } + }, + "indexes": { + "idx_ssh_credentials_user_id": { + "name": "idx_ssh_credentials_user_id", + "columns": [ + "user_id" + ], + "isUnique": false + } + }, + "foreignKeys": { + "ssh_credentials_user_id_users_id_fk": { + "name": "ssh_credentials_user_id_users_id_fk", + "tableFrom": "ssh_credentials", + "tableTo": "users", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": { + "ssh_credentials_id": { + "name": "ssh_credentials_id", + "columns": [ + "id" + ] + } + }, + "uniqueConstraints": { + "ssh_credentials_sync_id_unique": { + "name": "ssh_credentials_sync_id_unique", + "columns": [ + "sync_id" + ] + } + }, + "checkConstraint": {} + }, + "ssh_folders": { + "name": "ssh_folders", + "columns": { + "id": { + "name": "id", + "type": "int", + "primaryKey": false, + "notNull": true, + "autoincrement": true + }, + "user_id": { + "name": "user_id", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "color": { + "name": "color", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "icon": { + "name": "icon", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "credential_id": { + "name": "credential_id", + "type": "int", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "sort_order": { + "name": "sort_order", + "type": "int", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "sync_id": { + "name": "sync_id", + "type": "varchar(255)", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "local_only": { + "name": "local_only", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": false + }, + "created_at": { + "name": "created_at", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "(CURRENT_TIMESTAMP)" + }, + "updated_at": { + "name": "updated_at", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "(CURRENT_TIMESTAMP)" + } + }, + "indexes": { + "idx_ssh_folders_user_id": { + "name": "idx_ssh_folders_user_id", + "columns": [ + "user_id" + ], + "isUnique": false + } + }, + "foreignKeys": { + "ssh_folders_user_id_users_id_fk": { + "name": "ssh_folders_user_id_users_id_fk", + "tableFrom": "ssh_folders", + "tableTo": "users", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "ssh_folders_credential_id_ssh_credentials_id_fk": { + "name": "ssh_folders_credential_id_ssh_credentials_id_fk", + "tableFrom": "ssh_folders", + "tableTo": "ssh_credentials", + "columnsFrom": [ + "credential_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": { + "ssh_folders_id": { + "name": "ssh_folders_id", + "columns": [ + "id" + ] + } + }, + "uniqueConstraints": { + "ssh_folders_sync_id_unique": { + "name": "ssh_folders_sync_id_unique", + "columns": [ + "sync_id" + ] + } + }, + "checkConstraint": {} + }, + "sync_conflicts": { + "name": "sync_conflicts", + "columns": { + "id": { + "name": "id", + "type": "int", + "primaryKey": false, + "notNull": true, + "autoincrement": true + }, + "user_id": { + "name": "user_id", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "entity_type": { + "name": "entity_type", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "sync_id": { + "name": "sync_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "local_row": { + "name": "local_row", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "server_revision": { + "name": "server_revision", + "type": "int", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "created_at": { + "name": "created_at", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "(CURRENT_TIMESTAMP)" + } + }, + "indexes": { + "idx_sync_conflicts_user": { + "name": "idx_sync_conflicts_user", + "columns": [ + "user_id" + ], + "isUnique": false + } + }, + "foreignKeys": { + "sync_conflicts_user_id_users_id_fk": { + "name": "sync_conflicts_user_id_users_id_fk", + "tableFrom": "sync_conflicts", + "tableTo": "users", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": { + "sync_conflicts_id": { + "name": "sync_conflicts_id", + "columns": [ + "id" + ] + } + }, + "uniqueConstraints": {}, + "checkConstraint": {} + }, + "sync_link": { + "name": "sync_link", + "columns": { + "id": { + "name": "id", + "type": "int", + "primaryKey": false, + "notNull": true, + "autoincrement": true + }, + "user_id": { + "name": "user_id", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "server_url": { + "name": "server_url", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "server_name": { + "name": "server_name", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "server_version": { + "name": "server_version", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "session_token": { + "name": "session_token", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "custom_headers": { + "name": "custom_headers", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "basic_auth": { + "name": "basic_auth", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "allow_invalid_certificate": { + "name": "allow_invalid_certificate", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": false + }, + "remote_user_id": { + "name": "remote_user_id", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "remote_username": { + "name": "remote_username", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "account": { + "name": "account", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "scope": { + "name": "scope", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "known_types": { + "name": "known_types", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "cursor": { + "name": "cursor", + "type": "int", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": 0 + }, + "status": { + "name": "status", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "('idle')" + }, + "last_error": { + "name": "last_error", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "linked_at": { + "name": "linked_at", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "(CURRENT_TIMESTAMP)" + }, + "last_sync_at": { + "name": "last_sync_at", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + } + }, + "indexes": {}, + "foreignKeys": { + "sync_link_user_id_users_id_fk": { + "name": "sync_link_user_id_users_id_fk", + "tableFrom": "sync_link", + "tableTo": "users", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": { + "sync_link_id": { + "name": "sync_link_id", + "columns": [ + "id" + ] + } + }, + "uniqueConstraints": {}, + "checkConstraint": {} + }, + "sync_records": { + "name": "sync_records", + "columns": { + "id": { + "name": "id", + "type": "int", + "primaryKey": false, + "notNull": true, + "autoincrement": true + }, + "user_id": { + "name": "user_id", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "entity_type": { + "name": "entity_type", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "sync_id": { + "name": "sync_id", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "revision": { + "name": "revision", + "type": "int", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": 0 + }, + "seq": { + "name": "seq", + "type": "int", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": 0 + }, + "hash": { + "name": "hash", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "deleted": { + "name": "deleted", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": false + }, + "error": { + "name": "error", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "error_hash": { + "name": "error_hash", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "updated_at": { + "name": "updated_at", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "(CURRENT_TIMESTAMP)" + } + }, + "indexes": { + "idx_sync_records_user_entity_sync": { + "name": "idx_sync_records_user_entity_sync", + "columns": [ + "user_id", + "entity_type", + "sync_id" + ], + "isUnique": true + }, + "idx_sync_records_user_seq": { + "name": "idx_sync_records_user_seq", + "columns": [ + "user_id", + "seq" + ], + "isUnique": false + } + }, + "foreignKeys": { + "sync_records_user_id_users_id_fk": { + "name": "sync_records_user_id_users_id_fk", + "tableFrom": "sync_records", + "tableTo": "users", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": { + "sync_records_id": { + "name": "sync_records_id", + "columns": [ + "id" + ] + } + }, + "uniqueConstraints": {}, + "checkConstraint": {} + }, + "trusted_devices": { + "name": "trusted_devices", + "columns": { + "id": { + "name": "id", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "user_id": { + "name": "user_id", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "device_fingerprint": { + "name": "device_fingerprint", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "device_type": { + "name": "device_type", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "device_info": { + "name": "device_info", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "created_at": { + "name": "created_at", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "(CURRENT_TIMESTAMP)" + }, + "expires_at": { + "name": "expires_at", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "last_used_at": { + "name": "last_used_at", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "(CURRENT_TIMESTAMP)" + } + }, + "indexes": { + "idx_trusted_devices_user_id": { + "name": "idx_trusted_devices_user_id", + "columns": [ + "user_id" + ], + "isUnique": false + } + }, + "foreignKeys": { + "trusted_devices_user_id_users_id_fk": { + "name": "trusted_devices_user_id_users_id_fk", + "tableFrom": "trusted_devices", + "tableTo": "users", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": { + "trusted_devices_id": { + "name": "trusted_devices_id", + "columns": [ + "id" + ] + } + }, + "uniqueConstraints": {}, + "checkConstraint": {} + }, + "ui_preferences": { + "name": "ui_preferences", + "columns": { + "user_id": { + "name": "user_id", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "data": { + "name": "data", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "updated_at": { + "name": "updated_at", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "(CURRENT_TIMESTAMP)" + } + }, + "indexes": {}, + "foreignKeys": { + "ui_preferences_user_id_users_id_fk": { + "name": "ui_preferences_user_id_users_id_fk", + "tableFrom": "ui_preferences", + "tableTo": "users", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": { + "ui_preferences_user_id": { + "name": "ui_preferences_user_id", + "columns": [ + "user_id" + ] + } + }, + "uniqueConstraints": {}, + "checkConstraint": {} + }, + "user_external_identities": { + "name": "user_external_identities", + "columns": { + "id": { + "name": "id", + "type": "int", + "primaryKey": false, + "notNull": true, + "autoincrement": true + }, + "user_id": { + "name": "user_id", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "provider_id": { + "name": "provider_id", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "subject": { + "name": "subject", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "email": { + "name": "email", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "created_at": { + "name": "created_at", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "(CURRENT_TIMESTAMP)" + } + }, + "indexes": { + "idx_user_external_identities_provider_subject": { + "name": "idx_user_external_identities_provider_subject", + "columns": [ + "provider_id", + "subject" + ], + "isUnique": true + }, + "idx_user_external_identities_user": { + "name": "idx_user_external_identities_user", + "columns": [ + "user_id" + ], + "isUnique": false + } + }, + "foreignKeys": { + "user_external_identities_user_id_users_id_fk": { + "name": "user_external_identities_user_id_users_id_fk", + "tableFrom": "user_external_identities", + "tableTo": "users", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": { + "user_external_identities_id": { + "name": "user_external_identities_id", + "columns": [ + "id" + ] + } + }, + "uniqueConstraints": {}, + "checkConstraint": {} + }, + "user_open_tabs": { + "name": "user_open_tabs", + "columns": { + "id": { + "name": "id", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "user_id": { + "name": "user_id", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "tab_type": { + "name": "tab_type", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "host_id": { + "name": "host_id", + "type": "int", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "label": { + "name": "label", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "tab_order": { + "name": "tab_order", + "type": "int", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": 0 + }, + "backend_session_id": { + "name": "backend_session_id", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "created_at": { + "name": "created_at", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "(CURRENT_TIMESTAMP)" + }, + "updated_at": { + "name": "updated_at", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "(CURRENT_TIMESTAMP)" + } + }, + "indexes": { + "idx_user_open_tabs_user_id": { + "name": "idx_user_open_tabs_user_id", + "columns": [ + "user_id" + ], + "isUnique": false + } + }, + "foreignKeys": { + "user_open_tabs_user_id_users_id_fk": { + "name": "user_open_tabs_user_id_users_id_fk", + "tableFrom": "user_open_tabs", + "tableTo": "users", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "user_open_tabs_host_id_ssh_data_id_fk": { + "name": "user_open_tabs_host_id_ssh_data_id_fk", + "tableFrom": "user_open_tabs", + "tableTo": "ssh_data", + "columnsFrom": [ + "host_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": { + "user_open_tabs_id": { + "name": "user_open_tabs_id", + "columns": [ + "id" + ] + } + }, + "uniqueConstraints": {}, + "checkConstraint": {} + }, + "user_preferences": { + "name": "user_preferences", + "columns": { + "user_id": { + "name": "user_id", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "reopen_tabs_on_login": { + "name": "reopen_tabs_on_login", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": false + }, + "theme": { + "name": "theme", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "font_size": { + "name": "font_size", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "accent_color": { + "name": "accent_color", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "language": { + "name": "language", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "storage_mode": { + "name": "storage_mode", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "command_autocomplete": { + "name": "command_autocomplete", + "type": "boolean", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "command_palette_enabled": { + "name": "command_palette_enabled", + "type": "boolean", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "show_host_tags": { + "name": "show_host_tags", + "type": "boolean", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "host_tray_on_click": { + "name": "host_tray_on_click", + "type": "boolean", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "pin_app_rail": { + "name": "pin_app_rail", + "type": "boolean", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "expand_app_rail_on_hover": { + "name": "expand_app_rail_on_hover", + "type": "boolean", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "show_pin_app_rail_button": { + "name": "show_pin_app_rail_button", + "type": "boolean", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "folders_collapsed": { + "name": "folders_collapsed", + "type": "boolean", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "confirm_snippet_execution": { + "name": "confirm_snippet_execution", + "type": "boolean", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "disable_update_check": { + "name": "disable_update_check", + "type": "boolean", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "confirm_tab_close": { + "name": "confirm_tab_close", + "type": "boolean", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "hidden_rail_tabs": { + "name": "hidden_rail_tabs", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "compact_host_view": { + "name": "compact_host_view", + "type": "boolean", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "status_color_scheme": { + "name": "status_color_scheme", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "custom_themes": { + "name": "custom_themes", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "custom_keybindings": { + "name": "custom_keybindings", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "terminal_defaults": { + "name": "terminal_defaults", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "terminal_macros": { + "name": "terminal_macros", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "updated_at": { + "name": "updated_at", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "(CURRENT_TIMESTAMP)" + } + }, + "indexes": {}, + "foreignKeys": { + "user_preferences_user_id_users_id_fk": { + "name": "user_preferences_user_id_users_id_fk", + "tableFrom": "user_preferences", + "tableTo": "users", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": { + "user_preferences_user_id": { + "name": "user_preferences_user_id", + "columns": [ + "user_id" + ] + } + }, + "uniqueConstraints": {}, + "checkConstraint": {} + }, + "user_roles": { + "name": "user_roles", + "columns": { + "id": { + "name": "id", + "type": "int", + "primaryKey": false, + "notNull": true, + "autoincrement": true + }, + "user_id": { + "name": "user_id", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "role_id": { + "name": "role_id", + "type": "int", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "granted_by": { + "name": "granted_by", + "type": "varchar(255)", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "granted_at": { + "name": "granted_at", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "(CURRENT_TIMESTAMP)" + } + }, + "indexes": { + "idx_user_roles_user_role": { + "name": "idx_user_roles_user_role", + "columns": [ + "user_id", + "role_id" + ], + "isUnique": true + }, + "idx_user_roles_role_id": { + "name": "idx_user_roles_role_id", + "columns": [ + "role_id" + ], + "isUnique": false + } + }, + "foreignKeys": { + "user_roles_user_id_users_id_fk": { + "name": "user_roles_user_id_users_id_fk", + "tableFrom": "user_roles", + "tableTo": "users", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "user_roles_role_id_roles_id_fk": { + "name": "user_roles_role_id_roles_id_fk", + "tableFrom": "user_roles", + "tableTo": "roles", + "columnsFrom": [ + "role_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "user_roles_granted_by_users_id_fk": { + "name": "user_roles_granted_by_users_id_fk", + "tableFrom": "user_roles", + "tableTo": "users", + "columnsFrom": [ + "granted_by" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": { + "user_roles_id": { + "name": "user_roles_id", + "columns": [ + "id" + ] + } + }, + "uniqueConstraints": {}, + "checkConstraint": {} + }, + "user_second_factors": { + "name": "user_second_factors", + "columns": { + "id": { + "name": "id", + "type": "int", + "primaryKey": false, + "notNull": true, + "autoincrement": true + }, + "user_id": { + "name": "user_id", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "plugin_id": { + "name": "plugin_id", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "factor_id": { + "name": "factor_id", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "enrolled_at": { + "name": "enrolled_at", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "(CURRENT_TIMESTAMP)" + } + }, + "indexes": { + "idx_user_second_factors_user_factor": { + "name": "idx_user_second_factors_user_factor", + "columns": [ + "user_id", + "plugin_id", + "factor_id" + ], + "isUnique": true + } + }, + "foreignKeys": { + "user_second_factors_user_id_users_id_fk": { + "name": "user_second_factors_user_id_users_id_fk", + "tableFrom": "user_second_factors", + "tableTo": "users", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": { + "user_second_factors_id": { + "name": "user_second_factors_id", + "columns": [ + "id" + ] + } + }, + "uniqueConstraints": {}, + "checkConstraint": {} + }, + "users": { + "name": "users", + "columns": { + "id": { + "name": "id", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "username": { + "name": "username", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "password_hash": { + "name": "password_hash", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "is_admin": { + "name": "is_admin", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": false + }, + "is_oidc": { + "name": "is_oidc", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": false + }, + "oidc_identifier": { + "name": "oidc_identifier", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "sso_provider_id": { + "name": "sso_provider_id", + "type": "int", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "client_id": { + "name": "client_id", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "client_secret": { + "name": "client_secret", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "issuer_url": { + "name": "issuer_url", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "authorization_url": { + "name": "authorization_url", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "token_url": { + "name": "token_url", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "identifier_path": { + "name": "identifier_path", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "name_path": { + "name": "name_path", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "scopes": { + "name": "scopes", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false, + "default": "('openid email profile')" + }, + "registered_at": { + "name": "registered_at", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "(CURRENT_TIMESTAMP)" + }, + "donation_modal_dismissed": { + "name": "donation_modal_dismissed", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": false + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": { + "users_id": { + "name": "users_id", + "columns": [ + "id" + ] + } + }, + "uniqueConstraints": {}, + "checkConstraint": {} + } + }, + "views": {}, + "_meta": { + "schemas": {}, + "tables": {}, + "columns": {} + }, + "internal": { + "tables": {}, + "indexes": {} + } +} \ No newline at end of file diff --git a/drizzle/mysql/meta/_journal.json b/drizzle/mysql/meta/_journal.json index e20a4e154..e40f000e6 100644 --- a/drizzle/mysql/meta/_journal.json +++ b/drizzle/mysql/meta/_journal.json @@ -449,6 +449,13 @@ "when": 1790700739900, "tag": "0063_needy_radioactive_man", "breakpoints": true + }, + { + "idx": 64, + "version": "5", + "when": 1790704531888, + "tag": "0064_flippant_killer_shrike", + "breakpoints": true } ] } \ No newline at end of file diff --git a/drizzle/postgres/0064_sticky_pestilence.sql b/drizzle/postgres/0064_sticky_pestilence.sql new file mode 100644 index 000000000..190356856 --- /dev/null +++ b/drizzle/postgres/0064_sticky_pestilence.sql @@ -0,0 +1,5 @@ +-- ssh_data.autostart_password, autostart_key and autostart_key_password held +-- copies of a host's login for 2.8's autostart endpoint, which nothing has read +-- since. They leave the schema but stay in place, unused, until 3.0.0, so no +-- install loses what it stored. +SELECT 1; diff --git a/drizzle/postgres/meta/0064_snapshot.json b/drizzle/postgres/meta/0064_snapshot.json new file mode 100644 index 000000000..605a44fce --- /dev/null +++ b/drizzle/postgres/meta/0064_snapshot.json @@ -0,0 +1,4740 @@ +{ + "id": "b83f071e-0b09-4cee-a8a7-a767937de9d9", + "prevId": "30d79a7f-1cb5-4b61-aeb4-73ba1c0dc39d", + "version": "7", + "dialect": "postgresql", + "tables": { + "public.api_keys": { + "name": "api_keys", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "varchar(255)", + "primaryKey": true, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "token_hash": { + "name": "token_hash", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "token_prefix": { + "name": "token_prefix", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "CURRENT_TIMESTAMP" + }, + "expires_at": { + "name": "expires_at", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "last_used_at": { + "name": "last_used_at", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "is_active": { + "name": "is_active", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": true + } + }, + "indexes": { + "idx_api_keys_user_id": { + "name": "idx_api_keys_user_id", + "columns": [ + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "api_keys_user_id_users_id_fk": { + "name": "api_keys_user_id_users_id_fk", + "tableFrom": "api_keys", + "tableTo": "users", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.audit_logs": { + "name": "audit_logs", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "serial", + "primaryKey": true, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "varchar(255)", + "primaryKey": false, + "notNull": false + }, + "username": { + "name": "username", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "action": { + "name": "action", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true + }, + "resource_type": { + "name": "resource_type", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true + }, + "resource_id": { + "name": "resource_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "resource_name": { + "name": "resource_name", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "details": { + "name": "details", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "ip_address": { + "name": "ip_address", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "user_agent": { + "name": "user_agent", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "success": { + "name": "success", + "type": "boolean", + "primaryKey": false, + "notNull": true + }, + "error_message": { + "name": "error_message", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "timestamp": { + "name": "timestamp", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true, + "default": "CURRENT_TIMESTAMP" + } + }, + "indexes": { + "idx_audit_logs_timestamp": { + "name": "idx_audit_logs_timestamp", + "columns": [ + { + "expression": "timestamp", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_audit_logs_user_ts": { + "name": "idx_audit_logs_user_ts", + "columns": [ + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "timestamp", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_audit_logs_action_ts": { + "name": "idx_audit_logs_action_ts", + "columns": [ + { + "expression": "action", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "timestamp", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_audit_logs_resource_ts": { + "name": "idx_audit_logs_resource_ts", + "columns": [ + { + "expression": "resource_type", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "timestamp", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "audit_logs_user_id_users_id_fk": { + "name": "audit_logs_user_id_users_id_fk", + "tableFrom": "audit_logs", + "tableTo": "users", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.credential_access": { + "name": "credential_access", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "serial", + "primaryKey": true, + "notNull": true + }, + "credential_id": { + "name": "credential_id", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "varchar(255)", + "primaryKey": false, + "notNull": false + }, + "role_id": { + "name": "role_id", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "granted_by": { + "name": "granted_by", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true + }, + "permission_level": { + "name": "permission_level", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'use'" + }, + "expires_at": { + "name": "expires_at", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "CURRENT_TIMESTAMP" + } + }, + "indexes": { + "idx_credential_access_user_id": { + "name": "idx_credential_access_user_id", + "columns": [ + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_credential_access_role_id": { + "name": "idx_credential_access_role_id", + "columns": [ + { + "expression": "role_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_credential_access_credential_id": { + "name": "idx_credential_access_credential_id", + "columns": [ + { + "expression": "credential_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "credential_access_credential_id_ssh_credentials_id_fk": { + "name": "credential_access_credential_id_ssh_credentials_id_fk", + "tableFrom": "credential_access", + "tableTo": "ssh_credentials", + "columnsFrom": [ + "credential_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "credential_access_user_id_users_id_fk": { + "name": "credential_access_user_id_users_id_fk", + "tableFrom": "credential_access", + "tableTo": "users", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "credential_access_role_id_roles_id_fk": { + "name": "credential_access_role_id_roles_id_fk", + "tableFrom": "credential_access", + "tableTo": "roles", + "columnsFrom": [ + "role_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "credential_access_granted_by_users_id_fk": { + "name": "credential_access_granted_by_users_id_fk", + "tableFrom": "credential_access", + "tableTo": "users", + "columnsFrom": [ + "granted_by" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.credential_sidebar_preferences": { + "name": "credential_sidebar_preferences", + "schema": "", + "columns": { + "user_id": { + "name": "user_id", + "type": "varchar(255)", + "primaryKey": true, + "notNull": true + }, + "data": { + "name": "data", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "updated_at": { + "name": "updated_at", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "CURRENT_TIMESTAMP" + } + }, + "indexes": {}, + "foreignKeys": { + "credential_sidebar_preferences_user_id_users_id_fk": { + "name": "credential_sidebar_preferences_user_id_users_id_fk", + "tableFrom": "credential_sidebar_preferences", + "tableTo": "users", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.folder_access": { + "name": "folder_access", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "serial", + "primaryKey": true, + "notNull": true + }, + "owner_user_id": { + "name": "owner_user_id", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true + }, + "folder": { + "name": "folder", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "varchar(255)", + "primaryKey": false, + "notNull": false + }, + "role_id": { + "name": "role_id", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "granted_by": { + "name": "granted_by", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true + }, + "permission_level": { + "name": "permission_level", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'connect'" + }, + "expires_at": { + "name": "expires_at", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "CURRENT_TIMESTAMP" + } + }, + "indexes": { + "idx_folder_access_owner_folder": { + "name": "idx_folder_access_owner_folder", + "columns": [ + { + "expression": "owner_user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "folder", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "folder_access_owner_user_id_users_id_fk": { + "name": "folder_access_owner_user_id_users_id_fk", + "tableFrom": "folder_access", + "tableTo": "users", + "columnsFrom": [ + "owner_user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "folder_access_user_id_users_id_fk": { + "name": "folder_access_user_id_users_id_fk", + "tableFrom": "folder_access", + "tableTo": "users", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "folder_access_role_id_roles_id_fk": { + "name": "folder_access_role_id_roles_id_fk", + "tableFrom": "folder_access", + "tableTo": "roles", + "columnsFrom": [ + "role_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "folder_access_granted_by_users_id_fk": { + "name": "folder_access_granted_by_users_id_fk", + "tableFrom": "folder_access", + "tableTo": "users", + "columnsFrom": [ + "granted_by" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.host_access": { + "name": "host_access", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "serial", + "primaryKey": true, + "notNull": true + }, + "host_id": { + "name": "host_id", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "varchar(255)", + "primaryKey": false, + "notNull": false + }, + "role_id": { + "name": "role_id", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "granted_by": { + "name": "granted_by", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true + }, + "permission_level": { + "name": "permission_level", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'connect'" + }, + "expires_at": { + "name": "expires_at", + "type": "varchar(255)", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "CURRENT_TIMESTAMP" + }, + "last_accessed_at": { + "name": "last_accessed_at", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "access_count": { + "name": "access_count", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + } + }, + "indexes": { + "idx_host_access_user_id": { + "name": "idx_host_access_user_id", + "columns": [ + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_host_access_role_id": { + "name": "idx_host_access_role_id", + "columns": [ + { + "expression": "role_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_host_access_host_id": { + "name": "idx_host_access_host_id", + "columns": [ + { + "expression": "host_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_host_access_expires_at": { + "name": "idx_host_access_expires_at", + "columns": [ + { + "expression": "expires_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "host_access_host_id_ssh_data_id_fk": { + "name": "host_access_host_id_ssh_data_id_fk", + "tableFrom": "host_access", + "tableTo": "ssh_data", + "columnsFrom": [ + "host_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "host_access_user_id_users_id_fk": { + "name": "host_access_user_id_users_id_fk", + "tableFrom": "host_access", + "tableTo": "users", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "host_access_role_id_roles_id_fk": { + "name": "host_access_role_id_roles_id_fk", + "tableFrom": "host_access", + "tableTo": "roles", + "columnsFrom": [ + "role_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "host_access_granted_by_users_id_fk": { + "name": "host_access_granted_by_users_id_fk", + "tableFrom": "host_access", + "tableTo": "users", + "columnsFrom": [ + "granted_by" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.host_protocol_auth": { + "name": "host_protocol_auth", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "serial", + "primaryKey": true, + "notNull": true + }, + "host_id": { + "name": "host_id", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true + }, + "protocol": { + "name": "protocol", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true + }, + "auth_type": { + "name": "auth_type", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'direct'" + }, + "credential_id": { + "name": "credential_id", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "username": { + "name": "username", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "password": { + "name": "password", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "fields": { + "name": "fields", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "secret_fields": { + "name": "secret_fields", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "CURRENT_TIMESTAMP" + }, + "updated_at": { + "name": "updated_at", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "CURRENT_TIMESTAMP" + } + }, + "indexes": { + "idx_host_protocol_auth_host_protocol": { + "name": "idx_host_protocol_auth_host_protocol", + "columns": [ + { + "expression": "host_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "protocol", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_host_protocol_auth_user": { + "name": "idx_host_protocol_auth_user", + "columns": [ + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_host_protocol_auth_credential": { + "name": "idx_host_protocol_auth_credential", + "columns": [ + { + "expression": "credential_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "host_protocol_auth_host_id_ssh_data_id_fk": { + "name": "host_protocol_auth_host_id_ssh_data_id_fk", + "tableFrom": "host_protocol_auth", + "tableTo": "ssh_data", + "columnsFrom": [ + "host_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "host_protocol_auth_user_id_users_id_fk": { + "name": "host_protocol_auth_user_id_users_id_fk", + "tableFrom": "host_protocol_auth", + "tableTo": "users", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "host_protocol_auth_credential_id_ssh_credentials_id_fk": { + "name": "host_protocol_auth_credential_id_ssh_credentials_id_fk", + "tableFrom": "host_protocol_auth", + "tableTo": "ssh_credentials", + "columnsFrom": [ + "credential_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.host_sidebar_preferences": { + "name": "host_sidebar_preferences", + "schema": "", + "columns": { + "user_id": { + "name": "user_id", + "type": "varchar(255)", + "primaryKey": true, + "notNull": true + }, + "data": { + "name": "data", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "updated_at": { + "name": "updated_at", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "CURRENT_TIMESTAMP" + } + }, + "indexes": {}, + "foreignKeys": { + "host_sidebar_preferences_user_id_users_id_fk": { + "name": "host_sidebar_preferences_user_id_users_id_fk", + "tableFrom": "host_sidebar_preferences", + "tableTo": "users", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.ssh_data": { + "name": "ssh_data", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "serial", + "primaryKey": true, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true + }, + "connection_type": { + "name": "connection_type", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'ssh'" + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "ip": { + "name": "ip", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "port": { + "name": "port", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "username": { + "name": "username", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "folder": { + "name": "folder", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "parent_host_id": { + "name": "parent_host_id", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "tags": { + "name": "tags", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "pin": { + "name": "pin", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "sort_order": { + "name": "sort_order", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "auth_type": { + "name": "auth_type", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "share_ssh_auth": { + "name": "share_ssh_auth", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "force_keyboard_interactive": { + "name": "force_keyboard_interactive", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "password": { + "name": "password", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "key": { + "name": "key", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "key_password": { + "name": "key_password", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "key_type": { + "name": "key_type", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "sudo_password": { + "name": "sudo_password", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "credential_id": { + "name": "credential_id", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "override_credential_username": { + "name": "override_credential_username", + "type": "boolean", + "primaryKey": false, + "notNull": false + }, + "jump_hosts": { + "name": "jump_hosts", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "status_check_enabled": { + "name": "status_check_enabled", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": true + }, + "status_check_interval": { + "name": "status_check_interval", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "terminal_config": { + "name": "terminal_config", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "ssh_options": { + "name": "ssh_options", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "quick_actions": { + "name": "quick_actions", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "notes": { + "name": "notes", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "enable_ssh": { + "name": "enable_ssh", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": true + }, + "ssh_port": { + "name": "ssh_port", + "type": "integer", + "primaryKey": false, + "notNull": false, + "default": 22 + }, + "use_socks5": { + "name": "use_socks5", + "type": "boolean", + "primaryKey": false, + "notNull": false + }, + "socks5_host": { + "name": "socks5_host", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "socks5_port": { + "name": "socks5_port", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "socks5_username": { + "name": "socks5_username", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "socks5_password": { + "name": "socks5_password", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "socks5_proxy_chain": { + "name": "socks5_proxy_chain", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "connection_origin": { + "name": "connection_origin", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "port_knock_sequence": { + "name": "port_knock_sequence", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "host_key_fingerprint": { + "name": "host_key_fingerprint", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "host_key_type": { + "name": "host_key_type", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "host_key_algorithm": { + "name": "host_key_algorithm", + "type": "text", + "primaryKey": false, + "notNull": false, + "default": "'sha256'" + }, + "host_key_first_seen": { + "name": "host_key_first_seen", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "host_key_last_verified": { + "name": "host_key_last_verified", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "host_key_changed_count": { + "name": "host_key_changed_count", + "type": "integer", + "primaryKey": false, + "notNull": false, + "default": 0 + }, + "sync_id": { + "name": "sync_id", + "type": "varchar(255)", + "primaryKey": false, + "notNull": false + }, + "local_only": { + "name": "local_only", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "shared_source": { + "name": "shared_source", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "CURRENT_TIMESTAMP" + }, + "updated_at": { + "name": "updated_at", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "CURRENT_TIMESTAMP" + } + }, + "indexes": { + "idx_ssh_data_user_id": { + "name": "idx_ssh_data_user_id", + "columns": [ + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_ssh_data_parent_host": { + "name": "idx_ssh_data_parent_host", + "columns": [ + { + "expression": "parent_host_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_ssh_data_credential": { + "name": "idx_ssh_data_credential", + "columns": [ + { + "expression": "credential_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "ssh_data_user_id_users_id_fk": { + "name": "ssh_data_user_id_users_id_fk", + "tableFrom": "ssh_data", + "tableTo": "users", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "ssh_data_parent_host_id_ssh_data_id_fk": { + "name": "ssh_data_parent_host_id_ssh_data_id_fk", + "tableFrom": "ssh_data", + "tableTo": "ssh_data", + "columnsFrom": [ + "parent_host_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + }, + "ssh_data_credential_id_ssh_credentials_id_fk": { + "name": "ssh_data_credential_id_ssh_credentials_id_fk", + "tableFrom": "ssh_data", + "tableTo": "ssh_credentials", + "columnsFrom": [ + "credential_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "ssh_data_sync_id_unique": { + "name": "ssh_data_sync_id_unique", + "nullsNotDistinct": false, + "columns": [ + "sync_id" + ] + } + }, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.plugin_install_counts": { + "name": "plugin_install_counts", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "serial", + "primaryKey": true, + "notNull": true + }, + "plugin_id": { + "name": "plugin_id", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true + }, + "registry_id": { + "name": "registry_id", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true + }, + "count": { + "name": "count", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "source": { + "name": "source", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'aggregate-telemetry'" + }, + "updated_at": { + "name": "updated_at", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "CURRENT_TIMESTAMP" + } + }, + "indexes": { + "idx_plugin_install_counts_plugin_registry": { + "name": "idx_plugin_install_counts_plugin_registry", + "columns": [ + { + "expression": "plugin_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "registry_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.plugin_migrations": { + "name": "plugin_migrations", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "serial", + "primaryKey": true, + "notNull": true + }, + "plugin_id": { + "name": "plugin_id", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true + }, + "migration_id": { + "name": "migration_id", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true + }, + "checksum": { + "name": "checksum", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "applied_at": { + "name": "applied_at", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "CURRENT_TIMESTAMP" + } + }, + "indexes": { + "idx_plugin_migrations_plugin_migration": { + "name": "idx_plugin_migrations_plugin_migration", + "columns": [ + { + "expression": "plugin_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "migration_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "plugin_migrations_plugin_id_plugins_id_fk": { + "name": "plugin_migrations_plugin_id_plugins_id_fk", + "tableFrom": "plugin_migrations", + "tableTo": "plugins", + "columnsFrom": [ + "plugin_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.plugin_permission_grants": { + "name": "plugin_permission_grants", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "serial", + "primaryKey": true, + "notNull": true + }, + "plugin_id": { + "name": "plugin_id", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true + }, + "capability": { + "name": "capability", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true + }, + "granted_at": { + "name": "granted_at", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "CURRENT_TIMESTAMP" + }, + "granted_by": { + "name": "granted_by", + "type": "varchar(255)", + "primaryKey": false, + "notNull": false + }, + "source": { + "name": "source", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'admin'" + } + }, + "indexes": { + "idx_plugin_permission_grants_plugin_capability": { + "name": "idx_plugin_permission_grants_plugin_capability", + "columns": [ + { + "expression": "plugin_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "capability", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "plugin_permission_grants_plugin_id_plugins_id_fk": { + "name": "plugin_permission_grants_plugin_id_plugins_id_fk", + "tableFrom": "plugin_permission_grants", + "tableTo": "plugins", + "columnsFrom": [ + "plugin_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "plugin_permission_grants_granted_by_users_id_fk": { + "name": "plugin_permission_grants_granted_by_users_id_fk", + "tableFrom": "plugin_permission_grants", + "tableTo": "users", + "columnsFrom": [ + "granted_by" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.plugin_registries": { + "name": "plugin_registries", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "varchar(255)", + "primaryKey": true, + "notNull": true + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "url": { + "name": "url", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "kind": { + "name": "kind", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'community'" + }, + "enabled": { + "name": "enabled", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": true + }, + "signing_key": { + "name": "signing_key", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "last_checked_at": { + "name": "last_checked_at", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "last_index_hash": { + "name": "last_index_hash", + "type": "text", + "primaryKey": false, + "notNull": false + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.plugin_settings": { + "name": "plugin_settings", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "serial", + "primaryKey": true, + "notNull": true + }, + "plugin_id": { + "name": "plugin_id", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true + }, + "scope": { + "name": "scope", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true + }, + "scope_id": { + "name": "scope_id", + "type": "varchar(255)", + "primaryKey": false, + "notNull": false + }, + "key": { + "name": "key", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true + }, + "value": { + "name": "value", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "encrypted": { + "name": "encrypted", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "updated_at": { + "name": "updated_at", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "CURRENT_TIMESTAMP" + } + }, + "indexes": { + "idx_plugin_settings_scope_key": { + "name": "idx_plugin_settings_scope_key", + "columns": [ + { + "expression": "plugin_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "scope", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "scope_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "key", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_plugin_settings_plugin_scope": { + "name": "idx_plugin_settings_plugin_scope", + "columns": [ + { + "expression": "plugin_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "scope", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "plugin_settings_plugin_id_plugins_id_fk": { + "name": "plugin_settings_plugin_id_plugins_id_fk", + "tableFrom": "plugin_settings", + "tableTo": "plugins", + "columnsFrom": [ + "plugin_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.plugin_storage": { + "name": "plugin_storage", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "serial", + "primaryKey": true, + "notNull": true + }, + "plugin_id": { + "name": "plugin_id", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true + }, + "key": { + "name": "key", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true + }, + "value": { + "name": "value", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "updated_at": { + "name": "updated_at", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "CURRENT_TIMESTAMP" + } + }, + "indexes": { + "idx_plugin_storage_plugin_key": { + "name": "idx_plugin_storage_plugin_key", + "columns": [ + { + "expression": "plugin_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "key", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "plugin_storage_plugin_id_plugins_id_fk": { + "name": "plugin_storage_plugin_id_plugins_id_fk", + "tableFrom": "plugin_storage", + "tableTo": "plugins", + "columnsFrom": [ + "plugin_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.plugins": { + "name": "plugins", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "varchar(255)", + "primaryKey": true, + "notNull": true + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "version": { + "name": "version", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "tier": { + "name": "tier", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'available'" + }, + "source": { + "name": "source", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'community'" + }, + "registry_id": { + "name": "registry_id", + "type": "varchar(255)", + "primaryKey": false, + "notNull": false + }, + "state": { + "name": "state", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'disabled'" + }, + "last_error": { + "name": "last_error", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "installed_at": { + "name": "installed_at", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "CURRENT_TIMESTAMP" + }, + "updated_at": { + "name": "updated_at", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "CURRENT_TIMESTAMP" + }, + "auto_update": { + "name": "auto_update", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "manifest_json": { + "name": "manifest_json", + "type": "text", + "primaryKey": false, + "notNull": true + } + }, + "indexes": { + "idx_plugins_registry_id": { + "name": "idx_plugins_registry_id", + "columns": [ + { + "expression": "registry_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.rbac_applied_defaults": { + "name": "rbac_applied_defaults", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "serial", + "primaryKey": true, + "notNull": true + }, + "role_name": { + "name": "role_name", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true + }, + "permission": { + "name": "permission", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true + }, + "applied_at": { + "name": "applied_at", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "CURRENT_TIMESTAMP" + } + }, + "indexes": { + "idx_rbac_applied_defaults_role_permission": { + "name": "idx_rbac_applied_defaults_role_permission", + "columns": [ + { + "expression": "role_name", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "permission", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.rbac_known_permissions": { + "name": "rbac_known_permissions", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "serial", + "primaryKey": true, + "notNull": true + }, + "permission": { + "name": "permission", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true + }, + "plugin_id": { + "name": "plugin_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "first_seen_at": { + "name": "first_seen_at", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "CURRENT_TIMESTAMP" + } + }, + "indexes": { + "idx_rbac_known_permissions_permission": { + "name": "idx_rbac_known_permissions_permission", + "columns": [ + { + "expression": "permission", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.recent_activity": { + "name": "recent_activity", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "serial", + "primaryKey": true, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true + }, + "type": { + "name": "type", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "host_id": { + "name": "host_id", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "host_name": { + "name": "host_name", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "timestamp": { + "name": "timestamp", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true, + "default": "CURRENT_TIMESTAMP" + } + }, + "indexes": { + "idx_recent_activity_user_ts": { + "name": "idx_recent_activity_user_ts", + "columns": [ + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "timestamp", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "recent_activity_user_id_users_id_fk": { + "name": "recent_activity_user_id_users_id_fk", + "tableFrom": "recent_activity", + "tableTo": "users", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "recent_activity_host_id_ssh_data_id_fk": { + "name": "recent_activity_host_id_ssh_data_id_fk", + "tableFrom": "recent_activity", + "tableTo": "ssh_data", + "columnsFrom": [ + "host_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.roles": { + "name": "roles", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "serial", + "primaryKey": true, + "notNull": true + }, + "name": { + "name": "name", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true + }, + "display_name": { + "name": "display_name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "description": { + "name": "description", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "is_system": { + "name": "is_system", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "permissions": { + "name": "permissions", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "CURRENT_TIMESTAMP" + }, + "updated_at": { + "name": "updated_at", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "CURRENT_TIMESTAMP" + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "roles_name_unique": { + "name": "roles_name_unique", + "nullsNotDistinct": false, + "columns": [ + "name" + ] + } + }, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.sessions": { + "name": "sessions", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "varchar(255)", + "primaryKey": true, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true + }, + "jwt_token": { + "name": "jwt_token", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "device_type": { + "name": "device_type", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "device_info": { + "name": "device_info", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "oidc_sub": { + "name": "oidc_sub", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "oidc_sid": { + "name": "oidc_sid", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "sso_provider_id": { + "name": "sso_provider_id", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "CURRENT_TIMESTAMP" + }, + "expires_at": { + "name": "expires_at", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true + }, + "last_active_at": { + "name": "last_active_at", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "CURRENT_TIMESTAMP" + } + }, + "indexes": { + "idx_sessions_user_id": { + "name": "idx_sessions_user_id", + "columns": [ + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_sessions_expires_at": { + "name": "idx_sessions_expires_at", + "columns": [ + { + "expression": "expires_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "sessions_user_id_users_id_fk": { + "name": "sessions_user_id_users_id_fk", + "tableFrom": "sessions", + "tableTo": "users", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.settings": { + "name": "settings", + "schema": "", + "columns": { + "key": { + "name": "key", + "type": "varchar(255)", + "primaryKey": true, + "notNull": true + }, + "value": { + "name": "value", + "type": "text", + "primaryKey": false, + "notNull": true + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.shared_credential_secrets": { + "name": "shared_credential_secrets", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "serial", + "primaryKey": true, + "notNull": true + }, + "credential_access_id": { + "name": "credential_access_id", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "target_user_id": { + "name": "target_user_id", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true + }, + "credential_id": { + "name": "credential_id", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "encrypted_username": { + "name": "encrypted_username", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "auth_type": { + "name": "auth_type", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'password'" + }, + "encrypted_password": { + "name": "encrypted_password", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "encrypted_key": { + "name": "encrypted_key", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "encrypted_key_password": { + "name": "encrypted_key_password", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "key_type": { + "name": "key_type", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "public_key": { + "name": "public_key", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "cert_public_key": { + "name": "cert_public_key", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "CURRENT_TIMESTAMP" + }, + "updated_at": { + "name": "updated_at", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "CURRENT_TIMESTAMP" + } + }, + "indexes": { + "idx_shared_credential_secrets_scope": { + "name": "idx_shared_credential_secrets_scope", + "columns": [ + { + "expression": "credential_access_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "target_user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_shared_credential_secrets_target": { + "name": "idx_shared_credential_secrets_target", + "columns": [ + { + "expression": "target_user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "credential_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "shared_credential_secrets_target_user_id_users_id_fk": { + "name": "shared_credential_secrets_target_user_id_users_id_fk", + "tableFrom": "shared_credential_secrets", + "tableTo": "users", + "columnsFrom": [ + "target_user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "shared_credential_secrets_credential_id_ssh_credentials_id_fk": { + "name": "shared_credential_secrets_credential_id_ssh_credentials_id_fk", + "tableFrom": "shared_credential_secrets", + "tableTo": "ssh_credentials", + "columnsFrom": [ + "credential_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "shared_cred_secrets_access_id_fk": { + "name": "shared_cred_secrets_access_id_fk", + "tableFrom": "shared_credential_secrets", + "tableTo": "credential_access", + "columnsFrom": [ + "credential_access_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.shared_host_auth_overrides": { + "name": "shared_host_auth_overrides", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "serial", + "primaryKey": true, + "notNull": true + }, + "host_id": { + "name": "host_id", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true + }, + "protocol": { + "name": "protocol", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true, + "default": "'ssh'" + }, + "credential_id": { + "name": "credential_id", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "CURRENT_TIMESTAMP" + }, + "updated_at": { + "name": "updated_at", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "CURRENT_TIMESTAMP" + } + }, + "indexes": { + "shared_host_auth_overrides_host_user_protocol_unique": { + "name": "shared_host_auth_overrides_host_user_protocol_unique", + "columns": [ + { + "expression": "host_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "protocol", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "shared_host_auth_overrides_host_id_ssh_data_id_fk": { + "name": "shared_host_auth_overrides_host_id_ssh_data_id_fk", + "tableFrom": "shared_host_auth_overrides", + "tableTo": "ssh_data", + "columnsFrom": [ + "host_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "shared_host_auth_overrides_user_id_users_id_fk": { + "name": "shared_host_auth_overrides_user_id_users_id_fk", + "tableFrom": "shared_host_auth_overrides", + "tableTo": "users", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "shared_host_auth_overrides_credential_id_ssh_credentials_id_fk": { + "name": "shared_host_auth_overrides_credential_id_ssh_credentials_id_fk", + "tableFrom": "shared_host_auth_overrides", + "tableTo": "ssh_credentials", + "columnsFrom": [ + "credential_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.shared_host_secrets": { + "name": "shared_host_secrets", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "serial", + "primaryKey": true, + "notNull": true + }, + "host_access_id": { + "name": "host_access_id", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "target_user_id": { + "name": "target_user_id", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true + }, + "protocol": { + "name": "protocol", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true, + "default": "'ssh'" + }, + "source_type": { + "name": "source_type", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'credential'" + }, + "original_credential_id": { + "name": "original_credential_id", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "encrypted_username": { + "name": "encrypted_username", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "encrypted_auth_type": { + "name": "encrypted_auth_type", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "encrypted_password": { + "name": "encrypted_password", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "encrypted_key": { + "name": "encrypted_key", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "encrypted_key_password": { + "name": "encrypted_key_password", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "encrypted_key_type": { + "name": "encrypted_key_type", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "encrypted_domain": { + "name": "encrypted_domain", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "encrypted_fields": { + "name": "encrypted_fields", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "CURRENT_TIMESTAMP" + }, + "updated_at": { + "name": "updated_at", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "CURRENT_TIMESTAMP" + } + }, + "indexes": { + "idx_shared_host_secrets_scope": { + "name": "idx_shared_host_secrets_scope", + "columns": [ + { + "expression": "host_access_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "target_user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "protocol", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "shared_host_secrets_host_access_id_host_access_id_fk": { + "name": "shared_host_secrets_host_access_id_host_access_id_fk", + "tableFrom": "shared_host_secrets", + "tableTo": "host_access", + "columnsFrom": [ + "host_access_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "shared_host_secrets_target_user_id_users_id_fk": { + "name": "shared_host_secrets_target_user_id_users_id_fk", + "tableFrom": "shared_host_secrets", + "tableTo": "users", + "columnsFrom": [ + "target_user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "shared_host_secrets_original_credential_id_ssh_credentials_id_fk": { + "name": "shared_host_secrets_original_credential_id_ssh_credentials_id_fk", + "tableFrom": "shared_host_secrets", + "tableTo": "ssh_credentials", + "columnsFrom": [ + "original_credential_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.ssh_credential_usage": { + "name": "ssh_credential_usage", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "serial", + "primaryKey": true, + "notNull": true + }, + "credential_id": { + "name": "credential_id", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "host_id": { + "name": "host_id", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true + }, + "used_at": { + "name": "used_at", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "CURRENT_TIMESTAMP" + } + }, + "indexes": { + "idx_ssh_credential_usage_credential": { + "name": "idx_ssh_credential_usage_credential", + "columns": [ + { + "expression": "credential_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_ssh_credential_usage_user": { + "name": "idx_ssh_credential_usage_user", + "columns": [ + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "ssh_credential_usage_credential_id_ssh_credentials_id_fk": { + "name": "ssh_credential_usage_credential_id_ssh_credentials_id_fk", + "tableFrom": "ssh_credential_usage", + "tableTo": "ssh_credentials", + "columnsFrom": [ + "credential_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "ssh_credential_usage_host_id_ssh_data_id_fk": { + "name": "ssh_credential_usage_host_id_ssh_data_id_fk", + "tableFrom": "ssh_credential_usage", + "tableTo": "ssh_data", + "columnsFrom": [ + "host_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "ssh_credential_usage_user_id_users_id_fk": { + "name": "ssh_credential_usage_user_id_users_id_fk", + "tableFrom": "ssh_credential_usage", + "tableTo": "users", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.ssh_credentials": { + "name": "ssh_credentials", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "serial", + "primaryKey": true, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "description": { + "name": "description", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "folder": { + "name": "folder", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "tags": { + "name": "tags", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "pin": { + "name": "pin", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "sort_order": { + "name": "sort_order", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "auth_type": { + "name": "auth_type", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "username": { + "name": "username", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "password": { + "name": "password", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "key": { + "name": "key", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "private_key": { + "name": "private_key", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "public_key": { + "name": "public_key", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "key_password": { + "name": "key_password", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "key_type": { + "name": "key_type", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "detected_key_type": { + "name": "detected_key_type", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "cert_public_key": { + "name": "cert_public_key", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "usage_count": { + "name": "usage_count", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "last_used": { + "name": "last_used", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "sync_id": { + "name": "sync_id", + "type": "varchar(255)", + "primaryKey": false, + "notNull": false + }, + "shared_source": { + "name": "shared_source", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "CURRENT_TIMESTAMP" + }, + "updated_at": { + "name": "updated_at", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "CURRENT_TIMESTAMP" + } + }, + "indexes": { + "idx_ssh_credentials_user_id": { + "name": "idx_ssh_credentials_user_id", + "columns": [ + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "ssh_credentials_user_id_users_id_fk": { + "name": "ssh_credentials_user_id_users_id_fk", + "tableFrom": "ssh_credentials", + "tableTo": "users", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "ssh_credentials_sync_id_unique": { + "name": "ssh_credentials_sync_id_unique", + "nullsNotDistinct": false, + "columns": [ + "sync_id" + ] + } + }, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.ssh_folders": { + "name": "ssh_folders", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "serial", + "primaryKey": true, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "color": { + "name": "color", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "icon": { + "name": "icon", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "credential_id": { + "name": "credential_id", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "sort_order": { + "name": "sort_order", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "sync_id": { + "name": "sync_id", + "type": "varchar(255)", + "primaryKey": false, + "notNull": false + }, + "local_only": { + "name": "local_only", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "created_at": { + "name": "created_at", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "CURRENT_TIMESTAMP" + }, + "updated_at": { + "name": "updated_at", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "CURRENT_TIMESTAMP" + } + }, + "indexes": { + "idx_ssh_folders_user_id": { + "name": "idx_ssh_folders_user_id", + "columns": [ + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "ssh_folders_user_id_users_id_fk": { + "name": "ssh_folders_user_id_users_id_fk", + "tableFrom": "ssh_folders", + "tableTo": "users", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "ssh_folders_credential_id_ssh_credentials_id_fk": { + "name": "ssh_folders_credential_id_ssh_credentials_id_fk", + "tableFrom": "ssh_folders", + "tableTo": "ssh_credentials", + "columnsFrom": [ + "credential_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "ssh_folders_sync_id_unique": { + "name": "ssh_folders_sync_id_unique", + "nullsNotDistinct": false, + "columns": [ + "sync_id" + ] + } + }, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.sync_conflicts": { + "name": "sync_conflicts", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "serial", + "primaryKey": true, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true + }, + "entity_type": { + "name": "entity_type", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "sync_id": { + "name": "sync_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "local_row": { + "name": "local_row", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "server_revision": { + "name": "server_revision", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "CURRENT_TIMESTAMP" + } + }, + "indexes": { + "idx_sync_conflicts_user": { + "name": "idx_sync_conflicts_user", + "columns": [ + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "sync_conflicts_user_id_users_id_fk": { + "name": "sync_conflicts_user_id_users_id_fk", + "tableFrom": "sync_conflicts", + "tableTo": "users", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.sync_link": { + "name": "sync_link", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "serial", + "primaryKey": true, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true + }, + "server_url": { + "name": "server_url", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "server_name": { + "name": "server_name", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "server_version": { + "name": "server_version", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "session_token": { + "name": "session_token", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "custom_headers": { + "name": "custom_headers", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "basic_auth": { + "name": "basic_auth", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "allow_invalid_certificate": { + "name": "allow_invalid_certificate", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "remote_user_id": { + "name": "remote_user_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "remote_username": { + "name": "remote_username", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "account": { + "name": "account", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "scope": { + "name": "scope", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "known_types": { + "name": "known_types", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "cursor": { + "name": "cursor", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "status": { + "name": "status", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'idle'" + }, + "last_error": { + "name": "last_error", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "linked_at": { + "name": "linked_at", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "CURRENT_TIMESTAMP" + }, + "last_sync_at": { + "name": "last_sync_at", + "type": "text", + "primaryKey": false, + "notNull": false + } + }, + "indexes": {}, + "foreignKeys": { + "sync_link_user_id_users_id_fk": { + "name": "sync_link_user_id_users_id_fk", + "tableFrom": "sync_link", + "tableTo": "users", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.sync_records": { + "name": "sync_records", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "serial", + "primaryKey": true, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true + }, + "entity_type": { + "name": "entity_type", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true + }, + "sync_id": { + "name": "sync_id", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true + }, + "revision": { + "name": "revision", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "seq": { + "name": "seq", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "hash": { + "name": "hash", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "deleted": { + "name": "deleted", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "error": { + "name": "error", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "error_hash": { + "name": "error_hash", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "updated_at": { + "name": "updated_at", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "CURRENT_TIMESTAMP" + } + }, + "indexes": { + "idx_sync_records_user_entity_sync": { + "name": "idx_sync_records_user_entity_sync", + "columns": [ + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "entity_type", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "sync_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_sync_records_user_seq": { + "name": "idx_sync_records_user_seq", + "columns": [ + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "seq", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "sync_records_user_id_users_id_fk": { + "name": "sync_records_user_id_users_id_fk", + "tableFrom": "sync_records", + "tableTo": "users", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.trusted_devices": { + "name": "trusted_devices", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "varchar(255)", + "primaryKey": true, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true + }, + "device_fingerprint": { + "name": "device_fingerprint", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "device_type": { + "name": "device_type", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "device_info": { + "name": "device_info", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "CURRENT_TIMESTAMP" + }, + "expires_at": { + "name": "expires_at", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "last_used_at": { + "name": "last_used_at", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "CURRENT_TIMESTAMP" + } + }, + "indexes": { + "idx_trusted_devices_user_id": { + "name": "idx_trusted_devices_user_id", + "columns": [ + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "trusted_devices_user_id_users_id_fk": { + "name": "trusted_devices_user_id_users_id_fk", + "tableFrom": "trusted_devices", + "tableTo": "users", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.ui_preferences": { + "name": "ui_preferences", + "schema": "", + "columns": { + "user_id": { + "name": "user_id", + "type": "varchar(255)", + "primaryKey": true, + "notNull": true + }, + "data": { + "name": "data", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "updated_at": { + "name": "updated_at", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "CURRENT_TIMESTAMP" + } + }, + "indexes": {}, + "foreignKeys": { + "ui_preferences_user_id_users_id_fk": { + "name": "ui_preferences_user_id_users_id_fk", + "tableFrom": "ui_preferences", + "tableTo": "users", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.user_external_identities": { + "name": "user_external_identities", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "serial", + "primaryKey": true, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true + }, + "provider_id": { + "name": "provider_id", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true + }, + "subject": { + "name": "subject", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true + }, + "email": { + "name": "email", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "CURRENT_TIMESTAMP" + } + }, + "indexes": { + "idx_user_external_identities_provider_subject": { + "name": "idx_user_external_identities_provider_subject", + "columns": [ + { + "expression": "provider_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "subject", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_user_external_identities_user": { + "name": "idx_user_external_identities_user", + "columns": [ + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "user_external_identities_user_id_users_id_fk": { + "name": "user_external_identities_user_id_users_id_fk", + "tableFrom": "user_external_identities", + "tableTo": "users", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.user_open_tabs": { + "name": "user_open_tabs", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "varchar(255)", + "primaryKey": true, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true + }, + "tab_type": { + "name": "tab_type", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "host_id": { + "name": "host_id", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "label": { + "name": "label", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "tab_order": { + "name": "tab_order", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 0 + }, + "backend_session_id": { + "name": "backend_session_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "CURRENT_TIMESTAMP" + }, + "updated_at": { + "name": "updated_at", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "CURRENT_TIMESTAMP" + } + }, + "indexes": { + "idx_user_open_tabs_user_id": { + "name": "idx_user_open_tabs_user_id", + "columns": [ + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "user_open_tabs_user_id_users_id_fk": { + "name": "user_open_tabs_user_id_users_id_fk", + "tableFrom": "user_open_tabs", + "tableTo": "users", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "user_open_tabs_host_id_ssh_data_id_fk": { + "name": "user_open_tabs_host_id_ssh_data_id_fk", + "tableFrom": "user_open_tabs", + "tableTo": "ssh_data", + "columnsFrom": [ + "host_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.user_preferences": { + "name": "user_preferences", + "schema": "", + "columns": { + "user_id": { + "name": "user_id", + "type": "varchar(255)", + "primaryKey": true, + "notNull": true + }, + "reopen_tabs_on_login": { + "name": "reopen_tabs_on_login", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "theme": { + "name": "theme", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "font_size": { + "name": "font_size", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "accent_color": { + "name": "accent_color", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "language": { + "name": "language", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "storage_mode": { + "name": "storage_mode", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "command_autocomplete": { + "name": "command_autocomplete", + "type": "boolean", + "primaryKey": false, + "notNull": false + }, + "command_palette_enabled": { + "name": "command_palette_enabled", + "type": "boolean", + "primaryKey": false, + "notNull": false + }, + "show_host_tags": { + "name": "show_host_tags", + "type": "boolean", + "primaryKey": false, + "notNull": false + }, + "host_tray_on_click": { + "name": "host_tray_on_click", + "type": "boolean", + "primaryKey": false, + "notNull": false + }, + "pin_app_rail": { + "name": "pin_app_rail", + "type": "boolean", + "primaryKey": false, + "notNull": false + }, + "expand_app_rail_on_hover": { + "name": "expand_app_rail_on_hover", + "type": "boolean", + "primaryKey": false, + "notNull": false + }, + "show_pin_app_rail_button": { + "name": "show_pin_app_rail_button", + "type": "boolean", + "primaryKey": false, + "notNull": false + }, + "folders_collapsed": { + "name": "folders_collapsed", + "type": "boolean", + "primaryKey": false, + "notNull": false + }, + "confirm_snippet_execution": { + "name": "confirm_snippet_execution", + "type": "boolean", + "primaryKey": false, + "notNull": false + }, + "disable_update_check": { + "name": "disable_update_check", + "type": "boolean", + "primaryKey": false, + "notNull": false + }, + "confirm_tab_close": { + "name": "confirm_tab_close", + "type": "boolean", + "primaryKey": false, + "notNull": false + }, + "hidden_rail_tabs": { + "name": "hidden_rail_tabs", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "compact_host_view": { + "name": "compact_host_view", + "type": "boolean", + "primaryKey": false, + "notNull": false + }, + "status_color_scheme": { + "name": "status_color_scheme", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "custom_themes": { + "name": "custom_themes", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "custom_keybindings": { + "name": "custom_keybindings", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "terminal_defaults": { + "name": "terminal_defaults", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "terminal_macros": { + "name": "terminal_macros", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "updated_at": { + "name": "updated_at", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "CURRENT_TIMESTAMP" + } + }, + "indexes": {}, + "foreignKeys": { + "user_preferences_user_id_users_id_fk": { + "name": "user_preferences_user_id_users_id_fk", + "tableFrom": "user_preferences", + "tableTo": "users", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.user_roles": { + "name": "user_roles", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "serial", + "primaryKey": true, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true + }, + "role_id": { + "name": "role_id", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "granted_by": { + "name": "granted_by", + "type": "varchar(255)", + "primaryKey": false, + "notNull": false + }, + "granted_at": { + "name": "granted_at", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "CURRENT_TIMESTAMP" + } + }, + "indexes": { + "idx_user_roles_user_role": { + "name": "idx_user_roles_user_role", + "columns": [ + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "role_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + }, + "idx_user_roles_role_id": { + "name": "idx_user_roles_role_id", + "columns": [ + { + "expression": "role_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "user_roles_user_id_users_id_fk": { + "name": "user_roles_user_id_users_id_fk", + "tableFrom": "user_roles", + "tableTo": "users", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "user_roles_role_id_roles_id_fk": { + "name": "user_roles_role_id_roles_id_fk", + "tableFrom": "user_roles", + "tableTo": "roles", + "columnsFrom": [ + "role_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "user_roles_granted_by_users_id_fk": { + "name": "user_roles_granted_by_users_id_fk", + "tableFrom": "user_roles", + "tableTo": "users", + "columnsFrom": [ + "granted_by" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.user_second_factors": { + "name": "user_second_factors", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "serial", + "primaryKey": true, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true + }, + "plugin_id": { + "name": "plugin_id", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true + }, + "factor_id": { + "name": "factor_id", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true + }, + "enrolled_at": { + "name": "enrolled_at", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "CURRENT_TIMESTAMP" + } + }, + "indexes": { + "idx_user_second_factors_user_factor": { + "name": "idx_user_second_factors_user_factor", + "columns": [ + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "plugin_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "factor_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "user_second_factors_user_id_users_id_fk": { + "name": "user_second_factors_user_id_users_id_fk", + "tableFrom": "user_second_factors", + "tableTo": "users", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.users": { + "name": "users", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "varchar(255)", + "primaryKey": true, + "notNull": true + }, + "username": { + "name": "username", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "password_hash": { + "name": "password_hash", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "is_admin": { + "name": "is_admin", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "is_oidc": { + "name": "is_oidc", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "oidc_identifier": { + "name": "oidc_identifier", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "sso_provider_id": { + "name": "sso_provider_id", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "client_id": { + "name": "client_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "client_secret": { + "name": "client_secret", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "issuer_url": { + "name": "issuer_url", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "authorization_url": { + "name": "authorization_url", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "token_url": { + "name": "token_url", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "identifier_path": { + "name": "identifier_path", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "name_path": { + "name": "name_path", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "scopes": { + "name": "scopes", + "type": "text", + "primaryKey": false, + "notNull": false, + "default": "'openid email profile'" + }, + "registered_at": { + "name": "registered_at", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "CURRENT_TIMESTAMP" + }, + "donation_modal_dismissed": { + "name": "donation_modal_dismissed", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + } + }, + "enums": {}, + "schemas": {}, + "sequences": {}, + "roles": {}, + "policies": {}, + "views": {}, + "_meta": { + "columns": {}, + "schemas": {}, + "tables": {} + } +} \ No newline at end of file diff --git a/drizzle/postgres/meta/_journal.json b/drizzle/postgres/meta/_journal.json index 6caadff3a..02726b9dd 100644 --- a/drizzle/postgres/meta/_journal.json +++ b/drizzle/postgres/meta/_journal.json @@ -449,6 +449,13 @@ "when": 1790700738799, "tag": "0063_giant_starfox", "breakpoints": true + }, + { + "idx": 64, + "version": "7", + "when": 1790704531255, + "tag": "0064_sticky_pestilence", + "breakpoints": true } ] } \ No newline at end of file diff --git a/drizzle/sqlite/0059_adorable_wrecking_crew.sql b/drizzle/sqlite/0059_adorable_wrecking_crew.sql new file mode 100644 index 000000000..190356856 --- /dev/null +++ b/drizzle/sqlite/0059_adorable_wrecking_crew.sql @@ -0,0 +1,5 @@ +-- ssh_data.autostart_password, autostart_key and autostart_key_password held +-- copies of a host's login for 2.8's autostart endpoint, which nothing has read +-- since. They leave the schema but stay in place, unused, until 3.0.0, so no +-- install loses what it stored. +SELECT 1; diff --git a/drizzle/sqlite/meta/0059_snapshot.json b/drizzle/sqlite/meta/0059_snapshot.json new file mode 100644 index 000000000..0f8704a16 --- /dev/null +++ b/drizzle/sqlite/meta/0059_snapshot.json @@ -0,0 +1,4482 @@ +{ + "version": "6", + "dialect": "sqlite", + "id": "cd464460-6903-476e-8da9-f19f207bc2dc", + "prevId": "6cf2bc9e-0162-4233-a2c0-0285be6f8763", + "tables": { + "api_keys": { + "name": "api_keys", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true, + "autoincrement": false + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "token_hash": { + "name": "token_hash", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "token_prefix": { + "name": "token_prefix", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "created_at": { + "name": "created_at", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "CURRENT_TIMESTAMP" + }, + "expires_at": { + "name": "expires_at", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "last_used_at": { + "name": "last_used_at", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "is_active": { + "name": "is_active", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": true + } + }, + "indexes": { + "idx_api_keys_user_id": { + "name": "idx_api_keys_user_id", + "columns": [ + "user_id" + ], + "isUnique": false + } + }, + "foreignKeys": { + "api_keys_user_id_users_id_fk": { + "name": "api_keys_user_id_users_id_fk", + "tableFrom": "api_keys", + "tableTo": "users", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "checkConstraints": {} + }, + "audit_logs": { + "name": "audit_logs", + "columns": { + "id": { + "name": "id", + "type": "integer", + "primaryKey": true, + "notNull": true, + "autoincrement": true + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "username": { + "name": "username", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "action": { + "name": "action", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "resource_type": { + "name": "resource_type", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "resource_id": { + "name": "resource_id", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "resource_name": { + "name": "resource_name", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "details": { + "name": "details", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "ip_address": { + "name": "ip_address", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "user_agent": { + "name": "user_agent", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "success": { + "name": "success", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "error_message": { + "name": "error_message", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "timestamp": { + "name": "timestamp", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "CURRENT_TIMESTAMP" + } + }, + "indexes": { + "idx_audit_logs_timestamp": { + "name": "idx_audit_logs_timestamp", + "columns": [ + "timestamp" + ], + "isUnique": false + }, + "idx_audit_logs_user_ts": { + "name": "idx_audit_logs_user_ts", + "columns": [ + "user_id", + "timestamp" + ], + "isUnique": false + }, + "idx_audit_logs_action_ts": { + "name": "idx_audit_logs_action_ts", + "columns": [ + "action", + "timestamp" + ], + "isUnique": false + }, + "idx_audit_logs_resource_ts": { + "name": "idx_audit_logs_resource_ts", + "columns": [ + "resource_type", + "timestamp" + ], + "isUnique": false + } + }, + "foreignKeys": { + "audit_logs_user_id_users_id_fk": { + "name": "audit_logs_user_id_users_id_fk", + "tableFrom": "audit_logs", + "tableTo": "users", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "checkConstraints": {} + }, + "credential_access": { + "name": "credential_access", + "columns": { + "id": { + "name": "id", + "type": "integer", + "primaryKey": true, + "notNull": true, + "autoincrement": true + }, + "credential_id": { + "name": "credential_id", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "role_id": { + "name": "role_id", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "granted_by": { + "name": "granted_by", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "permission_level": { + "name": "permission_level", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "'use'" + }, + "expires_at": { + "name": "expires_at", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "created_at": { + "name": "created_at", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "CURRENT_TIMESTAMP" + } + }, + "indexes": { + "idx_credential_access_user_id": { + "name": "idx_credential_access_user_id", + "columns": [ + "user_id" + ], + "isUnique": false + }, + "idx_credential_access_role_id": { + "name": "idx_credential_access_role_id", + "columns": [ + "role_id" + ], + "isUnique": false + }, + "idx_credential_access_credential_id": { + "name": "idx_credential_access_credential_id", + "columns": [ + "credential_id" + ], + "isUnique": false + } + }, + "foreignKeys": { + "credential_access_credential_id_ssh_credentials_id_fk": { + "name": "credential_access_credential_id_ssh_credentials_id_fk", + "tableFrom": "credential_access", + "tableTo": "ssh_credentials", + "columnsFrom": [ + "credential_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "credential_access_user_id_users_id_fk": { + "name": "credential_access_user_id_users_id_fk", + "tableFrom": "credential_access", + "tableTo": "users", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "credential_access_role_id_roles_id_fk": { + "name": "credential_access_role_id_roles_id_fk", + "tableFrom": "credential_access", + "tableTo": "roles", + "columnsFrom": [ + "role_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "credential_access_granted_by_users_id_fk": { + "name": "credential_access_granted_by_users_id_fk", + "tableFrom": "credential_access", + "tableTo": "users", + "columnsFrom": [ + "granted_by" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "checkConstraints": {} + }, + "credential_sidebar_preferences": { + "name": "credential_sidebar_preferences", + "columns": { + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": true, + "notNull": true, + "autoincrement": false + }, + "data": { + "name": "data", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "updated_at": { + "name": "updated_at", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "CURRENT_TIMESTAMP" + } + }, + "indexes": {}, + "foreignKeys": { + "credential_sidebar_preferences_user_id_users_id_fk": { + "name": "credential_sidebar_preferences_user_id_users_id_fk", + "tableFrom": "credential_sidebar_preferences", + "tableTo": "users", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "checkConstraints": {} + }, + "folder_access": { + "name": "folder_access", + "columns": { + "id": { + "name": "id", + "type": "integer", + "primaryKey": true, + "notNull": true, + "autoincrement": true + }, + "owner_user_id": { + "name": "owner_user_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "folder": { + "name": "folder", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "role_id": { + "name": "role_id", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "granted_by": { + "name": "granted_by", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "permission_level": { + "name": "permission_level", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "'connect'" + }, + "expires_at": { + "name": "expires_at", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "created_at": { + "name": "created_at", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "CURRENT_TIMESTAMP" + } + }, + "indexes": { + "idx_folder_access_owner_folder": { + "name": "idx_folder_access_owner_folder", + "columns": [ + "owner_user_id", + "folder" + ], + "isUnique": false + } + }, + "foreignKeys": { + "folder_access_owner_user_id_users_id_fk": { + "name": "folder_access_owner_user_id_users_id_fk", + "tableFrom": "folder_access", + "tableTo": "users", + "columnsFrom": [ + "owner_user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "folder_access_user_id_users_id_fk": { + "name": "folder_access_user_id_users_id_fk", + "tableFrom": "folder_access", + "tableTo": "users", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "folder_access_role_id_roles_id_fk": { + "name": "folder_access_role_id_roles_id_fk", + "tableFrom": "folder_access", + "tableTo": "roles", + "columnsFrom": [ + "role_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "folder_access_granted_by_users_id_fk": { + "name": "folder_access_granted_by_users_id_fk", + "tableFrom": "folder_access", + "tableTo": "users", + "columnsFrom": [ + "granted_by" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "checkConstraints": {} + }, + "host_access": { + "name": "host_access", + "columns": { + "id": { + "name": "id", + "type": "integer", + "primaryKey": true, + "notNull": true, + "autoincrement": true + }, + "host_id": { + "name": "host_id", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "role_id": { + "name": "role_id", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "granted_by": { + "name": "granted_by", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "permission_level": { + "name": "permission_level", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "'connect'" + }, + "expires_at": { + "name": "expires_at", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "created_at": { + "name": "created_at", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "CURRENT_TIMESTAMP" + }, + "last_accessed_at": { + "name": "last_accessed_at", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "access_count": { + "name": "access_count", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": 0 + } + }, + "indexes": { + "idx_host_access_user_id": { + "name": "idx_host_access_user_id", + "columns": [ + "user_id" + ], + "isUnique": false + }, + "idx_host_access_role_id": { + "name": "idx_host_access_role_id", + "columns": [ + "role_id" + ], + "isUnique": false + }, + "idx_host_access_host_id": { + "name": "idx_host_access_host_id", + "columns": [ + "host_id" + ], + "isUnique": false + }, + "idx_host_access_expires_at": { + "name": "idx_host_access_expires_at", + "columns": [ + "expires_at" + ], + "isUnique": false + } + }, + "foreignKeys": { + "host_access_host_id_ssh_data_id_fk": { + "name": "host_access_host_id_ssh_data_id_fk", + "tableFrom": "host_access", + "tableTo": "ssh_data", + "columnsFrom": [ + "host_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "host_access_user_id_users_id_fk": { + "name": "host_access_user_id_users_id_fk", + "tableFrom": "host_access", + "tableTo": "users", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "host_access_role_id_roles_id_fk": { + "name": "host_access_role_id_roles_id_fk", + "tableFrom": "host_access", + "tableTo": "roles", + "columnsFrom": [ + "role_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "host_access_granted_by_users_id_fk": { + "name": "host_access_granted_by_users_id_fk", + "tableFrom": "host_access", + "tableTo": "users", + "columnsFrom": [ + "granted_by" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "checkConstraints": {} + }, + "host_protocol_auth": { + "name": "host_protocol_auth", + "columns": { + "id": { + "name": "id", + "type": "integer", + "primaryKey": true, + "notNull": true, + "autoincrement": true + }, + "host_id": { + "name": "host_id", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "protocol": { + "name": "protocol", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "auth_type": { + "name": "auth_type", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "'direct'" + }, + "credential_id": { + "name": "credential_id", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "username": { + "name": "username", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "password": { + "name": "password", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "fields": { + "name": "fields", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "secret_fields": { + "name": "secret_fields", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "created_at": { + "name": "created_at", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "CURRENT_TIMESTAMP" + }, + "updated_at": { + "name": "updated_at", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "CURRENT_TIMESTAMP" + } + }, + "indexes": { + "idx_host_protocol_auth_host_protocol": { + "name": "idx_host_protocol_auth_host_protocol", + "columns": [ + "host_id", + "protocol" + ], + "isUnique": true + }, + "idx_host_protocol_auth_user": { + "name": "idx_host_protocol_auth_user", + "columns": [ + "user_id" + ], + "isUnique": false + }, + "idx_host_protocol_auth_credential": { + "name": "idx_host_protocol_auth_credential", + "columns": [ + "credential_id" + ], + "isUnique": false + } + }, + "foreignKeys": { + "host_protocol_auth_host_id_ssh_data_id_fk": { + "name": "host_protocol_auth_host_id_ssh_data_id_fk", + "tableFrom": "host_protocol_auth", + "tableTo": "ssh_data", + "columnsFrom": [ + "host_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "host_protocol_auth_user_id_users_id_fk": { + "name": "host_protocol_auth_user_id_users_id_fk", + "tableFrom": "host_protocol_auth", + "tableTo": "users", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "host_protocol_auth_credential_id_ssh_credentials_id_fk": { + "name": "host_protocol_auth_credential_id_ssh_credentials_id_fk", + "tableFrom": "host_protocol_auth", + "tableTo": "ssh_credentials", + "columnsFrom": [ + "credential_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "checkConstraints": {} + }, + "host_sidebar_preferences": { + "name": "host_sidebar_preferences", + "columns": { + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": true, + "notNull": true, + "autoincrement": false + }, + "data": { + "name": "data", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "updated_at": { + "name": "updated_at", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "CURRENT_TIMESTAMP" + } + }, + "indexes": {}, + "foreignKeys": { + "host_sidebar_preferences_user_id_users_id_fk": { + "name": "host_sidebar_preferences_user_id_users_id_fk", + "tableFrom": "host_sidebar_preferences", + "tableTo": "users", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "checkConstraints": {} + }, + "ssh_data": { + "name": "ssh_data", + "columns": { + "id": { + "name": "id", + "type": "integer", + "primaryKey": true, + "notNull": true, + "autoincrement": true + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "connection_type": { + "name": "connection_type", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "'ssh'" + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "ip": { + "name": "ip", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "port": { + "name": "port", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "username": { + "name": "username", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "folder": { + "name": "folder", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "parent_host_id": { + "name": "parent_host_id", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "tags": { + "name": "tags", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "pin": { + "name": "pin", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": false + }, + "sort_order": { + "name": "sort_order", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "auth_type": { + "name": "auth_type", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "share_ssh_auth": { + "name": "share_ssh_auth", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": false + }, + "force_keyboard_interactive": { + "name": "force_keyboard_interactive", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "password": { + "name": "password", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "key": { + "name": "key", + "type": "text(8192)", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "key_password": { + "name": "key_password", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "key_type": { + "name": "key_type", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "sudo_password": { + "name": "sudo_password", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "credential_id": { + "name": "credential_id", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "override_credential_username": { + "name": "override_credential_username", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "jump_hosts": { + "name": "jump_hosts", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "status_check_enabled": { + "name": "status_check_enabled", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": true + }, + "status_check_interval": { + "name": "status_check_interval", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "terminal_config": { + "name": "terminal_config", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "ssh_options": { + "name": "ssh_options", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "quick_actions": { + "name": "quick_actions", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "notes": { + "name": "notes", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "enable_ssh": { + "name": "enable_ssh", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": true + }, + "ssh_port": { + "name": "ssh_port", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false, + "default": 22 + }, + "use_socks5": { + "name": "use_socks5", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "socks5_host": { + "name": "socks5_host", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "socks5_port": { + "name": "socks5_port", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "socks5_username": { + "name": "socks5_username", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "socks5_password": { + "name": "socks5_password", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "socks5_proxy_chain": { + "name": "socks5_proxy_chain", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "connection_origin": { + "name": "connection_origin", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "port_knock_sequence": { + "name": "port_knock_sequence", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "host_key_fingerprint": { + "name": "host_key_fingerprint", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "host_key_type": { + "name": "host_key_type", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "host_key_algorithm": { + "name": "host_key_algorithm", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false, + "default": "'sha256'" + }, + "host_key_first_seen": { + "name": "host_key_first_seen", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "host_key_last_verified": { + "name": "host_key_last_verified", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "host_key_changed_count": { + "name": "host_key_changed_count", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false, + "default": 0 + }, + "sync_id": { + "name": "sync_id", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "local_only": { + "name": "local_only", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": false + }, + "shared_source": { + "name": "shared_source", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "created_at": { + "name": "created_at", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "CURRENT_TIMESTAMP" + }, + "updated_at": { + "name": "updated_at", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "CURRENT_TIMESTAMP" + } + }, + "indexes": { + "ssh_data_sync_id_unique": { + "name": "ssh_data_sync_id_unique", + "columns": [ + "sync_id" + ], + "isUnique": true + }, + "idx_ssh_data_user_id": { + "name": "idx_ssh_data_user_id", + "columns": [ + "user_id" + ], + "isUnique": false + }, + "idx_ssh_data_parent_host": { + "name": "idx_ssh_data_parent_host", + "columns": [ + "parent_host_id" + ], + "isUnique": false + }, + "idx_ssh_data_credential": { + "name": "idx_ssh_data_credential", + "columns": [ + "credential_id" + ], + "isUnique": false + } + }, + "foreignKeys": { + "ssh_data_user_id_users_id_fk": { + "name": "ssh_data_user_id_users_id_fk", + "tableFrom": "ssh_data", + "tableTo": "users", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "ssh_data_parent_host_id_ssh_data_id_fk": { + "name": "ssh_data_parent_host_id_ssh_data_id_fk", + "tableFrom": "ssh_data", + "tableTo": "ssh_data", + "columnsFrom": [ + "parent_host_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + }, + "ssh_data_credential_id_ssh_credentials_id_fk": { + "name": "ssh_data_credential_id_ssh_credentials_id_fk", + "tableFrom": "ssh_data", + "tableTo": "ssh_credentials", + "columnsFrom": [ + "credential_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "checkConstraints": {} + }, + "plugin_install_counts": { + "name": "plugin_install_counts", + "columns": { + "id": { + "name": "id", + "type": "integer", + "primaryKey": true, + "notNull": true, + "autoincrement": true + }, + "plugin_id": { + "name": "plugin_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "registry_id": { + "name": "registry_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "count": { + "name": "count", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": 0 + }, + "source": { + "name": "source", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "'aggregate-telemetry'" + }, + "updated_at": { + "name": "updated_at", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "CURRENT_TIMESTAMP" + } + }, + "indexes": { + "idx_plugin_install_counts_plugin_registry": { + "name": "idx_plugin_install_counts_plugin_registry", + "columns": [ + "plugin_id", + "registry_id" + ], + "isUnique": true + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "checkConstraints": {} + }, + "plugin_migrations": { + "name": "plugin_migrations", + "columns": { + "id": { + "name": "id", + "type": "integer", + "primaryKey": true, + "notNull": true, + "autoincrement": true + }, + "plugin_id": { + "name": "plugin_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "migration_id": { + "name": "migration_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "checksum": { + "name": "checksum", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "applied_at": { + "name": "applied_at", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "CURRENT_TIMESTAMP" + } + }, + "indexes": { + "idx_plugin_migrations_plugin_migration": { + "name": "idx_plugin_migrations_plugin_migration", + "columns": [ + "plugin_id", + "migration_id" + ], + "isUnique": true + } + }, + "foreignKeys": { + "plugin_migrations_plugin_id_plugins_id_fk": { + "name": "plugin_migrations_plugin_id_plugins_id_fk", + "tableFrom": "plugin_migrations", + "tableTo": "plugins", + "columnsFrom": [ + "plugin_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "checkConstraints": {} + }, + "plugin_permission_grants": { + "name": "plugin_permission_grants", + "columns": { + "id": { + "name": "id", + "type": "integer", + "primaryKey": true, + "notNull": true, + "autoincrement": true + }, + "plugin_id": { + "name": "plugin_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "capability": { + "name": "capability", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "granted_at": { + "name": "granted_at", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "CURRENT_TIMESTAMP" + }, + "granted_by": { + "name": "granted_by", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "source": { + "name": "source", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "'admin'" + } + }, + "indexes": { + "idx_plugin_permission_grants_plugin_capability": { + "name": "idx_plugin_permission_grants_plugin_capability", + "columns": [ + "plugin_id", + "capability" + ], + "isUnique": true + } + }, + "foreignKeys": { + "plugin_permission_grants_plugin_id_plugins_id_fk": { + "name": "plugin_permission_grants_plugin_id_plugins_id_fk", + "tableFrom": "plugin_permission_grants", + "tableTo": "plugins", + "columnsFrom": [ + "plugin_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "plugin_permission_grants_granted_by_users_id_fk": { + "name": "plugin_permission_grants_granted_by_users_id_fk", + "tableFrom": "plugin_permission_grants", + "tableTo": "users", + "columnsFrom": [ + "granted_by" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "checkConstraints": {} + }, + "plugin_registries": { + "name": "plugin_registries", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true, + "autoincrement": false + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "url": { + "name": "url", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "kind": { + "name": "kind", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "'community'" + }, + "enabled": { + "name": "enabled", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": true + }, + "signing_key": { + "name": "signing_key", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "last_checked_at": { + "name": "last_checked_at", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "last_index_hash": { + "name": "last_index_hash", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "checkConstraints": {} + }, + "plugin_settings": { + "name": "plugin_settings", + "columns": { + "id": { + "name": "id", + "type": "integer", + "primaryKey": true, + "notNull": true, + "autoincrement": true + }, + "plugin_id": { + "name": "plugin_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "scope": { + "name": "scope", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "scope_id": { + "name": "scope_id", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "key": { + "name": "key", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "value": { + "name": "value", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "encrypted": { + "name": "encrypted", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": false + }, + "updated_at": { + "name": "updated_at", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "CURRENT_TIMESTAMP" + } + }, + "indexes": { + "idx_plugin_settings_scope_key": { + "name": "idx_plugin_settings_scope_key", + "columns": [ + "plugin_id", + "scope", + "scope_id", + "key" + ], + "isUnique": true + }, + "idx_plugin_settings_plugin_scope": { + "name": "idx_plugin_settings_plugin_scope", + "columns": [ + "plugin_id", + "scope" + ], + "isUnique": false + } + }, + "foreignKeys": { + "plugin_settings_plugin_id_plugins_id_fk": { + "name": "plugin_settings_plugin_id_plugins_id_fk", + "tableFrom": "plugin_settings", + "tableTo": "plugins", + "columnsFrom": [ + "plugin_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "checkConstraints": {} + }, + "plugin_storage": { + "name": "plugin_storage", + "columns": { + "id": { + "name": "id", + "type": "integer", + "primaryKey": true, + "notNull": true, + "autoincrement": true + }, + "plugin_id": { + "name": "plugin_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "key": { + "name": "key", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "value": { + "name": "value", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "updated_at": { + "name": "updated_at", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "CURRENT_TIMESTAMP" + } + }, + "indexes": { + "idx_plugin_storage_plugin_key": { + "name": "idx_plugin_storage_plugin_key", + "columns": [ + "plugin_id", + "key" + ], + "isUnique": true + } + }, + "foreignKeys": { + "plugin_storage_plugin_id_plugins_id_fk": { + "name": "plugin_storage_plugin_id_plugins_id_fk", + "tableFrom": "plugin_storage", + "tableTo": "plugins", + "columnsFrom": [ + "plugin_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "checkConstraints": {} + }, + "plugins": { + "name": "plugins", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true, + "autoincrement": false + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "version": { + "name": "version", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "tier": { + "name": "tier", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "'available'" + }, + "source": { + "name": "source", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "'community'" + }, + "registry_id": { + "name": "registry_id", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "state": { + "name": "state", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "'disabled'" + }, + "last_error": { + "name": "last_error", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "installed_at": { + "name": "installed_at", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "CURRENT_TIMESTAMP" + }, + "updated_at": { + "name": "updated_at", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "CURRENT_TIMESTAMP" + }, + "auto_update": { + "name": "auto_update", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": false + }, + "manifest_json": { + "name": "manifest_json", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + } + }, + "indexes": { + "idx_plugins_registry_id": { + "name": "idx_plugins_registry_id", + "columns": [ + "registry_id" + ], + "isUnique": false + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "checkConstraints": {} + }, + "rbac_applied_defaults": { + "name": "rbac_applied_defaults", + "columns": { + "id": { + "name": "id", + "type": "integer", + "primaryKey": true, + "notNull": true, + "autoincrement": true + }, + "role_name": { + "name": "role_name", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "permission": { + "name": "permission", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "applied_at": { + "name": "applied_at", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "CURRENT_TIMESTAMP" + } + }, + "indexes": { + "idx_rbac_applied_defaults_role_permission": { + "name": "idx_rbac_applied_defaults_role_permission", + "columns": [ + "role_name", + "permission" + ], + "isUnique": true + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "checkConstraints": {} + }, + "rbac_known_permissions": { + "name": "rbac_known_permissions", + "columns": { + "id": { + "name": "id", + "type": "integer", + "primaryKey": true, + "notNull": true, + "autoincrement": true + }, + "permission": { + "name": "permission", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "plugin_id": { + "name": "plugin_id", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "first_seen_at": { + "name": "first_seen_at", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "CURRENT_TIMESTAMP" + } + }, + "indexes": { + "idx_rbac_known_permissions_permission": { + "name": "idx_rbac_known_permissions_permission", + "columns": [ + "permission" + ], + "isUnique": true + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "checkConstraints": {} + }, + "recent_activity": { + "name": "recent_activity", + "columns": { + "id": { + "name": "id", + "type": "integer", + "primaryKey": true, + "notNull": true, + "autoincrement": true + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "type": { + "name": "type", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "host_id": { + "name": "host_id", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "host_name": { + "name": "host_name", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "timestamp": { + "name": "timestamp", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "CURRENT_TIMESTAMP" + } + }, + "indexes": { + "idx_recent_activity_user_ts": { + "name": "idx_recent_activity_user_ts", + "columns": [ + "user_id", + "timestamp" + ], + "isUnique": false + } + }, + "foreignKeys": { + "recent_activity_user_id_users_id_fk": { + "name": "recent_activity_user_id_users_id_fk", + "tableFrom": "recent_activity", + "tableTo": "users", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "recent_activity_host_id_ssh_data_id_fk": { + "name": "recent_activity_host_id_ssh_data_id_fk", + "tableFrom": "recent_activity", + "tableTo": "ssh_data", + "columnsFrom": [ + "host_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "checkConstraints": {} + }, + "roles": { + "name": "roles", + "columns": { + "id": { + "name": "id", + "type": "integer", + "primaryKey": true, + "notNull": true, + "autoincrement": true + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "display_name": { + "name": "display_name", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "description": { + "name": "description", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "is_system": { + "name": "is_system", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": false + }, + "permissions": { + "name": "permissions", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "created_at": { + "name": "created_at", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "CURRENT_TIMESTAMP" + }, + "updated_at": { + "name": "updated_at", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "CURRENT_TIMESTAMP" + } + }, + "indexes": { + "roles_name_unique": { + "name": "roles_name_unique", + "columns": [ + "name" + ], + "isUnique": true + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "checkConstraints": {} + }, + "sessions": { + "name": "sessions", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true, + "autoincrement": false + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "jwt_token": { + "name": "jwt_token", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "device_type": { + "name": "device_type", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "device_info": { + "name": "device_info", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "oidc_sub": { + "name": "oidc_sub", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "oidc_sid": { + "name": "oidc_sid", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "sso_provider_id": { + "name": "sso_provider_id", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "created_at": { + "name": "created_at", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "CURRENT_TIMESTAMP" + }, + "expires_at": { + "name": "expires_at", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "last_active_at": { + "name": "last_active_at", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "CURRENT_TIMESTAMP" + } + }, + "indexes": { + "idx_sessions_user_id": { + "name": "idx_sessions_user_id", + "columns": [ + "user_id" + ], + "isUnique": false + }, + "idx_sessions_expires_at": { + "name": "idx_sessions_expires_at", + "columns": [ + "expires_at" + ], + "isUnique": false + } + }, + "foreignKeys": { + "sessions_user_id_users_id_fk": { + "name": "sessions_user_id_users_id_fk", + "tableFrom": "sessions", + "tableTo": "users", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "checkConstraints": {} + }, + "settings": { + "name": "settings", + "columns": { + "key": { + "name": "key", + "type": "text", + "primaryKey": true, + "notNull": true, + "autoincrement": false + }, + "value": { + "name": "value", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "checkConstraints": {} + }, + "shared_credential_secrets": { + "name": "shared_credential_secrets", + "columns": { + "id": { + "name": "id", + "type": "integer", + "primaryKey": true, + "notNull": true, + "autoincrement": true + }, + "credential_access_id": { + "name": "credential_access_id", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "target_user_id": { + "name": "target_user_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "credential_id": { + "name": "credential_id", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "encrypted_username": { + "name": "encrypted_username", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "auth_type": { + "name": "auth_type", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "'password'" + }, + "encrypted_password": { + "name": "encrypted_password", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "encrypted_key": { + "name": "encrypted_key", + "type": "text(16384)", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "encrypted_key_password": { + "name": "encrypted_key_password", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "key_type": { + "name": "key_type", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "public_key": { + "name": "public_key", + "type": "text(4096)", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "cert_public_key": { + "name": "cert_public_key", + "type": "text(8192)", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "created_at": { + "name": "created_at", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "CURRENT_TIMESTAMP" + }, + "updated_at": { + "name": "updated_at", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "CURRENT_TIMESTAMP" + } + }, + "indexes": { + "idx_shared_credential_secrets_scope": { + "name": "idx_shared_credential_secrets_scope", + "columns": [ + "credential_access_id", + "target_user_id" + ], + "isUnique": true + }, + "idx_shared_credential_secrets_target": { + "name": "idx_shared_credential_secrets_target", + "columns": [ + "target_user_id", + "credential_id" + ], + "isUnique": false + } + }, + "foreignKeys": { + "shared_credential_secrets_target_user_id_users_id_fk": { + "name": "shared_credential_secrets_target_user_id_users_id_fk", + "tableFrom": "shared_credential_secrets", + "tableTo": "users", + "columnsFrom": [ + "target_user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "shared_credential_secrets_credential_id_ssh_credentials_id_fk": { + "name": "shared_credential_secrets_credential_id_ssh_credentials_id_fk", + "tableFrom": "shared_credential_secrets", + "tableTo": "ssh_credentials", + "columnsFrom": [ + "credential_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "shared_cred_secrets_access_id_fk": { + "name": "shared_cred_secrets_access_id_fk", + "tableFrom": "shared_credential_secrets", + "tableTo": "credential_access", + "columnsFrom": [ + "credential_access_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "checkConstraints": {} + }, + "shared_host_auth_overrides": { + "name": "shared_host_auth_overrides", + "columns": { + "id": { + "name": "id", + "type": "integer", + "primaryKey": true, + "notNull": true, + "autoincrement": true + }, + "host_id": { + "name": "host_id", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "protocol": { + "name": "protocol", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "'ssh'" + }, + "credential_id": { + "name": "credential_id", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "created_at": { + "name": "created_at", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "CURRENT_TIMESTAMP" + }, + "updated_at": { + "name": "updated_at", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "CURRENT_TIMESTAMP" + } + }, + "indexes": { + "shared_host_auth_overrides_host_user_protocol_unique": { + "name": "shared_host_auth_overrides_host_user_protocol_unique", + "columns": [ + "host_id", + "user_id", + "protocol" + ], + "isUnique": true + } + }, + "foreignKeys": { + "shared_host_auth_overrides_host_id_ssh_data_id_fk": { + "name": "shared_host_auth_overrides_host_id_ssh_data_id_fk", + "tableFrom": "shared_host_auth_overrides", + "tableTo": "ssh_data", + "columnsFrom": [ + "host_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "shared_host_auth_overrides_user_id_users_id_fk": { + "name": "shared_host_auth_overrides_user_id_users_id_fk", + "tableFrom": "shared_host_auth_overrides", + "tableTo": "users", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "shared_host_auth_overrides_credential_id_ssh_credentials_id_fk": { + "name": "shared_host_auth_overrides_credential_id_ssh_credentials_id_fk", + "tableFrom": "shared_host_auth_overrides", + "tableTo": "ssh_credentials", + "columnsFrom": [ + "credential_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "checkConstraints": {} + }, + "shared_host_secrets": { + "name": "shared_host_secrets", + "columns": { + "id": { + "name": "id", + "type": "integer", + "primaryKey": true, + "notNull": true, + "autoincrement": true + }, + "host_access_id": { + "name": "host_access_id", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "target_user_id": { + "name": "target_user_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "protocol": { + "name": "protocol", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "'ssh'" + }, + "source_type": { + "name": "source_type", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "'credential'" + }, + "original_credential_id": { + "name": "original_credential_id", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "encrypted_username": { + "name": "encrypted_username", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "encrypted_auth_type": { + "name": "encrypted_auth_type", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "encrypted_password": { + "name": "encrypted_password", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "encrypted_key": { + "name": "encrypted_key", + "type": "text(16384)", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "encrypted_key_password": { + "name": "encrypted_key_password", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "encrypted_key_type": { + "name": "encrypted_key_type", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "encrypted_domain": { + "name": "encrypted_domain", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "encrypted_fields": { + "name": "encrypted_fields", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "created_at": { + "name": "created_at", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "CURRENT_TIMESTAMP" + }, + "updated_at": { + "name": "updated_at", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "CURRENT_TIMESTAMP" + } + }, + "indexes": { + "idx_shared_host_secrets_scope": { + "name": "idx_shared_host_secrets_scope", + "columns": [ + "host_access_id", + "target_user_id", + "protocol" + ], + "isUnique": true + } + }, + "foreignKeys": { + "shared_host_secrets_host_access_id_host_access_id_fk": { + "name": "shared_host_secrets_host_access_id_host_access_id_fk", + "tableFrom": "shared_host_secrets", + "tableTo": "host_access", + "columnsFrom": [ + "host_access_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "shared_host_secrets_target_user_id_users_id_fk": { + "name": "shared_host_secrets_target_user_id_users_id_fk", + "tableFrom": "shared_host_secrets", + "tableTo": "users", + "columnsFrom": [ + "target_user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "shared_host_secrets_original_credential_id_ssh_credentials_id_fk": { + "name": "shared_host_secrets_original_credential_id_ssh_credentials_id_fk", + "tableFrom": "shared_host_secrets", + "tableTo": "ssh_credentials", + "columnsFrom": [ + "original_credential_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "checkConstraints": {} + }, + "ssh_credential_usage": { + "name": "ssh_credential_usage", + "columns": { + "id": { + "name": "id", + "type": "integer", + "primaryKey": true, + "notNull": true, + "autoincrement": true + }, + "credential_id": { + "name": "credential_id", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "host_id": { + "name": "host_id", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "used_at": { + "name": "used_at", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "CURRENT_TIMESTAMP" + } + }, + "indexes": { + "idx_ssh_credential_usage_credential": { + "name": "idx_ssh_credential_usage_credential", + "columns": [ + "credential_id" + ], + "isUnique": false + }, + "idx_ssh_credential_usage_user": { + "name": "idx_ssh_credential_usage_user", + "columns": [ + "user_id" + ], + "isUnique": false + } + }, + "foreignKeys": { + "ssh_credential_usage_credential_id_ssh_credentials_id_fk": { + "name": "ssh_credential_usage_credential_id_ssh_credentials_id_fk", + "tableFrom": "ssh_credential_usage", + "tableTo": "ssh_credentials", + "columnsFrom": [ + "credential_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "ssh_credential_usage_host_id_ssh_data_id_fk": { + "name": "ssh_credential_usage_host_id_ssh_data_id_fk", + "tableFrom": "ssh_credential_usage", + "tableTo": "ssh_data", + "columnsFrom": [ + "host_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "ssh_credential_usage_user_id_users_id_fk": { + "name": "ssh_credential_usage_user_id_users_id_fk", + "tableFrom": "ssh_credential_usage", + "tableTo": "users", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "checkConstraints": {} + }, + "ssh_credentials": { + "name": "ssh_credentials", + "columns": { + "id": { + "name": "id", + "type": "integer", + "primaryKey": true, + "notNull": true, + "autoincrement": true + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "description": { + "name": "description", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "folder": { + "name": "folder", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "tags": { + "name": "tags", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "pin": { + "name": "pin", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": false + }, + "sort_order": { + "name": "sort_order", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "auth_type": { + "name": "auth_type", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "username": { + "name": "username", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "password": { + "name": "password", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "key": { + "name": "key", + "type": "text(16384)", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "private_key": { + "name": "private_key", + "type": "text(16384)", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "public_key": { + "name": "public_key", + "type": "text(4096)", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "key_password": { + "name": "key_password", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "key_type": { + "name": "key_type", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "detected_key_type": { + "name": "detected_key_type", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "cert_public_key": { + "name": "cert_public_key", + "type": "text(8192)", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "usage_count": { + "name": "usage_count", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": 0 + }, + "last_used": { + "name": "last_used", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "sync_id": { + "name": "sync_id", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "shared_source": { + "name": "shared_source", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "created_at": { + "name": "created_at", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "CURRENT_TIMESTAMP" + }, + "updated_at": { + "name": "updated_at", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "CURRENT_TIMESTAMP" + } + }, + "indexes": { + "ssh_credentials_sync_id_unique": { + "name": "ssh_credentials_sync_id_unique", + "columns": [ + "sync_id" + ], + "isUnique": true + }, + "idx_ssh_credentials_user_id": { + "name": "idx_ssh_credentials_user_id", + "columns": [ + "user_id" + ], + "isUnique": false + } + }, + "foreignKeys": { + "ssh_credentials_user_id_users_id_fk": { + "name": "ssh_credentials_user_id_users_id_fk", + "tableFrom": "ssh_credentials", + "tableTo": "users", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "checkConstraints": {} + }, + "ssh_folders": { + "name": "ssh_folders", + "columns": { + "id": { + "name": "id", + "type": "integer", + "primaryKey": true, + "notNull": true, + "autoincrement": true + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "color": { + "name": "color", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "icon": { + "name": "icon", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "credential_id": { + "name": "credential_id", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "sort_order": { + "name": "sort_order", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "sync_id": { + "name": "sync_id", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "local_only": { + "name": "local_only", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": false + }, + "created_at": { + "name": "created_at", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "CURRENT_TIMESTAMP" + }, + "updated_at": { + "name": "updated_at", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "CURRENT_TIMESTAMP" + } + }, + "indexes": { + "ssh_folders_sync_id_unique": { + "name": "ssh_folders_sync_id_unique", + "columns": [ + "sync_id" + ], + "isUnique": true + }, + "idx_ssh_folders_user_id": { + "name": "idx_ssh_folders_user_id", + "columns": [ + "user_id" + ], + "isUnique": false + } + }, + "foreignKeys": { + "ssh_folders_user_id_users_id_fk": { + "name": "ssh_folders_user_id_users_id_fk", + "tableFrom": "ssh_folders", + "tableTo": "users", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "ssh_folders_credential_id_ssh_credentials_id_fk": { + "name": "ssh_folders_credential_id_ssh_credentials_id_fk", + "tableFrom": "ssh_folders", + "tableTo": "ssh_credentials", + "columnsFrom": [ + "credential_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "checkConstraints": {} + }, + "sync_conflicts": { + "name": "sync_conflicts", + "columns": { + "id": { + "name": "id", + "type": "integer", + "primaryKey": true, + "notNull": true, + "autoincrement": true + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "entity_type": { + "name": "entity_type", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "sync_id": { + "name": "sync_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "local_row": { + "name": "local_row", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "server_revision": { + "name": "server_revision", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "created_at": { + "name": "created_at", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "CURRENT_TIMESTAMP" + } + }, + "indexes": { + "idx_sync_conflicts_user": { + "name": "idx_sync_conflicts_user", + "columns": [ + "user_id" + ], + "isUnique": false + } + }, + "foreignKeys": { + "sync_conflicts_user_id_users_id_fk": { + "name": "sync_conflicts_user_id_users_id_fk", + "tableFrom": "sync_conflicts", + "tableTo": "users", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "checkConstraints": {} + }, + "sync_link": { + "name": "sync_link", + "columns": { + "id": { + "name": "id", + "type": "integer", + "primaryKey": true, + "notNull": true, + "autoincrement": true + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "server_url": { + "name": "server_url", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "server_name": { + "name": "server_name", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "server_version": { + "name": "server_version", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "session_token": { + "name": "session_token", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "custom_headers": { + "name": "custom_headers", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "basic_auth": { + "name": "basic_auth", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "allow_invalid_certificate": { + "name": "allow_invalid_certificate", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": false + }, + "remote_user_id": { + "name": "remote_user_id", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "remote_username": { + "name": "remote_username", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "account": { + "name": "account", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "scope": { + "name": "scope", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "known_types": { + "name": "known_types", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "cursor": { + "name": "cursor", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": 0 + }, + "status": { + "name": "status", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "'idle'" + }, + "last_error": { + "name": "last_error", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "linked_at": { + "name": "linked_at", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "CURRENT_TIMESTAMP" + }, + "last_sync_at": { + "name": "last_sync_at", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + } + }, + "indexes": {}, + "foreignKeys": { + "sync_link_user_id_users_id_fk": { + "name": "sync_link_user_id_users_id_fk", + "tableFrom": "sync_link", + "tableTo": "users", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "checkConstraints": {} + }, + "sync_records": { + "name": "sync_records", + "columns": { + "id": { + "name": "id", + "type": "integer", + "primaryKey": true, + "notNull": true, + "autoincrement": true + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "entity_type": { + "name": "entity_type", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "sync_id": { + "name": "sync_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "revision": { + "name": "revision", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": 0 + }, + "seq": { + "name": "seq", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": 0 + }, + "hash": { + "name": "hash", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "deleted": { + "name": "deleted", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": false + }, + "error": { + "name": "error", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "error_hash": { + "name": "error_hash", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "updated_at": { + "name": "updated_at", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "CURRENT_TIMESTAMP" + } + }, + "indexes": { + "idx_sync_records_user_entity_sync": { + "name": "idx_sync_records_user_entity_sync", + "columns": [ + "user_id", + "entity_type", + "sync_id" + ], + "isUnique": true + }, + "idx_sync_records_user_seq": { + "name": "idx_sync_records_user_seq", + "columns": [ + "user_id", + "seq" + ], + "isUnique": false + } + }, + "foreignKeys": { + "sync_records_user_id_users_id_fk": { + "name": "sync_records_user_id_users_id_fk", + "tableFrom": "sync_records", + "tableTo": "users", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "checkConstraints": {} + }, + "trusted_devices": { + "name": "trusted_devices", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true, + "autoincrement": false + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "device_fingerprint": { + "name": "device_fingerprint", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "device_type": { + "name": "device_type", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "device_info": { + "name": "device_info", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "created_at": { + "name": "created_at", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "CURRENT_TIMESTAMP" + }, + "expires_at": { + "name": "expires_at", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "last_used_at": { + "name": "last_used_at", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "CURRENT_TIMESTAMP" + } + }, + "indexes": { + "idx_trusted_devices_user_id": { + "name": "idx_trusted_devices_user_id", + "columns": [ + "user_id" + ], + "isUnique": false + } + }, + "foreignKeys": { + "trusted_devices_user_id_users_id_fk": { + "name": "trusted_devices_user_id_users_id_fk", + "tableFrom": "trusted_devices", + "tableTo": "users", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "checkConstraints": {} + }, + "ui_preferences": { + "name": "ui_preferences", + "columns": { + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": true, + "notNull": true, + "autoincrement": false + }, + "data": { + "name": "data", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "updated_at": { + "name": "updated_at", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "CURRENT_TIMESTAMP" + } + }, + "indexes": {}, + "foreignKeys": { + "ui_preferences_user_id_users_id_fk": { + "name": "ui_preferences_user_id_users_id_fk", + "tableFrom": "ui_preferences", + "tableTo": "users", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "checkConstraints": {} + }, + "user_external_identities": { + "name": "user_external_identities", + "columns": { + "id": { + "name": "id", + "type": "integer", + "primaryKey": true, + "notNull": true, + "autoincrement": true + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "provider_id": { + "name": "provider_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "subject": { + "name": "subject", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "email": { + "name": "email", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "created_at": { + "name": "created_at", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "CURRENT_TIMESTAMP" + } + }, + "indexes": { + "idx_user_external_identities_provider_subject": { + "name": "idx_user_external_identities_provider_subject", + "columns": [ + "provider_id", + "subject" + ], + "isUnique": true + }, + "idx_user_external_identities_user": { + "name": "idx_user_external_identities_user", + "columns": [ + "user_id" + ], + "isUnique": false + } + }, + "foreignKeys": { + "user_external_identities_user_id_users_id_fk": { + "name": "user_external_identities_user_id_users_id_fk", + "tableFrom": "user_external_identities", + "tableTo": "users", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "checkConstraints": {} + }, + "user_open_tabs": { + "name": "user_open_tabs", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true, + "autoincrement": false + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "tab_type": { + "name": "tab_type", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "host_id": { + "name": "host_id", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "label": { + "name": "label", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "tab_order": { + "name": "tab_order", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": 0 + }, + "backend_session_id": { + "name": "backend_session_id", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "created_at": { + "name": "created_at", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "CURRENT_TIMESTAMP" + }, + "updated_at": { + "name": "updated_at", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "CURRENT_TIMESTAMP" + } + }, + "indexes": { + "idx_user_open_tabs_user_id": { + "name": "idx_user_open_tabs_user_id", + "columns": [ + "user_id" + ], + "isUnique": false + } + }, + "foreignKeys": { + "user_open_tabs_user_id_users_id_fk": { + "name": "user_open_tabs_user_id_users_id_fk", + "tableFrom": "user_open_tabs", + "tableTo": "users", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "user_open_tabs_host_id_ssh_data_id_fk": { + "name": "user_open_tabs_host_id_ssh_data_id_fk", + "tableFrom": "user_open_tabs", + "tableTo": "ssh_data", + "columnsFrom": [ + "host_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "checkConstraints": {} + }, + "user_preferences": { + "name": "user_preferences", + "columns": { + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": true, + "notNull": true, + "autoincrement": false + }, + "reopen_tabs_on_login": { + "name": "reopen_tabs_on_login", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": false + }, + "theme": { + "name": "theme", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "font_size": { + "name": "font_size", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "accent_color": { + "name": "accent_color", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "language": { + "name": "language", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "storage_mode": { + "name": "storage_mode", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "command_autocomplete": { + "name": "command_autocomplete", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "command_palette_enabled": { + "name": "command_palette_enabled", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "show_host_tags": { + "name": "show_host_tags", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "host_tray_on_click": { + "name": "host_tray_on_click", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "pin_app_rail": { + "name": "pin_app_rail", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "expand_app_rail_on_hover": { + "name": "expand_app_rail_on_hover", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "show_pin_app_rail_button": { + "name": "show_pin_app_rail_button", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "folders_collapsed": { + "name": "folders_collapsed", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "confirm_snippet_execution": { + "name": "confirm_snippet_execution", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "disable_update_check": { + "name": "disable_update_check", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "confirm_tab_close": { + "name": "confirm_tab_close", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "hidden_rail_tabs": { + "name": "hidden_rail_tabs", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "compact_host_view": { + "name": "compact_host_view", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "status_color_scheme": { + "name": "status_color_scheme", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "custom_themes": { + "name": "custom_themes", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "custom_keybindings": { + "name": "custom_keybindings", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "terminal_defaults": { + "name": "terminal_defaults", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "terminal_macros": { + "name": "terminal_macros", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "updated_at": { + "name": "updated_at", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "CURRENT_TIMESTAMP" + } + }, + "indexes": {}, + "foreignKeys": { + "user_preferences_user_id_users_id_fk": { + "name": "user_preferences_user_id_users_id_fk", + "tableFrom": "user_preferences", + "tableTo": "users", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "checkConstraints": {} + }, + "user_roles": { + "name": "user_roles", + "columns": { + "id": { + "name": "id", + "type": "integer", + "primaryKey": true, + "notNull": true, + "autoincrement": true + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "role_id": { + "name": "role_id", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "granted_by": { + "name": "granted_by", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "granted_at": { + "name": "granted_at", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "CURRENT_TIMESTAMP" + } + }, + "indexes": { + "idx_user_roles_user_role": { + "name": "idx_user_roles_user_role", + "columns": [ + "user_id", + "role_id" + ], + "isUnique": true + }, + "idx_user_roles_role_id": { + "name": "idx_user_roles_role_id", + "columns": [ + "role_id" + ], + "isUnique": false + } + }, + "foreignKeys": { + "user_roles_user_id_users_id_fk": { + "name": "user_roles_user_id_users_id_fk", + "tableFrom": "user_roles", + "tableTo": "users", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "user_roles_role_id_roles_id_fk": { + "name": "user_roles_role_id_roles_id_fk", + "tableFrom": "user_roles", + "tableTo": "roles", + "columnsFrom": [ + "role_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "user_roles_granted_by_users_id_fk": { + "name": "user_roles_granted_by_users_id_fk", + "tableFrom": "user_roles", + "tableTo": "users", + "columnsFrom": [ + "granted_by" + ], + "columnsTo": [ + "id" + ], + "onDelete": "set null", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "checkConstraints": {} + }, + "user_second_factors": { + "name": "user_second_factors", + "columns": { + "id": { + "name": "id", + "type": "integer", + "primaryKey": true, + "notNull": true, + "autoincrement": true + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "plugin_id": { + "name": "plugin_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "factor_id": { + "name": "factor_id", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "enrolled_at": { + "name": "enrolled_at", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "CURRENT_TIMESTAMP" + } + }, + "indexes": { + "idx_user_second_factors_user_factor": { + "name": "idx_user_second_factors_user_factor", + "columns": [ + "user_id", + "plugin_id", + "factor_id" + ], + "isUnique": true + } + }, + "foreignKeys": { + "user_second_factors_user_id_users_id_fk": { + "name": "user_second_factors_user_id_users_id_fk", + "tableFrom": "user_second_factors", + "tableTo": "users", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "checkConstraints": {} + }, + "users": { + "name": "users", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true, + "autoincrement": false + }, + "username": { + "name": "username", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "password_hash": { + "name": "password_hash", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false + }, + "is_admin": { + "name": "is_admin", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": false + }, + "is_oidc": { + "name": "is_oidc", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": false + }, + "oidc_identifier": { + "name": "oidc_identifier", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "sso_provider_id": { + "name": "sso_provider_id", + "type": "integer", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "client_id": { + "name": "client_id", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "client_secret": { + "name": "client_secret", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "issuer_url": { + "name": "issuer_url", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "authorization_url": { + "name": "authorization_url", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "token_url": { + "name": "token_url", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "identifier_path": { + "name": "identifier_path", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "name_path": { + "name": "name_path", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false + }, + "scopes": { + "name": "scopes", + "type": "text", + "primaryKey": false, + "notNull": false, + "autoincrement": false, + "default": "'openid email profile'" + }, + "registered_at": { + "name": "registered_at", + "type": "text", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": "CURRENT_TIMESTAMP" + }, + "donation_modal_dismissed": { + "name": "donation_modal_dismissed", + "type": "integer", + "primaryKey": false, + "notNull": true, + "autoincrement": false, + "default": false + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "checkConstraints": {} + } + }, + "views": {}, + "enums": {}, + "_meta": { + "schemas": {}, + "tables": {}, + "columns": {} + }, + "internal": { + "indexes": {} + } +} \ No newline at end of file diff --git a/drizzle/sqlite/meta/_journal.json b/drizzle/sqlite/meta/_journal.json index 1fdf032c3..44d54e2cf 100644 --- a/drizzle/sqlite/meta/_journal.json +++ b/drizzle/sqlite/meta/_journal.json @@ -414,6 +414,13 @@ "when": 1790700721290, "tag": "0058_bitter_thunderbolt", "breakpoints": true + }, + { + "idx": 59, + "version": "6", + "when": 1790704530590, + "tag": "0059_adorable_wrecking_crew", + "breakpoints": true } ] } \ No newline at end of file diff --git a/package.json b/package.json index bda7bbe2a..28d4e4ec6 100644 --- a/package.json +++ b/package.json @@ -19,7 +19,7 @@ "postinstall": "node scripts/patch-app-builder-lib.cjs && node scripts/patch-guacamole-lite.cjs && node scripts/patch-guacamole-common-js.cjs && node scripts/patch-better-sqlite3.cjs && node scripts/patch-nan.cjs && node scripts/patch-node-pty.cjs && node scripts/patch-xterm-android-ime.cjs && node scripts/patch-ssh2-agent.cjs", "prepare": "husky || true", "prebuild": "node scripts/write-electron-build-info.cjs", - "lint": "node scripts/generate-dialect-schema.cjs --check && npm run plugin:validate-manifest && eslint . && node scripts/check-importmap-csp.cjs && node scripts/check-core-plugin-ids.cjs", + "lint": "node scripts/generate-dialect-schema.cjs --check && npm run plugin:validate-manifest && eslint . && node scripts/check-importmap-csp.cjs && node scripts/check-core-plugin-ids.cjs && node scripts/check-sdk-ui-exports.cjs && node scripts/check-plugin-locales.cjs && node scripts/check-test-locations.cjs", "lint:fix": "eslint --fix .", "type-check": "tsc -b --force", "test": "vitest run", diff --git a/packages/plugin-sdk/src/backend.ts b/packages/plugin-sdk/src/backend.ts index cc018f370..4ebe8d072 100644 --- a/packages/plugin-sdk/src/backend.ts +++ b/packages/plugin-sdk/src/backend.ts @@ -556,55 +556,118 @@ export interface PluginHostSummary { } /** - * A host record wide enough for a plugin that creates or updates hosts on the - * user's behalf (import, discovery, sync), decrypted for that user. Unlike - * PluginHostSummary this carries the fields a plugin needs to set up a - * connectable host, not just what a list view shows. Still no secret auth - * material (password, key, vault tokens): a plugin that creates a host picks - * an authType and, for "credential", a credentialId it does not need to see - * the contents of. + * A host as ctx.hosts hands it to a plugin that creates, updates or scans + * hosts on the user's behalf (import, discovery, sync), decrypted for that + * user. Every field is listed here and core builds it field by field, so a + * core column a plugin needs has to be added to this contract first. Carries + * no secret auth material (password, key, vault tokens): a plugin that + * creates a host picks an authType and, for "credential", a credentialId it + * does not need to see the contents of. */ export interface PluginHostRecord { id: number; userId: string; + /** Stable across a desktop and the server it syncs with. */ + syncId: string | null; name: string | null; ip: string; port: number; username: string; authType: string; - credentialId?: number | null; - overrideCredentialUsername?: boolean | null; - connectionType?: string | null; + credentialId: number | null; + overrideCredentialUsername: boolean; + /** "ssh", or the id of the plugin protocol a host without SSH uses. */ + connectionType: string; + /** Comma-separated, as ssh_data stores them. */ tags: string | null; folder: string | null; - jumpHosts?: unknown; - enableSsh?: boolean | null; + parentHostId: number | null; + pin: boolean; + notes: string | null; + jumpHosts: PluginHostJumpHost[]; + enableSsh: boolean; + sshPort: number | null; + statusCheckEnabled: boolean; + /** Seconds between status checks; null follows the global setting. */ + statusCheckInterval: number | null; + connectionOrigin: "local" | "remote" | null; /** Keepalive, legacy algorithms, agent and environment options. */ - sshOptions?: HostSshOptions | null; - createdAt?: string | null; - updatedAt?: string | null; - [key: string]: unknown; + sshOptions: HostSshOptions; + /** + * The calling plugin's own host settings, secrets redacted. Another + * plugin's settings are that plugin's to hand out, through a service. + */ + pluginSettings: Record; + /** Core's last reachability check, or null before the first one. */ + status: PluginHostStatusEntry | null; + /** Desktop only: kept on this device, never synced to the server. */ + localOnly: boolean; + createdAt: string | null; + updatedAt: string | null; +} + +export interface PluginHostJumpHost { + hostId: number; } /** - * Fields a plugin may set when creating a host it will own or manage. Fields - * that belong to another plugin's host settings (a protocol switch or port) are - * handed to that plugin's host import normalizer, as on a bulk import. + * The fields a plugin may set when it creates a host. A key not listed here + * is refused with an error rather than dropped. Host settings go in + * `pluginSettings`, keyed by the plugin that declares them, and are + * validated against that plugin's manifest: an undeclared key is refused, and + * settings for a plugin that is not running are skipped and logged. */ -export type PluginHostCreateInput = Partial< - Omit -> & { +export interface PluginHostCreateInput { name: string; ip: string; port: number; username: string; authType: string; -}; + credentialId?: number | null; + overrideCredentialUsername?: boolean; + connectionType?: string; + /** Comma-separated or a list. */ + tags?: string | string[] | null; + folder?: string | null; + pin?: boolean; + notes?: string | null; + jumpHosts?: PluginHostJumpHost[] | null; + enableSsh?: boolean; + sshPort?: number | null; + statusCheckEnabled?: boolean; + statusCheckInterval?: number | null; + forceKeyboardInteractive?: boolean; + sshOptions?: HostSshOptions | null; + /** Host settings by plugin id, the shape a Termix export carries. */ + pluginSettings?: Record>; +} -/** Fields a plugin may change on a host it already created or was granted access to. */ -export type PluginHostUpdateInput = Partial< - Omit ->; +/** Fields a plugin may change on a host the acting user owns. */ +export type PluginHostUpdateInput = Partial; + +/** Every key PluginHostCreateInput and PluginHostUpdateInput accept. */ +export const PLUGIN_HOST_INPUT_KEYS = [ + "name", + "ip", + "port", + "username", + "authType", + "credentialId", + "overrideCredentialUsername", + "connectionType", + "tags", + "folder", + "pin", + "notes", + "jumpHosts", + "enableSsh", + "sshPort", + "statusCheckEnabled", + "statusCheckInterval", + "forceKeyboardInteractive", + "sshOptions", + "pluginSettings", +] as const satisfies readonly (keyof PluginHostCreateInput)[]; /** The same shape canAccessHost returns internally, without secrets. */ export interface PluginHostAccess { diff --git a/packages/plugin-sdk/src/frontend.ts b/packages/plugin-sdk/src/frontend.ts index 1893c18bb..dd76de797 100644 --- a/packages/plugin-sdk/src/frontend.ts +++ b/packages/plugin-sdk/src/frontend.ts @@ -29,9 +29,10 @@ export type IconComponent = ComponentType<{ }>; /** - * A host as the shell holds it. Only the identifying fields are typed; the - * rest of the record is passed through as the shell has it, so a plugin - * that needs a feature column reads it by name. + * A host as the shell hands it to a plugin. Every field is listed here and + * core builds the record field by field, so a plugin cannot come to depend on + * a core column that is not part of this contract. A plugin's own host + * settings are in `pluginSettings[]`. */ export interface PluginHostRecord { id: string; @@ -41,6 +42,25 @@ export interface PluginHostRecord { username?: string; folder?: string; tags?: string[]; + pin?: boolean; + notes?: string; + /** Stable across a desktop and the server it syncs with. */ + syncId?: string | null; + /** Sub-host nesting: the host this one is organized under. */ + parentHostId?: string | null; + authType?: string; + credentialId?: string | number | null; + overrideCredentialUsername?: boolean; + /** "ssh", or the id of the plugin protocol a host without SSH uses. */ + connectionType?: string; + /** Desktop app: where connections to this host start from. */ + connectionOrigin?: "local" | "remote" | null; + enableSsh?: boolean; + sshPort?: number; + jumpHosts?: { hostId: string | number }[]; + statusCheckEnabled?: boolean; + /** Seconds between status checks; null follows the global setting. */ + statusCheckInterval?: number | null; /** Keepalive, legacy algorithms, agent and environment options. */ sshOptions?: HostSshOptions | null; /** Each enabled plugin's host settings, secrets redacted. */ @@ -49,7 +69,34 @@ export interface PluginHostRecord { protocolAuth?: Record; /** Set on a Quick Connect host, which is never saved. */ quickConnectLogin?: QuickConnectLogin; - [key: string]: unknown; + /** Quick Connect only: core can save this host as it is. */ + quickConnectSavable?: boolean; + /** Assigned when a host is opened in a tab; tells duplicate tabs apart. */ + instanceId?: string; + /** Core's status: "online" once a login worked. */ + status?: "online" | "reachable" | "offline" | "unknown"; + online?: boolean; + /** Someone else owns this host and shared it with the user. */ + isShared?: boolean; + permissionLevel?: "connect" | "view" | "edit" | "manage"; + sharedExpiresAt?: string; + ownerUsername?: string; + /** + * A shared host's login per protocol ("ssh" or a plugin protocol): whether + * the owner shared theirs, and the recipient's own credential if they had + * to pick one. + */ + authOverrides?: Partial>; + /** A read-only copy of a host shared with the linked account. */ + sharedCopy?: boolean; + /** Desktop only: kept on this device, never synced to the server. */ + localOnly?: boolean; +} + +export interface HostAuthOverrideSummary { + credentialId?: number | string; + required: boolean; + ownerAuthShared: boolean; } /** The protocol login a Quick Connect host carries, in plain text. */ diff --git a/packages/plugin-sdk/src/testing.ts b/packages/plugin-sdk/src/testing.ts index 3fb429a7d..93edc751a 100644 --- a/packages/plugin-sdk/src/testing.ts +++ b/packages/plugin-sdk/src/testing.ts @@ -8,7 +8,11 @@ * The vitest config these run under comes from @termix/plugin-sdk/vitest-preset. */ -import { LoginMethodError, PluginCapabilityError } from "./backend.js"; +import { + LoginMethodError, + PLUGIN_HOST_INPUT_KEYS, + PluginCapabilityError, +} from "./backend.js"; import type { PluginContext, PluginDisposables, @@ -396,6 +400,74 @@ function noopLogger(): PluginLogger { }; } +const HOST_INPUT_KEYS = new Set(PLUGIN_HOST_INPUT_KEYS); + +/** Refuses a key ctx.hosts does not take, the way core does. */ +function checkHostInput(input: PluginHostUpdateInput): void { + const unknown = Object.keys(input ?? {}).filter( + (key) => !HOST_INPUT_KEYS.has(key), + ); + if (unknown.length > 0) { + throw new Error(`ctx.hosts does not take ${unknown.join(", ")}`); + } +} + +function emptyHostRecord(id: number, userId: string): PluginHostRecord { + return { + id, + userId, + syncId: null, + name: null, + ip: "", + port: 22, + username: "", + authType: "password", + credentialId: null, + overrideCredentialUsername: false, + connectionType: "ssh", + tags: null, + folder: null, + parentHostId: null, + pin: false, + notes: null, + jumpHosts: [], + enableSsh: true, + sshPort: null, + statusCheckEnabled: true, + statusCheckInterval: null, + connectionOrigin: null, + sshOptions: {}, + pluginSettings: {}, + status: null, + localOnly: false, + createdAt: null, + updatedAt: null, + }; +} + +function applyHostInput( + record: PluginHostRecord, + input: PluginHostUpdateInput, +): PluginHostRecord { + const { + tags, + pluginSettings: _settings, + forceKeyboardInteractive: _fki, + ...rest + } = input; + const next: PluginHostRecord = { ...record }; + for (const [key, value] of Object.entries(rest)) { + if (value !== undefined) + (next as unknown as Record)[key] = value; + } + if (tags !== undefined) { + next.tags = Array.isArray(tags) ? tags.join(",") : tags; + } + if (next.jumpHosts === null) next.jumpHosts = []; + if (next.sshOptions === null) next.sshOptions = {}; + return next; +} + /** * A context double good enough to call activate() against in a unit test. * Nothing here is capability-checked: a test asserting a capability gate @@ -823,14 +895,12 @@ export function createFakeContext( create: async ( host: PluginHostCreateInput, ): Promise => { + checkHostInput(host); const id = nextHostId++; - const record: PluginHostRecord = { - tags: null, - folder: null, - ...host, - id, - userId: actor ?? "unknown", - }; + const record = applyHostInput( + emptyHostRecord(id, actor ?? "unknown"), + host, + ); hostRecordsById.set(id, record); return record; }, @@ -838,9 +908,10 @@ export function createFakeContext( hostId: number, patch: PluginHostUpdateInput, ): Promise => { + checkHostInput(patch); const existing = hostRecordsById.get(hostId); if (!existing) return null; - const updated = { ...existing, ...patch }; + const updated = applyHostInput(existing, patch); hostRecordsById.set(hostId, updated); return updated; }, diff --git a/plugins/ai/locales/en.json b/plugins/ai/locales/en.json index de591e668..7b5758ffa 100644 --- a/plugins/ai/locales/en.json +++ b/plugins/ai/locales/en.json @@ -112,5 +112,8 @@ "aiEnableTitle": "Turn it on", "aiEnableDesc": "Adds an assistant that reads your setup and suggests changes you approve. Needs a provider you supply, such as a local Ollama.", "aiNote": "Nothing is sent anywhere until you add a provider and send a message." + }, + "hosts": { + "docsLink": "View docs" } } diff --git a/plugins/ai/locales/translated/af_ZA.json b/plugins/ai/locales/translated/af_ZA.json index 29f4c6b94..dd52664ca 100644 --- a/plugins/ai/locales/translated/af_ZA.json +++ b/plugins/ai/locales/translated/af_ZA.json @@ -83,5 +83,8 @@ "description": "Laat die KI-assistent toe om in hierdie gasheer se terminaal te help. Standaard afgeskakel, en KI moet steeds vir jou rekening geaktiveer word." } } + }, + "hosts": { + "docsLink": "Bekyk dokumente" } } diff --git a/plugins/ai/locales/translated/ar_SA.json b/plugins/ai/locales/translated/ar_SA.json index ba724303a..037576844 100644 --- a/plugins/ai/locales/translated/ar_SA.json +++ b/plugins/ai/locales/translated/ar_SA.json @@ -83,5 +83,8 @@ "description": "اسمح للمساعد الذكي بالمساعدة في طرفية هذا المضيف. هذه الميزة معطلة افتراضيًا، ولا يزال يتعين تفعيلها لحسابك." } } + }, + "hosts": { + "docsLink": "عرض المستندات" } } diff --git a/plugins/ai/locales/translated/bg_BG.json b/plugins/ai/locales/translated/bg_BG.json index fdb3dfbc4..0d43bc3d4 100644 --- a/plugins/ai/locales/translated/bg_BG.json +++ b/plugins/ai/locales/translated/bg_BG.json @@ -83,5 +83,8 @@ "description": "Разрешете на AI асистента да помага в терминала на този хост. Изключено по подразбиране и все още изисква AI да е активиран за вашия акаунт." } } + }, + "hosts": { + "docsLink": "Преглед на документи" } } diff --git a/plugins/ai/locales/translated/bn_BD.json b/plugins/ai/locales/translated/bn_BD.json index ee68fa6f3..b9cd9691c 100644 --- a/plugins/ai/locales/translated/bn_BD.json +++ b/plugins/ai/locales/translated/bn_BD.json @@ -83,5 +83,8 @@ "description": "এই হোস্টের টার্মিনালে সাহায্য করার জন্য এআই অ্যাসিস্ট্যান্টকে অনুমতি দিন। এটি ডিফল্টরূপে বন্ধ থাকে এবং আপনার অ্যাকাউন্টের জন্য এআই চালু করা প্রয়োজন।" } } + }, + "hosts": { + "docsLink": "নথি দেখুন" } } diff --git a/plugins/ai/locales/translated/ca_ES.json b/plugins/ai/locales/translated/ca_ES.json index 84926cdd4..975dfddb6 100644 --- a/plugins/ai/locales/translated/ca_ES.json +++ b/plugins/ai/locales/translated/ca_ES.json @@ -83,5 +83,8 @@ "description": "Permet que l'assistent d'IA ajudi al terminal d'aquest amfitrió. Desactivat per defecte, però encara cal que la IA estigui activada per al teu compte." } } + }, + "hosts": { + "docsLink": "Veure documents" } } diff --git a/plugins/ai/locales/translated/cs_CZ.json b/plugins/ai/locales/translated/cs_CZ.json index 75f959974..fd86bd263 100644 --- a/plugins/ai/locales/translated/cs_CZ.json +++ b/plugins/ai/locales/translated/cs_CZ.json @@ -83,5 +83,8 @@ "description": "Povolit asistentovi s umělou inteligencí pomáhat v terminálu tohoto hostitele. Ve výchozím nastavení vypnuto, ale stále vyžaduje, aby byla pro váš účet povolena umělá inteligence." } } + }, + "hosts": { + "docsLink": "Zobrazit dokumenty" } } diff --git a/plugins/ai/locales/translated/da_DK.json b/plugins/ai/locales/translated/da_DK.json index 921eb9491..bc1406446 100644 --- a/plugins/ai/locales/translated/da_DK.json +++ b/plugins/ai/locales/translated/da_DK.json @@ -83,5 +83,8 @@ "description": "Tillad AI-assistenten at hjælpe i denne værts terminal. Deaktiveret som standard, og kræver stadig, at AI er aktiveret for din konto." } } + }, + "hosts": { + "docsLink": "Se dokumenter" } } diff --git a/plugins/ai/locales/translated/de_DE.json b/plugins/ai/locales/translated/de_DE.json index de5760035..538102fc8 100644 --- a/plugins/ai/locales/translated/de_DE.json +++ b/plugins/ai/locales/translated/de_DE.json @@ -83,5 +83,8 @@ "description": "Erlauben Sie dem KI-Assistenten, im Terminal dieses Hosts Hilfe zu leisten. Standardmäßig deaktiviert; die KI muss weiterhin für Ihr Konto aktiviert sein." } } + }, + "hosts": { + "docsLink": "Dokumentation anzeigen" } } diff --git a/plugins/ai/locales/translated/el_GR.json b/plugins/ai/locales/translated/el_GR.json index 4d01bc3d1..ca0178afb 100644 --- a/plugins/ai/locales/translated/el_GR.json +++ b/plugins/ai/locales/translated/el_GR.json @@ -83,5 +83,8 @@ "description": "Επιτρέψτε στον βοηθό τεχνητής νοημοσύνης να βοηθά στο τερματικό αυτού του κεντρικού υπολογιστή. Απενεργοποιημένο από προεπιλογή και εξακολουθεί να χρειάζεται ενεργοποιημένη την τεχνητή νοημοσύνη για τον λογαριασμό σας." } } + }, + "hosts": { + "docsLink": "Προβολή εγγράφων" } } diff --git a/plugins/ai/locales/translated/es_ES.json b/plugins/ai/locales/translated/es_ES.json index ce7fb65b2..c3ffb8803 100644 --- a/plugins/ai/locales/translated/es_ES.json +++ b/plugins/ai/locales/translated/es_ES.json @@ -83,5 +83,8 @@ "description": "Permite que el asistente de IA te ayude en la terminal de este host. Está desactivado por defecto y aún así necesitas tener la IA habilitada para tu cuenta." } } + }, + "hosts": { + "docsLink": "Ver documentación" } } diff --git a/plugins/ai/locales/translated/fi_FI.json b/plugins/ai/locales/translated/fi_FI.json index 44d0957df..abbd525e4 100644 --- a/plugins/ai/locales/translated/fi_FI.json +++ b/plugins/ai/locales/translated/fi_FI.json @@ -83,5 +83,8 @@ "description": "Salli tekoälyavustaja auttaa tämän isännän terminaalissa. Oletusarvoisesti pois päältä, mutta tekoälyn on silti oltava käytössä tililläsi." } } + }, + "hosts": { + "docsLink": "Näytä dokumentit" } } diff --git a/plugins/ai/locales/translated/fr_FR.json b/plugins/ai/locales/translated/fr_FR.json index 646ef3758..7192d287f 100644 --- a/plugins/ai/locales/translated/fr_FR.json +++ b/plugins/ai/locales/translated/fr_FR.json @@ -83,5 +83,8 @@ "description": "Autoriser l'assistant IA à vous aider dans le terminal de cet hôte. Désactivé par défaut ; l'IA doit être activée pour votre compte." } } + }, + "hosts": { + "docsLink": "Voir la documentation" } } diff --git a/plugins/ai/locales/translated/he_IL.json b/plugins/ai/locales/translated/he_IL.json index 722022f18..34237734f 100644 --- a/plugins/ai/locales/translated/he_IL.json +++ b/plugins/ai/locales/translated/he_IL.json @@ -83,5 +83,8 @@ "description": "אפשר לעוזר הבינה המלאכותית לסייע במסוף של מארח זה. כבוי כברירת מחדל, ועדיין נדרשת הפעלת בינה מלאכותית עבור חשבונך." } } + }, + "hosts": { + "docsLink": "הצג מסמכים" } } diff --git a/plugins/ai/locales/translated/hi_IN.json b/plugins/ai/locales/translated/hi_IN.json index e7d052027..fc6603d21 100644 --- a/plugins/ai/locales/translated/hi_IN.json +++ b/plugins/ai/locales/translated/hi_IN.json @@ -83,5 +83,8 @@ "description": "इस होस्ट के टर्मिनल में एआई सहायक को मदद करने की अनुमति दें। यह डिफ़ॉल्ट रूप से बंद है, लेकिन आपके खाते के लिए एआई को सक्षम करना आवश्यक है।" } } + }, + "hosts": { + "docsLink": "दस्तावेज़ देखें" } } diff --git a/plugins/ai/locales/translated/hu_HU.json b/plugins/ai/locales/translated/hu_HU.json index 62b8dcce3..43b9b6b70 100644 --- a/plugins/ai/locales/translated/hu_HU.json +++ b/plugins/ai/locales/translated/hu_HU.json @@ -83,5 +83,8 @@ "description": "Engedélyezi a mesterséges intelligencia asszisztensének a gazdagép terminálján való segítséget. Alapértelmezés szerint ki van kapcsolva, de továbbra is engedélyeznie kell a mesterséges intelligenciát a fiókjában." } } + }, + "hosts": { + "docsLink": "Dokumentumok megtekintése" } } diff --git a/plugins/ai/locales/translated/id_ID.json b/plugins/ai/locales/translated/id_ID.json index 085d298fe..d88244757 100644 --- a/plugins/ai/locales/translated/id_ID.json +++ b/plugins/ai/locales/translated/id_ID.json @@ -83,5 +83,8 @@ "description": "Izinkan asisten AI untuk membantu di terminal host ini. Secara default dinonaktifkan, dan AI tetap perlu diaktifkan untuk akun Anda." } } + }, + "hosts": { + "docsLink": "Lihat dokumen" } } diff --git a/plugins/ai/locales/translated/it_IT.json b/plugins/ai/locales/translated/it_IT.json index 6f4ae61c9..860f734f9 100644 --- a/plugins/ai/locales/translated/it_IT.json +++ b/plugins/ai/locales/translated/it_IT.json @@ -83,5 +83,8 @@ "description": "Consenti all'assistente IA di fornire assistenza nel terminale di questo host. Disattivato per impostazione predefinita, ma è necessario abilitare l'IA per il tuo account." } } + }, + "hosts": { + "docsLink": "Visualizza documentazione" } } diff --git a/plugins/ai/locales/translated/ja_JP.json b/plugins/ai/locales/translated/ja_JP.json index d3d1baf94..312788b6e 100644 --- a/plugins/ai/locales/translated/ja_JP.json +++ b/plugins/ai/locales/translated/ja_JP.json @@ -83,5 +83,8 @@ "description": "このホストのターミナルでAIアシスタントによる支援を許可します。デフォルトでは無効になっており、アカウントでAIを有効にする必要があります。" } } + }, + "hosts": { + "docsLink": "ドキュメントを表示" } } diff --git a/plugins/ai/locales/translated/ko_KR.json b/plugins/ai/locales/translated/ko_KR.json index 5adb3155f..96d6865bf 100644 --- a/plugins/ai/locales/translated/ko_KR.json +++ b/plugins/ai/locales/translated/ko_KR.json @@ -83,5 +83,8 @@ "description": "이 호스트의 터미널에서 AI 도우미의 도움을 받을 수 있도록 허용합니다. 기본적으로 비활성화되어 있으며, 계정에 AI 기능이 활성화되어 있어야 합니다." } } + }, + "hosts": { + "docsLink": "문서 보기" } } diff --git a/plugins/ai/locales/translated/nl_NL.json b/plugins/ai/locales/translated/nl_NL.json index db37a0f6e..0e37ce183 100644 --- a/plugins/ai/locales/translated/nl_NL.json +++ b/plugins/ai/locales/translated/nl_NL.json @@ -83,5 +83,8 @@ "description": "Sta de AI-assistent toe om te helpen in de terminal van deze host. Standaard uitgeschakeld, maar AI moet nog steeds voor uw account zijn ingeschakeld." } } + }, + "hosts": { + "docsLink": "Documenten bekijken" } } diff --git a/plugins/ai/locales/translated/no_NO.json b/plugins/ai/locales/translated/no_NO.json index 70ca3dcef..62affb69f 100644 --- a/plugins/ai/locales/translated/no_NO.json +++ b/plugins/ai/locales/translated/no_NO.json @@ -83,5 +83,8 @@ "description": "Tillat at AI-assistenten hjelper til i denne vertens terminal. Av som standard, og krever fortsatt at AI er aktivert for kontoen din." } } + }, + "hosts": { + "docsLink": "Vis dokumenter" } } diff --git a/plugins/ai/locales/translated/pl_PL.json b/plugins/ai/locales/translated/pl_PL.json index 4e3bc8f2b..946e537be 100644 --- a/plugins/ai/locales/translated/pl_PL.json +++ b/plugins/ai/locales/translated/pl_PL.json @@ -83,5 +83,8 @@ "description": "Zezwól asystentowi AI na pomoc w terminalu tego hosta. Domyślnie wyłączone, ale nadal wymaga włączenia AI na Twoim koncie." } } + }, + "hosts": { + "docsLink": "Zobacz dokumentację" } } diff --git a/plugins/ai/locales/translated/pt_BR.json b/plugins/ai/locales/translated/pt_BR.json index 4b1737b15..b56f6208e 100644 --- a/plugins/ai/locales/translated/pt_BR.json +++ b/plugins/ai/locales/translated/pt_BR.json @@ -83,5 +83,8 @@ "description": "Permita que o assistente de IA ajude no terminal deste host. Desativado por padrão, mas ainda precisa que a IA esteja ativada para sua conta." } } + }, + "hosts": { + "docsLink": "Ver documentos" } } diff --git a/plugins/ai/locales/translated/pt_PT.json b/plugins/ai/locales/translated/pt_PT.json index 09a98f01d..b4c6149b4 100644 --- a/plugins/ai/locales/translated/pt_PT.json +++ b/plugins/ai/locales/translated/pt_PT.json @@ -83,5 +83,8 @@ "description": "Permita que o assistente de IA ajude no terminal deste host. Desativado por defeito, mas ainda precisa que a IA esteja ativada para a sua conta." } } + }, + "hosts": { + "docsLink": "Ver documentação" } } diff --git a/plugins/ai/locales/translated/ro_RO.json b/plugins/ai/locales/translated/ro_RO.json index b567ea3e9..1486173fd 100644 --- a/plugins/ai/locales/translated/ro_RO.json +++ b/plugins/ai/locales/translated/ro_RO.json @@ -83,5 +83,8 @@ "description": "Permiteți asistentului AI să vă ajute în terminalul acestei gazde. Dezactivat în mod implicit, dar este nevoie ca AI să fie activat pentru contul dvs." } } + }, + "hosts": { + "docsLink": "Vizualizați documentele" } } diff --git a/plugins/ai/locales/translated/ru_RU.json b/plugins/ai/locales/translated/ru_RU.json index c883756ce..17b8968b1 100644 --- a/plugins/ai/locales/translated/ru_RU.json +++ b/plugins/ai/locales/translated/ru_RU.json @@ -83,5 +83,8 @@ "description": "Разрешите помощнику с искусственным интеллектом помогать на терминале этого хоста. По умолчанию отключено, но для вашей учетной записи ИИ все равно должен быть включен." } } + }, + "hosts": { + "docsLink": "Документация" } } diff --git a/plugins/ai/locales/translated/sr_SP.json b/plugins/ai/locales/translated/sr_SP.json index 73828853e..793577f0f 100644 --- a/plugins/ai/locales/translated/sr_SP.json +++ b/plugins/ai/locales/translated/sr_SP.json @@ -83,5 +83,8 @@ "description": "Дозволите вештачкој интелигенцији да помогне у терминалу овог хоста. Искључено је подразумевано, а и даље је потребно да вештачка интелигенција буде омогућена за ваш налог." } } + }, + "hosts": { + "docsLink": "Прикажи документе" } } diff --git a/plugins/ai/locales/translated/sv_SE.json b/plugins/ai/locales/translated/sv_SE.json index edfaf6a9c..2671da31f 100644 --- a/plugins/ai/locales/translated/sv_SE.json +++ b/plugins/ai/locales/translated/sv_SE.json @@ -83,5 +83,8 @@ "description": "Tillåt AI-assistenten att hjälpa till i den här värdens terminal. Av som standard och kräver fortfarande att AI är aktiverat för ditt konto." } } + }, + "hosts": { + "docsLink": "Visa dokument" } } diff --git a/plugins/ai/locales/translated/th_TH.json b/plugins/ai/locales/translated/th_TH.json index bf9605514..451db02ba 100644 --- a/plugins/ai/locales/translated/th_TH.json +++ b/plugins/ai/locales/translated/th_TH.json @@ -83,5 +83,8 @@ "description": "อนุญาตให้ผู้ช่วย AI ช่วยเหลือในเทอร์มินัลของโฮสต์นี้ โดยค่าเริ่มต้นจะปิดอยู่ และยังคงต้องเปิดใช้งาน AI สำหรับบัญชีของคุณก่อน" } } + }, + "hosts": { + "docsLink": "ดูเอกสาร" } } diff --git a/plugins/ai/locales/translated/tr_TR.json b/plugins/ai/locales/translated/tr_TR.json index 04ee35384..8d22abf89 100644 --- a/plugins/ai/locales/translated/tr_TR.json +++ b/plugins/ai/locales/translated/tr_TR.json @@ -83,5 +83,8 @@ "description": "Bu sunucunun terminalinde yapay zeka asistanının yardımcı olmasına izin verin. Varsayılan olarak kapalıdır ve hesabınız için yapay zekanın etkinleştirilmiş olması gerekir." } } + }, + "hosts": { + "docsLink": "Dokümanları görüntüle" } } diff --git a/plugins/ai/locales/translated/uk_UA.json b/plugins/ai/locales/translated/uk_UA.json index 43385159c..afbc7f59b 100644 --- a/plugins/ai/locales/translated/uk_UA.json +++ b/plugins/ai/locales/translated/uk_UA.json @@ -83,5 +83,8 @@ "description": "Дозволити помічнику зі штучним інтелектом допомагати в терміналі цього хоста. Вимкнено за замовчуванням, але все одно потребує ввімкнення штучного інтелекту для вашого облікового запису." } } + }, + "hosts": { + "docsLink": "Переглянути документи" } } diff --git a/plugins/ai/locales/translated/vi_VN.json b/plugins/ai/locales/translated/vi_VN.json index 737683517..f96e93f71 100644 --- a/plugins/ai/locales/translated/vi_VN.json +++ b/plugins/ai/locales/translated/vi_VN.json @@ -83,5 +83,8 @@ "description": "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." } } + }, + "hosts": { + "docsLink": "Xem tài liệu" } } diff --git a/plugins/ai/locales/translated/zh_CN.json b/plugins/ai/locales/translated/zh_CN.json index 06c5cd6cd..c22094096 100644 --- a/plugins/ai/locales/translated/zh_CN.json +++ b/plugins/ai/locales/translated/zh_CN.json @@ -83,5 +83,8 @@ "description": "允许 AI 助手在此主机的终端上提供帮助。默认情况下处于关闭状态,但仍需在您的帐户中启用 AI 功能。" } } + }, + "hosts": { + "docsLink": "查看文档" } } diff --git a/plugins/ai/locales/translated/zh_TW.json b/plugins/ai/locales/translated/zh_TW.json index 71cf15e0a..1f56ed0e6 100644 --- a/plugins/ai/locales/translated/zh_TW.json +++ b/plugins/ai/locales/translated/zh_TW.json @@ -83,5 +83,8 @@ "description": "允許 AI 助理在此主機的終端機上提供協助。預設為關閉狀態,但仍需在您的帳戶中啟用 AI 功能。" } } + }, + "hosts": { + "docsLink": "檢視文件" } } diff --git a/plugins/ai/src/backend/tools/executor.ts b/plugins/ai/src/backend/tools/executor.ts index 7637ab512..17cce89a0 100644 --- a/plugins/ai/src/backend/tools/executor.ts +++ b/plugins/ai/src/backend/tools/executor.ts @@ -1,4 +1,5 @@ import type { Client } from "ssh2"; +import type { PluginHostUpdateInput } from "@termix/plugin-sdk/backend"; import { execCommand } from "@termix/plugin-sdk/host-commands"; import { getTool } from "./catalog.js"; import type { ToolDeps } from "./types.js"; @@ -93,7 +94,7 @@ export async function applyProposal( const hostId = requireNumber(payload.hostId, "hostId"); const changes = (payload.changes ?? {}) as Record; - const updates: Record = {}; + const updates: PluginHostUpdateInput = {}; if (changes.name !== undefined) updates.name = requireString(changes.name, "name"); if (changes.ip !== undefined) diff --git a/plugins/docker/locales/en.json b/plugins/docker/locales/en.json index bf17c9e19..631c3a919 100644 --- a/plugins/docker/locales/en.json +++ b/plugins/docker/locales/en.json @@ -112,7 +112,9 @@ "feature_docker_desc": "See containers, read logs and watch stats on any host running Docker." }, "terminal": { - "retry": "Retry" + "retry": "Retry", + "clipboardReadFailed": "Failed to read from clipboard. Make sure clipboard permissions are granted.", + "clipboardWriteFailed": "Failed to copy to clipboard. Make sure the page is served over HTTPS or localhost." }, "permissions": { "use": { @@ -133,5 +135,13 @@ "podman": "Podman" } } + }, + "errors": { + "remoteServerRequired": "Remote server required. Connect a remote server in Settings to use this connection type." + }, + "hosts": { + "docsLink": "View docs", + "hostNotFound": "Host not found", + "loadingHost": "Loading host..." } } diff --git a/plugins/docker/locales/translated/af_ZA.json b/plugins/docker/locales/translated/af_ZA.json index c56143f1c..a0b91cfff 100644 --- a/plugins/docker/locales/translated/af_ZA.json +++ b/plugins/docker/locales/translated/af_ZA.json @@ -114,5 +114,17 @@ "podman": "Podman" } } + }, + "errors": { + "remoteServerRequired": "Afstandbediener word benodig. Koppel 'n afstandbediener in Instellings om hierdie verbindingstipe te gebruik." + }, + "hosts": { + "docsLink": "Bekyk dokumente", + "hostNotFound": "Gasheer nie gevind nie", + "loadingHost": "Laai gasheer..." + }, + "terminal": { + "clipboardReadFailed": "Kon nie vanaf knipbord lees nie. Maak seker dat knipbordtoestemmings toegestaan is.", + "clipboardWriteFailed": "Kon nie na knipbord kopieer nie. Maak seker dat die bladsy oor HTTPS of localhost bedien word." } } diff --git a/plugins/docker/locales/translated/ar_SA.json b/plugins/docker/locales/translated/ar_SA.json index fa0c39f6e..aee542733 100644 --- a/plugins/docker/locales/translated/ar_SA.json +++ b/plugins/docker/locales/translated/ar_SA.json @@ -114,5 +114,17 @@ "podman": "Podman" } } + }, + "errors": { + "remoteServerRequired": "يلزم وجود خادم بعيد. قم بتوصيل خادم بعيد في الإعدادات لاستخدام نوع الاتصال هذا." + }, + "hosts": { + "docsLink": "عرض المستندات", + "hostNotFound": "المضيف غير موجود", + "loadingHost": "جارٍ تحميل المضيف..." + }, + "terminal": { + "clipboardReadFailed": "فشلت القراءة من الحافظة. تأكد من منح أذونات الحافظة.", + "clipboardWriteFailed": "فشل النسخ إلى الحافظة. تأكد من تقديم الصفحة عبر HTTPS أو localhost." } } diff --git a/plugins/docker/locales/translated/bg_BG.json b/plugins/docker/locales/translated/bg_BG.json index 28bb1bd56..9343d324f 100644 --- a/plugins/docker/locales/translated/bg_BG.json +++ b/plugins/docker/locales/translated/bg_BG.json @@ -114,5 +114,17 @@ "podman": "Подман" } } + }, + "errors": { + "remoteServerRequired": "Изисква се отдалечен сървър. Свържете се с отдалечен сървър в „Настройки“, за да използвате този тип връзка." + }, + "hosts": { + "docsLink": "Преглед на документи", + "hostNotFound": "Хостът не е намерен", + "loadingHost": "Зареждане на хоста..." + }, + "terminal": { + "clipboardReadFailed": "Четенето от клипборда не бе успешно. Уверете се, че са предоставени разрешения за достъп до клипборда.", + "clipboardWriteFailed": "Копирането в буфера не бе успешно. Уверете се, че страницата се предоставя през HTTPS или localhost." } } diff --git a/plugins/docker/locales/translated/bn_BD.json b/plugins/docker/locales/translated/bn_BD.json index f1edad4b7..ccf797258 100644 --- a/plugins/docker/locales/translated/bn_BD.json +++ b/plugins/docker/locales/translated/bn_BD.json @@ -114,5 +114,17 @@ "podman": "পডম্যান" } } + }, + "errors": { + "remoteServerRequired": "রিমোট সার্ভার প্রয়োজন। এই সংযোগের ধরণটি ব্যবহার করতে সেটিংস-এ একটি রিমোট সার্ভার সংযুক্ত করুন।" + }, + "hosts": { + "docsLink": "নথি দেখুন", + "hostNotFound": "হোস্ট খুঁজে পাওয়া যায়নি", + "loadingHost": "হোস্ট লোড হচ্ছে..." + }, + "terminal": { + "clipboardReadFailed": "ক্লিপবোর্ড থেকে পড়তে ব্যর্থ হয়েছে। নিশ্চিত করুন যে ক্লিপবোর্ডের অনুমতি দেওয়া আছে।", + "clipboardWriteFailed": "ক্লিপবোর্ডে কপি করা সম্ভব হয়নি। নিশ্চিত করুন যে পৃষ্ঠাটি HTTPS বা লোকালহোস্টের মাধ্যমে পরিবেশিত হচ্ছে।" } } diff --git a/plugins/docker/locales/translated/ca_ES.json b/plugins/docker/locales/translated/ca_ES.json index 6b6c60414..e22d5cbe3 100644 --- a/plugins/docker/locales/translated/ca_ES.json +++ b/plugins/docker/locales/translated/ca_ES.json @@ -114,5 +114,17 @@ "podman": "Podman" } } + }, + "errors": { + "remoteServerRequired": "Cal un servidor remot. Connecteu un servidor remot a Configuració per utilitzar aquest tipus de connexió." + }, + "hosts": { + "docsLink": "Veure documents", + "hostNotFound": "No s'ha trobat l'amfitrió", + "loadingHost": "S'està carregant l'amfitrió..." + }, + "terminal": { + "clipboardReadFailed": "No s'ha pogut llegir del porta-retalls. Assegureu-vos que els permisos del porta-retalls estiguin concedits.", + "clipboardWriteFailed": "No s'ha pogut copiar al porta-retalls. Assegureu-vos que la pàgina es serveix per HTTPS o localhost." } } diff --git a/plugins/docker/locales/translated/cs_CZ.json b/plugins/docker/locales/translated/cs_CZ.json index 644ae1161..cd07beb1e 100644 --- a/plugins/docker/locales/translated/cs_CZ.json +++ b/plugins/docker/locales/translated/cs_CZ.json @@ -114,5 +114,17 @@ "podman": "Podman" } } + }, + "errors": { + "remoteServerRequired": "Je vyžadován vzdálený server. Pro použití tohoto typu připojení se připojte ke vzdálenému serveru v Nastavení." + }, + "hosts": { + "docsLink": "Zobrazit dokumenty", + "hostNotFound": "Hostitel nenalezen", + "loadingHost": "Načítání hostitele..." + }, + "terminal": { + "clipboardReadFailed": "Čtení ze schránky se nezdařilo. Ujistěte se, že máte povolena přístup ke schránce.", + "clipboardWriteFailed": "Kopírování do schránky se nezdařilo. Ujistěte se, že stránka je zobrazována přes HTTPS nebo localhost." } } diff --git a/plugins/docker/locales/translated/da_DK.json b/plugins/docker/locales/translated/da_DK.json index ce5643037..2477a6b8c 100644 --- a/plugins/docker/locales/translated/da_DK.json +++ b/plugins/docker/locales/translated/da_DK.json @@ -114,5 +114,17 @@ "podman": "Podman" } } + }, + "errors": { + "remoteServerRequired": "Fjernserver kræves. Opret forbindelse til en fjernserver i Indstillinger for at bruge denne forbindelsestype." + }, + "hosts": { + "docsLink": "Se dokumenter", + "hostNotFound": "Værten blev ikke fundet", + "loadingHost": "Indlæser vært..." + }, + "terminal": { + "clipboardReadFailed": "Kunne ikke læse fra udklipsholderen. Sørg for, at der er givet tilladelse til udklipsholderen.", + "clipboardWriteFailed": "Kunne ikke kopiere til udklipsholder. Sørg for, at siden serveres via HTTPS eller localhost." } } diff --git a/plugins/docker/locales/translated/de_DE.json b/plugins/docker/locales/translated/de_DE.json index 6c049d4e2..160fedc9f 100644 --- a/plugins/docker/locales/translated/de_DE.json +++ b/plugins/docker/locales/translated/de_DE.json @@ -114,5 +114,17 @@ "podman": "Podman" } } + }, + "errors": { + "remoteServerRequired": "Remote-Server erforderlich. Um diesen Verbindungstyp zu verwenden, verbinden Sie einen Remote-Server in den Einstellungen." + }, + "hosts": { + "docsLink": "Dokumentation anzeigen", + "hostNotFound": "Host nicht gefunden", + "loadingHost": "Host wird geladen..." + }, + "terminal": { + "clipboardReadFailed": "Lesen aus der Zwischenablage fehlgeschlagen. Stellen Sie sicher, dass die Zwischenablageberechtigungen erteilt wurden.", + "clipboardWriteFailed": "Kopieren in die Zwischenablage fehlgeschlagen. Stellen Sie sicher, dass die Seite über HTTPS oder localhost bereitgestellt wird." } } diff --git a/plugins/docker/locales/translated/el_GR.json b/plugins/docker/locales/translated/el_GR.json index 42c5ae4de..3287379ef 100644 --- a/plugins/docker/locales/translated/el_GR.json +++ b/plugins/docker/locales/translated/el_GR.json @@ -114,5 +114,17 @@ "podman": "Πόντμαν" } } + }, + "errors": { + "remoteServerRequired": "Απαιτείται απομακρυσμένος διακομιστής. Συνδέστε έναν απομακρυσμένο διακομιστή στις Ρυθμίσεις για να χρησιμοποιήσετε αυτόν τον τύπο σύνδεσης." + }, + "hosts": { + "docsLink": "Προβολή εγγράφων", + "hostNotFound": "Δεν βρέθηκε κεντρικός υπολογιστής", + "loadingHost": "Φόρτωση κεντρικού υπολογιστή..." + }, + "terminal": { + "clipboardReadFailed": "Αποτυχία ανάγνωσης από το πρόχειρο. Βεβαιωθείτε ότι έχουν εκχωρηθεί δικαιώματα στο πρόχειρο.", + "clipboardWriteFailed": "Αποτυχία αντιγραφής στο πρόχειρο. Βεβαιωθείτε ότι η σελίδα προβάλλεται μέσω HTTPS ή localhost." } } diff --git a/plugins/docker/locales/translated/es_ES.json b/plugins/docker/locales/translated/es_ES.json index ae87d08fc..e3fd2b972 100644 --- a/plugins/docker/locales/translated/es_ES.json +++ b/plugins/docker/locales/translated/es_ES.json @@ -114,5 +114,17 @@ "podman": "Podman" } } + }, + "errors": { + "remoteServerRequired": "Se requiere un servidor remoto. Conecte un servidor remoto en Configuración para usar este tipo de conexión." + }, + "hosts": { + "docsLink": "Ver documentación", + "hostNotFound": "Host no encontrado", + "loadingHost": "Cargando host..." + }, + "terminal": { + "clipboardReadFailed": "No se pudo leer del portapapeles. Asegúrese de que los permisos del portapapeles estén concedidos.", + "clipboardWriteFailed": "Error al copiar al portapapeles. Asegúrese de que la página se sirva a través de HTTPS o en localhost." } } diff --git a/plugins/docker/locales/translated/fi_FI.json b/plugins/docker/locales/translated/fi_FI.json index 3c03edc78..df4289e82 100644 --- a/plugins/docker/locales/translated/fi_FI.json +++ b/plugins/docker/locales/translated/fi_FI.json @@ -114,5 +114,17 @@ "podman": "Podman" } } + }, + "errors": { + "remoteServerRequired": "Etäpalvelin vaaditaan. Yhdistä etäpalvelin asetuksissa käyttääksesi tätä yhteystyyppiä." + }, + "hosts": { + "docsLink": "Näytä dokumentit", + "hostNotFound": "Isäntää ei löydy", + "loadingHost": "Ladataan isäntää..." + }, + "terminal": { + "clipboardReadFailed": "Leikepöydän lukeminen epäonnistui. Varmista, että leikepöydän käyttöoikeudet on myönnetty.", + "clipboardWriteFailed": "Kopiointi leikepöydälle epäonnistui. Varmista, että sivua käytetään HTTPS:n tai paikallisen isännän kautta." } } diff --git a/plugins/docker/locales/translated/fr_FR.json b/plugins/docker/locales/translated/fr_FR.json index 931a11678..18650af02 100644 --- a/plugins/docker/locales/translated/fr_FR.json +++ b/plugins/docker/locales/translated/fr_FR.json @@ -114,5 +114,17 @@ "podman": "Podman" } } + }, + "errors": { + "remoteServerRequired": "Serveur distant requis. Connectez un serveur distant dans les paramètres pour utiliser ce type de connexion." + }, + "hosts": { + "docsLink": "Voir la documentation", + "hostNotFound": "Hôte introuvable", + "loadingHost": "Chargement de l'hôte..." + }, + "terminal": { + "clipboardReadFailed": "Échec de la lecture du presse-papiers. Assurez-vous que les autorisations du presse-papiers sont accordées.", + "clipboardWriteFailed": "Échec de la copie dans le presse-papiers. Assurez-vous que la page est servie en HTTPS ou localhost." } } diff --git a/plugins/docker/locales/translated/he_IL.json b/plugins/docker/locales/translated/he_IL.json index e063da67d..1454d74a8 100644 --- a/plugins/docker/locales/translated/he_IL.json +++ b/plugins/docker/locales/translated/he_IL.json @@ -114,5 +114,17 @@ "podman": "פודמן" } } + }, + "errors": { + "remoteServerRequired": "נדרש שרת מרוחק. יש להתחבר לשרת מרוחק בהגדרות כדי להשתמש בסוג חיבור זה." + }, + "hosts": { + "docsLink": "הצג מסמכים", + "hostNotFound": "המארח לא נמצא", + "loadingHost": "טוען מארח..." + }, + "terminal": { + "clipboardReadFailed": "הקריאה מהלוח נכשלה. ודא שהרשאות הלוח ניתנות.", + "clipboardWriteFailed": "ההעתקה ללוח נכשלה. ודא שהדף מוגש דרך HTTPS או localhost." } } diff --git a/plugins/docker/locales/translated/hi_IN.json b/plugins/docker/locales/translated/hi_IN.json index 331c1fbc0..f8bacaae9 100644 --- a/plugins/docker/locales/translated/hi_IN.json +++ b/plugins/docker/locales/translated/hi_IN.json @@ -114,5 +114,17 @@ "podman": "Podman" } } + }, + "errors": { + "remoteServerRequired": "रिमोट सर्वर आवश्यक है। इस कनेक्शन प्रकार का उपयोग करने के लिए सेटिंग्स में जाकर रिमोट सर्वर कनेक्ट करें।" + }, + "hosts": { + "docsLink": "दस्तावेज़ देखें", + "hostNotFound": "होस्ट नहीं मिला", + "loadingHost": "होस्ट लोड हो रहा है..." + }, + "terminal": { + "clipboardReadFailed": "क्लिपबोर्ड से पढ़ने में विफल। सुनिश्चित करें कि क्लिपबोर्ड अनुमतियाँ दी गई हैं।", + "clipboardWriteFailed": "क्लिपबोर्ड पर कॉपी करने में विफल। सुनिश्चित करें कि पेज HTTPS या लोकलहोस्ट पर सर्व किया गया है।" } } diff --git a/plugins/docker/locales/translated/hu_HU.json b/plugins/docker/locales/translated/hu_HU.json index 7a5c4b20e..d871357ae 100644 --- a/plugins/docker/locales/translated/hu_HU.json +++ b/plugins/docker/locales/translated/hu_HU.json @@ -114,5 +114,17 @@ "podman": "Podman" } } + }, + "errors": { + "remoteServerRequired": "Távoli szerver szükséges. Csatlakoztasson egy távoli szervert a Beállításokban a kapcsolattípus használatához." + }, + "hosts": { + "docsLink": "Dokumentumok megtekintése", + "hostNotFound": "Nem található gazdagép", + "loadingHost": "Gazdagép betöltése..." + }, + "terminal": { + "clipboardReadFailed": "Nem sikerült beolvasni a vágólapról. Győződjön meg arról, hogy a vágólapra vonatkozó engedélyek meg vannak adva.", + "clipboardWriteFailed": "Nem sikerült a vágólapra másolni. Győződjön meg arról, hogy az oldal HTTPS vagy localhost protokollon keresztül jelenik meg." } } diff --git a/plugins/docker/locales/translated/id_ID.json b/plugins/docker/locales/translated/id_ID.json index 52c9d3583..07eb0cb88 100644 --- a/plugins/docker/locales/translated/id_ID.json +++ b/plugins/docker/locales/translated/id_ID.json @@ -114,5 +114,17 @@ "podman": "Podman" } } + }, + "errors": { + "remoteServerRequired": "Diperlukan server jarak jauh. Hubungkan server jarak jauh di Pengaturan untuk menggunakan jenis koneksi ini." + }, + "hosts": { + "docsLink": "Lihat dokumen", + "hostNotFound": "Host tidak ditemukan", + "loadingHost": "Memuat host..." + }, + "terminal": { + "clipboardReadFailed": "Gagal membaca dari clipboard. Pastikan izin clipboard telah diberikan.", + "clipboardWriteFailed": "Gagal menyalin ke papan klip. Pastikan halaman disajikan melalui HTTPS atau localhost." } } diff --git a/plugins/docker/locales/translated/it_IT.json b/plugins/docker/locales/translated/it_IT.json index 4f6c78139..6ec4a296d 100644 --- a/plugins/docker/locales/translated/it_IT.json +++ b/plugins/docker/locales/translated/it_IT.json @@ -114,5 +114,17 @@ "podman": "Podman" } } + }, + "errors": { + "remoteServerRequired": "È necessario un server remoto. Per utilizzare questo tipo di connessione, collega un server remoto nelle Impostazioni." + }, + "hosts": { + "docsLink": "Visualizza documentazione", + "hostNotFound": "Host non trovato", + "loadingHost": "Caricamento host..." + }, + "terminal": { + "clipboardReadFailed": "Lettura dagli appunti non riuscita. Assicurati che i permessi degli appunti siano stati concessi.", + "clipboardWriteFailed": "Copia negli appunti non riuscita. Assicurati che la pagina sia servita via HTTPS o localhost." } } diff --git a/plugins/docker/locales/translated/ja_JP.json b/plugins/docker/locales/translated/ja_JP.json index 506c017f4..7a35d30b9 100644 --- a/plugins/docker/locales/translated/ja_JP.json +++ b/plugins/docker/locales/translated/ja_JP.json @@ -114,5 +114,17 @@ "podman": "Podman" } } + }, + "errors": { + "remoteServerRequired": "リモートサーバーが必要です。この接続タイプを使用するには、設定でリモートサーバーを接続してください。" + }, + "hosts": { + "docsLink": "ドキュメントを表示", + "hostNotFound": "ホストが見つかりません", + "loadingHost": "ホストを読み込み中..." + }, + "terminal": { + "clipboardReadFailed": "クリップボードからの読み取りに失敗しました。クリップボードのアクセス許可が付与されていることを確認してください。", + "clipboardWriteFailed": "クリップボードへのコピーに失敗しました。ページがHTTPSまたはlocalhostで提供されていることを確認してください。" } } diff --git a/plugins/docker/locales/translated/ko_KR.json b/plugins/docker/locales/translated/ko_KR.json index 8574921c7..00cff812a 100644 --- a/plugins/docker/locales/translated/ko_KR.json +++ b/plugins/docker/locales/translated/ko_KR.json @@ -114,5 +114,17 @@ "podman": "Podman" } } + }, + "errors": { + "remoteServerRequired": "원격 서버가 필요합니다. 이 연결 유형을 사용하려면 설정에서 원격 서버를 연결하세요." + }, + "hosts": { + "docsLink": "문서 보기", + "hostNotFound": "호스트를 찾을 수 없습니다", + "loadingHost": "호스트 로드 중..." + }, + "terminal": { + "clipboardReadFailed": "클립보드에서 읽지 못했습니다. 클립보드 권한이 허용되었는지 확인하세요.", + "clipboardWriteFailed": "클립보드에 복사하지 못했습니다. 페이지가 HTTPS 또는 localhost에서 제공되는지 확인하세요." } } diff --git a/plugins/docker/locales/translated/nl_NL.json b/plugins/docker/locales/translated/nl_NL.json index 5d5c1d2f3..2bf0b4341 100644 --- a/plugins/docker/locales/translated/nl_NL.json +++ b/plugins/docker/locales/translated/nl_NL.json @@ -114,5 +114,17 @@ "podman": "Podman" } } + }, + "errors": { + "remoteServerRequired": "Externe server vereist. Verbind een externe server in de instellingen om dit verbindingstype te gebruiken." + }, + "hosts": { + "docsLink": "Documenten bekijken", + "hostNotFound": "Host niet gevonden", + "loadingHost": "Host wordt geladen..." + }, + "terminal": { + "clipboardReadFailed": "Het lezen van het klembord is mislukt. Zorg ervoor dat de juiste klembordrechten zijn verleend.", + "clipboardWriteFailed": "Kopiëren naar klembord mislukt. Zorg ervoor dat de pagina via HTTPS of localhost wordt aangeboden." } } diff --git a/plugins/docker/locales/translated/no_NO.json b/plugins/docker/locales/translated/no_NO.json index d43b58508..f749a2d98 100644 --- a/plugins/docker/locales/translated/no_NO.json +++ b/plugins/docker/locales/translated/no_NO.json @@ -114,5 +114,17 @@ "podman": "Podman" } } + }, + "errors": { + "remoteServerRequired": "Ekstern server kreves. Koble til en ekstern server i Innstillinger for å bruke denne tilkoblingstypen." + }, + "hosts": { + "docsLink": "Vis dokumenter", + "hostNotFound": "Verten ble ikke funnet", + "loadingHost": "Laster inn vert ..." + }, + "terminal": { + "clipboardReadFailed": "Kunne ikke lese fra utklippstavlen. Sørg for at utklippstavlen har tillatelser.", + "clipboardWriteFailed": "Kunne ikke kopiere til utklippstavlen. Sørg for at siden serveres via HTTPS eller localhost." } } diff --git a/plugins/docker/locales/translated/pl_PL.json b/plugins/docker/locales/translated/pl_PL.json index 7f459e472..1570c6e6c 100644 --- a/plugins/docker/locales/translated/pl_PL.json +++ b/plugins/docker/locales/translated/pl_PL.json @@ -114,5 +114,17 @@ "podman": "Podman" } } + }, + "errors": { + "remoteServerRequired": "Wymagany jest serwer zdalny. Połącz się z serwerem zdalnym w Ustawieniach, aby korzystać z tego typu połączenia." + }, + "hosts": { + "docsLink": "Zobacz dokumentację", + "hostNotFound": "Nie znaleziono hosta", + "loadingHost": "Ładowanie hosta..." + }, + "terminal": { + "clipboardReadFailed": "Nie udało się odczytać danych ze schowka. Upewnij się, że uprawnienia do schowka zostały przyznane.", + "clipboardWriteFailed": "Nie udało się skopiować do schowka. Upewnij się, że strona jest serwowana przez HTTPS lub localhost." } } diff --git a/plugins/docker/locales/translated/pt_BR.json b/plugins/docker/locales/translated/pt_BR.json index 476b3dc58..b5db6a8d2 100644 --- a/plugins/docker/locales/translated/pt_BR.json +++ b/plugins/docker/locales/translated/pt_BR.json @@ -114,5 +114,17 @@ "podman": "Podman" } } + }, + "errors": { + "remoteServerRequired": "É necessário um servidor remoto. Conecte um servidor remoto nas Configurações para usar este tipo de conexão." + }, + "hosts": { + "docsLink": "Ver documentos", + "hostNotFound": "Host não encontrado", + "loadingHost": "Carregando host..." + }, + "terminal": { + "clipboardReadFailed": "Não foi possível ler o conteúdo da área de transferência. Certifique-se de que as permissões de acesso à área de transferência estejam concedidas.", + "clipboardWriteFailed": "Falha ao copiar para a área de transferência. Certifique-se de que a página esteja sendo servida via HTTPS ou localhost." } } diff --git a/plugins/docker/locales/translated/pt_PT.json b/plugins/docker/locales/translated/pt_PT.json index a4e875d40..9dffc37a7 100644 --- a/plugins/docker/locales/translated/pt_PT.json +++ b/plugins/docker/locales/translated/pt_PT.json @@ -114,5 +114,17 @@ "podman": "Podman" } } + }, + "errors": { + "remoteServerRequired": "É necessário um servidor remoto. Ligue um servidor remoto nas Definições para utilizar este tipo de ligação." + }, + "hosts": { + "docsLink": "Ver documentação", + "hostNotFound": "Host não encontrado", + "loadingHost": "A carregar o host..." + }, + "terminal": { + "clipboardReadFailed": "Erro ao ler da área de transferência. Certifique-se de que as permissões da área de transferência foram concedidas.", + "clipboardWriteFailed": "Erro ao copiar para a área de transferência. Certifique-se de que a página é servida via HTTPS ou localhost." } } diff --git a/plugins/docker/locales/translated/ro_RO.json b/plugins/docker/locales/translated/ro_RO.json index 467be7b47..6ed5116c1 100644 --- a/plugins/docker/locales/translated/ro_RO.json +++ b/plugins/docker/locales/translated/ro_RO.json @@ -114,5 +114,17 @@ "podman": "Podman" } } + }, + "errors": { + "remoteServerRequired": "Este necesar un server la distanță. Conectați un server la distanță în Setări pentru a utiliza acest tip de conexiune." + }, + "hosts": { + "docsLink": "Vizualizați documentele", + "hostNotFound": "Gazdă negăsită", + "loadingHost": "Se încarcă gazda..." + }, + "terminal": { + "clipboardReadFailed": "Citirea din clipboard nu a reușit. Asigurați-vă că permisiunile de acces la clipboard sunt acordate.", + "clipboardWriteFailed": "Copierea în clipboard nu a reușit. Asigurați-vă că pagina este servită prin HTTPS sau localhost." } } diff --git a/plugins/docker/locales/translated/ru_RU.json b/plugins/docker/locales/translated/ru_RU.json index c7af28c18..f3759f1c3 100644 --- a/plugins/docker/locales/translated/ru_RU.json +++ b/plugins/docker/locales/translated/ru_RU.json @@ -114,5 +114,17 @@ "podman": "Podman" } } + }, + "errors": { + "remoteServerRequired": "Требуется удаленный сервер. Для использования этого типа подключения подключите удаленный сервер в настройках." + }, + "hosts": { + "docsLink": "Документация", + "hostNotFound": "Хост не найден", + "loadingHost": "Загрузка хоста..." + }, + "terminal": { + "clipboardReadFailed": "Не удалось прочитать из буфера обмена. Убедитесь, что предоставлены разрешения на доступ к буферу обмена.", + "clipboardWriteFailed": "Не удалось скопировать в буфер обмена. Убедитесь, что страница загружена по HTTPS или с localhost." } } diff --git a/plugins/docker/locales/translated/sr_SP.json b/plugins/docker/locales/translated/sr_SP.json index c545b4218..d2695248b 100644 --- a/plugins/docker/locales/translated/sr_SP.json +++ b/plugins/docker/locales/translated/sr_SP.json @@ -114,5 +114,17 @@ "podman": "Подман" } } + }, + "errors": { + "remoteServerRequired": "Потребан је удаљени сервер. Повежите се са удаљеним сервером у Подешавањима да бисте користили овај тип везе." + }, + "hosts": { + "docsLink": "Прикажи документе", + "hostNotFound": "Хост није пронађен", + "loadingHost": "Учитавање хоста..." + }, + "terminal": { + "clipboardReadFailed": "Читање из међуспремника није успело. Уверите се да су дозволе за међуспремник одобрене.", + "clipboardWriteFailed": "Копирање у међуспремник није успело. Уверите се да се страница приказује преко HTTPS-а или localhost-а." } } diff --git a/plugins/docker/locales/translated/sv_SE.json b/plugins/docker/locales/translated/sv_SE.json index b79586510..302c82793 100644 --- a/plugins/docker/locales/translated/sv_SE.json +++ b/plugins/docker/locales/translated/sv_SE.json @@ -114,5 +114,17 @@ "podman": "Podman" } } + }, + "errors": { + "remoteServerRequired": "Fjärrserver krävs. Anslut en fjärrserver i Inställningar för att använda den här anslutningstypen." + }, + "hosts": { + "docsLink": "Visa dokument", + "hostNotFound": "Värden hittades inte", + "loadingHost": "Laddar värd..." + }, + "terminal": { + "clipboardReadFailed": "Kunde inte läsa från urklipp. Kontrollera att behörigheter för urklipp är beviljade.", + "clipboardWriteFailed": "Kunde inte kopiera till urklipp. Kontrollera att sidan serveras via HTTPS eller localhost." } } diff --git a/plugins/docker/locales/translated/th_TH.json b/plugins/docker/locales/translated/th_TH.json index aa2863717..84e8edc11 100644 --- a/plugins/docker/locales/translated/th_TH.json +++ b/plugins/docker/locales/translated/th_TH.json @@ -114,5 +114,17 @@ "podman": "พอดแมน" } } + }, + "errors": { + "remoteServerRequired": "จำเป็นต้องใช้เซิร์ฟเวอร์ระยะไกล เชื่อมต่อเซิร์ฟเวอร์ระยะไกลในการตั้งค่าเพื่อใช้ประเภทการเชื่อมต่อนี้" + }, + "hosts": { + "docsLink": "ดูเอกสาร", + "hostNotFound": "ไม่พบโฮสต์", + "loadingHost": "กำลังโหลดโฮสต์..." + }, + "terminal": { + "clipboardReadFailed": "ไม่สามารถอ่านข้อมูลจากคลิปบอร์ดได้ โปรดตรวจสอบให้แน่ใจว่าได้ให้สิทธิ์การเข้าถึงคลิปบอร์ดแล้ว", + "clipboardWriteFailed": "ไม่สามารถคัดลอกไปยังคลิปบอร์ดได้ โปรดตรวจสอบให้แน่ใจว่าหน้าเว็บนั้นให้บริการผ่าน HTTPS หรือ localhost" } } diff --git a/plugins/docker/locales/translated/tr_TR.json b/plugins/docker/locales/translated/tr_TR.json index 09c7db79a..7a9eff0eb 100644 --- a/plugins/docker/locales/translated/tr_TR.json +++ b/plugins/docker/locales/translated/tr_TR.json @@ -114,5 +114,17 @@ "podman": "Podman" } } + }, + "errors": { + "remoteServerRequired": "Uzak sunucu gereklidir. Bu bağlantı türünü kullanmak için Ayarlar'dan bir uzak sunucu bağlayın." + }, + "hosts": { + "docsLink": "Dokümanları görüntüle", + "hostNotFound": "Host bulunamadı", + "loadingHost": "Host yükleniyor..." + }, + "terminal": { + "clipboardReadFailed": "Panodan okuma başarısız oldu. Pano izinlerinin verildiğinden emin olun.", + "clipboardWriteFailed": "Panoya kopyalama başarısız oldu. Sayfanın HTTPS veya localhost üzerinden sunulduğundan emin olun." } } diff --git a/plugins/docker/locales/translated/uk_UA.json b/plugins/docker/locales/translated/uk_UA.json index 940c27fb3..d7c3488b9 100644 --- a/plugins/docker/locales/translated/uk_UA.json +++ b/plugins/docker/locales/translated/uk_UA.json @@ -114,5 +114,17 @@ "podman": "Подман" } } + }, + "errors": { + "remoteServerRequired": "Потрібен віддалений сервер. Підключіться до віддаленого сервера в налаштуваннях, щоб використовувати цей тип підключення." + }, + "hosts": { + "docsLink": "Переглянути документи", + "hostNotFound": "Хост не знайдено", + "loadingHost": "Завантаження хоста..." + }, + "terminal": { + "clipboardReadFailed": "Не вдалося прочитати з буфера обміну. Переконайтеся, що надано дозволи на доступ до буфера обміну.", + "clipboardWriteFailed": "Не вдалося скопіювати в буфер обміну. Переконайтеся, що сторінка обслуговується через HTTPS або localhost." } } diff --git a/plugins/docker/locales/translated/vi_VN.json b/plugins/docker/locales/translated/vi_VN.json index 015f456cd..9f8815520 100644 --- a/plugins/docker/locales/translated/vi_VN.json +++ b/plugins/docker/locales/translated/vi_VN.json @@ -114,5 +114,17 @@ "podman": "Podman" } } + }, + "errors": { + "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." + }, + "hosts": { + "docsLink": "Xem tài liệu", + "hostNotFound": "Không tìm thấy máy chủ", + "loadingHost": "Đang tải máy chủ..." + }, + "terminal": { + "clipboardReadFailed": "Đọc từ clipboard thất bại. Đảm bảo quyền truy cập clipboard đã được cấp.", + "clipboardWriteFailed": "Sao chép vào clipboard thất bại. Đảm bảo trang được phục vụ qua HTTPS hoặc localhost." } } diff --git a/plugins/docker/locales/translated/zh_CN.json b/plugins/docker/locales/translated/zh_CN.json index f7bb97f76..172869aac 100644 --- a/plugins/docker/locales/translated/zh_CN.json +++ b/plugins/docker/locales/translated/zh_CN.json @@ -114,5 +114,17 @@ "podman": "Podman" } } + }, + "errors": { + "remoteServerRequired": "需要远程服务器。请在“设置”中连接远程服务器以使用此连接类型。" + }, + "hosts": { + "docsLink": "查看文档", + "hostNotFound": "未找到主机", + "loadingHost": "正在加载主机..." + }, + "terminal": { + "clipboardReadFailed": "从剪贴板读取失败。请确保已授予剪贴板权限。", + "clipboardWriteFailed": "复制到剪贴板失败。请确保页面通过 HTTPS 或 localhost 提供服务。" } } diff --git a/plugins/docker/locales/translated/zh_TW.json b/plugins/docker/locales/translated/zh_TW.json index 7e35542c0..e2f68d5c7 100644 --- a/plugins/docker/locales/translated/zh_TW.json +++ b/plugins/docker/locales/translated/zh_TW.json @@ -114,5 +114,17 @@ "podman": "Podman" } } + }, + "errors": { + "remoteServerRequired": "需要遠端伺服器。請在「設定」中連接遠端伺服器以使用此連線類型。" + }, + "hosts": { + "docsLink": "檢視文件", + "hostNotFound": "找不到主機", + "loadingHost": "正在載入主機..." + }, + "terminal": { + "clipboardReadFailed": "從剪貼簿讀取失敗。請確認已授予剪貼簿權限。", + "clipboardWriteFailed": "複製到剪貼簿失敗。請確認頁面是透過 HTTPS 或 localhost 提供。" } } diff --git a/plugins/docker/src/frontend/DockerApp.tsx b/plugins/docker/src/frontend/DockerApp.tsx index fda68d35d..91cabc614 100644 --- a/plugins/docker/src/frontend/DockerApp.tsx +++ b/plugins/docker/src/frontend/DockerApp.tsx @@ -2,7 +2,7 @@ import { ConnectionScreen, FullScreenAppWrapper } from "@termix/plugin-sdk/ui"; import React from "react"; import { useTranslation } from "@termix/plugin-sdk/frontend"; import { DockerManager } from "./DockerManager.tsx"; -import { toDockerHost } from "./types"; +import { toDockerHost, type DockerHostSource } from "./types"; interface DockerAppProps { hostId?: string; @@ -37,9 +37,7 @@ const DockerApp: React.FC = ({ hostId }) => { return ( , - )} + host={toDockerHost(hostConfig as unknown as DockerHostSource)} title={hostConfig.name || `${hostConfig.username}@${hostConfig.ip}`} isVisible={true} isTopbarOpen={false} diff --git a/plugins/docker/src/frontend/DockerManager.tsx b/plugins/docker/src/frontend/DockerManager.tsx index 0f6ac0071..cdcf1483c 100644 --- a/plugins/docker/src/frontend/DockerManager.tsx +++ b/plugins/docker/src/frontend/DockerManager.tsx @@ -90,10 +90,7 @@ function DockerManagerInner({ // standalone window has no shell, so it keeps the host it was given. const liveRecord = useHost(host?.id); const currentHost = React.useMemo( - () => - liveRecord - ? toDockerHost(liveRecord as unknown as Record) - : host, + () => (liveRecord ? toDockerHost(liveRecord) : host), [liveRecord, host], ); const enabled = dockerEnabled(currentHost); diff --git a/plugins/docker/src/frontend/DockerWidget.tsx b/plugins/docker/src/frontend/DockerWidget.tsx index 46e584122..0098d6a8a 100644 --- a/plugins/docker/src/frontend/DockerWidget.tsx +++ b/plugins/docker/src/frontend/DockerWidget.tsx @@ -27,7 +27,7 @@ function DockerWidget({ ); } - const host = toDockerHost(record as unknown as Record); + const host = toDockerHost(record); return (
} /> diff --git a/plugins/docker/src/frontend/index.tsx b/plugins/docker/src/frontend/index.tsx index 1e192ecc1..a74c64eb2 100644 --- a/plugins/docker/src/frontend/index.tsx +++ b/plugins/docker/src/frontend/index.tsx @@ -9,10 +9,10 @@ import type { import { DockerManager } from "./DockerManager"; import DockerApp from "./DockerApp"; import { dockerWidget } from "./DockerWidget"; -import { dockerEnabled, toDockerHost } from "./types"; +import { dockerEnabled, toDockerHost, type DockerHostSource } from "./types"; function DockerTab({ host, sshHost, label, isVisible }: TabProps) { - const record = (host ?? sshHost) as Record | undefined; + const record = host ?? (sshHost as DockerHostSource | undefined); return ( | undefined>; } +/** The fields toDockerHost reads from a shell or API host. */ +export type DockerHostSource = Omit & { + id: string | number; + name?: string | null; +}; + /** Any host record the shell or an API hands over, as a DockerHost. */ -export function toDockerHost(record: Record): DockerHost { +export function toDockerHost(record: DockerHostSource): DockerHost { return { - ...(record as unknown as DockerHost), id: Number(record.id), + name: record.name ?? undefined, + ip: record.ip, + port: record.port, + username: record.username, + syncId: record.syncId ?? null, + connectionOrigin: record.connectionOrigin ?? null, + pluginSettings: record.pluginSettings, }; } diff --git a/plugins/file-manager/locales/en.json b/plugins/file-manager/locales/en.json index 45d34e7ac..de40398c6 100644 --- a/plugins/file-manager/locales/en.json +++ b/plugins/file-manager/locales/en.json @@ -360,7 +360,15 @@ "cannotLoadPdf": "Cannot load PDF", "pdfLoadError": "There was an error loading this PDF file.", "loadingPdf": "Loading PDF...", - "loadingPage": "Loading page..." + "loadingPage": "Loading page...", + "cancel": "Cancel", + "copiedItems_one": "Copied {{count}} item", + "copiedItems_other": "Copied {{count}} items", + "deleteCopiedFileFailed": "Could not delete the copy of {{name}}: {{error}}", + "dragMovedItems_one": "Moved {{count}} item to {{target}}", + "dragMovedItems_other": "Moved {{count}} items to {{target}}", + "moveBackFileFailed": "Could not move {{name}} back: {{error}}", + "terminal": "Terminal: {{host}} ({{path}})" }, "sftpTransfer": { "title": "SFTP", @@ -409,6 +417,109 @@ "hosts": { "fileManager": "File Manager", "fileManagerUrlCopied": "File Manager URL copied", - "copyFileManagerUrlAction": "Copy File Manager URL" + "copyFileManagerUrlAction": "Copy File Manager URL", + "docsLink": "View docs", + "hostNotFound": "Host not found", + "loadingHost": "Loading host..." + }, + "onboarding": { + "feature_files": "File manager", + "feature_files_desc": "Browse, upload, download and edit files over SFTP without leaving the app." + }, + "terminal": { + "runTitle": "Running {{command}} - {{host}}", + "terminalTitle": "Terminal - {{host}}", + "terminalWithPath": "Terminal - {{host}}:{{path}}" + }, + "transfer": { + "browseFolders": "Browse destination folders", + "browsePathError": "Could not open this path on the destination host.", + "browsePathWillBeCreated": "This folder does not exist yet. It will be created when the transfer starts.", + "cancel": "Cancel", + "cleanupDestFiles": "Clean up destination", + "cleanupDestFilesError": "Cleanup failed", + "cleanupDestFilesNothing": "Nothing to clean up on the destination", + "cleanupDestFilesPartial": "Some partial files could not be removed", + "cleanupDestFilesSuccess": "Removed partial files from the destination", + "confirmCopy": "Copy", + "confirmMove": "Move", + "copyFolderToHost": "Copy folder to host…", + "copyItemsToHost": "Copy {{count}} items to host…", + "copyToHost": "Copy to host…", + "destinationPath": "Destination path", + "destMustBeDirectory": "Destination must be a directory for multi-item transfers", + "goUp": "Go up", + "hostAuthRequired": "Authentication required — open File Manager on this host first", + "hostConnecting": "Connecting…", + "hostConnectionFailed": "Connection failed", + "hostDisconnected": "Not connected", + "hostReady": "Ready", + "itemsSummary": "{{count}} items", + "jumpHostLimitation": "Both hosts must be reachable from the Termix server. Direct host-to-host routing is not supported.", + "methodAuto": "Auto", + "methodAutoHint": "Picks tar or per-file SFTP based on file count, size, and compressibility. Single files always use streaming SFTP.", + "methodItemSftp": "Per-file SFTP", + "methodItemSftpHint": "Transfer each file individually over SFTP. Works on all hosts including Windows.", + "methodItemSftpLimitation": "Each file uses the same SFTP stream as a single-file copy, one after another. Progress is combined across all files, so the bar moves slowly during large files.", + "methodLabel": "Transfer method", + "methodPreviewError": "Could not preview transfer method. The server will still pick a method when you start.", + "methodPreviewLoading": "Calculating transfer method…", + "methodPreviewScanSummary": "{{fileCount}} files, {{totalSize}} total (scanned on source host).", + "methodPreviewWillUseItemSftp": "Will use: Per-file SFTP", + "methodPreviewWillUseTar": "Will use: Tar archive", + "methodReason": { + "user_item_sftp": "You chose per-file SFTP.", + "user_tar": "You chose tar archive.", + "tar_unavailable": "Tar is not available on one or both hosts — per-file SFTP will be used instead.", + "windows_host": "A Windows host is involved — tar is not used.", + "auto_multi_large": "Auto: multiple files including a large file ({{largestSize}}) with compressible data — tar bundles into one transfer.", + "auto_single_large_in_archive": "Auto: one large file ({{largestSize}}) in this set — per-file SFTP.", + "auto_many_incompressible": "Auto: mostly incompressible data — per-file SFTP.", + "auto_many_files": "Auto: many files ({{fileCount}}) — tar reduces per-file overhead.", + "auto_default": "Auto: per-file SFTP for this set." + }, + "methodTar": "Tar archive", + "methodTarHint": "Compress on source, transfer one archive, extract on destination. Requires tar on both Unix hosts.", + "metricsCompress": "Compress on source: {{duration}}", + "metricsExtract": "Extract on destination: {{duration}}", + "metricsPrepare": "Prepare destination: {{duration}}", + "metricsRouteBenchmark": "Route probe — direct: {{direct}}, relay: {{relay}}", + "metricsSourceDelete": "Remove from source: {{duration}}", + "metricsTotal": "Total: {{duration}}", + "metricsTransfer": "End-to-end: {{throughput}} ({{duration}})", + "metricsVerify": "SHA-256 verified: {{duration}}", + "moveFolderToHost": "Move folder to host…", + "moveItemsToHost": "Move {{count}} items to host…", + "moveToHost": "Move to host…", + "noHostsConnected": "No other file-manager hosts available.", + "noHostsConnectedHint": "Add another SSH host with File Manager enabled in Host Manager.", + "parallelSegmentsHint": "Large files are split into 256 MB chunks. Multiple lanes use separate connections (like starting several transfers) for higher total throughput.", + "parallelSegmentsLabel": "Parallel transfer lanes", + "parallelSegmentsOption": "{{count}} lanes", + "progressBenchmarking": "Selecting the fastest transfer route…", + "progressBytes": "{{transferred}} / {{total}}", + "progressCancel": "Cancel", + "progressCancelling": "Cancelling…", + "progressCompressing": "Compressing on source host…", + "progressExtracting": "Extracting on destination…", + "progressItems": "{{current}} / {{total}} files", + "progressReconnecting": "Reconnecting…", + "progressStalled": "Stalled", + "progressTotalSpeed": "{{speed}} total ({{lanes}} lanes)", + "progressTransferring": "Transferring data…", + "progressTransferringItems": "Transferring files ({{current}} of {{total}})…", + "progressVerifying": "Verifying file integrity…", + "recentDestinations": "Recent destinations", + "resumedHint": "Reconnected to an active transfer started in another window.", + "retryTransfer": "Retry", + "retryTransferError": "Retry failed", + "selectDestinationHost": "Select destination host", + "transferCancelled": "Transfer cancelled", + "transferCancelledCopyHint": "Partial files may remain on the destination.", + "transferCancelledMoveHint": "Partial files may remain on the destination. Source files were not removed.", + "transferError": "Transfer failed", + "transferFailedRetryHint": "Partial data was kept on the destination. Retry will resume when the connection is back.", + "transferPartialHint": "Could not transfer: {{paths}}", + "transferSuccess": "Transfer complete" } } diff --git a/plugins/file-manager/locales/translated/af_ZA.json b/plugins/file-manager/locales/translated/af_ZA.json index a7a6da613..fd4079049 100644 --- a/plugins/file-manager/locales/translated/af_ZA.json +++ b/plugins/file-manager/locales/translated/af_ZA.json @@ -382,7 +382,10 @@ "defaultPathLabel": "Standaardpad", "fileManagerPathHint": "Die gids om oop te maak wanneer die lêerbestuurder vir hierdie gasheer begin.", "fileManagerUrlCopied": "Lêerbestuurder-URL gekopieer", - "copyFileManagerUrlAction": "Kopieer Lêerbestuurder URL" + "copyFileManagerUrlAction": "Kopieer Lêerbestuurder URL", + "docsLink": "Bekyk dokumente", + "hostNotFound": "Gasheer nie gevind nie", + "loadingHost": "Laai gasheer..." }, "settings": { "host": { @@ -406,5 +409,105 @@ "nav": { "sftp": "SFTP", "files": "Lêers" + }, + "onboarding": { + "feature_files": "Lêerbestuurder", + "feature_files_desc": "Blaai, laai op, laai af en wysig lêers via SFTP sonder om die toepassing te verlaat." + }, + "terminal": { + "runTitle": "Hardloop {{command}} - {{host}}", + "terminalTitle": "Terminaal - {{host}}", + "terminalWithPath": "Terminaal - {{host}}:{{path}}" + }, + "transfer": { + "browseFolders": "Blaai deur bestemmingsmappe", + "browsePathError": "Kon nie hierdie pad op die bestemmingsgasheer oopmaak nie.", + "browsePathWillBeCreated": "Hierdie vouer bestaan nog nie. Dit sal geskep word wanneer die oordrag begin.", + "cancel": "Kanselleer", + "cleanupDestFiles": "Maak bestemming skoon", + "cleanupDestFilesError": "Opruiming het misluk", + "cleanupDestFilesNothing": "Niks om op die bestemming op te ruim nie", + "cleanupDestFilesPartial": "Sommige gedeeltelike lêers kon nie verwyder word nie", + "cleanupDestFilesSuccess": "Gedeeltelike lêers van die bestemming verwyder", + "confirmCopy": "Kopieer", + "confirmMove": "Beweeg", + "copyFolderToHost": "Kopieer lêergids na gasheer…", + "copyItemsToHost": "Kopieer {{count}} items om… aan te bied", + "copyToHost": "Kopieer na gasheer…", + "destinationPath": "Bestemmingspad", + "destMustBeDirectory": "Bestemming moet 'n gids wees vir oordragte van verskeie items", + "goUp": "Gaan op", + "hostAuthRequired": "Verifikasie vereis — maak eers Lêerbestuurder op hierdie gasheer oop", + "hostConnecting": "Verbind…", + "hostConnectionFailed": "Verbinding het misluk", + "hostDisconnected": "Nie gekoppel nie", + "hostReady": "Gereed", + "itemsSummary": "{{count}} items", + "jumpHostLimitation": "Beide gashere moet vanaf die Termix-bediener bereikbaar wees. Direkte gasheer-tot-gasheer-roetering word nie ondersteun nie.", + "methodAuto": "Outomaties", + "methodAutoHint": "Kies tar- of per-lêer SFTP gebaseer op lêertelling, grootte en saampersbaarheid. Enkele lêers gebruik altyd stroom-SFTP.", + "methodItemSftp": "SFTP per lêer", + "methodItemSftpHint": "Dra elke lêer individueel oor SFTP. Werk op alle gashere, insluitend Windows.", + "methodItemSftpLimitation": "Elke lêer gebruik dieselfde SFTP-stroom as 'n enkellêerkopie, een na die ander. Vordering word oor alle lêers gekombineer, so die balk beweeg stadig tydens groot lêers.", + "methodLabel": "Oordragmetode", + "methodPreviewError": "Kon nie oordragmetode voorskou nie. Die bediener sal steeds 'n metode kies wanneer jy begin.", + "methodPreviewLoading": "Berekening van oordragmetode…", + "methodPreviewScanSummary": "{{fileCount}} lêers, {{totalSize}} totaal (geskandeer op brongasheer).", + "methodPreviewWillUseItemSftp": "Sal gebruik: SFTP per lêer", + "methodPreviewWillUseTar": "Sal gebruik: Tar-argief", + "methodReason": { + "user_item_sftp": "Jy het SFTP per lêer gekies.", + "user_tar": "Jy het teer-argief gekies.", + "tar_unavailable": "Teer is nie beskikbaar op een of albei gashere nie — SFTP per lêer sal eerder gebruik word.", + "windows_host": "'n Windows-gasheer is betrokke — teer word nie gebruik nie.", + "auto_multi_large": "Outomaties: veelvuldige lêers, insluitend 'n groot lêer ({{largestSize}}) met saampersbare data — teer bundels in een oordrag.", + "auto_single_large_in_archive": "Outomaties: een groot lêer ({{largestSize}}) in hierdie stel — SFTP per lêer.", + "auto_many_incompressible": "Outomaties: meestal onsaampersbare data — SFTP per lêer.", + "auto_many_files": "Outomaties: baie lêers ({{fileCount}}) — teer verminder oorhoofse koste per lêer.", + "auto_default": "Outomaties: SFTP per lêer vir hierdie stel." + }, + "methodTar": "Teer-argief", + "methodTarHint": "Komprimeer op bron, dra een argief oor, onttrek op bestemming. Vereis tar op beide Unix-gashere.", + "metricsCompress": "Kompresseer op bron: {{duration}}", + "metricsExtract": "Uittreksel op bestemming: {{duration}}", + "metricsPrepare": "Berei bestemming voor: {{duration}}", + "metricsRouteBenchmark": "Roete-sonde — direk: {{direct}}, aflos: {{relay}}", + "metricsSourceDelete": "Verwyder van bron: {{duration}}", + "metricsTotal": "Totaal: {{duration}}", + "metricsTransfer": "Van begin tot einde: {{throughput}} ({{duration}})", + "metricsVerify": "SHA-256 geverifieer: {{duration}}", + "moveFolderToHost": "Skuif vouer na gasheer…", + "moveItemsToHost": "Skuif {{count}} items om… te huisves", + "moveToHost": "Skuif na gasheer…", + "noHostsConnected": "Geen ander lêerbestuurder-gashere beskikbaar nie.", + "noHostsConnectedHint": "Voeg nog 'n SSH-gasheer by met Lêerbestuurder geaktiveer in Gasheerbestuurder.", + "parallelSegmentsHint": "Groot lêers word in 256 MB-stukke verdeel. Verskeie bane gebruik afsonderlike verbindings (soos om verskeie oordragte te begin) vir hoër totale deurset.", + "parallelSegmentsLabel": "Parallelle oordragbane", + "parallelSegmentsOption": "{{count}} bane", + "progressBenchmarking": "Die vinnigste oordragroete kies…", + "progressBytes": "{{transferred}} / {{total}}", + "progressCancel": "Kanselleer", + "progressCancelling": "Kanselleer…", + "progressCompressing": "Kompressering op brongasheer…", + "progressExtracting": "Onttrek op bestemming…", + "progressItems": "{{current}} / {{total}} lêers", + "progressReconnecting": "Herverbind…", + "progressStalled": "Vasgevang", + "progressTotalSpeed": "{{speed}} totaal ({{lanes}} bane)", + "progressTransferring": "Oordrag van data…", + "progressTransferringItems": "Oordrag van lêers ({{current}} van {{total}})…", + "progressVerifying": "Verifieer lêerintegriteit…", + "recentDestinations": "Onlangse bestemmings", + "resumedHint": "Herverbind met 'n aktiewe oordrag wat in 'n ander venster begin is.", + "retryTransfer": "Probeer weer", + "retryTransferError": "Herprobeer het misluk", + "selectDestinationHost": "Kies bestemmingsgasheer", + "transferCancelled": "Oordrag gekanselleer", + "transferCancelledCopyHint": "Gedeeltelike lêers mag dalk op die bestemming bly.", + "transferCancelledMoveHint": "Gedeeltelike lêers mag dalk op die bestemming bly. Bronlêers is nie verwyder nie.", + "transferError": "Oordrag het misluk", + "transferFailedRetryHint": "Gedeeltelike data is op die bestemming gehou. Herprobeer sal hervat word wanneer die verbinding terug is.", + "transferPartialHint": "Kon nie oordra nie: {{paths}}", + "transferSuccess": "Oordrag voltooi" } } diff --git a/plugins/file-manager/locales/translated/ar_SA.json b/plugins/file-manager/locales/translated/ar_SA.json index cdf3acb14..2cd51f5fc 100644 --- a/plugins/file-manager/locales/translated/ar_SA.json +++ b/plugins/file-manager/locales/translated/ar_SA.json @@ -382,7 +382,10 @@ "defaultPathLabel": "المسار الافتراضي", "fileManagerPathHint": "الدليل الذي سيتم فتحه عند تشغيل مدير الملفات لهذا المضيف.", "fileManagerUrlCopied": "تم نسخ رابط مدير الملفات", - "copyFileManagerUrlAction": "نسخ رابط مدير الملفات" + "copyFileManagerUrlAction": "نسخ رابط مدير الملفات", + "docsLink": "عرض المستندات", + "hostNotFound": "المضيف غير موجود", + "loadingHost": "جارٍ تحميل المضيف..." }, "settings": { "host": { @@ -406,5 +409,105 @@ "nav": { "sftp": "SFTP", "files": "الملفات" + }, + "onboarding": { + "feature_files": "مدير الملفات", + "feature_files_desc": "تصفح الملفات وقم بتحميلها وتنزيلها وتعديلها عبر بروتوكول SFTP دون مغادرة التطبيق." + }, + "terminal": { + "runTitle": "تشغيل {{command}} - {{host}}", + "terminalTitle": "الطرفية - {{host}}", + "terminalWithPath": "الطرفية - {{host}}:{{path}}" + }, + "transfer": { + "browseFolders": "تصفح مجلدات الوجهة", + "browsePathError": "تعذر فتح هذا المسار على المضيف الوجهة.", + "browsePathWillBeCreated": "هذا المجلد غير موجود بعد. سيتم إنشاؤه عند بدء النقل.", + "cancel": "إلغاء", + "cleanupDestFiles": "تنظيف الوجهة", + "cleanupDestFilesError": "فشل التنظيف", + "cleanupDestFilesNothing": "لا شيء للتنظيف على الوجهة", + "cleanupDestFilesPartial": "تعذر إزالة بعض الملفات الجزئية", + "cleanupDestFilesSuccess": "تمت إزالة الملفات الجزئية من الوجهة", + "confirmCopy": "نسخ", + "confirmMove": "نقل", + "copyFolderToHost": "نسخ المجلد إلى المضيف…", + "copyItemsToHost": "نسخ {{count}} عناصر إلى المضيف…", + "copyToHost": "نسخ إلى المضيف…", + "destinationPath": "مسار الوجهة", + "destMustBeDirectory": "يجب أن تكون الوجهة مجلدًا لنقل عناصر متعددة", + "goUp": "للأعلى", + "hostAuthRequired": "المصادقة مطلوبة — افتح مدير الملفات على هذا المضيف أولاً", + "hostConnecting": "جارٍ الاتصال…", + "hostConnectionFailed": "فشل الاتصال", + "hostDisconnected": "غير متصل", + "hostReady": "جاهز", + "itemsSummary": "{{count}} عنصر", + "jumpHostLimitation": "يجب أن يكون كلا المضيفين قابلين للوصول من خادم Termix. التوجيه المباشر من مضيف إلى مضيف غير مدعوم.", + "methodAuto": "تلقائي", + "methodAutoHint": "يختار tar أو SFTP لكل ملف بناءً على عدد الملفات وحجمها وقابلية الضغط. الملفات المفردة تستخدم دائمًا SFTP التدفقي.", + "methodItemSftp": "SFTP لكل ملف", + "methodItemSftpHint": "نقل كل ملف على حدة عبر SFTP. يعمل على جميع المضيفين بما في ذلك Windows.", + "methodItemSftpLimitation": "يستخدم كل ملف نفس تدفق SFTP كنسخ الملف الواحد، واحداً تلو الآخر. يُجمع التقدم عبر جميع الملفات، لذا يتحرك الشريط ببطء أثناء الملفات الكبيرة.", + "methodLabel": "طريقة النقل", + "methodPreviewError": "تعذّر معاينة طريقة النقل. سيختار الخادم طريقة عند بدء النقل.", + "methodPreviewLoading": "جارٍ حساب طريقة النقل…", + "methodPreviewScanSummary": "{{fileCount}} ملفات، {{totalSize}} إجمالي (تم المسح على المضيف المصدر).", + "methodPreviewWillUseItemSftp": "سيُستخدم: SFTP لكل ملف", + "methodPreviewWillUseTar": "سيُستخدم: أرشيف Tar", + "methodReason": { + "user_item_sftp": "اخترت SFTP لكل ملف.", + "user_tar": "اخترت أرشيف tar.", + "tar_unavailable": "tar غير متوفر على أحد المضيفين أو كليهما — سيُستخدم SFTP لكل ملف بدلاً من ذلك.", + "windows_host": "يوجد مضيف Windows — لا يُستخدم tar.", + "auto_multi_large": "تلقائي: عدة ملفات بما فيها ملف كبير ({{largestSize}}) ببيانات قابلة للضغط — يجمعها tar في حزمة واحدة.", + "auto_single_large_in_archive": "تلقائي: ملف كبير واحد ({{largestSize}}) في هذه المجموعة — SFTP لكل ملف.", + "auto_many_incompressible": "تلقائي: البيانات غالبًا غير قابلة للضغط — SFTP لكل ملف.", + "auto_many_files": "تلقائي: عدة ملفات ({{fileCount}}) — يقلل tar الحمل لكل ملف.", + "auto_default": "تلقائي: SFTP لكل ملف لهذه المجموعة." + }, + "methodTar": "أرشيف Tar", + "methodTarHint": "ضغط على المصدر، نقل أرشيف واحد، فك على الوجهة. يتطلب tar على كلا المضيفين Unix.", + "metricsCompress": "ضغط على المصدر: {{duration}}", + "metricsExtract": "فك على الوجهة: {{duration}}", + "metricsPrepare": "تحضير الوجهة: {{duration}}", + "metricsRouteBenchmark": "مسبار المسار — مباشر: {{direct}}، مرحل: {{relay}}", + "metricsSourceDelete": "إزالة من المصدر: {{duration}}", + "metricsTotal": "الإجمالي: {{duration}}", + "metricsTransfer": "نقل شامل: {{throughput}} ({{duration}})", + "metricsVerify": "تم التحقق من SHA-256: {{duration}}", + "moveFolderToHost": "نقل المجلد إلى المضيف…", + "moveItemsToHost": "نقل {{count}} عناصر إلى المضيف…", + "moveToHost": "نقل إلى المضيف…", + "noHostsConnected": "لا تتوفر مضيفات أخرى لمدير الملفات.", + "noHostsConnectedHint": "أضف مضيف SSH آخر مع تمكين مدير الملفات في مدير المضيفات.", + "parallelSegmentsHint": "تُقسم الملفات الكبيرة إلى أجزاء بحجم 256 ميغابايت. تستخدم المسارات المتعددة اتصالات منفصلة (مثل بدء عدة عمليات نقل) لتحقيق إنتاجية إجمالية أعلى.", + "parallelSegmentsLabel": "مسارات النقل المتوازية", + "parallelSegmentsOption": "{{count}} مسارات", + "progressBenchmarking": "اختيار أسرع مسار نقل…", + "progressBytes": "{{transferred}} / {{total}}", + "progressCancel": "إلغاء", + "progressCancelling": "جارٍ الإلغاء…", + "progressCompressing": "جارٍ الضغط على المضيف المصدر…", + "progressExtracting": "جارٍ الفك على الوجهة…", + "progressItems": "{{current}} / {{total}} ملفات", + "progressReconnecting": "جارٍ إعادة الاتصال…", + "progressStalled": "متوقف", + "progressTotalSpeed": "{{speed}} إجمالي ({{lanes}} مسارات)", + "progressTransferring": "جارٍ نقل البيانات…", + "progressTransferringItems": "جارٍ نقل الملفات ({{current}} من {{total}})…", + "progressVerifying": "التحقق من سلامة الملف…", + "recentDestinations": "الوجهات الأخيرة", + "resumedHint": "تمت إعادة الاتصال بنقل نشط بدأ في نافذة أخرى.", + "retryTransfer": "إعادة المحاولة", + "retryTransferError": "فشلت إعادة المحاولة", + "selectDestinationHost": "تحديد المضيف الوجهة", + "transferCancelled": "تم إلغاء النقل", + "transferCancelledCopyHint": "قد تبقى ملفات جزئية على الوجهة.", + "transferCancelledMoveHint": "قد تبقى ملفات جزئية على الوجهة. لم يتم حذف ملفات المصدر.", + "transferError": "فشل النقل", + "transferFailedRetryHint": "تم الاحتفاظ بالبيانات الجزئية على الوجهة. ستُستأنف إعادة المحاولة عند عودة الاتصال.", + "transferPartialHint": "تعذر النقل: {{paths}}", + "transferSuccess": "اكتمل النقل" } } diff --git a/plugins/file-manager/locales/translated/bg_BG.json b/plugins/file-manager/locales/translated/bg_BG.json index 81bff1eb1..de720cbf0 100644 --- a/plugins/file-manager/locales/translated/bg_BG.json +++ b/plugins/file-manager/locales/translated/bg_BG.json @@ -382,7 +382,10 @@ "defaultPathLabel": "Път по подразбиране", "fileManagerPathHint": "Директорията, която да се отвори при стартиране на файловия мениджър за този хост.", "fileManagerUrlCopied": "URL адресът на файловия мениджър е копиран", - "copyFileManagerUrlAction": "Копиране на URL адреса на файловия мениджър" + "copyFileManagerUrlAction": "Копиране на URL адреса на файловия мениджър", + "docsLink": "Преглед на документи", + "hostNotFound": "Хостът не е намерен", + "loadingHost": "Зареждане на хоста..." }, "settings": { "host": { @@ -406,5 +409,105 @@ "nav": { "sftp": "SFTP", "files": "Файлове" + }, + "onboarding": { + "feature_files": "Файлов мениджър", + "feature_files_desc": "Преглеждайте, качвайте, изтегляйте и редактирайте файлове през SFTP, без да напускате приложението." + }, + "terminal": { + "runTitle": "Изпълнява се {{command}} - {{host}}", + "terminalTitle": "Терминал - {{host}}", + "terminalWithPath": "Терминал - {{host}}:{{path}}" + }, + "transfer": { + "browseFolders": "Преглед на целевите папки", + "browsePathError": "Не можа да се отвори този път на целевия хост.", + "browsePathWillBeCreated": "Тази папка все още не съществува. Тя ще бъде създадена, когато започне прехвърлянето.", + "cancel": "Отказ", + "cleanupDestFiles": "Почистване на дестинацията", + "cleanupDestFilesError": "Почистването не бе успешно", + "cleanupDestFilesNothing": "Няма нищо за почистване на дестинацията", + "cleanupDestFilesPartial": "Някои частични файлове не можаха да бъдат премахнати", + "cleanupDestFilesSuccess": "Премахнати частични файлове от местоназначението", + "confirmCopy": "Копиране", + "confirmMove": "Преместване", + "copyFolderToHost": "Копиране на папката на хост…", + "copyItemsToHost": "Копиране на {{count}} елементи за хостване на…", + "copyToHost": "Копиране към хост…", + "destinationPath": "Път на местоназначението", + "destMustBeDirectory": "Дестинацията трябва да е директория за прехвърляне на множество елементи", + "goUp": "Качи се нагоре", + "hostAuthRequired": "Изисква се удостоверяване — първо отворете Файловия мениджър на този хост", + "hostConnecting": "Свързване…", + "hostConnectionFailed": "Връзката не бе успешна", + "hostDisconnected": "Няма връзка", + "hostReady": "Готов", + "itemsSummary": "{{count}} артикули", + "jumpHostLimitation": "И двата хоста трябва да са достъпни от Termix сървъра. Директното маршрутизиране от хост към хост не се поддържа.", + "methodAuto": "Автоматично", + "methodAutoHint": "Избира tar или SFTP за всеки файл въз основа на броя, размера и компресируемостта на файловете. Отделните файлове винаги използват стрийминг SFTP.", + "methodItemSftp": "SFTP за всеки файл", + "methodItemSftpHint": "Прехвърляйте всеки файл поотделно през SFTP. Работи на всички хостове, включително Windows.", + "methodItemSftpLimitation": "Всеки файл използва същия SFTP поток като копие на един файл, следвани един след друг. Напредъкът се комбинира във всички файлове, така че лентата се движи бавно при големи файлове.", + "methodLabel": "Метод на прехвърляне", + "methodPreviewError": "Не можа да се прегледа методът за прехвърляне. Сървърът все пак ще избере метод, когато стартирате.", + "methodPreviewLoading": "Метод за изчисляване на трансфер…", + "methodPreviewScanSummary": "{{fileCount}} файлове, {{totalSize}} общо (сканирани на изходния хост).", + "methodPreviewWillUseItemSftp": "Ще използва: SFTP за всеки файл", + "methodPreviewWillUseTar": "Ще използвам: Tar архив", + "methodReason": { + "user_item_sftp": "Избрали сте SFTP за всеки файл.", + "user_tar": "Избрахте tar архив.", + "tar_unavailable": "Tar не е наличен на единия или и на двата хоста — вместо това ще се използва SFTP за всеки файл.", + "windows_host": "Включен е хост на Windows — tar не се използва.", + "auto_multi_large": "Автоматично: множество файлове, включително голям файл ({{largestSize}}) със свиваеми данни — tar пакети в един трансфер.", + "auto_single_large_in_archive": "Автоматично: един голям файл ({{largestSize}}) в този набор — SFTP за всеки файл.", + "auto_many_incompressible": "Автоматично: предимно некомпресируеми данни — SFTP за всеки файл.", + "auto_many_files": "Автоматично: много файлове ({{fileCount}}) — tar намалява натоварването на всеки файл.", + "auto_default": "Автоматично: SFTP за всеки файл за този набор." + }, + "methodTar": "Тар архив", + "methodTarHint": "Компресиране при източника, прехвърляне на един архив, разархивиране при местоназначението. Изисква tar и на двата Unix хоста.", + "metricsCompress": "Компресиране при източника: {{duration}}", + "metricsExtract": "Извличане в местоназначението: {{duration}}", + "metricsPrepare": "Подготовка на дестинацията: {{duration}}", + "metricsRouteBenchmark": "Сонда за маршрут — директна: {{direct}}, релейна: {{relay}}", + "metricsSourceDelete": "Премахване от източника: {{duration}}", + "metricsTotal": "Общо: {{duration}}", + "metricsTransfer": "От край до край: {{throughput}} ({{duration}})", + "metricsVerify": "SHA-256 проверен: {{duration}}", + "moveFolderToHost": "Преместване на папката на хост…", + "moveItemsToHost": "Преместете {{count}} елементи, за да хоствате…", + "moveToHost": "Преместване към хост…", + "noHostsConnected": "Няма други налични хостове за файлови мениджъри.", + "noHostsConnectedHint": "Добавете друг SSH хост с активиран файлов мениджър в Host Manager.", + "parallelSegmentsHint": "Големите файлове се разделят на парчета от 256 MB. Няколко канала използват отделни връзки (като стартиране на няколко трансфера) за по-висока обща пропускателна способност.", + "parallelSegmentsLabel": "Паралелни трансферни ленти", + "parallelSegmentsOption": "{{count}} ленти", + "progressBenchmarking": "Избор на най-бързия маршрут за трансфер…", + "progressBytes": "{{transferred}} / {{total}}", + "progressCancel": "Отказ", + "progressCancelling": "Анулиране…", + "progressCompressing": "Компресиране на изходния хост…", + "progressExtracting": "Извличане в местоназначението…", + "progressItems": "{{current}} / {{total}} файлове", + "progressReconnecting": "Повторно свързване…", + "progressStalled": "Застоял", + "progressTotalSpeed": "{{speed}} общо ({{lanes}} ленти)", + "progressTransferring": "Прехвърляне на данни…", + "progressTransferringItems": "Прехвърляне на файлове ({{current}} от {{total}})…", + "progressVerifying": "Проверка на целостта на файла…", + "recentDestinations": "Последни дестинации", + "resumedHint": "Възстановена е връзка с активно прехвърляне, започнато в друг прозорец.", + "retryTransfer": "Опитай отново", + "retryTransferError": "Повторният опит не бе успешен", + "selectDestinationHost": "Изберете целеви хост", + "transferCancelled": "Прехвърлянето е анулирано", + "transferCancelledCopyHint": "Частични файлове може да останат в местоназначението.", + "transferCancelledMoveHint": "Възможно е част от файловете да са останали в местоназначението. Изходните файлове не са премахнати.", + "transferError": "Прехвърлянето не бе успешно", + "transferFailedRetryHint": "В местоназначението са запазени частични данни. Повторният опит ще се възобнови, когато връзката се възстанови.", + "transferPartialHint": "Не можа да се прехвърли: {{paths}}", + "transferSuccess": "Прехвърлянето е завършено" } } diff --git a/plugins/file-manager/locales/translated/bn_BD.json b/plugins/file-manager/locales/translated/bn_BD.json index 65c087a38..754a65353 100644 --- a/plugins/file-manager/locales/translated/bn_BD.json +++ b/plugins/file-manager/locales/translated/bn_BD.json @@ -382,7 +382,10 @@ "defaultPathLabel": "ডিফল্ট পথ", "fileManagerPathHint": "এই হোস্টের জন্য ফাইল ম্যানেজার চালু হলে যে ডিরেক্টরিটি খুলবে।", "fileManagerUrlCopied": "ফাইল ম্যানেজার ইউআরএল কপি করা হয়েছে", - "copyFileManagerUrlAction": "ফাইল ম্যানেজার ইউআরএল কপি করুন" + "copyFileManagerUrlAction": "ফাইল ম্যানেজার ইউআরএল কপি করুন", + "docsLink": "নথি দেখুন", + "hostNotFound": "হোস্ট খুঁজে পাওয়া যায়নি", + "loadingHost": "হোস্ট লোড হচ্ছে..." }, "settings": { "host": { @@ -406,5 +409,105 @@ "nav": { "sftp": "এসএফটিপি", "files": "ফাইল" + }, + "onboarding": { + "feature_files": "ফাইল ম্যানেজার", + "feature_files_desc": "অ্যাপ থেকে বের না হয়েই SFTP-এর মাধ্যমে ফাইল ব্রাউজ, আপলোড, ডাউনলোড এবং সম্পাদনা করুন।" + }, + "terminal": { + "runTitle": "দৌড়ানো {{command}} - {{host}}", + "terminalTitle": "টার্মিনাল - {{host}}", + "terminalWithPath": "টার্মিনাল - {{host}}:{{path}}" + }, + "transfer": { + "browseFolders": "গন্তব্য ফোল্ডারগুলি ব্রাউজ করুন", + "browsePathError": "গন্তব্য হোস্টে এই পাথটি খোলা সম্ভব হয়নি।", + "browsePathWillBeCreated": "এই ফোল্ডারটি এখনও তৈরি হয়নি। স্থানান্তর শুরু হলে এটি তৈরি হয়ে যাবে।", + "cancel": "বাতিল করুন", + "cleanupDestFiles": "পরিষ্কার করার গন্তব্য", + "cleanupDestFilesError": "পরিষ্কার করা ব্যর্থ হয়েছে", + "cleanupDestFilesNothing": "গন্তব্যে পরিষ্কার করার কিছু নেই।", + "cleanupDestFilesPartial": "কিছু আংশিক ফাইল সরানো যায়নি", + "cleanupDestFilesSuccess": "গন্তব্য থেকে আংশিক ফাইল সরানো হয়েছে", + "confirmCopy": "অনুলিপি", + "confirmMove": "স্থানান্তর", + "copyFolderToHost": "ফোল্ডারটি হোস্টে কপি করুন…", + "copyItemsToHost": "{{count}} টি আইটেম হোস্টে কপি করুন…", + "copyToHost": "হোস্টে কপি করুন…", + "destinationPath": "গন্তব্য পথ", + "destMustBeDirectory": "একাধিক আইটেম স্থানান্তরের জন্য গন্তব্য অবশ্যই একটি ডিরেক্টরি হতে হবে।", + "goUp": "উপরে যান", + "hostAuthRequired": "প্রমাণীকরণ আবশ্যক — প্রথমে এই হোস্টে ফাইল ম্যানেজার খুলুন।", + "hostConnecting": "… সংযোগ করা হচ্ছে", + "hostConnectionFailed": "সংযোগ ব্যর্থ হয়েছে", + "hostDisconnected": "সংযুক্ত নয়", + "hostReady": "প্রস্তুত", + "itemsSummary": "{{count}} আইটেম", + "jumpHostLimitation": "উভয় হোস্টকেই টারমিক্স সার্ভার থেকে পৌঁছানো সম্ভব হতে হবে। সরাসরি হোস্ট-টু-হোস্ট রাউটিং সমর্থিত নয়।", + "methodAuto": "অটো", + "methodAutoHint": "ফাইলের সংখ্যা, আকার এবং সংকোচনযোগ্যতার উপর ভিত্তি করে tar অথবা ফাইল-ভিত্তিক SFTP নির্বাচন করে। একক ফাইলের ক্ষেত্রে সর্বদা স্ট্রিমিং SFTP ব্যবহৃত হয়।", + "methodItemSftp": "প্রতি-ফাইল এসএফটিপি", + "methodItemSftpHint": "SFTP-এর মাধ্যমে প্রতিটি ফাইল আলাদাভাবে স্থানান্তর করুন। উইন্ডোজ সহ সকল হোস্টে কাজ করে।", + "methodItemSftpLimitation": "প্রতিটি ফাইল একই SFTP স্ট্রিম ব্যবহার করে একটির পর একটি একক-ফাইল কপি হিসেবে তৈরি হয়। সমস্ত ফাইলের অগ্রগতি একত্রিত করা হয়, তাই বড় ফাইলের ক্ষেত্রে বারটি ধীরে চলে।", + "methodLabel": "স্থানান্তর পদ্ধতি", + "methodPreviewError": "স্থানান্তর পদ্ধতির প্রিভিউ দেখা সম্ভব হয়নি। আপনি চালু করার সময় সার্ভার নিজেই একটি পদ্ধতি বেছে নেবে।", + "methodPreviewLoading": "স্থানান্তর পদ্ধতি গণনা করা হচ্ছে…", + "methodPreviewScanSummary": "{{fileCount}} টি ফাইল, {{totalSize}} টি মোট (উৎস হোস্টে স্ক্যান করা হয়েছে)।", + "methodPreviewWillUseItemSftp": "ব্যবহার করা হবে: প্রতি-ফাইল এসএফটিপি", + "methodPreviewWillUseTar": "ব্যবহৃত হবে: টার আর্কাইভ", + "methodReason": { + "user_item_sftp": "আপনি ফাইল-ভিত্তিক এসএফটিপি বেছে নিয়েছেন।", + "user_tar": "আপনি tar আর্কাইভটি বেছে নিয়েছেন।", + "tar_unavailable": "এক বা উভয় হোস্টে Tar উপলব্ধ না থাকায়, এর পরিবর্তে ফাইল-ভিত্তিক SFTP ব্যবহার করা হবে।", + "windows_host": "এখানে একটি উইন্ডোজ হোস্ট জড়িত — tar ব্যবহৃত হয় না।", + "auto_multi_large": "স্বয়ংক্রিয়: সংকোচনযোগ্য ডেটা সহ একটি বড় ফাইল ({{largestSize}}) সহ একাধিক ফাইল — tar বান্ডেল করে একটি একক স্থানান্তরে পাঠানো হয়।", + "auto_single_large_in_archive": "স্বয়ংক্রিয়: এই সেটে একটি বড় ফাইল ({{largestSize}}) — ফাইল-ভিত্তিক SFTP।", + "auto_many_incompressible": "স্বয়ংক্রিয়: প্রধানত অসংকোচনযোগ্য ডেটা — ফাইল-ভিত্তিক এসএফটিপি।", + "auto_many_files": "স্বয়ংক্রিয়: একাধিক ফাইল ({{fileCount}}) — tar প্রতি-ফাইল ওভারহেড কমায়।", + "auto_default": "স্বয়ংক্রিয়: এই সেটের জন্য প্রতি-ফাইল এসএফটিপি।" + }, + "methodTar": "টার আর্কাইভ", + "methodTarHint": "উৎসস্থলে কম্প্রেস করুন, একটি আর্কাইভ স্থানান্তর করুন, এবং গন্তব্যে এক্সট্র্যাক্ট করুন। উভয় ইউনিক্স হোস্টে tar প্রয়োজন।", + "metricsCompress": "উৎস থেকে সংকুচিত করুন: {{duration}}", + "metricsExtract": "গন্তব্যে নিষ্কাশন: {{duration}}", + "metricsPrepare": "গন্তব্য প্রস্তুত করুন: {{duration}}", + "metricsRouteBenchmark": "রুট প্রোব — সরাসরি: {{direct}}, রিলে: {{relay}}", + "metricsSourceDelete": "উৎস থেকে সরান: {{duration}}", + "metricsTotal": "মোট: {{duration}}", + "metricsTransfer": "প্রান্ত থেকে প্রান্ত: {{throughput}} ({{duration}})", + "metricsVerify": "SHA-256 দ্বারা যাচাইকৃত: {{duration}}", + "moveFolderToHost": "ফোল্ডারটি হোস্টে সরান…", + "moveItemsToHost": "{{count}} টি আইটেম… টি হোস্টে সরান", + "moveToHost": "হোস্টে যান…", + "noHostsConnected": "অন্য কোনো ফাইল-ম্যানেজার হোস্ট উপলব্ধ নেই।", + "noHostsConnectedHint": "হোস্ট ম্যানেজারে ফাইল ম্যানেজার সক্রিয় করা আছে এমন আরেকটি SSH হোস্ট যোগ করুন।", + "parallelSegmentsHint": "বড় ফাইলগুলোকে ২৫৬ মেগাবাইটের খণ্ডে ভাগ করা হয়। মোট থ্রুপুট বাড়ানোর জন্য একাধিক লেন আলাদা সংযোগ ব্যবহার করে (যেমন কয়েকটি ট্রান্সফার শুরু করা)।", + "parallelSegmentsLabel": "সমান্তরাল স্থানান্তর লেন", + "parallelSegmentsOption": "{{count}} লেন", + "progressBenchmarking": "দ্রুততম স্থানান্তর পথ নির্বাচন করা হচ্ছে…", + "progressBytes": "{{transferred}} / {{total}}", + "progressCancel": "বাতিল করুন", + "progressCancelling": "বাতিল করা হচ্ছে…", + "progressCompressing": "উৎস হোস্টে সংকুচিত করা হচ্ছে…", + "progressExtracting": "গন্তব্য… থেকে নিষ্কাশন করা হচ্ছে", + "progressItems": "{{current}} / {{total}} ফাইল", + "progressReconnecting": "পুনরায় সংযোগ স্থাপন…", + "progressStalled": "স্থবির", + "progressTotalSpeed": "{{speed}} মোট ({{lanes}} লেন)", + "progressTransferring": "ডেটা স্থানান্তর করা হচ্ছে…", + "progressTransferringItems": "ফাইল স্থানান্তর করা হচ্ছে ({{current}} {{total}})…", + "progressVerifying": "ফাইলের অখণ্ডতা যাচাই করা হচ্ছে…", + "recentDestinations": "সাম্প্রতিক গন্তব্যস্থল", + "resumedHint": "অন্য একটি উইন্ডোতে শুরু হওয়া একটি সক্রিয় ট্রান্সফারের সাথে পুনরায় সংযুক্ত হওয়া গেছে।", + "retryTransfer": "পুনরায় চেষ্টা করুন", + "retryTransferError": "পুনরায় চেষ্টা ব্যর্থ হয়েছে", + "selectDestinationHost": "গন্তব্য হোস্ট নির্বাচন করুন", + "transferCancelled": "স্থানান্তর বাতিল করা হয়েছে", + "transferCancelledCopyHint": "গন্তব্যে আংশিক ফাইল থেকে যেতে পারে।", + "transferCancelledMoveHint": "গন্তব্যে আংশিক ফাইল থেকে যেতে পারে। মূল ফাইলগুলো সরানো হয়নি।", + "transferError": "স্থানান্তর ব্যর্থ হয়েছে", + "transferFailedRetryHint": "গন্তব্যে আংশিক ডেটা সংরক্ষিত হয়েছে। সংযোগ ফিরে এলে পুনরায় চেষ্টা শুরু হবে।", + "transferPartialHint": "স্থানান্তর করা যায়নি: {{paths}}", + "transferSuccess": "স্থানান্তর সম্পন্ন হয়েছে" } } diff --git a/plugins/file-manager/locales/translated/ca_ES.json b/plugins/file-manager/locales/translated/ca_ES.json index 355f3b870..78207a117 100644 --- a/plugins/file-manager/locales/translated/ca_ES.json +++ b/plugins/file-manager/locales/translated/ca_ES.json @@ -382,7 +382,10 @@ "defaultPathLabel": "Camí predeterminat", "fileManagerPathHint": "El directori que s'obrirà quan s'iniciï el gestor de fitxers per a aquest amfitrió.", "fileManagerUrlCopied": "S'ha copiat l'URL del gestor de fitxers", - "copyFileManagerUrlAction": "Copia l'URL del gestor de fitxers" + "copyFileManagerUrlAction": "Copia l'URL del gestor de fitxers", + "docsLink": "Veure documents", + "hostNotFound": "No s'ha trobat l'amfitrió", + "loadingHost": "S'està carregant l'amfitrió..." }, "settings": { "host": { @@ -406,5 +409,105 @@ "nav": { "sftp": "SFTP", "files": "Fitxers" + }, + "onboarding": { + "feature_files": "Gestor de fitxers", + "feature_files_desc": "Navegueu, pengeu, descarregueu i editeu fitxers a través de SFTP sense sortir de l'aplicació." + }, + "terminal": { + "runTitle": "Executant {{command}} - {{host}}", + "terminalTitle": "Terminal - {{host}}", + "terminalWithPath": "Terminal - {{host}}:{{path}}" + }, + "transfer": { + "browseFolders": "Navega per les carpetes de destinació", + "browsePathError": "No s'ha pogut obrir aquesta ruta a l'amfitrió de destinació.", + "browsePathWillBeCreated": "Aquesta carpeta encara no existeix. Es crearà quan comenci la transferència.", + "cancel": "Cancel·la", + "cleanupDestFiles": "Neteja la destinació", + "cleanupDestFilesError": "La neteja ha fallat", + "cleanupDestFilesNothing": "Res a netejar a la destinació", + "cleanupDestFilesPartial": "No s'han pogut eliminar alguns fitxers parcials", + "cleanupDestFilesSuccess": "S'han eliminat fitxers parcials de la destinació", + "confirmCopy": "Còpia", + "confirmMove": "Moure", + "copyFolderToHost": "Copia la carpeta a l'amfitrió…", + "copyItemsToHost": "Copia els elements {{count}} a l'amfitrió…", + "copyToHost": "Copia a l'amfitrió…", + "destinationPath": "Camí de destinació", + "destMustBeDirectory": "La destinació ha de ser un directori per a transferències de diversos elements", + "goUp": "Puja", + "hostAuthRequired": "Cal autenticació: obriu primer el Gestor de fitxers en aquest amfitrió.", + "hostConnecting": "Connectant…", + "hostConnectionFailed": "La connexió ha fallat", + "hostDisconnected": "No connectat", + "hostReady": "Llest", + "itemsSummary": "{{count}} elements", + "jumpHostLimitation": "Tots dos hosts han de ser accessibles des del servidor Termix. No s'admet l'encaminament directe d'host a host.", + "methodAuto": "Automàtic", + "methodAutoHint": "Tria SFTP tar o per fitxer en funció del nombre de fitxers, la mida i la compressibilitat. Els fitxers individuals sempre utilitzen SFTP en temps real.", + "methodItemSftp": "SFTP per fitxer", + "methodItemSftpHint": "Transfereix cada fitxer individualment per SFTP. Funciona en tots els hosts, inclòs Windows.", + "methodItemSftpLimitation": "Cada fitxer utilitza el mateix flux SFTP com una còpia d'un sol fitxer, un darrere l'altre. El progrés es combina en tots els fitxers, de manera que la barra es mou lentament durant els fitxers grans.", + "methodLabel": "Mètode de transferència", + "methodPreviewError": "No s'ha pogut previsualitzar el mètode de transferència. El servidor encara triarà un mètode quan l'inicieu.", + "methodPreviewLoading": "Càlcul del mètode de transferència…", + "methodPreviewScanSummary": "{{fileCount}} fitxers, {{totalSize}} total (escanejats a l'amfitrió d'origen).", + "methodPreviewWillUseItemSftp": "Utilitzarà: SFTP per fitxer", + "methodPreviewWillUseTar": "Utilitzarà: Arxiu Tar", + "methodReason": { + "user_item_sftp": "Heu triat SFTP per fitxer.", + "user_tar": "Has triat l'arxiu tar.", + "tar_unavailable": "Tar no està disponible en un o tots dos hosts; s'utilitzarà SFTP per fitxer.", + "windows_host": "Hi ha un host de Windows implicat; no s'utilitza tar.", + "auto_multi_large": "Automàtic: diversos fitxers, inclòs un fitxer gran ({{largestSize}}) amb dades compressibles: paquets de fitxers tar en una sola transferència.", + "auto_single_large_in_archive": "Automàtic: un fitxer gran ({{largestSize}}) en aquest conjunt — SFTP per fitxer.", + "auto_many_incompressible": "Automàtic: dades majoritàriament incompressibles — SFTP per fitxer.", + "auto_many_files": "Automàtic: molts fitxers ({{fileCount}}) — tar redueix la sobrecàrrega per fitxer.", + "auto_default": "Automàtic: SFTP per fitxer per a aquest conjunt." + }, + "methodTar": "Arxiu Tar", + "methodTarHint": "Comprimir a l'origen, transferir un arxiu, extreure a la destinació. Requereix tar en ambdós hosts Unix.", + "metricsCompress": "Comprimir a la font: {{duration}}", + "metricsExtract": "Extracte a la destinació: {{duration}}", + "metricsPrepare": "Prepara la destinació: {{duration}}", + "metricsRouteBenchmark": "Sonda de ruta — directa: {{direct}}, relé: {{relay}}", + "metricsSourceDelete": "Elimina de la font: {{duration}}", + "metricsTotal": "Total: {{duration}}", + "metricsTransfer": "Extrem a extrem: {{throughput}} ({{duration}})", + "metricsVerify": "SHA-256 verificat: {{duration}}", + "moveFolderToHost": "Mou la carpeta a l'amfitrió…", + "moveItemsToHost": "Mou els elements {{count}} a l'amfitrió…", + "moveToHost": "Moure a l'amfitrió…", + "noHostsConnected": "No hi ha altres amfitrions de gestors de fitxers disponibles.", + "noHostsConnectedHint": "Afegiu un altre amfitrió SSH amb el Gestor de fitxers habilitat al Gestor d'amfitrions.", + "parallelSegmentsHint": "Els fitxers grans es divideixen en blocs de 256 MB. Els carrils múltiples utilitzen connexions separades (com ara iniciar diverses transferències) per a un rendiment total més alt.", + "parallelSegmentsLabel": "Carrils de transferència paral·lels", + "parallelSegmentsOption": "carrils {{count}}", + "progressBenchmarking": "Selecció de la ruta de transferència més ràpida…", + "progressBytes": "{{transferred}} / {{total}}", + "progressCancel": "Cancel·la", + "progressCancelling": "Cancel·lant…", + "progressCompressing": "Compressió a l'amfitrió d'origen…", + "progressExtracting": "Extraient a la destinació…", + "progressItems": "{{current}} / {{total}} fitxers", + "progressReconnecting": "Reconnectant…", + "progressStalled": "Estancat", + "progressTotalSpeed": "{{speed}} total ({{lanes}} carrils)", + "progressTransferring": "Transferència de dades…", + "progressTransferringItems": "Transferència de fitxers ({{current}} de {{total}})…", + "progressVerifying": "Verificació de la integritat del fitxer…", + "recentDestinations": "Destinacions recents", + "resumedHint": "S'ha tornat a connectar a una transferència activa iniciada en una altra finestra.", + "retryTransfer": "Torna-ho a intentar", + "retryTransferError": "No s'ha pogut reintentar.", + "selectDestinationHost": "Selecciona l'amfitrió de destinació", + "transferCancelled": "Transferència cancel·lada", + "transferCancelledCopyHint": "És possible que hi hagi fitxers parcials a la destinació.", + "transferCancelledMoveHint": "És possible que hi hagi fitxers parcials a la destinació. No s'han eliminat els fitxers d'origen.", + "transferError": "La transferència ha fallat", + "transferFailedRetryHint": "S'han conservat dades parcials a la destinació. El reintent es reprendrà quan es restableixi la connexió.", + "transferPartialHint": "No s'ha pogut transferir: {{paths}}", + "transferSuccess": "Transferència completada" } } diff --git a/plugins/file-manager/locales/translated/cs_CZ.json b/plugins/file-manager/locales/translated/cs_CZ.json index 027d3f4d4..7facfa704 100644 --- a/plugins/file-manager/locales/translated/cs_CZ.json +++ b/plugins/file-manager/locales/translated/cs_CZ.json @@ -382,7 +382,10 @@ "defaultPathLabel": "Výchozí cesta", "fileManagerPathHint": "Adresář, který se má otevřít při spuštění správce souborů pro tento hostitel.", "fileManagerUrlCopied": "URL adresa Správce souborů zkopírována", - "copyFileManagerUrlAction": "Kopírovat URL Správce souborů" + "copyFileManagerUrlAction": "Kopírovat URL Správce souborů", + "docsLink": "Zobrazit dokumenty", + "hostNotFound": "Hostitel nenalezen", + "loadingHost": "Načítání hostitele..." }, "settings": { "host": { @@ -406,5 +409,105 @@ "nav": { "sftp": "SFTP", "files": "Soubory" + }, + "onboarding": { + "feature_files": "Správce souborů", + "feature_files_desc": "Procházejte, nahrávejte, stahujte a upravujte soubory přes SFTP, aniž byste museli opustit aplikaci." + }, + "terminal": { + "runTitle": "Spuštěno {{command}} - {{host}}", + "terminalTitle": "Terminál - {{host}}", + "terminalWithPath": "Terminál - {{host}}:{{path}}" + }, + "transfer": { + "browseFolders": "Procházet cílové složky", + "browsePathError": "Tuto cestu se nepodařilo otevřít na cílovém hostiteli.", + "browsePathWillBeCreated": "Tato složka zatím neexistuje. Bude vytvořena po zahájení přenosu.", + "cancel": "Zrušit", + "cleanupDestFiles": "Vyčistit cíl", + "cleanupDestFilesError": "Vyčištění se nezdařilo", + "cleanupDestFilesNothing": "Na cílové destinaci není co uklízet", + "cleanupDestFilesPartial": "Některé částečné soubory se nepodařilo odstranit.", + "cleanupDestFilesSuccess": "Z cílového umístění byly odstraněny částečné soubory.", + "confirmCopy": "Kopie", + "confirmMove": "Pohyb", + "copyFolderToHost": "Zkopírovat složku na hostitele…", + "copyItemsToHost": "Zkopírovat {{count}} položek pro hostování…", + "copyToHost": "Kopírovat na hostitele…", + "destinationPath": "Cílová cesta", + "destMustBeDirectory": "Cíl musí být adresář pro přenosy více položek.", + "goUp": "Jdi nahoru", + "hostAuthRequired": "Vyžadováno ověření – nejprve otevřete Správce souborů na tomto hostiteli.", + "hostConnecting": "Připojování…", + "hostConnectionFailed": "Připojení se nezdařilo", + "hostDisconnected": "Nepřipojeno", + "hostReady": "Připraveno", + "itemsSummary": "{{count}} položek", + "jumpHostLimitation": "Oba hostitelé musí být dosažitelné ze serveru Termix. Přímé směrování mezi hostiteli není podporováno.", + "methodAuto": "Auto", + "methodAutoHint": "Vybírá tar nebo SFTP pro jednotlivé soubory na základě počtu souborů, velikosti a komprimovatelnosti. Jednotlivé soubory vždy používají streamovaný SFTP.", + "methodItemSftp": "SFTP pro jednotlivé soubory", + "methodItemSftpHint": "Přeneste každý soubor jednotlivě přes SFTP. Funguje na všech hostitelích včetně Windows.", + "methodItemSftpLimitation": "Každý soubor používá stejný SFTP stream jako kopie jednoho souboru, jeden po druhém. Průběh je sloučen napříč všemi soubory, takže se ukazatel u velkých souborů pohybuje pomalu.", + "methodLabel": "Způsob přenosu", + "methodPreviewError": "Nepodařilo se zobrazit náhled metody přenosu. Server si metodu vybere i po spuštění.", + "methodPreviewLoading": "Výpočet metody převodu…", + "methodPreviewScanSummary": "{{fileCount}} souborů, {{totalSize}} celkem (naskenováno na zdrojovém hostiteli).", + "methodPreviewWillUseItemSftp": "Použije se: SFTP pro jednotlivé soubory", + "methodPreviewWillUseTar": "Použiji: archiv Tar", + "methodReason": { + "user_item_sftp": "Zvolili jste SFTP pro jednotlivé soubory.", + "user_tar": "Zvolili jste archiv tar.", + "tar_unavailable": "Tar není k dispozici na jednom nebo obou hostitelích — místo toho bude použit protokol SFTP pro jednotlivé soubory.", + "windows_host": "Je zapojen hostitelský systém Windows – tar se nepoužívá.", + "auto_multi_large": "Automaticky: více souborů včetně velkého souboru ({{largestSize}}) s komprimovatelnými daty — tar se sbalí do jednoho přenosu.", + "auto_single_large_in_archive": "Automaticky: jeden velký soubor ({{largestSize}}) v této sadě – SFTP pro každý soubor.", + "auto_many_incompressible": "Auto: většinou nekomprimovatelná data – SFTP pro jednotlivé soubory.", + "auto_many_files": "Automaticky: mnoho souborů ({{fileCount}}) – tar snižuje režii pro každý soubor.", + "auto_default": "Automaticky: SFTP pro jednotlivé soubory pro tuto sadu." + }, + "methodTar": "Archiv Tar", + "methodTarHint": "Komprimace ve zdroji, přenos jednoho archivu, extrakce v cíli. Vyžaduje tar na obou unixových hostitelích.", + "metricsCompress": "Komprimovat u zdroje: {{duration}}", + "metricsExtract": "Extrahovat v cíli: {{duration}}", + "metricsPrepare": "Připravit cíl: {{duration}}", + "metricsRouteBenchmark": "Sonda trasy — přímá: {{direct}}, relé: {{relay}}", + "metricsSourceDelete": "Odebrat ze zdroje: {{duration}}", + "metricsTotal": "Celkem: {{duration}}", + "metricsTransfer": "Konec od konce: {{throughput}} ({{duration}})", + "metricsVerify": "SHA-256 ověřeno: {{duration}}", + "moveFolderToHost": "Přesunout složku na hostitele…", + "moveItemsToHost": "Přesunout {{count}} položek na hostitele…", + "moveToHost": "Přesunout na hostitele…", + "noHostsConnected": "Žádní další hostitelé souborů nejsou k dispozici.", + "noHostsConnectedHint": "Přidejte dalšího hostitele SSH s povoleným Správcem souborů ve Správci hostitelů.", + "parallelSegmentsHint": "Velké soubory jsou rozděleny na bloky o velikosti 256 MB. Více linek používá samostatná připojení (například spuštění několika přenosů) pro vyšší celkovou propustnost.", + "parallelSegmentsLabel": "Paralelní přestupní pruhy", + "parallelSegmentsOption": "{{count}} jízdních pruhů", + "progressBenchmarking": "Výběr nejrychlejší trasy přestupu…", + "progressBytes": "{{transferred}} / {{total}}", + "progressCancel": "Zrušit", + "progressCancelling": "Zrušení…", + "progressCompressing": "Komprese na zdrojovém hostiteli…", + "progressExtracting": "Extrahování v cíli…", + "progressItems": "{{current}} / {{total}} souborů", + "progressReconnecting": "Opětovné připojení…", + "progressStalled": "Zastaveno", + "progressTotalSpeed": "{{speed}} celkem ({{lanes}} pruhů)", + "progressTransferring": "Přenos dat…", + "progressTransferringItems": "Přenos souborů ({{current}} z {{total}})…", + "progressVerifying": "Ověřování integrity souboru…", + "recentDestinations": "Nedávné destinace", + "resumedHint": "Znovu připojeno k aktivnímu přenosu zahájenému v jiném okně.", + "retryTransfer": "Zkusit znovu", + "retryTransferError": "Opakovaný pokus se nezdařil", + "selectDestinationHost": "Vyberte cílového hostitele", + "transferCancelled": "Převod zrušen", + "transferCancelledCopyHint": "V cílovém úložišti mohou zůstat jen částečné soubory.", + "transferCancelledMoveHint": "V cílovém umístění mohou zůstat jen některé soubory. Zdrojové soubory nebyly odstraněny.", + "transferError": "Přenos se nezdařil", + "transferFailedRetryHint": "V cíli byla uložena částečná data. Po obnovení připojení bude pokus pokračovat.", + "transferPartialHint": "Nepodařilo se přenést: {{paths}}", + "transferSuccess": "Převod dokončen" } } diff --git a/plugins/file-manager/locales/translated/da_DK.json b/plugins/file-manager/locales/translated/da_DK.json index 85e6a8b4c..a10cdbb00 100644 --- a/plugins/file-manager/locales/translated/da_DK.json +++ b/plugins/file-manager/locales/translated/da_DK.json @@ -382,7 +382,10 @@ "defaultPathLabel": "Standardsti", "fileManagerPathHint": "Den mappe, der skal åbnes, når filhåndteringen starter for denne vært.", "fileManagerUrlCopied": "URL'en til filhåndtering er kopieret", - "copyFileManagerUrlAction": "Kopiér URL til filhåndtering" + "copyFileManagerUrlAction": "Kopiér URL til filhåndtering", + "docsLink": "Se dokumenter", + "hostNotFound": "Værten blev ikke fundet", + "loadingHost": "Indlæser vært..." }, "settings": { "host": { @@ -406,5 +409,105 @@ "nav": { "sftp": "SFTP", "files": "Filer" + }, + "onboarding": { + "feature_files": "Filhåndtering", + "feature_files_desc": "Gennemse, upload, download og rediger filer via SFTP uden at forlade appen." + }, + "terminal": { + "runTitle": "Kører {{command}} - {{host}}", + "terminalTitle": "Terminal - {{host}}", + "terminalWithPath": "Terminal - {{host}}:{{path}}" + }, + "transfer": { + "browseFolders": "Gennemse destinationsmapper", + "browsePathError": "Kunne ikke åbne denne sti på destinationsværten.", + "browsePathWillBeCreated": "Denne mappe findes ikke endnu. Den vil blive oprettet, når overførslen starter.", + "cancel": "Ophæve", + "cleanupDestFiles": "Oprydningsdestination", + "cleanupDestFilesError": "Oprydning mislykkedes", + "cleanupDestFilesNothing": "Intet at rydde op på destinationen", + "cleanupDestFilesPartial": "Nogle delvise filer kunne ikke fjernes", + "cleanupDestFilesSuccess": "Fjernede delvise filer fra destinationen", + "confirmCopy": "Kopi", + "confirmMove": "Flytte", + "copyFolderToHost": "Kopiér mappe til vært…", + "copyItemsToHost": "Kopiér {{count}} elementer til at være vært for…", + "copyToHost": "Kopiér til vært…", + "destinationPath": "Destinationssti", + "destMustBeDirectory": "Destinationen skal være en mappe for overførsler af flere elementer", + "goUp": "Gå op", + "hostAuthRequired": "Godkendelse kræves — åbn først Filhåndtering på denne vært", + "hostConnecting": "Forbinder…", + "hostConnectionFailed": "Forbindelsen mislykkedes", + "hostDisconnected": "Ikke forbundet", + "hostReady": "Parat", + "itemsSummary": "{{count}} elementer", + "jumpHostLimitation": "Begge værter skal kunne nås fra Termix-serveren. Direkte vært-til-vært-routing understøttes ikke.", + "methodAuto": "Bil", + "methodAutoHint": "Vælger tar eller SFTP pr. fil baseret på antal filer, størrelse og komprimerbarhed. Enkeltfiler bruger altid streaming SFTP.", + "methodItemSftp": "SFTP pr. fil", + "methodItemSftpHint": "Overfør hver fil individuelt via SFTP. Fungerer på alle værter, inklusive Windows.", + "methodItemSftpLimitation": "Hver fil bruger den samme SFTP-strøm som en enkelt filkopi, én efter én. Status kombineres på tværs af alle filer, så bjælken bevæger sig langsomt under store filer.", + "methodLabel": "Overførselsmetode", + "methodPreviewError": "Kunne ikke forhåndsvise overførselsmetoden. Serveren vil stadig vælge en metode, når du starter.", + "methodPreviewLoading": "Beregning af overførselsmetode…", + "methodPreviewScanSummary": "{{fileCount}} filer, {{totalSize}} i alt (scannet på kildevært).", + "methodPreviewWillUseItemSftp": "Vil bruge: SFTP pr. fil", + "methodPreviewWillUseTar": "Vil bruge: Tar-arkiv", + "methodReason": { + "user_item_sftp": "Du valgte SFTP pr. fil.", + "user_tar": "Du valgte tar-arkivet.", + "tar_unavailable": "Tar er ikke tilgængelig på en eller begge værter — SFTP pr. fil vil blive brugt i stedet.", + "windows_host": "En Windows-vært er involveret — tar bruges ikke.", + "auto_multi_large": "Auto: flere filer inklusive en stor fil ({{largestSize}}) med komprimerbare data — tar samler filer i én overførsel.", + "auto_single_large_in_archive": "Auto: én stor fil ({{largestSize}}) i dette sæt — SFTP pr. fil.", + "auto_many_incompressible": "Auto: for det meste inkomprimerbare data — SFTP pr. fil.", + "auto_many_files": "Auto: mange filer ({{fileCount}}) — tar reducerer overhead pr. fil.", + "auto_default": "Auto: SFTP pr. fil for dette sæt." + }, + "methodTar": "Tar-arkiv", + "methodTarHint": "Komprimer ved kildekode, overfør ét arkiv, udpak ved destination. Kræver tar på begge Unix-værter.", + "metricsCompress": "Komprimer på kilde: {{duration}}", + "metricsExtract": "Udtræk på destination: {{duration}}", + "metricsPrepare": "Forbered destination: {{duration}}", + "metricsRouteBenchmark": "Rutesonde — direkte: {{direct}}, relæ: {{relay}}", + "metricsSourceDelete": "Fjern fra kilde: {{duration}}", + "metricsTotal": "I alt: {{duration}}", + "metricsTransfer": "End-to-end: {{throughput}} ({{duration}})", + "metricsVerify": "SHA-256 verificeret: {{duration}}", + "moveFolderToHost": "Flyt mappe til vært…", + "moveItemsToHost": "Flyt {{count}} elementer til at være vært for…", + "moveToHost": "Flyt til vært…", + "noHostsConnected": "Ingen andre filhåndteringsværter tilgængelige.", + "noHostsConnectedHint": "Tilføj en anden SSH-vært med Filhåndtering aktiveret i Værtshåndtering.", + "parallelSegmentsHint": "Store filer opdeles i bidder på 256 MB. Flere baner bruger separate forbindelser (f.eks. at starte flere overførsler) for at opnå en højere samlet gennemløbshastighed.", + "parallelSegmentsLabel": "Parallelle overførselsbaner", + "parallelSegmentsOption": "{{count}} baner", + "progressBenchmarking": "Valg af den hurtigste overførselsrute…", + "progressBytes": "{{transferred}} / {{total}}", + "progressCancel": "Ophæve", + "progressCancelling": "Annullerer…", + "progressCompressing": "Komprimering på kildevært…", + "progressExtracting": "Udpakning på destination…", + "progressItems": "{{current}} / {{total}} filer", + "progressReconnecting": "Genopretter forbindelse…", + "progressStalled": "Standset", + "progressTotalSpeed": "{{speed}} i alt ({{lanes}} baner)", + "progressTransferring": "Overførsel af data…", + "progressTransferringItems": "Overførsel af filer ({{current}} af {{total}})…", + "progressVerifying": "Bekræfter filintegritet…", + "recentDestinations": "Seneste destinationer", + "resumedHint": "Genoprettet forbindelse til en aktiv overførsel, der er startet i et andet vindue.", + "retryTransfer": "Prøv igen", + "retryTransferError": "Genforsøg mislykkedes", + "selectDestinationHost": "Vælg destinationsvært", + "transferCancelled": "Overførsel annulleret", + "transferCancelledCopyHint": "Delvise filer kan forblive på destinationen.", + "transferCancelledMoveHint": "Delvise filer kan forblive på destinationen. Kildefilerne blev ikke fjernet.", + "transferError": "Overførslen mislykkedes", + "transferFailedRetryHint": "Delvise data blev gemt på destinationen. Forsøget genoptages, når forbindelsen er tilbage.", + "transferPartialHint": "Kunne ikke overføre: {{paths}}", + "transferSuccess": "Overførsel fuldført" } } diff --git a/plugins/file-manager/locales/translated/de_DE.json b/plugins/file-manager/locales/translated/de_DE.json index a6637e124..b5ed64840 100644 --- a/plugins/file-manager/locales/translated/de_DE.json +++ b/plugins/file-manager/locales/translated/de_DE.json @@ -382,7 +382,10 @@ "defaultPathLabel": "Standardpfad", "fileManagerPathHint": "Das Verzeichnis, das geöffnet wird, wenn der Dateimanager für diesen Host gestartet wird.", "fileManagerUrlCopied": "Dateimanager-URL kopiert", - "copyFileManagerUrlAction": "Dateimanager-URL kopieren" + "copyFileManagerUrlAction": "Dateimanager-URL kopieren", + "docsLink": "Dokumentation anzeigen", + "hostNotFound": "Host nicht gefunden", + "loadingHost": "Host wird geladen..." }, "settings": { "host": { @@ -406,5 +409,105 @@ "nav": { "sftp": "SFTP", "files": "Dateien" + }, + "onboarding": { + "feature_files": "Dateimanager", + "feature_files_desc": "Durchsuchen, hochladen, herunterladen und bearbeiten Sie Dateien über SFTP, ohne die App zu verlassen." + }, + "terminal": { + "runTitle": "Ausführung: {{command}} - {{host}}", + "terminalTitle": "Terminal - {{host}}", + "terminalWithPath": "Terminal - {{host}}:{{path}}" + }, + "transfer": { + "browseFolders": "Zielordner durchsuchen", + "browsePathError": "Dieser Pfad konnte auf dem Zielhost nicht geöffnet werden.", + "browsePathWillBeCreated": "Dieser Ordner existiert noch nicht. Er wird beim Start der Übertragung erstellt.", + "cancel": "Abbrechen", + "cleanupDestFiles": "Ziel bereinigen", + "cleanupDestFilesError": "Bereinigung fehlgeschlagen.", + "cleanupDestFilesNothing": "Nichts zum Bereinigen am Ziel.", + "cleanupDestFilesPartial": "Einige unvollständige Dateien konnten nicht entfernt werden.", + "cleanupDestFilesSuccess": "Unvollständige Dateien vom Ziel entfernt.", + "confirmCopy": "Kopieren", + "confirmMove": "Verschieben", + "copyFolderToHost": "Ordner zum Host kopieren …", + "copyItemsToHost": "{{count}} Elemente auf Host kopieren…", + "copyToHost": "Auf Host kopieren…", + "destinationPath": "Zielpfad", + "destMustBeDirectory": "Bei Übertragung mehrerer Elemente muss das Ziel ein Verzeichnis sein.", + "goUp": "Nach oben", + "hostAuthRequired": "Authentifizierung erforderlich — öffnen Sie zuerst den Dateimanager auf diesem Host", + "hostConnecting": "Verbinden …", + "hostConnectionFailed": "Verbindung fehlgeschlagen", + "hostDisconnected": "Nicht verbunden", + "hostReady": "Bereit", + "itemsSummary": "{{count}} Elemente", + "jumpHostLimitation": "Beide Hosts müssen vom Termix-Server aus erreichbar sein. Direktes Host-zu-Host-Routing wird nicht unterstützt.", + "methodAuto": "Automatisch", + "methodAutoHint": "Wählt Tar-Archiv oder dateiweise SFTP basierend auf Dateianzahl, Größe und Komprimierbarkeit. Einzelne Dateien verwenden immer Streaming-SFTP.", + "methodItemSftp": "Dateiweise SFTP", + "methodItemSftpHint": "Jede Datei einzeln per SFTP übertragen. Funktioniert auf allen Hosts einschließlich Windows.", + "methodItemSftpLimitation": "Jede Datei verwendet denselben SFTP-Stream wie bei einer Einzeldatei-Kopie, eine nach der anderen. Der Fortschritt wird über alle Dateien kombiniert, sodass der Balken bei großen Dateien nur langsam voranschreitet.", + "methodLabel": "Übertragungsmethode", + "methodPreviewError": "Vorschau der Übertragungsmethode nicht möglich. Der Server wählt beim Start trotzdem eine Methode.", + "methodPreviewLoading": "Übertragungsmethode wird berechnet…", + "methodPreviewScanSummary": "{{fileCount}} Dateien, {{totalSize}} gesamt (auf Quellhost gescannt).", + "methodPreviewWillUseItemSftp": "Verwendet: Dateiweise SFTP", + "methodPreviewWillUseTar": "Verwendet: Tar-Archiv", + "methodReason": { + "user_item_sftp": "Sie haben dateiweises SFTP ausgewählt.", + "user_tar": "Sie haben tar-Archiv ausgewählt.", + "tar_unavailable": "Tar ist auf einem oder beiden Hosts nicht verfügbar – stattdessen wird dateiweises SFTP verwendet.", + "windows_host": "Ein Windows-Host ist beteiligt – tar wird nicht verwendet.", + "auto_multi_large": "Automatisch: mehrere Dateien, darunter eine große Datei ({{largestSize}}) mit komprimierbaren Daten – tar bündelt sie in eine Übertragung.", + "auto_single_large_in_archive": "Automatisch: eine große Datei ({{largestSize}}) in diesem Satz – dateiweises SFTP.", + "auto_many_incompressible": "Automatisch: überwiegend nicht komprimierbare Daten – dateiweises SFTP.", + "auto_many_files": "Automatisch: viele Dateien ({{fileCount}}) – tar reduziert den Overhead pro Datei.", + "auto_default": "Automatisch: dateiweises SFTP für diesen Satz." + }, + "methodTar": "Tar-Archiv", + "methodTarHint": "Komprimieren auf der Quelle, ein Archiv übertragen, auf dem Ziel entpacken. Erfordert tar auf beiden Unix-Hosts.", + "metricsCompress": "Komprimieren auf der Quelle: {{duration}}", + "metricsExtract": "Entpacken auf dem Ziel: {{duration}}", + "metricsPrepare": "Ziel vorbereiten: {{duration}}", + "metricsRouteBenchmark": "Routenprüfung — direkt: {{direct}}, Relay: {{relay}}", + "metricsSourceDelete": "Löschen von der Quelle: {{duration}}", + "metricsTotal": "Gesamt: {{duration}}", + "metricsTransfer": "Ende-zu-Ende: {{throughput}} ({{duration}})", + "metricsVerify": "SHA-256 verifiziert: {{duration}}", + "moveFolderToHost": "Ordner zum Host verschieben …", + "moveItemsToHost": "{{count}} Elemente zum Host verschieben…", + "moveToHost": "Auf Host verschieben…", + "noHostsConnected": "Keine weiteren Dateimanager-Hosts verfügbar.", + "noHostsConnectedHint": "Fügen Sie einen weiteren SSH-Host mit aktiviertem Dateimanager im Host-Manager hinzu.", + "parallelSegmentsHint": "Große Dateien werden in 256-MB-Blöcke aufgeteilt. Mehrere Kanäle verwenden eigene Verbindungen (ähnlich wie mehrere gleichzeitige Übertragungen) für einen höheren Gesamtdurchsatz.", + "parallelSegmentsLabel": "Parallele Übertragungskanäle", + "parallelSegmentsOption": "{{count}} Kanäle", + "progressBenchmarking": "Auswahl der schnellsten Transferroute…", + "progressBytes": "{{transferred}} / {{total}}", + "progressCancel": "Abbrechen", + "progressCancelling": "Wird abgebrochen…", + "progressCompressing": "Komprimieren auf dem Quellhost…", + "progressExtracting": "Entpacken auf dem Zielhost…", + "progressItems": "{{current}} / {{total}} Dateien", + "progressReconnecting": "Neu verbinden…", + "progressStalled": "Stockt", + "progressTotalSpeed": "{{speed}} gesamt ({{lanes}} Kanäle)", + "progressTransferring": "Daten übertragen…", + "progressTransferringItems": "Übertragen von Dateien ({{current}} von {{total}})…", + "progressVerifying": "Dateiintegrität wird überprüft…", + "recentDestinations": "Letzte Ziele", + "resumedHint": "Erneut mit einer aktiven Übertragung verbunden, die in einem anderen Fenster gestartet wurde.", + "retryTransfer": "Wiederholen", + "retryTransferError": "Wiederholung fehlgeschlagen.", + "selectDestinationHost": "Zielhost auswählen", + "transferCancelled": "Übertragung abgebrochen", + "transferCancelledCopyHint": "Unvollständige Dateien können am Zielort verbleiben.", + "transferCancelledMoveHint": "Unvollständige Dateien können am Zielort verbleiben. Quelldateien wurden nicht entfernt.", + "transferError": "Übertragung fehlgeschlagen", + "transferFailedRetryHint": "Unvollständige Daten wurden am Ziel beibehalten. Die Wiederholung wird fortgesetzt, sobald die Verbindung wiederhergestellt ist.", + "transferPartialHint": "Konnte nicht übertragen werden: {{paths}}", + "transferSuccess": "Übertragung abgeschlossen" } } diff --git a/plugins/file-manager/locales/translated/el_GR.json b/plugins/file-manager/locales/translated/el_GR.json index 0f85593e1..4a142bf83 100644 --- a/plugins/file-manager/locales/translated/el_GR.json +++ b/plugins/file-manager/locales/translated/el_GR.json @@ -382,7 +382,10 @@ "defaultPathLabel": "Προεπιλεγμένη διαδρομή", "fileManagerPathHint": "Ο κατάλογος που θα ανοίξει κατά την εκκίνηση του διαχειριστή αρχείων για αυτόν τον κεντρικό υπολογιστή.", "fileManagerUrlCopied": "Η διεύθυνση URL του διαχειριστή αρχείων αντιγράφηκε", - "copyFileManagerUrlAction": "Αντιγραφή URL Διαχείρισης Αρχείων" + "copyFileManagerUrlAction": "Αντιγραφή URL Διαχείρισης Αρχείων", + "docsLink": "Προβολή εγγράφων", + "hostNotFound": "Δεν βρέθηκε κεντρικός υπολογιστής", + "loadingHost": "Φόρτωση κεντρικού υπολογιστή..." }, "settings": { "host": { @@ -406,5 +409,105 @@ "nav": { "sftp": "SFTP", "files": "Αρχεία" + }, + "onboarding": { + "feature_files": "Διαχειριστής αρχείων", + "feature_files_desc": "Περιηγηθείτε, ανεβάστε, κατεβάστε και επεξεργαστείτε αρχεία μέσω SFTP χωρίς να φύγετε από την εφαρμογή." + }, + "terminal": { + "runTitle": "Εκτέλεση {{command}} - {{host}}", + "terminalTitle": "Τερματικό - {{host}}", + "terminalWithPath": "Τερματικό - {{host}}:{{path}}" + }, + "transfer": { + "browseFolders": "Αναζήτηση φακέλων προορισμού", + "browsePathError": "Δεν ήταν δυνατό το άνοιγμα αυτής της διαδρομής στον κεντρικό υπολογιστή προορισμού.", + "browsePathWillBeCreated": "Αυτός ο φάκελος δεν υπάρχει ακόμη. Θα δημιουργηθεί όταν ξεκινήσει η μεταφορά.", + "cancel": "Ματαίωση", + "cleanupDestFiles": "Καθαρισμός προορισμού", + "cleanupDestFilesError": "Ο καθαρισμός απέτυχε", + "cleanupDestFilesNothing": "Δεν υπάρχει τίποτα προς διόρθωση στον προορισμό", + "cleanupDestFilesPartial": "Δεν ήταν δυνατή η κατάργηση ορισμένων τμηματικών αρχείων", + "cleanupDestFilesSuccess": "Αφαιρέθηκαν μερικά αρχεία από τον προορισμό", + "confirmCopy": "Αντίγραφο", + "confirmMove": "Κίνηση", + "copyFolderToHost": "Αντιγραφή φακέλου στον κεντρικό υπολογιστή…", + "copyItemsToHost": "Αντιγραφή στοιχείων {{count}} για φιλοξενία…", + "copyToHost": "Αντιγραφή στον κεντρικό υπολογιστή…", + "destinationPath": "Διαδρομή προορισμού", + "destMustBeDirectory": "Ο προορισμός πρέπει να είναι ένας κατάλογος για μεταφορές πολλαπλών στοιχείων", + "goUp": "Ανεβαίνω", + "hostAuthRequired": "Απαιτείται έλεγχος ταυτότητας — ανοίξτε πρώτα τη Διαχείριση αρχείων σε αυτόν τον κεντρικό υπολογιστή", + "hostConnecting": "Σύνδεση…", + "hostConnectionFailed": "Η σύνδεση απέτυχε", + "hostDisconnected": "Δεν είναι συνδεδεμένο", + "hostReady": "Ετοιμος", + "itemsSummary": "{{count}} στοιχεία", + "jumpHostLimitation": "Και οι δύο κεντρικοί υπολογιστές πρέπει να είναι προσβάσιμοι από τον διακομιστή Termix. Δεν υποστηρίζεται η άμεση δρομολόγηση από κεντρικό υπολογιστή σε κεντρικό υπολογιστή.", + "methodAuto": "Αυτο", + "methodAutoHint": "Επιλέγει SFTP tar ή ανά αρχείο με βάση τον αριθμό αρχείων, το μέγεθος και τη συμπιεστότητα. Τα μεμονωμένα αρχεία χρησιμοποιούν πάντα SFTP ροής.", + "methodItemSftp": "SFTP ανά αρχείο", + "methodItemSftpHint": "Μεταφέρετε κάθε αρχείο ξεχωριστά μέσω SFTP. Λειτουργεί σε όλους τους κεντρικούς υπολογιστές, συμπεριλαμβανομένων των Windows.", + "methodItemSftpLimitation": "Κάθε αρχείο χρησιμοποιεί την ίδια ροή SFTP ως αντίγραφο ενός μόνο αρχείου, το ένα μετά το άλλο. Η πρόοδος συνδυάζεται σε όλα τα αρχεία, επομένως η γραμμή κινείται αργά κατά τη διάρκεια μεγάλων αρχείων.", + "methodLabel": "Μέθοδος μεταφοράς", + "methodPreviewError": "Δεν ήταν δυνατή η προεπισκόπηση της μεθόδου μεταφοράς. Ο διακομιστής θα επιλέξει μια μέθοδο κατά την εκκίνηση.", + "methodPreviewLoading": "Υπολογισμός μεθόδου μεταφοράς…", + "methodPreviewScanSummary": "{{fileCount}} αρχεία, {{totalSize}} συνολικά (σαρωμένα στον κεντρικό υπολογιστή προέλευσης).", + "methodPreviewWillUseItemSftp": "Θα χρησιμοποιηθεί: SFTP ανά αρχείο", + "methodPreviewWillUseTar": "Θα χρησιμοποιηθεί: Αρχείο Tar", + "methodReason": { + "user_item_sftp": "Επιλέξατε SFTP ανά αρχείο.", + "user_tar": "Επιλέξατε το αρχείο tar.", + "tar_unavailable": "Το Tar δεν είναι διαθέσιμο σε έναν ή και στους δύο κεντρικούς υπολογιστές — θα χρησιμοποιηθεί αντ' αυτού το SFTP ανά αρχείο.", + "windows_host": "Εμπλέκεται ένας κεντρικός υπολογιστής των Windows — δεν χρησιμοποιείται το tar.", + "auto_multi_large": "Αυτόματα: πολλά αρχεία, συμπεριλαμβανομένου ενός μεγάλου αρχείου ({{largestSize}}) με συμπιέσιμα δεδομένα — tar ομαδοποιεί σε μία μεταφορά.", + "auto_single_large_in_archive": "Αυτόματα: ένα μεγάλο αρχείο ({{largestSize}}) σε αυτό το σύνολο — ανά αρχείο SFTP.", + "auto_many_incompressible": "Αυτόματα: ως επί το πλείστον ασυμπίεστα δεδομένα — SFTP ανά αρχείο.", + "auto_many_files": "Αυτόματα: πολλά αρχεία ({{fileCount}}) — το tar μειώνει την επιβάρυνση ανά αρχείο.", + "auto_default": "Αυτόματα: SFTP ανά αρχείο για αυτό το σύνολο." + }, + "methodTar": "Αρχείο Tar", + "methodTarHint": "Συμπίεση στην πηγή, μεταφορά ενός αρχείου, εξαγωγή στον προορισμό. Απαιτείται tar και στους δύο κεντρικούς υπολογιστές Unix.", + "metricsCompress": "Συμπίεση στην πηγή: {{duration}}", + "metricsExtract": "Εξαγωγή στον προορισμό: {{duration}}", + "metricsPrepare": "Προετοιμασία προορισμού: {{duration}}", + "metricsRouteBenchmark": "Δρομολόγηση ανιχνευτή — άμεση: {{direct}}, αναμετάδοση: {{relay}}", + "metricsSourceDelete": "Αφαίρεση από την πηγή: {{duration}}", + "metricsTotal": "Σύνολο: {{duration}}", + "metricsTransfer": "Από άκρο σε άκρο: {{throughput}} ({{duration}})", + "metricsVerify": "Επαληθεύτηκε το SHA-256: {{duration}}", + "moveFolderToHost": "Μετακίνηση φακέλου στον κεντρικό υπολογιστή…", + "moveItemsToHost": "Μετακίνηση στοιχείων {{count}} για να φιλοξενήσει το…", + "moveToHost": "Μετακίνηση στον κεντρικό υπολογιστή…", + "noHostsConnected": "Δεν υπάρχουν άλλοι διαθέσιμοι κεντρικοί υπολογιστές διαχείρισης αρχείων.", + "noHostsConnectedHint": "Προσθέστε έναν άλλο κεντρικό υπολογιστή SSH με ενεργοποιημένο το File Manager στο Host Manager.", + "parallelSegmentsHint": "Τα μεγάλα αρχεία χωρίζονται σε κομμάτια των 256 MB. Πολλαπλές λωρίδες χρησιμοποιούν ξεχωριστές συνδέσεις (όπως η έναρξη αρκετών μεταφορών) για υψηλότερη συνολική απόδοση.", + "parallelSegmentsLabel": "Παράλληλες λωρίδες μετεπιβίβασης", + "parallelSegmentsOption": "{{count}} λωρίδες", + "progressBenchmarking": "Επιλογή της ταχύτερης διαδρομής μεταφοράς…", + "progressBytes": "{{transferred}} / {{total}}", + "progressCancel": "Ματαίωση", + "progressCancelling": "Ακύρωση…", + "progressCompressing": "Συμπίεση στον κεντρικό υπολογιστή προέλευσης…", + "progressExtracting": "Εξαγωγή στον προορισμό…", + "progressItems": "{{current}} / {{total}} αρχεία", + "progressReconnecting": "Επανασύνδεση…", + "progressStalled": "Σταματημένο", + "progressTotalSpeed": "{{speed}} σύνολο ({{lanes}} λωρίδες)", + "progressTransferring": "Μεταφορά δεδομένων…", + "progressTransferringItems": "Μεταφορά αρχείων ({{current}} από {{total}})…", + "progressVerifying": "Επαλήθευση ακεραιότητας αρχείου…", + "recentDestinations": "Πρόσφατοι προορισμοί", + "resumedHint": "Επανασύνδεση με μια ενεργή μεταφορά που ξεκίνησε σε άλλο παράθυρο.", + "retryTransfer": "Δοκιμάζω πάλι", + "retryTransferError": "Η επανάληψη απέτυχε", + "selectDestinationHost": "Επιλέξτε κεντρικό υπολογιστή προορισμού", + "transferCancelled": "Η μεταφορά ακυρώθηκε.", + "transferCancelledCopyHint": "Ενδέχεται να παραμείνουν μερικά αρχεία στον προορισμό.", + "transferCancelledMoveHint": "Ενδέχεται να παραμείνουν μερικά αρχεία στον προορισμό. Τα αρχεία προέλευσης δεν καταργήθηκαν.", + "transferError": "Η μεταφορά απέτυχε", + "transferFailedRetryHint": "Μερικά δεδομένα διατηρήθηκαν στον προορισμό. Η επανάληψη θα συνεχιστεί όταν αποκατασταθεί η σύνδεση.", + "transferPartialHint": "Δεν ήταν δυνατή η μεταφορά: {{paths}}", + "transferSuccess": "Η μεταφορά ολοκληρώθηκε" } } diff --git a/plugins/file-manager/locales/translated/es_ES.json b/plugins/file-manager/locales/translated/es_ES.json index e99569451..32502951c 100644 --- a/plugins/file-manager/locales/translated/es_ES.json +++ b/plugins/file-manager/locales/translated/es_ES.json @@ -382,7 +382,10 @@ "defaultPathLabel": "Ruta predeterminada", "fileManagerPathHint": "Directorio que se abre al iniciar el gestor de archivos para este host.", "fileManagerUrlCopied": "URL del gestor de archivos copiada", - "copyFileManagerUrlAction": "Copiar URL del gestor de archivos" + "copyFileManagerUrlAction": "Copiar URL del gestor de archivos", + "docsLink": "Ver documentación", + "hostNotFound": "Host no encontrado", + "loadingHost": "Cargando host..." }, "settings": { "host": { @@ -406,5 +409,105 @@ "nav": { "sftp": "SFTP", "files": "Archivos" + }, + "onboarding": { + "feature_files": "Gestor de archivos", + "feature_files_desc": "Navega, sube, descarga y edita archivos a través de SFTP sin salir de la aplicación." + }, + "terminal": { + "runTitle": "Ejecutando {{command}} - {{host}}", + "terminalTitle": "Terminal - {{host}}", + "terminalWithPath": "Terminal - {{host}}:{{path}}" + }, + "transfer": { + "browseFolders": "Examinar carpetas de destino", + "browsePathError": "No se pudo abrir esta ruta en el host de destino.", + "browsePathWillBeCreated": "Esta carpeta no existe aún. Se creará al iniciar la transferencia.", + "cancel": "Cancelar", + "cleanupDestFiles": "Limpiar destino", + "cleanupDestFilesError": "Error al limpiar", + "cleanupDestFilesNothing": "Nada que limpiar en el destino", + "cleanupDestFilesPartial": "Algunos archivos parciales no se pudieron eliminar", + "cleanupDestFilesSuccess": "Se eliminaron los archivos parciales del destino", + "confirmCopy": "Copiar", + "confirmMove": "Mover", + "copyFolderToHost": "Copiar carpeta al host…", + "copyItemsToHost": "Copiar {{count}} elementos al host…", + "copyToHost": "Copiar al host…", + "destinationPath": "Ruta de destino", + "destMustBeDirectory": "El destino debe ser un directorio para transferencias de múltiples elementos", + "goUp": "Subir", + "hostAuthRequired": "Se requiere autenticación — abre primero el Gestor de Archivos en este host", + "hostConnecting": "Conectando…", + "hostConnectionFailed": "Conexión fallida", + "hostDisconnected": "No conectado", + "hostReady": "Listo", + "itemsSummary": "{{count}} elementos", + "jumpHostLimitation": "Ambos equipos deben ser accesibles desde el servidor de Termix. No se admite el enrutamiento directo entre equipos.", + "methodAuto": "Automático", + "methodAutoHint": "Elige tar o SFTP por archivo según el número de archivos, tamaño y compresibilidad. Los archivos individuales siempre usan SFTP por transmisión continua.", + "methodItemSftp": "SFTP por archivo", + "methodItemSftpHint": "Transfiere cada archivo individualmente por SFTP. Funciona en todos los equipos, incluido Windows.", + "methodItemSftpLimitation": "Cada archivo usa el mismo flujo SFTP que una copia de un solo archivo, uno tras otro. El progreso se combina en todos los archivos, por lo que la barra se mueve lentamente durante archivos grandes.", + "methodLabel": "Método de transferencia", + "methodPreviewError": "No se pudo previsualizar el método de transferencia. El servidor seleccionará un método al iniciar.", + "methodPreviewLoading": "Calculando el método de transferencia…", + "methodPreviewScanSummary": "{{fileCount}} archivos, {{totalSize}} total (analizado en el equipo de origen).", + "methodPreviewWillUseItemSftp": "Se usará: SFTP por archivo", + "methodPreviewWillUseTar": "Se usará: Archivo Tar", + "methodReason": { + "user_item_sftp": "Has elegido SFTP por archivo.", + "user_tar": "Has elegido archivo tar.", + "tar_unavailable": "Tar no está disponible en uno o ambos hosts; se usará SFTP por archivo.", + "windows_host": "Hay un host Windows implicado; no se usa tar.", + "auto_multi_large": "Auto: múltiples archivos incluido uno grande ({{largestSize}}) con datos comprimibles; tar los agrupa en una sola transferencia.", + "auto_single_large_in_archive": "Auto: un archivo grande ({{largestSize}}) en este conjunto; SFTP por archivo.", + "auto_many_incompressible": "Auto: datos mayoritariamente incompresibles; SFTP por archivo.", + "auto_many_files": "Auto: muchos archivos ({{fileCount}}); tar reduce la sobrecarga por archivo.", + "auto_default": "Auto: SFTP por archivo para este conjunto." + }, + "methodTar": "Archivo Tar", + "methodTarHint": "Comprime en origen, transfiere un archivo, extrae en destino. Necesita tar en ambos equipos Unix.", + "metricsCompress": "Compresión en origen: {{duration}}", + "metricsExtract": "Extracción en destino: {{duration}}", + "metricsPrepare": "Preparar destino: {{duration}}", + "metricsRouteBenchmark": "Sondeo de ruta: directo: {{direct}}, retransmisión: {{relay}}", + "metricsSourceDelete": "Eliminación del origen: {{duration}}", + "metricsTotal": "Total: {{duration}}", + "metricsTransfer": "Extremo a extremo: {{throughput}} ({{duration}})", + "metricsVerify": "SHA-256 verificado: {{duration}}", + "moveFolderToHost": "Mover carpeta al host…", + "moveItemsToHost": "Mover {{count}} elementos al host…", + "moveToHost": "Mover al host…", + "noHostsConnected": "No hay otros hosts de gestor de archivos disponibles.", + "noHostsConnectedHint": "Añade otro host SSH con el Gestor de Archivos habilitado en el Administrador de Hosts.", + "parallelSegmentsHint": "Los archivos grandes se dividen en fragmentos de 256 MB. Varias vías utilizan conexiones separadas (como iniciar varias transferencias) para un mayor rendimiento total.", + "parallelSegmentsLabel": "Vías de transferencia en paralelo", + "parallelSegmentsOption": "{{count}} vías", + "progressBenchmarking": "Seleccionar la ruta de transferencia más rápida…", + "progressBytes": "{{transferred}} / {{total}}", + "progressCancel": "Cancelar", + "progressCancelling": "Cancelando…", + "progressCompressing": "Comprimiendo en el equipo de origen…", + "progressExtracting": "Extrayendo en el destino…", + "progressItems": "{{current}} / {{total}} archivos", + "progressReconnecting": "Reconectando…", + "progressStalled": "Estancado", + "progressTotalSpeed": "{{speed}} total ({{lanes}} vías)", + "progressTransferring": "Transfiriendo datos…", + "progressTransferringItems": "Transfiriendo archivos ({{current}} de {{total}})…", + "progressVerifying": "Verificando la integridad del archivo…", + "recentDestinations": "Destinos recientes", + "resumedHint": "Reconectado a una transferencia activa iniciada en otra ventana.", + "retryTransfer": "Reintentar", + "retryTransferError": "Error al reintentar", + "selectDestinationHost": "Seleccionar host de destino", + "transferCancelled": "Transferencia cancelada", + "transferCancelledCopyHint": "Pueden quedar archivos parciales en el destino.", + "transferCancelledMoveHint": "Pueden quedar archivos parciales en el destino. Los archivos de origen no se eliminaron.", + "transferError": "Transferencia fallida", + "transferFailedRetryHint": "Se conservaron datos parciales en el destino. El reintento se reanudará cuando se restablezca la conexión.", + "transferPartialHint": "No se pudo transferir: {{paths}}", + "transferSuccess": "Transferencia completada" } } diff --git a/plugins/file-manager/locales/translated/fi_FI.json b/plugins/file-manager/locales/translated/fi_FI.json index f4ba02170..92c3146dd 100644 --- a/plugins/file-manager/locales/translated/fi_FI.json +++ b/plugins/file-manager/locales/translated/fi_FI.json @@ -382,7 +382,10 @@ "defaultPathLabel": "Oletuspolku", "fileManagerPathHint": "Hakemisto, joka avataan, kun tiedostonhallinta käynnistyy tälle isännälle.", "fileManagerUrlCopied": "Tiedostonhallinnan URL-osoite kopioitu", - "copyFileManagerUrlAction": "Kopioi tiedostonhallinnan URL-osoite" + "copyFileManagerUrlAction": "Kopioi tiedostonhallinnan URL-osoite", + "docsLink": "Näytä dokumentit", + "hostNotFound": "Isäntää ei löydy", + "loadingHost": "Ladataan isäntää..." }, "settings": { "host": { @@ -406,5 +409,105 @@ "nav": { "sftp": "SFTP", "files": "Tiedostot" + }, + "onboarding": { + "feature_files": "Tiedostonhallinta", + "feature_files_desc": "Selaa, lähetä, lataa ja muokkaa tiedostoja SFTP:n kautta poistumatta sovelluksesta." + }, + "terminal": { + "runTitle": "Juoksemassa {{command}} - {{host}}", + "terminalTitle": "Pääte - {{host}}", + "terminalWithPath": "Pääte - {{host}}:{{path}}" + }, + "transfer": { + "browseFolders": "Selaa kohdekansioita", + "browsePathError": "Tätä polkua ei voitu avata kohdepalvelimella.", + "browsePathWillBeCreated": "Tätä kansiota ei ole vielä olemassa. Se luodaan, kun siirto alkaa.", + "cancel": "Peruuttaa", + "cleanupDestFiles": "Siivouskohde", + "cleanupDestFilesError": "Siivous epäonnistui", + "cleanupDestFilesNothing": "Ei mitään siivottavaa määränpäässä", + "cleanupDestFilesPartial": "Joitakin osittaisia tiedostoja ei voitu poistaa", + "cleanupDestFilesSuccess": "Osittainen tiedosto poistettu kohteesta", + "confirmCopy": "Kopioida", + "confirmMove": "Liikkua", + "copyFolderToHost": "Kopioi kansio isäntään…", + "copyItemsToHost": "Kopioi {{count}} kohdetta isäntään…", + "copyToHost": "Kopioi isäntäkoneeseen…", + "destinationPath": "Kohdepolku", + "destMustBeDirectory": "Määränpään on oltava hakemisto useiden kohteiden siirtoja varten", + "goUp": "Mene ylös", + "hostAuthRequired": "Todennus vaaditaan — avaa ensin tiedostonhallinta tällä isännöintikoneella", + "hostConnecting": "Yhdistetään…", + "hostConnectionFailed": "Yhteys epäonnistui", + "hostDisconnected": "Ei yhdistetty", + "hostReady": "Valmis", + "itemsSummary": "{{count}} kohdetta", + "jumpHostLimitation": "Molempien isäntien on oltava tavoitettavissa Termix-palvelimelta. Suoraa isäntien välistä reititystä ei tueta.", + "methodAuto": "Auto", + "methodAutoHint": "Valitsee tar- tai tiedostokohtaisen SFTP:n tiedostomäärän, koon ja pakkautuvuuden perusteella. Yksittäiset tiedostot käyttävät aina suoratoistettavaa SFTP:tä.", + "methodItemSftp": "Tiedostokohtainen SFTP", + "methodItemSftpHint": "Siirrä jokainen tiedosto erikseen SFTP:n kautta. Toimii kaikilla isännöintijärjestelmillä, mukaan lukien Windows.", + "methodItemSftpLimitation": "Jokainen tiedosto käyttää samaa SFTP-tietovirtaa kuin yksittäiset tiedostokopiot, yksi kerrallaan. Edistyminen yhdistetään kaikkien tiedostojen välillä, joten palkki liikkuu hitaasti suurten tiedostojen käsittelyssä.", + "methodLabel": "Siirtotapa", + "methodPreviewError": "Siirtomenetelmän esikatselu ei onnistunut. Palvelin valitsee silti menetelmän käynnistyksen yhteydessä.", + "methodPreviewLoading": "Siirtomenetelmän laskeminen…", + "methodPreviewScanSummary": "{{fileCount}} tiedostoa, {{totalSize}} yhteensä (skannattu lähdepalvelimella).", + "methodPreviewWillUseItemSftp": "Käytetään: Tiedostokohtaista SFTP:tä", + "methodPreviewWillUseTar": "Käytetään: Tar-arkistoa", + "methodReason": { + "user_item_sftp": "Valitsit tiedostokohtaisen SFTP:n.", + "user_tar": "Valitsit tar-arkiston.", + "tar_unavailable": "Tar ei ole käytettävissä yhdellä tai molemmilla isännillä — sen sijaan käytetään tiedostokohtaista SFTP:tä.", + "windows_host": "Windows-isäntä on mukana – tar-tiedostoa ei käytetä.", + "auto_multi_large": "Automaattinen: useita tiedostoja, mukaan lukien suuri tiedosto ({{largestSize}}), jossa on pakattavaa dataa — tar niputtaa yhdeksi siirroksi.", + "auto_single_large_in_archive": "Automaattinen: yksi suuri tiedosto ({{largestSize}}) tässä joukossa — tiedostokohtainen SFTP.", + "auto_many_incompressible": "Automaattinen: enimmäkseen pakkaamatonta dataa — tiedostokohtainen SFTP.", + "auto_many_files": "Automaattinen: monta tiedostoa ({{fileCount}}) — tar vähentää tiedostokohtaista laskentatehoa.", + "auto_default": "Automaattinen: tiedostokohtainen SFTP tälle joukolle." + }, + "methodTar": "Tar-arkisto", + "methodTarHint": "Pakkaa lähdekoodissa, siirrä yksi arkisto, pura kohdetiedostossa. Vaatii tar-tiedoston molemmissa Unix-koneissa.", + "metricsCompress": "Pakkaa lähdekoodissa: {{duration}}", + "metricsExtract": "Ote määränpäässä: {{duration}}", + "metricsPrepare": "Valmistele kohde: {{duration}}", + "metricsRouteBenchmark": "Reitityskoetin — suora: {{direct}}, välitys: {{relay}}", + "metricsSourceDelete": "Poista lähteestä: {{duration}}", + "metricsTotal": "Yhteensä: {{duration}}", + "metricsTransfer": "Päästä päähän: {{throughput}} ({{duration}})", + "metricsVerify": "SHA-256 vahvistettu: {{duration}}", + "moveFolderToHost": "Siirrä kansio isäntään…", + "moveItemsToHost": "Siirrä {{count}} kohdetta isäntään…", + "moveToHost": "Siirrä isäntäkoneeseen…", + "noHostsConnected": "Muita tiedostonhallintaohjelmia ei ole saatavilla.", + "noHostsConnectedHint": "Lisää toinen SSH-isäntä, jonka tiedostonhallinta on käytössä isäntähallinnassa.", + "parallelSegmentsHint": "Suuret tiedostot jaetaan 256 Mt:n osiin. Useat kaistat käyttävät erillisiä yhteyksiä (kuten useiden siirtojen aloittaminen) suuremman kokonaisläpivirtauksen saavuttamiseksi.", + "parallelSegmentsLabel": "Rinnakkaiset siirtokaistat", + "parallelSegmentsOption": "{{count}} kaistaa", + "progressBenchmarking": "Nopeimman vaihtoreitin valitseminen…", + "progressBytes": "{{transferred}} / {{total}}", + "progressCancel": "Peruuttaa", + "progressCancelling": "Peruutetaan…", + "progressCompressing": "Pakkaus lähdepalvelimella…", + "progressExtracting": "Puretaan kohteessa…", + "progressItems": "{{current}} / {{total}} tiedostoa", + "progressReconnecting": "Yhdistetään uudelleen…", + "progressStalled": "Pysähtynyt", + "progressTotalSpeed": "{{speed}} yhteensä ({{lanes}} kaistaa)", + "progressTransferring": "Tiedon siirtäminen…", + "progressTransferringItems": "Tiedostojen siirtäminen ({{current}} / {{total}})…", + "progressVerifying": "Tiedoston eheyden tarkistaminen…", + "recentDestinations": "Viimeaikaiset kohteet", + "resumedHint": "Yhdistetty uudelleen toisessa ikkunassa aloitettuun aktiiviseen siirtoon.", + "retryTransfer": "Yritä uudelleen", + "retryTransferError": "Uudelleenyritys epäonnistui", + "selectDestinationHost": "Valitse kohdeisäntä", + "transferCancelled": "Siirto peruttu", + "transferCancelledCopyHint": "Osittaisia tiedostoja voi jäädä kohteeseen.", + "transferCancelledMoveHint": "Kohdekansioon saattaa jäädä osittaisia tiedostoja. Lähdetiedostoja ei poistettu.", + "transferError": "Siirto epäonnistui", + "transferFailedRetryHint": "Kohteessa säilytettiin vain osa tiedoista. Uudelleenyritys jatkuu, kun yhteys on palannut.", + "transferPartialHint": "Siirto epäonnistui: {{paths}}", + "transferSuccess": "Siirto valmis" } } diff --git a/plugins/file-manager/locales/translated/fr_FR.json b/plugins/file-manager/locales/translated/fr_FR.json index 77ac8d592..d5ab87fb9 100644 --- a/plugins/file-manager/locales/translated/fr_FR.json +++ b/plugins/file-manager/locales/translated/fr_FR.json @@ -382,7 +382,10 @@ "defaultPathLabel": "Chemin par défaut", "fileManagerPathHint": "Le répertoire à ouvrir lors du lancement du gestionnaire de fichiers pour cet hôte.", "fileManagerUrlCopied": "URL du gestionnaire de fichiers copiée", - "copyFileManagerUrlAction": "Copier l'URL du gestionnaire de fichiers" + "copyFileManagerUrlAction": "Copier l'URL du gestionnaire de fichiers", + "docsLink": "Voir la documentation", + "hostNotFound": "Hôte introuvable", + "loadingHost": "Chargement de l'hôte..." }, "settings": { "host": { @@ -406,5 +409,105 @@ "nav": { "sftp": "SFTP", "files": "Fichiers" + }, + "onboarding": { + "feature_files": "Gestionnaire de fichiers", + "feature_files_desc": "Parcourez, téléchargez, chargez et modifiez des fichiers via SFTP sans quitter l'application." + }, + "terminal": { + "runTitle": "Exécution de {{command}} - {{host}}", + "terminalTitle": "Terminal - {{host}}", + "terminalWithPath": "Terminal - {{host}}:{{path}}" + }, + "transfer": { + "browseFolders": "Parcourir les dossiers de destination", + "browsePathError": "Impossible d’ouvrir ce chemin sur l’hôte de destination.", + "browsePathWillBeCreated": "Ce dossier n’existe pas encore. Il sera créé au début du transfert.", + "cancel": "Annuler", + "cleanupDestFiles": "Nettoyer la destination", + "cleanupDestFilesError": "Échec du nettoyage", + "cleanupDestFilesNothing": "Rien à nettoyer sur la destination", + "cleanupDestFilesPartial": "Certains fichiers partiels n'ont pas pu être supprimés", + "cleanupDestFilesSuccess": "Fichiers partiels supprimés de la destination", + "confirmCopy": "Copier", + "confirmMove": "Déplacer", + "copyFolderToHost": "Copier le dossier vers l’hôte…", + "copyItemsToHost": "Copier {{count}} éléments vers l’hôte…", + "copyToHost": "Copier vers l’hôte…", + "destinationPath": "Chemin de destination", + "destMustBeDirectory": "La destination doit être un dossier pour les transferts de plusieurs éléments", + "goUp": "Remonter", + "hostAuthRequired": "Authentification requise — ouvrez d’abord le gestionnaire de fichiers sur cet hôte", + "hostConnecting": "Connexion en cours…", + "hostConnectionFailed": "Échec de la connexion", + "hostDisconnected": "Non connecté", + "hostReady": "Prêt", + "itemsSummary": "{{count}} éléments", + "jumpHostLimitation": "Les deux hôtes doivent être accessibles depuis le serveur Termix. Le routage direct d’hôte à hôte n’est pas pris en charge.", + "methodAuto": "Auto", + "methodAutoHint": "Choisit l’archive tar ou le SFTP par fichier selon le nombre de fichiers, leur taille et leur compressibilité. Les fichiers uniques utilisent toujours le SFTP en continu (streaming).", + "methodItemSftp": "SFTP par fichier", + "methodItemSftpHint": "Transfère chaque fichier individuellement via SFTP. Fonctionne sur tous les hôtes, y compris Windows.", + "methodItemSftpLimitation": "Chaque fichier utilise le même flux SFTP qu’une copie de fichier unique, l’un après l’autre. La progression est combinée pour tous les fichiers, donc la barre avance lentement lors de gros fichiers.", + "methodLabel": "Méthode de transfert", + "methodPreviewError": "Impossible de prévisualiser la méthode de transfert. Le serveur choisira tout de même une méthode au lancement.", + "methodPreviewLoading": "Calcul de la méthode de transfert…", + "methodPreviewScanSummary": "{{fileCount}} fichiers, {{totalSize}} au total (analysés sur l’hôte source).", + "methodPreviewWillUseItemSftp": "Utilisera : SFTP par fichier", + "methodPreviewWillUseTar": "Utilisera : Archive tar", + "methodReason": { + "user_item_sftp": "Vous avez choisi SFTP par fichier.", + "user_tar": "Vous avez choisi l'archive tar.", + "tar_unavailable": "Tar n'est pas disponible sur l'un ou les deux hôtes — SFTP par fichier sera utilisé à la place.", + "windows_host": "Un hôte Windows est impliqué — tar n'est pas utilisé.", + "auto_multi_large": "Auto : plusieurs fichiers dont un fichier volumineux ({{largestSize}}) avec des données compressibles — tar regroupe en un seul transfert.", + "auto_single_large_in_archive": "Auto : un fichier volumineux ({{largestSize}}) dans cet ensemble — SFTP par fichier.", + "auto_many_incompressible": "Auto : données principalement incompressibles — SFTP par fichier.", + "auto_many_files": "Auto : nombreux fichiers ({{fileCount}}) — tar réduit la surcharge par fichier.", + "auto_default": "Auto : SFTP par fichier pour cet ensemble." + }, + "methodTar": "Archive tar", + "methodTarHint": "Compresse sur la source, transfère une archive, extrait sur la destination. Nécessite tar sur les deux hôtes Unix.", + "metricsCompress": "Compression sur la source : {{duration}}", + "metricsExtract": "Extraction sur la destination : {{duration}}", + "metricsPrepare": "Préparation de la destination : {{duration}}", + "metricsRouteBenchmark": "Sonde d'itinéraire — direct : {{direct}}, relais : {{relay}}", + "metricsSourceDelete": "Suppression depuis la source : {{duration}}", + "metricsTotal": "Total : {{duration}}", + "metricsTransfer": "De bout en bout : {{throughput}} ({{duration}})", + "metricsVerify": "Vérification SHA-256 : {{duration}}", + "moveFolderToHost": "Déplacer le dossier vers l’hôte…", + "moveItemsToHost": "Déplacer {{count}} éléments vers l’hôte…", + "moveToHost": "Déplacer vers l’hôte…", + "noHostsConnected": "Aucun autre hôte de gestionnaire de fichiers disponible.", + "noHostsConnectedHint": "Ajoutez un autre hôte SSH avec le gestionnaire de fichiers activé dans le gestionnaire d’hôtes.", + "parallelSegmentsHint": "Les fichiers volumineux sont divisés en segments de 256 Mo. Les voies multiples utilisent des connexions distinctes (comme lancer plusieurs transferts) pour un débit total plus élevé.", + "parallelSegmentsLabel": "Voies de transfert parallèles", + "parallelSegmentsOption": "{{count}} voies", + "progressBenchmarking": "Sélection de l'itinéraire de transfert le plus rapide…", + "progressBytes": "{{transferred}} / {{total}}", + "progressCancel": "Annuler", + "progressCancelling": "Annulation en cours…", + "progressCompressing": "Compression sur l’hôte source…", + "progressExtracting": "Extraction sur la destination…", + "progressItems": "{{current}} / {{total}} fichiers", + "progressReconnecting": "Reconnexion…", + "progressStalled": "Bloqué", + "progressTotalSpeed": "{{speed}} au total ({{lanes}} voies)", + "progressTransferring": "Transfert des données…", + "progressTransferringItems": "Transfert des fichiers ({{current}} sur {{total}})…", + "progressVerifying": "Vérification de l'intégrité du fichier…", + "recentDestinations": "Destinations récentes", + "resumedHint": "Reconnecté à un transfert actif démarré dans une autre fenêtre.", + "retryTransfer": "Réessayer", + "retryTransferError": "Échec de la nouvelle tentative", + "selectDestinationHost": "Sélectionner l’hôte de destination", + "transferCancelled": "Transfert annulé", + "transferCancelledCopyHint": "Des fichiers partiels peuvent subsister sur la destination.", + "transferCancelledMoveHint": "Des fichiers partiels peuvent subsister sur la destination. Les fichiers sources n'ont pas été supprimés.", + "transferError": "Échec du transfert", + "transferFailedRetryHint": "Des données partielles ont été conservées sur la destination. La nouvelle tentative reprendra lorsque la connexion sera rétablie.", + "transferPartialHint": "Impossible de transférer : {{paths}}", + "transferSuccess": "Transfert terminé" } } diff --git a/plugins/file-manager/locales/translated/he_IL.json b/plugins/file-manager/locales/translated/he_IL.json index 538f5ba8a..e3bfe8a11 100644 --- a/plugins/file-manager/locales/translated/he_IL.json +++ b/plugins/file-manager/locales/translated/he_IL.json @@ -382,7 +382,10 @@ "defaultPathLabel": "נתיב ברירת מחדל", "fileManagerPathHint": "הספרייה שתיפתח כאשר מנהל הקבצים יופעל עבור מארח זה.", "fileManagerUrlCopied": "כתובת ה-URL של מנהל הקבצים הועתקה", - "copyFileManagerUrlAction": "העתקת כתובת URL של מנהל הקבצים" + "copyFileManagerUrlAction": "העתקת כתובת URL של מנהל הקבצים", + "docsLink": "הצג מסמכים", + "hostNotFound": "המארח לא נמצא", + "loadingHost": "טוען מארח..." }, "settings": { "host": { @@ -406,5 +409,105 @@ "nav": { "sftp": "SFTP", "files": "קבצים" + }, + "onboarding": { + "feature_files": "מנהל הקבצים", + "feature_files_desc": "דפדף, העלה, הורד וערוך קבצים דרך SFTP מבלי לצאת מהאפליקציה." + }, + "terminal": { + "runTitle": "ריצה {{command}} - {{host}}", + "terminalTitle": "טרמינל - {{host}}", + "terminalWithPath": "טרמינל - {{host}}:{{path}}" + }, + "transfer": { + "browseFolders": "עיון בתיקיות יעד", + "browsePathError": "לא ניתן היה לפתוח נתיב זה במארח היעד.", + "browsePathWillBeCreated": "תיקייה זו עדיין לא קיימת. היא תיווצר כאשר ההעברה תתחיל.", + "cancel": "לְבַטֵל", + "cleanupDestFiles": "יעד ניקוי", + "cleanupDestFilesError": "הניקוי נכשל", + "cleanupDestFilesNothing": "אין מה לנקות ביעד", + "cleanupDestFilesPartial": "לא ניתן היה להסיר חלק מהקבצים", + "cleanupDestFilesSuccess": "הוסרו קבצים חלקיים מהיעד", + "confirmCopy": "לְהַעְתִיק", + "confirmMove": "מַהֲלָך", + "copyFolderToHost": "העתקת תיקייה למארח…", + "copyItemsToHost": "העתק את הפריטים {{count}} לאירוח…", + "copyToHost": "העתק למארח…", + "destinationPath": "נתיב היעד", + "destMustBeDirectory": "היעד חייב להיות ספרייה עבור העברות מרובות פריטים", + "goUp": "לַעֲלוֹת", + "hostAuthRequired": "נדרש אימות - פתח תחילה את מנהל הקבצים במארח זה", + "hostConnecting": "חיבור…", + "hostConnectionFailed": "החיבור נכשל", + "hostDisconnected": "לא מחובר", + "hostReady": "מוּכָן", + "itemsSummary": "פריטים {{count}}", + "jumpHostLimitation": "שני המארחים חייבים להיות נגישים משרת Termix. ניתוב ישיר ממארח למארח אינו נתמך.", + "methodAuto": "אוטומטי", + "methodAutoHint": "בוחר SFTP לפי קובץ או tar בהתבסס על ספירת הקבצים, גודלם ויכולת הדחיסה. קבצים בודדים תמיד משתמשים ב-SFTP בסטרימינג.", + "methodItemSftp": "SFTP לפי קובץ", + "methodItemSftpHint": "העבר כל קובץ בנפרד דרך SFTP. עובד על כל המארחים כולל Windows.", + "methodItemSftpLimitation": "כל קובץ משתמש באותו זרם SFTP כעותק של קובץ בודד, אחד אחרי השני. ההתקדמות משולבת על פני כל הקבצים, כך שהסרגל נע לאט במהלך קבצים גדולים.", + "methodLabel": "שיטת העברה", + "methodPreviewError": "לא ניתן היה להציג תצוגה מקדימה של שיטת ההעברה. השרת עדיין יבחר שיטה כשתתחיל.", + "methodPreviewLoading": "חישוב שיטת ההעברה…", + "methodPreviewScanSummary": "{{fileCount}} קבצים, {{totalSize}} סה\"כ (נסרק במארח המקור).", + "methodPreviewWillUseItemSftp": "ישתמש ב: SFTP לפי קובץ", + "methodPreviewWillUseTar": "אשתמש ב: ארכיון Tar", + "methodReason": { + "user_item_sftp": "בחרת SFTP לפי קובץ.", + "user_tar": "בחרת בארכיון tar.", + "tar_unavailable": "Tar אינו זמין באחד המארחים או בשניהם - במקום זאת ייעשה שימוש ב-SFTP לפי קובץ.", + "windows_host": "מחשב מארח של Windows מעורב - tar אינו בשימוש.", + "auto_multi_large": "אוטומטי: קבצים מרובים כולל קובץ גדול ({{largestSize}}) עם נתונים דחוסים - tar מאחד את הנתונים להעברה אחת.", + "auto_single_large_in_archive": "אוטומטי: קובץ גדול אחד ({{largestSize}}) בקבוצה זו - SFTP לכל קובץ.", + "auto_many_incompressible": "אוטומטי: נתונים לרוב בלתי ניתנים לדחיסה - SFTP לכל קובץ.", + "auto_many_files": "אוטומטי: קבצים רבים ({{fileCount}}) — tar מפחית את התקורה של כל קובץ.", + "auto_default": "אוטומטי: SFTP לכל קובץ עבור קבוצה זו." + }, + "methodTar": "ארכיון טאר", + "methodTarHint": "דחיסה במקור, העברת ארכיון אחד, חילוץ ביעד. דורש tar בשני מארחי יוניקס.", + "metricsCompress": "דחיסה במקור: {{duration}}", + "metricsExtract": "חילוץ ביעד: {{duration}}", + "metricsPrepare": "הכנת יעד: {{duration}}", + "metricsRouteBenchmark": "גשש מסלול — ישיר: {{direct}}, ממסר: {{relay}}", + "metricsSourceDelete": "הסר מהמקור: {{duration}}", + "metricsTotal": "סה\"כ: {{duration}}", + "metricsTransfer": "מקצה לקצה: {{throughput}} ({{duration}})", + "metricsVerify": "SHA-256 אומת: {{duration}}", + "moveFolderToHost": "העברת תיקייה למארח…", + "moveItemsToHost": "העבר {{count}} פריטים לאירוח…", + "moveToHost": "מעבר למארח…", + "noHostsConnected": "אין מארחי מנהל קבצים אחרים זמינים.", + "noHostsConnectedHint": "הוסף מארח SSH נוסף כאשר מנהל הקבצים מופעל במנהל המארחים.", + "parallelSegmentsHint": "קבצים גדולים מחולקים לחתיכות של 256 מגה-בייט. מספר נתיבים משתמשים בחיבורים נפרדים (כמו התחלת מספר העברות) לקבלת תפוקה כוללת גבוהה יותר.", + "parallelSegmentsLabel": "נתיבי מעבר מקבילים", + "parallelSegmentsOption": "נתיבים {{count}}", + "progressBenchmarking": "בחירת נתיב ההעברה המהיר ביותר…", + "progressBytes": "{{transferred}} / {{total}}", + "progressCancel": "לְבַטֵל", + "progressCancelling": "מבטל…", + "progressCompressing": "דחיסה במארח המקור…", + "progressExtracting": "מחלץ ביעד…", + "progressItems": "קבצים {{current}} / {{total}}", + "progressReconnecting": "מתחבר מחדש…", + "progressStalled": "אָבוּס", + "progressTotalSpeed": "סה\"כ {{speed}} (נתיבים{{lanes}})", + "progressTransferring": "העברת נתונים…", + "progressTransferringItems": "העברת קבצים ({{current}} מתוך {{total}})…", + "progressVerifying": "אימות שלמות הקובץ…", + "recentDestinations": "יעדים אחרונים", + "resumedHint": "התחבר מחדש להעברה פעילה שהתחילה בחלון אחר.", + "retryTransfer": "נסה שוב", + "retryTransferError": "ניסיון חוזר נכשל", + "selectDestinationHost": "בחר מארח יעד", + "transferCancelled": "ההעברה בוטלה", + "transferCancelledCopyHint": "ייתכן שיישארו קבצים חלקיים ביעד.", + "transferCancelledMoveHint": "ייתכן שיישארו קבצים חלקיים ביעד. קבצי המקור לא הוסרו.", + "transferError": "ההעברה נכשלה", + "transferFailedRetryHint": "נתונים חלקיים נשמרו ביעד. ניסיון חוזר יחודש כאשר החיבור יחזור.", + "transferPartialHint": "לא ניתן היה להעביר: {{paths}}", + "transferSuccess": "ההעברה הושלמה" } } diff --git a/plugins/file-manager/locales/translated/hi_IN.json b/plugins/file-manager/locales/translated/hi_IN.json index 613588481..8fad2b363 100644 --- a/plugins/file-manager/locales/translated/hi_IN.json +++ b/plugins/file-manager/locales/translated/hi_IN.json @@ -382,7 +382,10 @@ "defaultPathLabel": "डिफ़ॉल्ट पथ", "fileManagerPathHint": "जब इस होस्ट के लिए फ़ाइल प्रबंधक लॉन्च होता है तो खोलने के लिए निर्देशिका।", "fileManagerUrlCopied": "फ़ाइल प्रबंधक URL कॉपी किया गया", - "copyFileManagerUrlAction": "फ़ाइल प्रबंधक URL कॉपी करें" + "copyFileManagerUrlAction": "फ़ाइल प्रबंधक URL कॉपी करें", + "docsLink": "दस्तावेज़ देखें", + "hostNotFound": "होस्ट नहीं मिला", + "loadingHost": "होस्ट लोड हो रहा है..." }, "settings": { "host": { @@ -406,5 +409,105 @@ "nav": { "sftp": "एसएफटीपी", "files": "फ़ाइलें" + }, + "onboarding": { + "feature_files": "फ़ाइल मैनेजर", + "feature_files_desc": "ऐप छोड़े बिना SFTP के माध्यम से फाइलों को ब्राउज़ करें, अपलोड करें, डाउनलोड करें और संपादित करें।" + }, + "terminal": { + "runTitle": "{{command}} चल रहा है - {{host}}", + "terminalTitle": "टर्मिनल - {{host}}", + "terminalWithPath": "टर्मिनल - {{host}}:{{path}}" + }, + "transfer": { + "browseFolders": "गंतव्य फ़ोल्डर ब्राउज़ करें", + "browsePathError": "गंतव्य होस्ट पर यह पथ नहीं खोला जा सका।", + "browsePathWillBeCreated": "यह फ़ोल्डर अभी मौजूद नहीं है। स्थानांतरण शुरू होने पर इसे बनाया जाएगा।", + "cancel": "रद्द करें", + "cleanupDestFiles": "गंतव्य साफ करें", + "cleanupDestFilesError": "सफाई विफल रही।", + "cleanupDestFilesNothing": "गंतव्य पर साफ करने के लिए कुछ नहीं।", + "cleanupDestFilesPartial": "कुछ आंशिक फ़ाइलें नहीं हटाई जा सकीं।", + "cleanupDestFilesSuccess": "गंतव्य से आंशिक फ़ाइलें हटा दी गईं।", + "confirmCopy": "कॉपी करें", + "confirmMove": "स्थानांतरित करें", + "copyFolderToHost": "फ़ोल्डर होस्ट पर कॉपी करें…", + "copyItemsToHost": "{{count}} आइटम होस्ट पर कॉपी करें…", + "copyToHost": "होस्ट पर कॉपी करें…", + "destinationPath": "गंतव्य पथ", + "destMustBeDirectory": "कई आइटम स्थानांतरण के लिए गंतव्य एक निर्देशिका होना चाहिए", + "goUp": "ऊपर जाएं", + "hostAuthRequired": "प्रमाणीकरण आवश्यक है — पहले इस होस्ट पर फ़ाइल प्रबंधक खोलें", + "hostConnecting": "कनेक्ट हो रहा है…", + "hostConnectionFailed": "कनेक्शन विफल", + "hostDisconnected": "कनेक्ट नहीं है", + "hostReady": "तैयार", + "itemsSummary": "{{count}} आइटम", + "jumpHostLimitation": "दोनों होस्ट Termix सर्वर से पहुँच योग्य होने चाहिए। सीधा होस्ट-से-होस्ट रूटिंग समर्थित नहीं है।", + "methodAuto": "स्वचालित", + "methodAutoHint": "फ़ाइलों की संख्या, आकार और संपीड़न क्षमता के आधार पर tar या प्रति-फ़ाइल SFTP चुनता है। एकल फ़ाइलें हमेशा स्ट्रीमिंग SFTP का उपयोग करती हैं।", + "methodItemSftp": "प्रति-फ़ाइल SFTP", + "methodItemSftpHint": "प्रत्येक फ़ाइल को SFTP पर अलग-अलग स्थानांतरित करें। विंडोज़ सहित सभी होस्ट पर काम करता है।", + "methodItemSftpLimitation": "प्रत्येक फ़ाइल एक-एक करके एकल-फ़ाइल प्रतिलिपि के रूप में समान SFTP स्ट्रीम का उपयोग करती है। सभी फ़ाइलों में प्रगति संयुक्त होती है, इसलिए बड़ी फ़ाइलों के दौरान बार धीरे-धीरे चलता है।", + "methodLabel": "स्थानांतरण विधि", + "methodPreviewError": "स्थानांतरण विधि का पूर्वावलोकन नहीं किया जा सका। प्रारंभ करने पर सर्वर फिर भी एक विधि चुनेगा।", + "methodPreviewLoading": "स्थानांतरण विधि की गणना कर रहा है…", + "methodPreviewScanSummary": "{{fileCount}} फ़ाइलें, कुल {{totalSize}} (स्रोत होस्ट पर स्कैन किया गया)।", + "methodPreviewWillUseItemSftp": "उपयोग करेगा: प्रति-फ़ाइल SFTP", + "methodPreviewWillUseTar": "उपयोग करेगा: Tar संग्रह", + "methodReason": { + "user_item_sftp": "आपने प्रति-फ़ाइल SFTP चुना।", + "user_tar": "आपने tar संग्रह चुना।", + "tar_unavailable": "Tar एक या दोनों होस्ट पर उपलब्ध नहीं है — इसके बजाय प्रति-फ़ाइल SFTP का उपयोग किया जाएगा।", + "windows_host": "कोई Windows होस्ट शामिल है — tar का उपयोग नहीं होता।", + "auto_multi_large": "ऑटो: संपीड़न योग्य डेटा वाली एक बड़ी फ़ाइल ({{largestSize}}) सहित अनेक फ़ाइलें — tar एकल स्थानांतरण में बंडल करता है।", + "auto_single_large_in_archive": "ऑटो: इस सेट में एक बड़ी फ़ाइल ({{largestSize}}) — प्रति-फ़ाइल SFTP।", + "auto_many_incompressible": "ऑटो: अधिकतर असंपीड़नीय डेटा — प्रति-फ़ाइल SFTP।", + "auto_many_files": "ऑटो: बहुत सारी फ़ाइलें ({{fileCount}}) — tar प्रति-फ़ाइल ओवरहेड कम करता है।", + "auto_default": "ऑटो: इस सेट के लिए प्रति-फ़ाइल SFTP।" + }, + "methodTar": "Tar संग्रह", + "methodTarHint": "स्रोत पर संपीड़ित करें, एक संग्रह स्थानांतरित करें, गंतव्य पर निष्कर्षण करें। दोनों यूनिक्स होस्ट पर tar आवश्यक है।", + "metricsCompress": "स्रोत पर संपीड़न: {{duration}}", + "metricsExtract": "गंतव्य पर निष्कर्षण: {{duration}}", + "metricsPrepare": "गंतव्य तैयारी: {{duration}}", + "metricsRouteBenchmark": "रूट प्रोब — डायरेक्ट: {{direct}}, रिले: {{relay}}", + "metricsSourceDelete": "स्रोत से हटाना: {{duration}}", + "metricsTotal": "कुल: {{duration}}", + "metricsTransfer": "एंड-टू-एंड: {{throughput}} ({{duration}})", + "metricsVerify": "SHA-256 सत्यापित: {{duration}}", + "moveFolderToHost": "फ़ोल्डर होस्ट पर स्थानांतरित करें…", + "moveItemsToHost": "{{count}} आइटम होस्ट पर स्थानांतरित करें…", + "moveToHost": "होस्ट पर ले जाएँ…", + "noHostsConnected": "कोई अन्य फ़ाइल प्रबंधक होस्ट उपलब्ध नहीं है।", + "noHostsConnectedHint": "होस्ट प्रबंधक में फ़ाइल प्रबंधक सक्षम किए हुए एक और SSH होस्ट जोड़ें।", + "parallelSegmentsHint": "बड़ी फ़ाइलें 256 MB टुकड़ों में विभाजित होती हैं। एकाधिक लेन उच्च कुल थ्रूपुट के लिए अलग-अलग कनेक्शन का उपयोग करती हैं (जैसे कई स्थानांतरण प्रारंभ करना)।", + "parallelSegmentsLabel": "समानांतर स्थानांतरण लेन", + "parallelSegmentsOption": "{{count}} लेन", + "progressBenchmarking": "सबसे तेज़ स्थानांतरण मार्ग का चयन करना…", + "progressBytes": "{{transferred}} / {{total}}", + "progressCancel": "रद्द करें", + "progressCancelling": "रद्द कर रहा है…", + "progressCompressing": "स्रोत होस्ट पर संपीड़ित कर रहा है…", + "progressExtracting": "गंतव्य पर निष्कर्षण कर रहा है…", + "progressItems": "{{current}} / {{total}} फ़ाइलें", + "progressReconnecting": "पुनः कनेक्ट हो रहा है…", + "progressStalled": "रुका हुआ", + "progressTotalSpeed": "{{speed}} कुल ({{lanes}} लेन)", + "progressTransferring": "डेटा स्थानांतरित कर रहा है…", + "progressTransferringItems": "फ़ाइलें स्थानांतरित कर रहा है ({{current}} / {{total}})…", + "progressVerifying": "फ़ाइल की अखंडता का सत्यापन…", + "recentDestinations": "हाल के गंतव्य", + "resumedHint": "किसी अन्य विंडो में शुरू हुए सक्रिय स्थानांतरण से पुनः जुड़ा।", + "retryTransfer": "पुनः प्रयास करें", + "retryTransferError": "पुनः प्रयास विफल रहा।", + "selectDestinationHost": "गंतव्य होस्ट चुनें", + "transferCancelled": "स्थानांतरण रद्द किया गया।", + "transferCancelledCopyHint": "आंशिक फ़ाइलें गंतव्य पर रह सकती हैं।", + "transferCancelledMoveHint": "आंशिक फ़ाइलें गंतव्य पर रह सकती हैं। स्रोत फ़ाइलें नहीं हटाई गईं।", + "transferError": "स्थानांतरण विफल", + "transferFailedRetryHint": "आंशिक डेटा गंतव्य पर रखा गया था। कनेक्शन वापस आने पर पुनः प्रयास फिर से शुरू होगा।", + "transferPartialHint": "स्थानांतरित नहीं किया जा सका: {{paths}}", + "transferSuccess": "स्थानांतरण पूर्ण" } } diff --git a/plugins/file-manager/locales/translated/hu_HU.json b/plugins/file-manager/locales/translated/hu_HU.json index e1b7edd4e..7ca100da3 100644 --- a/plugins/file-manager/locales/translated/hu_HU.json +++ b/plugins/file-manager/locales/translated/hu_HU.json @@ -382,7 +382,10 @@ "defaultPathLabel": "Alapértelmezett elérési út", "fileManagerPathHint": "A könyvtár, amely megnyílik, amikor a fájlkezelő elindul ehhez a gazdagéphez.", "fileManagerUrlCopied": "Fájlkezelő URL-címe másolva", - "copyFileManagerUrlAction": "Fájlkezelő URL-címének másolása" + "copyFileManagerUrlAction": "Fájlkezelő URL-címének másolása", + "docsLink": "Dokumentumok megtekintése", + "hostNotFound": "Nem található gazdagép", + "loadingHost": "Gazdagép betöltése..." }, "settings": { "host": { @@ -406,5 +409,105 @@ "nav": { "sftp": "SFTP", "files": "Fájlok" + }, + "onboarding": { + "feature_files": "Fájlkezelő", + "feature_files_desc": "Böngésszen, töltsön fel, töltsön le és szerkeszthessen fájlokat SFTP-n keresztül az alkalmazás elhagyása nélkül." + }, + "terminal": { + "runTitle": "Futás {{command}} - {{host}}", + "terminalTitle": "Terminál - {{host}}", + "terminalWithPath": "Terminál - {{host}}:{{path}}" + }, + "transfer": { + "browseFolders": "Célmappák böngészése", + "browsePathError": "Nem sikerült megnyitni ezt az elérési utat a célgépen.", + "browsePathWillBeCreated": "Ez a mappa még nem létezik. Létrejön, amikor az átvitel megkezdődik.", + "cancel": "Mégsem", + "cleanupDestFiles": "Takarítási célpont", + "cleanupDestFilesError": "A tisztítás sikertelen", + "cleanupDestFilesNothing": "Nincs mit takarítani a célállomáson", + "cleanupDestFilesPartial": "Néhány részleges fájlt nem sikerült eltávolítani", + "cleanupDestFilesSuccess": "Részleges fájlok eltávolítva a célhelyről", + "confirmCopy": "Másolat", + "confirmMove": "Mozog", + "copyFolderToHost": "Mappa másolása a… gazdagépre", + "copyItemsToHost": "Másolja a {{count}} elemet a… hosztba", + "copyToHost": "Másolás a… gazdagépre", + "destinationPath": "Célútvonal", + "destMustBeDirectory": "Több elem átviteléhez a célnak egy könyvtárnak kell lennie", + "goUp": "Felmegy", + "hostAuthRequired": "Hitelesítés szükséges — először nyissa meg a Fájlkezelőt ezen a gépen", + "hostConnecting": "… csatlakoztatása", + "hostConnectionFailed": "Kapcsolódás sikertelen", + "hostDisconnected": "Nincs csatlakoztatva", + "hostReady": "Kész", + "itemsSummary": "{{count}} elem", + "jumpHostLimitation": "Mindkét gépnek elérhetőnek kell lennie a Termix szerverről. A közvetlen gépközi útvonalválasztás nem támogatott.", + "methodAuto": "Autó", + "methodAutoHint": "A fájlok száma, mérete és tömöríthetősége alapján választja ki a tar vagy a fájlonkénti SFTP protokollt. Az egyes fájlok mindig folyamatos SFTP-t használnak.", + "methodItemSftp": "Fájlonkénti SFTP", + "methodItemSftpHint": "Minden fájlt külön-külön átvihet SFTP-n keresztül. Minden gazdagépen működik, beleértve a Windowst is.", + "methodItemSftpLimitation": "Minden fájl ugyanazt az SFTP-folyamot használja, mint egyetlen fájl másolata, egymás után. A folyamat az összes fájlban összevonódik, így a sáv lassan mozog nagy fájlok esetén.", + "methodLabel": "Átviteli módszer", + "methodPreviewError": "Nem sikerült megtekinteni az átviteli módot. A szerver továbbra is kiválaszt egy módszert az indításkor.", + "methodPreviewLoading": "Átviteli módszer kiszámítása…", + "methodPreviewScanSummary": "{{fileCount}} fájl, {{totalSize}} összesen (a forrásgépen beolvasva).", + "methodPreviewWillUseItemSftp": "Használat: Fájlonkénti SFTP", + "methodPreviewWillUseTar": "Felhasználás: Tar archívum", + "methodReason": { + "user_item_sftp": "Fájlonkénti SFTP-t választottál.", + "user_tar": "A tar archívumot választottad.", + "tar_unavailable": "A Tar nem érhető el az egyik vagy mindkét hoszton – helyette fájlonkénti SFTP-t fog használni.", + "windows_host": "Egy Windows gazdagép érintett – tar-t nem használunk.", + "auto_multi_large": "Automatikus: több fájl, beleértve egy nagy fájlt ({{largestSize}}) tömöríthető adatokkal — a tar egyetlen átvitelbe csomagolja.", + "auto_single_large_in_archive": "Automatikus: egy nagy fájl ({{largestSize}}) ebben a készletben — fájlonként SFTP.", + "auto_many_incompressible": "Automatikus: többnyire tömöríthetetlen adatok — fájlonkénti SFTP.", + "auto_many_files": "Auto: sok fájl ({{fileCount}}) — a tar csökkenti a fájlonkénti terhelést.", + "auto_default": "Automatikus: fájlonkénti SFTP ehhez a készlethez." + }, + "methodTar": "Tar archívum", + "methodTarHint": "Tömörítés a forráskódban, egy archívum átvitele, kibontás a célkódban. Tar fájlt igényel mindkét Unix gépen.", + "metricsCompress": "Tömörítés forráskód szerint: {{duration}}", + "metricsExtract": "Kivonat a rendeltetési helyen: {{duration}}", + "metricsPrepare": "Célhely előkészítése: {{duration}}", + "metricsRouteBenchmark": "Útvonalszonda — közvetlen: {{direct}}, relé: {{relay}}", + "metricsSourceDelete": "Eltávolítás a forrásból: {{duration}}", + "metricsTotal": "Összesen: {{duration}}", + "metricsTransfer": "Végtől végig: {{throughput}} ({{duration}})", + "metricsVerify": "SHA-256 ellenőrizve: {{duration}}", + "moveFolderToHost": "Mappa áthelyezése a… gazdagépre", + "moveItemsToHost": "Áthelyez {{count}} elemet a… tárhelyre", + "moveToHost": "Áthelyezés a… gazdagépre", + "noHostsConnected": "Nincsenek más elérhető fájlkezelő gazdagépek.", + "noHostsConnectedHint": "Adjon hozzá egy másik SSH-hosztot, amelynél a Fájlkezelő engedélyezve van a Host Managerben.", + "parallelSegmentsHint": "A nagy fájlokat 256 MB-os darabokra osztja a rendszer. Több sáv külön kapcsolatokat használ (például több átvitel indítása) a nagyobb összátviteli sebesség érdekében.", + "parallelSegmentsLabel": "Párhuzamos átszállósávok", + "parallelSegmentsOption": "{{count}} sávok", + "progressBenchmarking": "A leggyorsabb átszállási útvonal kiválasztása…", + "progressBytes": "{{transferred}} / {{total}}", + "progressCancel": "Mégsem", + "progressCancelling": "Törlés…", + "progressCompressing": "Tömörítés a forrásgépen…", + "progressExtracting": "Kibontás a célállomáson…", + "progressItems": "{{current}} / {{total}} fájlok", + "progressReconnecting": "Újracsatlakozás…", + "progressStalled": "Elakadt", + "progressTotalSpeed": "{{speed}} összesen ({{lanes}} sávok)", + "progressTransferring": "Adatátvitel…", + "progressTransferringItems": "Fájlok átvitele ({{current}} / {{total}})…", + "progressVerifying": "Fájl integritásának ellenőrzése…", + "recentDestinations": "Legutóbbi úti célok", + "resumedHint": "Újracsatlakozva egy másik ablakban indított aktív átvitelhez.", + "retryTransfer": "Újrapróbálkozás", + "retryTransferError": "Újrapróbálkozás sikertelen", + "selectDestinationHost": "Célállomás kiválasztása", + "transferCancelled": "Átutalás törölve", + "transferCancelledCopyHint": "Részleges fájlok maradhatnak a célhelyen.", + "transferCancelledMoveHint": "Részleges fájlok maradhatnak a célhelyen. A forrásfájlok nem lettek eltávolítva.", + "transferError": "Átvitel sikertelen", + "transferFailedRetryHint": "Részleges adatok maradtak a célállomáson. Az újrapróbálkozás a kapcsolat helyreállásakor folytatódik.", + "transferPartialHint": "Nem sikerült átvinni: {{paths}}", + "transferSuccess": "Átvitel befejezve" } } diff --git a/plugins/file-manager/locales/translated/id_ID.json b/plugins/file-manager/locales/translated/id_ID.json index 02e86d710..fdb148fc2 100644 --- a/plugins/file-manager/locales/translated/id_ID.json +++ b/plugins/file-manager/locales/translated/id_ID.json @@ -382,7 +382,10 @@ "defaultPathLabel": "Jalur Default", "fileManagerPathHint": "Direktori yang akan dibuka saat pengelola file diluncurkan untuk host ini.", "fileManagerUrlCopied": "URL Pengelola File disalin", - "copyFileManagerUrlAction": "Salin URL Pengelola File" + "copyFileManagerUrlAction": "Salin URL Pengelola File", + "docsLink": "Lihat dokumen", + "hostNotFound": "Host tidak ditemukan", + "loadingHost": "Memuat host..." }, "settings": { "host": { @@ -406,5 +409,105 @@ "nav": { "sftp": "SFTP", "files": "Berkas" + }, + "onboarding": { + "feature_files": "Pengelola berkas", + "feature_files_desc": "Jelajahi, unggah, unduh, dan edit file melalui SFTP tanpa meninggalkan aplikasi." + }, + "terminal": { + "runTitle": "Menjalankan {{command}} - {{host}}", + "terminalTitle": "Terminal - {{host}}", + "terminalWithPath": "Terminal - {{host}}:{{path}}" + }, + "transfer": { + "browseFolders": "Telusuri folder tujuan", + "browsePathError": "Tidak dapat membuka jalur ini pada host tujuan.", + "browsePathWillBeCreated": "Folder ini belum ada. Folder ini akan dibuat saat transfer dimulai.", + "cancel": "Membatalkan", + "cleanupDestFiles": "Tujuan pembersihan", + "cleanupDestFilesError": "Pembersihan gagal", + "cleanupDestFilesNothing": "Tidak ada yang perlu dibersihkan di tempat tujuan.", + "cleanupDestFilesPartial": "Beberapa file parsial tidak dapat dihapus.", + "cleanupDestFilesSuccess": "File parsial telah dihapus dari tujuan.", + "confirmCopy": "Menyalin", + "confirmMove": "Bergerak", + "copyFolderToHost": "Salin folder ke host…", + "copyItemsToHost": "Salin {{count}} item ke host…", + "copyToHost": "Salin ke host…", + "destinationPath": "Jalur tujuan", + "destMustBeDirectory": "Tujuan harus berupa direktori untuk transfer multi-item.", + "goUp": "Naik", + "hostAuthRequired": "Diperlukan autentikasi — buka File Manager di host ini terlebih dahulu.", + "hostConnecting": "Menghubungkan…", + "hostConnectionFailed": "Koneksi gagal", + "hostDisconnected": "Tidak terhubung", + "hostReady": "Siap", + "itemsSummary": "{{count}} item", + "jumpHostLimitation": "Kedua host harus dapat dijangkau dari server Termix. Perutean langsung antar host tidak didukung.", + "methodAuto": "Mobil", + "methodAutoHint": "Memilih antara tar atau SFTP per-file berdasarkan jumlah file, ukuran, dan kemampuan kompresi. File tunggal selalu menggunakan SFTP streaming.", + "methodItemSftp": "SFTP per file", + "methodItemSftpHint": "Transfer setiap file secara individual melalui SFTP. Berfungsi di semua host termasuk Windows.", + "methodItemSftpLimitation": "Setiap berkas menggunakan aliran SFTP yang sama sebagai salinan berkas tunggal, satu demi satu. Kemajuan digabungkan di semua berkas, sehingga bilah kemajuan bergerak lambat selama pemrosesan berkas berukuran besar.", + "methodLabel": "Metode transfer", + "methodPreviewError": "Metode transfer tidak dapat dipratinjau. Server akan tetap memilih metode saat Anda memulai.", + "methodPreviewLoading": "Metode perhitungan transfer…", + "methodPreviewScanSummary": "{{fileCount}} berkas, {{totalSize}} total (dipindai pada host sumber).", + "methodPreviewWillUseItemSftp": "Akan menggunakan: SFTP per file", + "methodPreviewWillUseTar": "Akan menggunakan: Arsip Tar", + "methodReason": { + "user_item_sftp": "Anda memilih SFTP per-file.", + "user_tar": "Anda memilih arsip tar.", + "tar_unavailable": "Tar tidak tersedia di salah satu atau kedua host — SFTP per-file akan digunakan sebagai gantinya.", + "windows_host": "Sistem operasi yang digunakan adalah Windows — tar tidak digunakan.", + "auto_multi_large": "Otomatis: beberapa file termasuk file besar ({{largestSize}}) dengan data yang dapat dikompresi — tar menggabungkan menjadi satu transfer.", + "auto_single_large_in_archive": "Otomatis: satu file besar ({{largestSize}}) dalam set ini — SFTP per file.", + "auto_many_incompressible": "Otomatis: sebagian besar data tidak dapat dikompresi — SFTP per file.", + "auto_many_files": "Otomatis: banyak file ({{fileCount}}) — tar mengurangi overhead per file.", + "auto_default": "Otomatis: SFTP per-file untuk set ini." + }, + "methodTar": "Arsip Tar", + "methodTarHint": "Kompres di sumber, transfer satu arsip, ekstrak di tujuan. Membutuhkan tar di kedua host Unix.", + "metricsCompress": "Kompres pada sumber: {{duration}}", + "metricsExtract": "Ekstrak pada tujuan: {{duration}}", + "metricsPrepare": "Siapkan tujuan: {{duration}}", + "metricsRouteBenchmark": "Pemeriksaan rute — langsung: {{direct}}, relai: {{relay}}", + "metricsSourceDelete": "Hapus dari sumber: {{duration}}", + "metricsTotal": "Total: {{duration}}", + "metricsTransfer": "Ujung ke ujung: {{throughput}} ({{duration}})", + "metricsVerify": "SHA-256 terverifikasi: {{duration}}", + "moveFolderToHost": "Pindahkan folder ke host…", + "moveItemsToHost": "Pindahkan {{count}} item ke host…", + "moveToHost": "Pindah ke host…", + "noHostsConnected": "Tidak ada penyedia pengelola file lain yang tersedia.", + "noHostsConnectedHint": "Tambahkan host SSH lain dengan File Manager diaktifkan di Host Manager.", + "parallelSegmentsHint": "File berukuran besar dibagi menjadi bagian-bagian berukuran 256 MB. Beberapa jalur menggunakan koneksi terpisah (seperti memulai beberapa transfer) untuk throughput total yang lebih tinggi.", + "parallelSegmentsLabel": "Jalur transfer paralel", + "parallelSegmentsOption": "{{count}} jalur", + "progressBenchmarking": "Memilih rute transfer tercepat…", + "progressBytes": "{{transferred}} / {{total}}", + "progressCancel": "Membatalkan", + "progressCancelling": "Membatalkan…", + "progressCompressing": "Kompresi pada host sumber…", + "progressExtracting": "Mengekstraksi pada tujuan…", + "progressItems": "berkas {{current}} / {{total}}", + "progressReconnecting": "Menghubungkan kembali…", + "progressStalled": "Terhenti", + "progressTotalSpeed": "{{speed}} total ({{lanes}} lajur)", + "progressTransferring": "Mentransfer data…", + "progressTransferringItems": "Mentransfer berkas ({{current}} dari {{total}})…", + "progressVerifying": "Memverifikasi integritas file…", + "recentDestinations": "Destinasi terkini", + "resumedHint": "Terhubung kembali ke transfer aktif yang dimulai di jendela lain.", + "retryTransfer": "Mencoba kembali", + "retryTransferError": "Percobaan ulang gagal.", + "selectDestinationHost": "Pilih host tujuan", + "transferCancelled": "Transfer dibatalkan", + "transferCancelledCopyHint": "File yang tidak lengkap mungkin masih tersisa di tujuan.", + "transferCancelledMoveHint": "Sebagian berkas mungkin masih tersisa di tujuan. Berkas sumber tidak dihapus.", + "transferError": "Transfer gagal", + "transferFailedRetryHint": "Sebagian data tersimpan di tujuan. Upaya pengulangan akan dilanjutkan saat koneksi kembali pulih.", + "transferPartialHint": "Tidak dapat mentransfer: {{paths}}", + "transferSuccess": "Transfer selesai" } } diff --git a/plugins/file-manager/locales/translated/it_IT.json b/plugins/file-manager/locales/translated/it_IT.json index 78b48ef23..1dd34c9fa 100644 --- a/plugins/file-manager/locales/translated/it_IT.json +++ b/plugins/file-manager/locales/translated/it_IT.json @@ -382,7 +382,10 @@ "defaultPathLabel": "Percorso predefinito", "fileManagerPathHint": "La directory da aprire all'avvio del file manager per questo host.", "fileManagerUrlCopied": "URL file manager copiato", - "copyFileManagerUrlAction": "Copia URL File Manager" + "copyFileManagerUrlAction": "Copia URL File Manager", + "docsLink": "Visualizza documentazione", + "hostNotFound": "Host non trovato", + "loadingHost": "Caricamento host..." }, "settings": { "host": { @@ -406,5 +409,105 @@ "nav": { "sftp": "SFTP", "files": "File" + }, + "onboarding": { + "feature_files": "Gestore file", + "feature_files_desc": "Esplora, carica, scarica e modifica file tramite SFTP senza uscire dall'applicazione." + }, + "terminal": { + "runTitle": "Esecuzione {{command}} - {{host}}", + "terminalTitle": "Terminale - {{host}}", + "terminalWithPath": "Terminale - {{host}}:{{path}}" + }, + "transfer": { + "browseFolders": "Sfoglia cartelle di destinazione", + "browsePathError": "Impossibile aprire questo percorso sull'host di destinazione.", + "browsePathWillBeCreated": "Questa cartella non esiste ancora. Verrà creata all'avvio del trasferimento.", + "cancel": "Annulla", + "cleanupDestFiles": "Pulisci destinazione", + "cleanupDestFilesError": "Pulizia fallita", + "cleanupDestFilesNothing": "Niente da pulire sulla destinazione", + "cleanupDestFilesPartial": "Alcuni file parziali non sono stati rimossi", + "cleanupDestFilesSuccess": "File parziali rimossi dalla destinazione", + "confirmCopy": "Copia", + "confirmMove": "Sposta", + "copyFolderToHost": "Copia cartella sull'host…", + "copyItemsToHost": "Copia {{count}} elementi su host…", + "copyToHost": "Copia su host…", + "destinationPath": "Percorso di destinazione", + "destMustBeDirectory": "La destinazione deve essere una directory per il trasferimento di più elementi", + "goUp": "Salire", + "hostAuthRequired": "Autenticazione richiesta — aprire prima File Manager su questo host", + "hostConnecting": "Connessione in corso…", + "hostConnectionFailed": "Connessione non riuscita", + "hostDisconnected": "Non connesso", + "hostReady": "Pronto", + "itemsSummary": "{{count}} elementi", + "jumpHostLimitation": "Entrambi gli host devono essere raggiungibili dal server Termix. Il routing diretto host-to-host non è supportato.", + "methodAuto": "Auto", + "methodAutoHint": "Sceglie tar o SFTP per file in base al numero, dimensione e comprimibilità dei file. I file singoli usano sempre SFTP in streaming.", + "methodItemSftp": "SFTP per file", + "methodItemSftpHint": "Trasferisce ogni file singolarmente tramite SFTP. Funziona su tutti gli host, incluso Windows.", + "methodItemSftpLimitation": "Ogni file utilizza lo stesso flusso SFTP come una copia di file singolo, uno dopo l'altro. L'avanzamento è combinato su tutti i file, quindi la barra si muove lentamente durante i file di grandi dimensioni.", + "methodLabel": "Metodo di trasferimento", + "methodPreviewError": "Impossibile visualizzare l'anteprima del metodo di trasferimento. Il server sceglierà comunque un metodo all'avvio.", + "methodPreviewLoading": "Calcolo del metodo di trasferimento…", + "methodPreviewScanSummary": "{{fileCount}} file, {{totalSize}} in totale (scansionati sull'host sorgente).", + "methodPreviewWillUseItemSftp": "Userà: SFTP per file", + "methodPreviewWillUseTar": "Userà: Archivio Tar", + "methodReason": { + "user_item_sftp": "Hai scelto SFTP per-file.", + "user_tar": "Hai scelto archivio tar.", + "tar_unavailable": "Tar non è disponibile su uno o entrambi gli host — verrà utilizzato SFTP per-file.", + "windows_host": "È coinvolto un host Windows — tar non viene utilizzato.", + "auto_multi_large": "Auto: più file, incluso un file grande ({{largestSize}}) con dati comprimibili — tar li raggruppa in un unico trasferimento.", + "auto_single_large_in_archive": "Auto: un file grande ({{largestSize}}) in questo set — SFTP per-file.", + "auto_many_incompressible": "Auto: dati per lo più incomprimibili — SFTP per-file.", + "auto_many_files": "Auto: molti file ({{fileCount}}) — tar riduce il sovraccarico per-file.", + "auto_default": "Auto: SFTP per-file per questo set." + }, + "methodTar": "Archivio Tar", + "methodTarHint": "Comprime sul sorgente, trasferisce un archivio, estrae sulla destinazione. Richiede tar su entrambi gli host Unix.", + "metricsCompress": "Compressione sul sorgente: {{duration}}", + "metricsExtract": "Estrazione sulla destinazione: {{duration}}", + "metricsPrepare": "Prepara destinazione: {{duration}}", + "metricsRouteBenchmark": "Sondaggio di percorso — diretto: {{direct}}, relè: {{relay}}", + "metricsSourceDelete": "Rimozione dal sorgente: {{duration}}", + "metricsTotal": "Totale: {{duration}}", + "metricsTransfer": "End-to-end: {{throughput}} ({{duration}})", + "metricsVerify": "SHA-256 verificato: {{duration}}", + "moveFolderToHost": "Sposta cartella sull'host…", + "moveItemsToHost": "Sposta {{count}} elementi sull'host…", + "moveToHost": "Sposta su host…", + "noHostsConnected": "Nessun altro host con File Manager disponibile.", + "noHostsConnectedHint": "Aggiungi un altro host SSH con File Manager abilitato nella Gestione Host.", + "parallelSegmentsHint": "I file di grandi dimensioni vengono suddivisi in blocchi da 256 MB. Più corsie utilizzano connessioni separate (come avviare più trasferimenti) per una maggiore velocità complessiva.", + "parallelSegmentsLabel": "Corsie di trasferimento parallele", + "parallelSegmentsOption": "{{count}} corsie", + "progressBenchmarking": "Selezione del percorso di trasferimento più veloce…", + "progressBytes": "{{transferred}} / {{total}}", + "progressCancel": "Annulla", + "progressCancelling": "Annullamento in corso…", + "progressCompressing": "Compressione sull'host sorgente…", + "progressExtracting": "Estrazione sulla destinazione…", + "progressItems": "{{current}} / {{total}} file", + "progressReconnecting": "Riconnessione…", + "progressStalled": "Bloccato", + "progressTotalSpeed": "{{speed}} totale ({{lanes}} corsie)", + "progressTransferring": "Trasferimento dati…", + "progressTransferringItems": "Trasferimento file ({{current}} di {{total}})…", + "progressVerifying": "Verifica dell'integrità del file…", + "recentDestinations": "Destinazioni recenti", + "resumedHint": "Riconnesso a un trasferimento attivo avviato in un'altra finestra.", + "retryTransfer": "Riprova", + "retryTransferError": "Riprova fallita", + "selectDestinationHost": "Seleziona host di destinazione", + "transferCancelled": "Trasferimento annullato", + "transferCancelledCopyHint": "Potrebbero rimanere file parziali sulla destinazione.", + "transferCancelledMoveHint": "Potrebbero rimanere file parziali sulla destinazione. I file sorgente non sono stati rimossi.", + "transferError": "Trasferimento non riuscito", + "transferFailedRetryHint": "I dati parziali sono stati conservati sulla destinazione. Il nuovo tentativo riprenderà quando la connessione sarà ripristinata.", + "transferPartialHint": "Impossibile trasferire: {{paths}}", + "transferSuccess": "Trasferimento completato" } } diff --git a/plugins/file-manager/locales/translated/ja_JP.json b/plugins/file-manager/locales/translated/ja_JP.json index a1d5298aa..5ce62d15f 100644 --- a/plugins/file-manager/locales/translated/ja_JP.json +++ b/plugins/file-manager/locales/translated/ja_JP.json @@ -382,7 +382,10 @@ "defaultPathLabel": "デフォルトパス", "fileManagerPathHint": "このホストのファイルマネージャー起動時に開くディレクトリ", "fileManagerUrlCopied": "ファイルマネージャーURLをコピーしました", - "copyFileManagerUrlAction": "ファイルマネージャー URL をコピー" + "copyFileManagerUrlAction": "ファイルマネージャー URL をコピー", + "docsLink": "ドキュメントを表示", + "hostNotFound": "ホストが見つかりません", + "loadingHost": "ホストを読み込み中..." }, "settings": { "host": { @@ -406,5 +409,105 @@ "nav": { "sftp": "SFTP", "files": "ファイル" + }, + "onboarding": { + "feature_files": "ファイルマネージャー", + "feature_files_desc": "アプリを離れることなく、SFTP経由でファイルの閲覧、アップロード、ダウンロード、編集が可能です。" + }, + "terminal": { + "runTitle": "{{command}} 実行中 - {{host}}", + "terminalTitle": "ターミナル - {{host}}", + "terminalWithPath": "ターミナル - {{host}}:{{path}}" + }, + "transfer": { + "browseFolders": "転送先フォルダを参照", + "browsePathError": "転送先ホストでこのパスを開けませんでした。", + "browsePathWillBeCreated": "このフォルダはまだ存在しません。転送開始時に作成されます。", + "cancel": "キャンセル", + "cleanupDestFiles": "宛先をクリーンアップ", + "cleanupDestFilesError": "クリーンアップに失敗しました", + "cleanupDestFilesNothing": "宛先にクリーンアップするものはありません", + "cleanupDestFilesPartial": "一部の部分的なファイルを削除できませんでした", + "cleanupDestFilesSuccess": "宛先から部分的なファイルを削除しました", + "confirmCopy": "コピー", + "confirmMove": "移動", + "copyFolderToHost": "フォルダをホストにコピー…", + "copyItemsToHost": "{{count}}個のアイテムをホストにコピー...", + "copyToHost": "ホストにコピー...", + "destinationPath": "転送先パス", + "destMustBeDirectory": "複数アイテムの転送では転送先はディレクトリである必要があります", + "goUp": "上へ", + "hostAuthRequired": "認証が必要です — まずこのホストでファイルマネージャを開いてください", + "hostConnecting": "接続中…", + "hostConnectionFailed": "接続に失敗しました", + "hostDisconnected": "未接続", + "hostReady": "準備完了", + "itemsSummary": "{{count}} アイテム", + "jumpHostLimitation": "両方のホストが Termix サーバーから到達可能である必要があります。ホスト間直接ルーティングはサポートされていません。", + "methodAuto": "自動", + "methodAutoHint": "ファイル数、サイズ、圧縮可能性に基づいて tar またはファイル単位 SFTP を選択します。単一ファイルは常にストリーミング SFTP を使用します。", + "methodItemSftp": "ファイル単位 SFTP", + "methodItemSftpHint": "各ファイルを個別に SFTP で転送します。Windows を含むすべてのホストで動作します。", + "methodItemSftpLimitation": "各ファイルは単一ファイルコピーと同じ SFTP ストリームを順次使用します。進捗は全ファイルで統合されるため、大きなファイルではバーの動きが遅くなります。", + "methodLabel": "転送方式", + "methodPreviewError": "転送方式をプレビューできませんでした。開始時にサーバーが方式を選択します。", + "methodPreviewLoading": "転送方式を計算中…", + "methodPreviewScanSummary": "{{fileCount}} ファイル、合計 {{totalSize}} (ソースホストでスキャン)。", + "methodPreviewWillUseItemSftp": "使用方式: ファイル単位 SFTP", + "methodPreviewWillUseTar": "使用方式: Tar アーカイブ", + "methodReason": { + "user_item_sftp": "ファイルごとのSFTPを選択しました。", + "user_tar": "tarアーカイブを選択しました。", + "tar_unavailable": "一方または両方のホストでtarが利用できないため、代わりにファイルごとのSFTPが使用されます。", + "windows_host": "Windows ホストが含まれているため、tar は使用されません。", + "auto_multi_large": "自動: 複数ファイルに大きな圧縮可能なファイル ({{largestSize}}) が含まれるため、tarで1回の転送にまとめます。", + "auto_single_large_in_archive": "自動: このセットに1つの大きなファイル ({{largestSize}}) があるため、ファイルごとのSFTPです。", + "auto_many_incompressible": "自動: ほとんど圧縮不可能なデータのため、ファイルごとのSFTPです。", + "auto_many_files": "自動: 多数のファイル ({{fileCount}}) があるため、tarでファイルごとのオーバーヘッドを削減します。", + "auto_default": "自動: このセットではファイルごとのSFTPです。" + }, + "methodTar": "Tar アーカイブ", + "methodTarHint": "ソースで圧縮し、1つのアーカイブを転送し、送信先で展開します。両方の Unix ホストに tar が必要です。", + "metricsCompress": "送信元での圧縮: {{duration}}", + "metricsExtract": "送信先で展開: {{duration}}", + "metricsPrepare": "転送先の準備: {{duration}}", + "metricsRouteBenchmark": "ルートプローブ — 直接: {{direct}}、リレー: {{relay}}", + "metricsSourceDelete": "送信元から削除: {{duration}}", + "metricsTotal": "合計: {{duration}}", + "metricsTransfer": "エンドツーエンド: {{throughput}} ({{duration}})", + "metricsVerify": "SHA-256検証済み: {{duration}}", + "moveFolderToHost": "フォルダをホストに移動…", + "moveItemsToHost": "{{count}} アイテムをホストへ移動…", + "moveToHost": "ホストに移動...", + "noHostsConnected": "利用可能な他のファイルマネージャホストがありません。", + "noHostsConnectedHint": "ホストマネージャでファイルマネージャが有効なSSHホストを追加してください。", + "parallelSegmentsHint": "大きなファイルは 256 MB のチャンクに分割されます。複数レーンでは個別の接続を使用し (複数の転送を開始するように)、合計スループットが向上します。", + "parallelSegmentsLabel": "並列転送レーン", + "parallelSegmentsOption": "{{count}} レーン", + "progressBenchmarking": "最速の転送ルートを選択…", + "progressBytes": "{{transferred}} / {{total}}", + "progressCancel": "キャンセル", + "progressCancelling": "キャンセル中…", + "progressCompressing": "ソースホストで圧縮中…", + "progressExtracting": "送信先で展開中…", + "progressItems": "{{current}} / {{total}} ファイル", + "progressReconnecting": "再接続中…", + "progressStalled": "停滞中", + "progressTotalSpeed": "合計 {{speed}} ({{lanes}} レーン)", + "progressTransferring": "データ転送中…", + "progressTransferringItems": "ファイル転送中 ({{current}} / {{total}})…", + "progressVerifying": "ファイルの整合性を検証中…", + "recentDestinations": "最近の転送先", + "resumedHint": "別のウィンドウで開始されたアクティブな転送に再接続しました。", + "retryTransfer": "再試行", + "retryTransferError": "再試行に失敗しました", + "selectDestinationHost": "転送先ホストを選択", + "transferCancelled": "転送がキャンセルされました", + "transferCancelledCopyHint": "部分的なファイルが宛先に残る可能性があります。", + "transferCancelledMoveHint": "部分的なファイルが宛先に残る可能性があります。ソースファイルは削除されていません。", + "transferError": "転送に失敗しました", + "transferFailedRetryHint": "部分的なデータが宛先に保持されました。接続が復旧したら再試行が再開されます。", + "transferPartialHint": "転送できませんでした: {{paths}}", + "transferSuccess": "転送が完了しました" } } diff --git a/plugins/file-manager/locales/translated/ko_KR.json b/plugins/file-manager/locales/translated/ko_KR.json index d15608146..4004c3fb5 100644 --- a/plugins/file-manager/locales/translated/ko_KR.json +++ b/plugins/file-manager/locales/translated/ko_KR.json @@ -382,7 +382,10 @@ "defaultPathLabel": "기본 경로", "fileManagerPathHint": "이 호스트의 파일 관리자 실행 시 열리는 디렉터리입니다.", "fileManagerUrlCopied": "파일 관리자 URL 복사됨", - "copyFileManagerUrlAction": "파일 관리자 URL 복사" + "copyFileManagerUrlAction": "파일 관리자 URL 복사", + "docsLink": "문서 보기", + "hostNotFound": "호스트를 찾을 수 없습니다", + "loadingHost": "호스트 로드 중..." }, "settings": { "host": { @@ -406,5 +409,105 @@ "nav": { "sftp": "SFTP", "files": "파일" + }, + "onboarding": { + "feature_files": "파일 관리자", + "feature_files_desc": "앱을 종료하지 않고 SFTP를 통해 파일을 검색, 업로드, 다운로드 및 편집할 수 있습니다." + }, + "terminal": { + "runTitle": "{{command}} 실행 중 - {{host}}", + "terminalTitle": "터미널 - {{host}}", + "terminalWithPath": "터미널 - {{host}}:{{path}}" + }, + "transfer": { + "browseFolders": "대상 폴더 찾아보기", + "browsePathError": "대상 호스트에서 이 경로를 열 수 없습니다.", + "browsePathWillBeCreated": "이 폴더가 아직 존재하지 않습니다. 전송 시작 시 생성됩니다.", + "cancel": "취소", + "cleanupDestFiles": "대상 정리", + "cleanupDestFilesError": "정리 실패", + "cleanupDestFilesNothing": "대상에 정리할 항목이 없습니다.", + "cleanupDestFilesPartial": "일부 부분 파일을 제거할 수 없었습니다.", + "cleanupDestFilesSuccess": "대상에서 부분 파일을 제거했습니다.", + "confirmCopy": "복사", + "confirmMove": "이동", + "copyFolderToHost": "폴더를 호스트로 복사…", + "copyItemsToHost": "{{count}}개 항목을 호스트로 복사…", + "copyToHost": "호스트로 복사…", + "destinationPath": "대상 경로", + "destMustBeDirectory": "여러 항목 전송 시 대상은 디렉터리여야 합니다.", + "goUp": "위로", + "hostAuthRequired": "인증 필요 — 먼저 이 호스트에서 파일 관리자를 여십시오.", + "hostConnecting": "연결 중…", + "hostConnectionFailed": "연결 실패", + "hostDisconnected": "연결되지 않음", + "hostReady": "준비됨", + "itemsSummary": "{{count}}개 항목", + "jumpHostLimitation": "두 호스트 모두 Termix 서버에서 접근 가능해야 합니다. 호스트 간 직접 라우팅은 지원되지 않습니다.", + "methodAuto": "자동", + "methodAutoHint": "파일 수, 크기 및 압축 가능성을 기준으로 tar 또는 파일별 SFTP를 선택합니다. 단일 파일은 항상 스트리밍 SFTP를 사용합니다.", + "methodItemSftp": "파일별 SFTP", + "methodItemSftpHint": "SFTP를 통해 각 파일을 개별적으로 전송합니다. Windows를 포함한 모든 호스트에서 작동합니다.", + "methodItemSftpLimitation": "각 파일은 단일 파일 복사와 동일한 SFTP 스트림을 순차적으로 사용합니다. 진행률이 모든 파일에 걸쳐 결합되므로 대용량 파일에서는 진행 막대가 느리게 움직입니다.", + "methodLabel": "전송 방법", + "methodPreviewError": "전송 방법을 미리 볼 수 없습니다. 시작 시 서버가 방법을 선택합니다.", + "methodPreviewLoading": "전송 방법 계산 중…", + "methodPreviewScanSummary": "{{fileCount}}개 파일, 총 {{totalSize}} (소스 호스트에서 스캔됨).", + "methodPreviewWillUseItemSftp": "사용 예정: 파일별 SFTP", + "methodPreviewWillUseTar": "사용 예정: Tar 아카이브", + "methodReason": { + "user_item_sftp": "파일별 SFTP를 선택하셨습니다.", + "user_tar": "tar 아카이브를 선택하셨습니다.", + "tar_unavailable": "한쪽 또는 양쪽 호스트에서 tar를 사용할 수 없어 대신 파일별 SFTP를 사용합니다.", + "windows_host": "Windows 호스트가 포함되어 tar를 사용하지 않습니다.", + "auto_multi_large": "자동: 압축 가능한 대용량 파일({{largestSize}})을 포함한 여러 파일 — tar로 하나의 전송으로 묶습니다.", + "auto_single_large_in_archive": "자동: 이 세트에 대용량 파일({{largestSize}}) 하나 — 파일별 SFTP.", + "auto_many_incompressible": "자동: 대부분 압축 불가능한 데이터 — 파일별 SFTP.", + "auto_many_files": "자동: 다수의 파일({{fileCount}}) — tar로 파일별 오버헤드를 줄입니다.", + "auto_default": "자동: 이 세트에 대해 파일별 SFTP." + }, + "methodTar": "Tar 아카이브", + "methodTarHint": "소스에서 압축, 하나의 아카이브 전송, 목적지에서 추출. 두 Unix 호스트에 tar가 필요합니다.", + "metricsCompress": "소스에서 압축: {{duration}}", + "metricsExtract": "목적지에서 추출: {{duration}}", + "metricsPrepare": "대상 준비: {{duration}}", + "metricsRouteBenchmark": "경로 탐색 — 직접: {{direct}}, 중계: {{relay}}", + "metricsSourceDelete": "소스에서 제거: {{duration}}", + "metricsTotal": "총 시간: {{duration}}", + "metricsTransfer": "엔드 투 엔드: {{throughput}} ({{duration}})", + "metricsVerify": "SHA-256 검증 완료: {{duration}}", + "moveFolderToHost": "폴더를 호스트로 이동…", + "moveItemsToHost": "{{count}}개 항목을 호스트로 이동…", + "moveToHost": "호스트로 이동…", + "noHostsConnected": "사용 가능한 다른 파일 관리자 호스트가 없습니다.", + "noHostsConnectedHint": "호스트 관리자에서 파일 관리자가 활성화된 다른 SSH 호스트를 추가하세요.", + "parallelSegmentsHint": "대용량 파일은 256 MB 청크로 분할됩니다. 여러 레인은 별도 연결을 사용하여 (여러 전송을 시작하는 것처럼) 총 처리량을 높입니다.", + "parallelSegmentsLabel": "병렬 전송 레인", + "parallelSegmentsOption": "{{count}}개 레인", + "progressBenchmarking": "가장 빠른 이동 경로 선택…", + "progressBytes": "{{transferred}} / {{total}}", + "progressCancel": "취소", + "progressCancelling": "취소 중…", + "progressCompressing": "소스 호스트에서 압축 중…", + "progressExtracting": "목적지에서 추출 중…", + "progressItems": "{{current}} / {{total}} 파일", + "progressReconnecting": "재연결 중…", + "progressStalled": "지연됨", + "progressTotalSpeed": "총 {{speed}} ({{lanes}}개 레인)", + "progressTransferring": "데이터 전송 중…", + "progressTransferringItems": "파일 전송 중 ({{current}}/{{total}})…", + "progressVerifying": "파일 무결성 확인 중…", + "recentDestinations": "최근 대상", + "resumedHint": "다른 창에서 시작된 활성 전송에 다시 연결되었습니다.", + "retryTransfer": "재시도", + "retryTransferError": "재시도 실패", + "selectDestinationHost": "대상 호스트 선택", + "transferCancelled": "전송 취소됨", + "transferCancelledCopyHint": "대상에 부분 파일이 남아 있을 수 있습니다.", + "transferCancelledMoveHint": "대상에 부분 파일이 남아 있을 수 있습니다. 원본 파일은 제거되지 않았습니다.", + "transferError": "전송 실패", + "transferFailedRetryHint": "대상에 부분 데이터가 유지되었습니다. 연결이 복구되면 다시 시도하면 이어서 전송됩니다.", + "transferPartialHint": "전송할 수 없습니다: {{paths}}", + "transferSuccess": "전송 완료" } } diff --git a/plugins/file-manager/locales/translated/nl_NL.json b/plugins/file-manager/locales/translated/nl_NL.json index a06eaff4c..9f3d6a60c 100644 --- a/plugins/file-manager/locales/translated/nl_NL.json +++ b/plugins/file-manager/locales/translated/nl_NL.json @@ -382,7 +382,10 @@ "defaultPathLabel": "Standaardpad", "fileManagerPathHint": "De map die geopend moet worden wanneer de bestandsbeheerder voor deze host wordt gestart.", "fileManagerUrlCopied": "URL van bestandsbeheerder gekopieerd", - "copyFileManagerUrlAction": "Kopieer de URL van de bestandsbeheerder" + "copyFileManagerUrlAction": "Kopieer de URL van de bestandsbeheerder", + "docsLink": "Documenten bekijken", + "hostNotFound": "Host niet gevonden", + "loadingHost": "Host wordt geladen..." }, "settings": { "host": { @@ -406,5 +409,105 @@ "nav": { "sftp": "SFTP", "files": "Bestanden" + }, + "onboarding": { + "feature_files": "Bestandsbeheerder", + "feature_files_desc": "Blader door bestanden, upload ze, download ze en bewerk ze via SFTP zonder de app te verlaten." + }, + "terminal": { + "runTitle": "Bezig met uitvoeren van {{command}} - {{host}}", + "terminalTitle": "Terminal - {{host}}", + "terminalWithPath": "Terminal - {{host}}:{{path}}" + }, + "transfer": { + "browseFolders": "Blader door bestemmingsmappen", + "browsePathError": "Dit pad kon niet worden geopend op de doelhost.", + "browsePathWillBeCreated": "Deze map bestaat nog niet. Hij wordt aangemaakt zodra de overdracht start.", + "cancel": "Annuleren", + "cleanupDestFiles": "Opruimbestemming", + "cleanupDestFilesError": "Opruimen mislukt", + "cleanupDestFilesNothing": "Niets op te ruimen op de bestemming.", + "cleanupDestFilesPartial": "Sommige gedeeltelijke bestanden konden niet worden verwijderd.", + "cleanupDestFilesSuccess": "Gedeeltelijke bestanden verwijderd van de bestemming.", + "confirmCopy": "Kopiëren", + "confirmMove": "Beweging", + "copyFolderToHost": "Kopieer de map naar de host…", + "copyItemsToHost": "Kopieer {{count}} items naar host…", + "copyToHost": "Kopiëren naar host…", + "destinationPath": "Bestemmingspad", + "destMustBeDirectory": "De bestemming moet een adresboek zijn voor overdrachten van meerdere items.", + "goUp": "Ga omhoog", + "hostAuthRequired": "Authenticatie vereist — open eerst Bestandsbeheer op deze host.", + "hostConnecting": "Verbinding maken…", + "hostConnectionFailed": "Verbinding mislukt", + "hostDisconnected": "Niet verbonden", + "hostReady": "Klaar", + "itemsSummary": "{{count}} items", + "jumpHostLimitation": "Beide hosts moeten bereikbaar zijn vanaf de Termix-server. Directe routering tussen hosts wordt niet ondersteund.", + "methodAuto": "Auto", + "methodAutoHint": "Selecteert tar of SFTP per bestand op basis van het aantal bestanden, de grootte en de comprimeerbaarheid. Voor afzonderlijke bestanden wordt altijd streaming SFTP gebruikt.", + "methodItemSftp": "SFTP per bestand", + "methodItemSftpHint": "Verstuur elk bestand afzonderlijk via SFTP. Werkt op alle besturingssystemen, inclusief Windows.", + "methodItemSftpLimitation": "Elk bestand gebruikt dezelfde SFTP-stream als een kopie van een enkel bestand, de een na de ander. De voortgang wordt gecombineerd voor alle bestanden, waardoor de voortgangsbalk langzaam beweegt bij grote bestanden.", + "methodLabel": "Overdrachtsmethode", + "methodPreviewError": "De overdrachtsmethode kon niet worden bekeken. De server kiest nog steeds een methode wanneer u start.", + "methodPreviewLoading": "Berekeningsmethode voor overdracht…", + "methodPreviewScanSummary": "{{fileCount}} bestanden, {{totalSize}} totaal (gescand op de bronhost).", + "methodPreviewWillUseItemSftp": "Zal gebruikmaken van: SFTP per bestand", + "methodPreviewWillUseTar": "Zal gebruiken: Tar-archief", + "methodReason": { + "user_item_sftp": "Je hebt gekozen voor SFTP per bestand.", + "user_tar": "Je hebt gekozen voor een tar-archief.", + "tar_unavailable": "Tar is niet beschikbaar op een of beide hosts; in plaats daarvan wordt SFTP per bestand gebruikt.", + "windows_host": "Er wordt gebruikgemaakt van een Windows-host; tar wordt niet gebruikt.", + "auto_multi_large": "Automatisch: meerdere bestanden, waaronder een groot bestand ({{largestSize}}) met comprimeerbare gegevens — tar bundelt deze tot één overdracht.", + "auto_single_large_in_archive": "Auto: één groot bestand ({{largestSize}}) in deze set — SFTP per bestand.", + "auto_many_incompressible": "Automatisch: voornamelijk niet-comprimeerbare gegevens — SFTP per bestand.", + "auto_many_files": "Auto: veel bestanden ({{fileCount}}) — tar vermindert de overhead per bestand.", + "auto_default": "Automatisch: SFTP per bestand voor deze set." + }, + "methodTar": "Tar-archief", + "methodTarHint": "Comprimeer op de bron, verstuur één archiefbestand en pak het uit op de bestemming. Vereist tar op beide Unix-hosts.", + "metricsCompress": "Comprimeren op bron: {{duration}}", + "metricsExtract": "Uitpakken op bestemming: {{duration}}", + "metricsPrepare": "Bestemming voorbereiden: {{duration}}", + "metricsRouteBenchmark": "Route probe — direct: {{direct}}, relay: {{relay}}", + "metricsSourceDelete": "Verwijderen uit de bron: {{duration}}", + "metricsTotal": "Totaal: {{duration}}", + "metricsTransfer": "Einde tot einde: {{throughput}} ({{duration}})", + "metricsVerify": "SHA-256 geverifieerd: {{duration}}", + "moveFolderToHost": "Map verplaatsen naar host…", + "moveItemsToHost": "Verplaats {{count}} items naar host…", + "moveToHost": "Verplaats naar host…", + "noHostsConnected": "Er zijn geen andere bestandsbeheerhosts beschikbaar.", + "noHostsConnectedHint": "Voeg een andere SSH-host toe met Bestandsbeheer ingeschakeld in Hostbeheer.", + "parallelSegmentsHint": "Grote bestanden worden opgesplitst in blokken van 256 MB. Meerdere lanes gebruiken aparte verbindingen (alsof er meerdere overdrachten worden gestart) voor een hogere totale doorvoer.", + "parallelSegmentsLabel": "Parallelle transferstroken", + "parallelSegmentsOption": "{{count}} rijstroken", + "progressBenchmarking": "De snelste overstaproute selecteren…", + "progressBytes": "{{transferred}} / {{total}}", + "progressCancel": "Annuleren", + "progressCancelling": "Annuleren…", + "progressCompressing": "Comprimeren op de bronhost…", + "progressExtracting": "Uitpakken op bestemming…", + "progressItems": "{{current}} / {{total}} bestanden", + "progressReconnecting": "Opnieuw verbinding maken…", + "progressStalled": "Vastgelopen", + "progressTotalSpeed": "{{speed}} totaal ({{lanes}} rijstroken)", + "progressTransferring": "Gegevens overdragen…", + "progressTransferringItems": "Bestanden overdragen ({{current}} van {{total}})…", + "progressVerifying": "Bestandsintegriteit controleren…", + "recentDestinations": "Recente bestemmingen", + "resumedHint": "De verbinding met een actieve overdracht die in een ander venster is gestart, is hersteld.", + "retryTransfer": "Opnieuw proberen", + "retryTransferError": "Opnieuw proberen mislukt", + "selectDestinationHost": "Selecteer de bestemmingshost", + "transferCancelled": "Overdracht geannuleerd", + "transferCancelledCopyHint": "Er kunnen gedeeltelijke bestanden op de bestemming achterblijven.", + "transferCancelledMoveHint": "Er kunnen gedeeltelijke bestanden op de bestemming achterblijven. De bronbestanden zijn niet verwijderd.", + "transferError": "Overdracht mislukt", + "transferFailedRetryHint": "Er zijn gedeeltelijke gegevens op de bestemming bewaard gebleven. De herhaalpoging wordt hervat zodra de verbinding hersteld is.", + "transferPartialHint": "Overdracht mislukt: {{paths}}", + "transferSuccess": "Overdracht voltooid" } } diff --git a/plugins/file-manager/locales/translated/no_NO.json b/plugins/file-manager/locales/translated/no_NO.json index ac58d5527..f243db57d 100644 --- a/plugins/file-manager/locales/translated/no_NO.json +++ b/plugins/file-manager/locales/translated/no_NO.json @@ -382,7 +382,10 @@ "defaultPathLabel": "Standardsti", "fileManagerPathHint": "Katalogen som skal åpnes når filbehandleren starter for denne verten.", "fileManagerUrlCopied": "URL-adressen til filbehandleren er kopiert", - "copyFileManagerUrlAction": "Kopier URL-adressen til filbehandleren" + "copyFileManagerUrlAction": "Kopier URL-adressen til filbehandleren", + "docsLink": "Vis dokumenter", + "hostNotFound": "Verten ble ikke funnet", + "loadingHost": "Laster inn vert ..." }, "settings": { "host": { @@ -406,5 +409,105 @@ "nav": { "sftp": "SFTP", "files": "Filer" + }, + "onboarding": { + "feature_files": "Filbehandler", + "feature_files_desc": "Bla gjennom, last opp, last ned og rediger filer via SFTP uten å forlate appen." + }, + "terminal": { + "runTitle": "Kjører {{command}} - {{host}}", + "terminalTitle": "Terminal - {{host}}", + "terminalWithPath": "Terminal - {{host}}:{{path}}" + }, + "transfer": { + "browseFolders": "Bla gjennom målmapper", + "browsePathError": "Kunne ikke åpne denne banen på målverten.", + "browsePathWillBeCreated": "Denne mappen finnes ikke ennå. Den vil bli opprettet når overføringen starter.", + "cancel": "Kansellere", + "cleanupDestFiles": "Rydd opp destinasjonen", + "cleanupDestFilesError": "Opprydding mislyktes", + "cleanupDestFilesNothing": "Ingenting å rydde opp i på destinasjonen", + "cleanupDestFilesPartial": "Kunne ikke fjerne noen delvise filer", + "cleanupDestFilesSuccess": "Fjernet delvise filer fra destinasjonen", + "confirmCopy": "Kopiere", + "confirmMove": "Flytte", + "copyFolderToHost": "Kopier mappe til vert…", + "copyItemsToHost": "Kopier {{count}} elementer til å være vert for…", + "copyToHost": "Kopier til vert…", + "destinationPath": "Destinasjonssti", + "destMustBeDirectory": "Destinasjonen må være en katalog for overføringer av flere elementer", + "goUp": "Gå opp", + "hostAuthRequired": "Autentisering kreves – åpne Filbehandler på denne verten først", + "hostConnecting": "Kobler til…", + "hostConnectionFailed": "Tilkoblingen mislyktes", + "hostDisconnected": "Ikke tilkoblet", + "hostReady": "Ferdig", + "itemsSummary": "{{count}} elementer", + "jumpHostLimitation": "Begge vertene må være tilgjengelige fra Termix-serveren. Direkte vert-til-vert-ruting støttes ikke.", + "methodAuto": "Bil", + "methodAutoHint": "Velger tar eller SFTP per fil basert på antall filer, størrelse og komprimerbarhet. Enkeltfiler bruker alltid strømme-SFTP.", + "methodItemSftp": "SFTP per fil", + "methodItemSftpHint": "Overfør hver fil individuelt via SFTP. Fungerer på alle verter, inkludert Windows.", + "methodItemSftpLimitation": "Hver fil bruker den samme SFTP-strømmen som en enkeltfilskopi, én etter én. Fremdriften kombineres på tvers av alle filene, så linjen beveger seg sakte under store filer.", + "methodLabel": "Overføringsmetode", + "methodPreviewError": "Kunne ikke forhåndsvise overføringsmetoden. Serveren vil fortsatt velge en metode når du starter.", + "methodPreviewLoading": "Beregning av overføringsmetode…", + "methodPreviewScanSummary": "{{fileCount}} filer, {{totalSize}} totalt (skannet på kildeverten).", + "methodPreviewWillUseItemSftp": "Vil bruke: SFTP per fil", + "methodPreviewWillUseTar": "Vil bruke: Tar-arkiv", + "methodReason": { + "user_item_sftp": "Du valgte SFTP per fil.", + "user_tar": "Du valgte tar-arkiv.", + "tar_unavailable": "Tar er ikke tilgjengelig på én eller begge vertene – SFTP per fil vil bli brukt i stedet.", + "windows_host": "En Windows-vert er involvert – tar brukes ikke.", + "auto_multi_large": "Auto: flere filer, inkludert en stor fil ({{largestSize}}) med komprimerbare data — tar-pakker i én overføring.", + "auto_single_large_in_archive": "Auto: én stor fil ({{largestSize}}) i dette settet — SFTP per fil.", + "auto_many_incompressible": "Auto: stort sett inkomprimerbare data — SFTP per fil.", + "auto_many_files": "Auto: mange filer ({{fileCount}}) — tar reduserer overhead per fil.", + "auto_default": "Auto: SFTP per fil for dette settet." + }, + "methodTar": "Tar-arkiv", + "methodTarHint": "Komprimer på kildekode, overfør ett arkiv, pakk ut på destinasjon. Krever tar på begge Unix-vertene.", + "metricsCompress": "Komprimer på kilde: {{duration}}", + "metricsExtract": "Uttrekk på destinasjon: {{duration}}", + "metricsPrepare": "Forbered destinasjon: {{duration}}", + "metricsRouteBenchmark": "Rutesonde — direkte: {{direct}}, relé: {{relay}}", + "metricsSourceDelete": "Fjern fra kilden: {{duration}}", + "metricsTotal": "Totalt: {{duration}}", + "metricsTransfer": "Ende-til-ende: {{throughput}} ({{duration}})", + "metricsVerify": "SHA-256 bekreftet: {{duration}}", + "moveFolderToHost": "Flytt mappen til verten…", + "moveItemsToHost": "Flytt {{count}} elementer til vert for…", + "moveToHost": "Flytt til vert…", + "noHostsConnected": "Ingen andre filbehandlerverter tilgjengelig.", + "noHostsConnectedHint": "Legg til en annen SSH-vert med Filbehandling aktivert i Vertsbehandling.", + "parallelSegmentsHint": "Store filer deles inn i deler på 256 MB. Flere baner bruker separate tilkoblinger (som å starte flere overføringer) for høyere total gjennomstrømning.", + "parallelSegmentsLabel": "Parallelle overføringsfelt", + "parallelSegmentsOption": "{{count}} baner", + "progressBenchmarking": "Velge den raskeste overgangsruten…", + "progressBytes": "{{transferred}} / {{total}}", + "progressCancel": "Kansellere", + "progressCancelling": "Avbryter…", + "progressCompressing": "Komprimering på kildevert…", + "progressExtracting": "Uttrekker på destinasjon…", + "progressItems": "{{current}} / {{total}} filer", + "progressReconnecting": "Kobler til igjen…", + "progressStalled": "Fastlåst", + "progressTotalSpeed": "{{speed}} totalt ({{lanes}} baner)", + "progressTransferring": "Overføring av data…", + "progressTransferringItems": "Overføring av filer ({{current}} av {{total}})…", + "progressVerifying": "Verifiserer filintegritet…", + "recentDestinations": "Nylige destinasjoner", + "resumedHint": "Koblet til igjen en aktiv overføring som startet i et annet vindu.", + "retryTransfer": "Prøv på nytt", + "retryTransferError": "Forsøk på nytt mislyktes", + "selectDestinationHost": "Velg destinasjonsvert", + "transferCancelled": "Overføringen er avbrutt", + "transferCancelledCopyHint": "Delvise filer kan bli liggende igjen på destinasjonen.", + "transferCancelledMoveHint": "Delvise filer kan bli liggende igjen på destinasjonen. Kildefilene ble ikke fjernet.", + "transferError": "Overføringen mislyktes", + "transferFailedRetryHint": "Delvise data ble lagret på destinasjonen. Forsøket gjenopptas når forbindelsen er tilbake.", + "transferPartialHint": "Kunne ikke overføre: {{paths}}", + "transferSuccess": "Overføringen er fullført" } } diff --git a/plugins/file-manager/locales/translated/pl_PL.json b/plugins/file-manager/locales/translated/pl_PL.json index 4aa6e675e..961a902c1 100644 --- a/plugins/file-manager/locales/translated/pl_PL.json +++ b/plugins/file-manager/locales/translated/pl_PL.json @@ -382,7 +382,10 @@ "defaultPathLabel": "Domyślna ścieżka", "fileManagerPathHint": "Katalog, który zostanie otwarty po uruchomieniu menedżera plików dla tego hosta.", "fileManagerUrlCopied": "Skopiowano adres URL menedżera plików", - "copyFileManagerUrlAction": "Kopiuj adres URL menedżera plików" + "copyFileManagerUrlAction": "Kopiuj adres URL menedżera plików", + "docsLink": "Zobacz dokumentację", + "hostNotFound": "Nie znaleziono hosta", + "loadingHost": "Ładowanie hosta..." }, "settings": { "host": { @@ -406,5 +409,105 @@ "nav": { "sftp": "SFTP", "files": "Pliki" + }, + "onboarding": { + "feature_files": "Menedżer plików", + "feature_files_desc": "Przeglądaj, przesyłaj, pobieraj i edytuj pliki przez SFTP bez opuszczania aplikacji." + }, + "terminal": { + "runTitle": "Wykonywanie {{command}} - {{host}}", + "terminalTitle": "Terminal - {{host}}", + "terminalWithPath": "Terminal - {{host}}:{{path}}" + }, + "transfer": { + "browseFolders": "Przeglądaj foldery docelowe", + "browsePathError": "Nie można otworzyć tej ścieżki na hoście docelowym.", + "browsePathWillBeCreated": "Ten folder jeszcze nie istnieje. Zostanie utworzony po rozpoczęciu transferu.", + "cancel": "Anuluj", + "cleanupDestFiles": "Wyczyść miejsce docelowe", + "cleanupDestFilesError": "Czyszczenie nie powiodło się", + "cleanupDestFilesNothing": "Nie ma czego czyścić w miejscu docelowym", + "cleanupDestFilesPartial": "Niektórych częściowych plików nie można było usunąć", + "cleanupDestFilesSuccess": "Usunięto częściowe pliki z miejsca docelowego", + "confirmCopy": "Kopiuj", + "confirmMove": "Przenieś", + "copyFolderToHost": "Kopiuj folder do hosta…", + "copyItemsToHost": "Skopiuj {{count}} elementów do hosta…", + "copyToHost": "Kopiuj do hosta…", + "destinationPath": "Ścieżka docelowa", + "destMustBeDirectory": "Miejsce docelowe musi być katalogiem przy transferze wielu elementów", + "goUp": "W górę", + "hostAuthRequired": "Wymagane uwierzytelnienie: najpierw otwórz menedżer plików na tym hoście", + "hostConnecting": "Łączenie…", + "hostConnectionFailed": "Połączenie nieudane", + "hostDisconnected": "Nie połączono", + "hostReady": "Gotowy", + "itemsSummary": "{{count}} elementów", + "jumpHostLimitation": "Oba hosty muszą być osiągalne z serwera Termix. Bezpośrednie trasowanie między hostami nie jest obsługiwane.", + "methodAuto": "Auto", + "methodAutoHint": "Wybiera tar albo SFTP dla każdego pliku na podstawie liczby plików, ich rozmiaru i podatności na kompresję. Pojedyncze pliki zawsze używają strumieniowego SFTP.", + "methodItemSftp": "SFTP dla każdego pliku", + "methodItemSftpHint": "Przesyłaj każdy plik osobno przez SFTP. Działa na wszystkich hostach, w tym Windows.", + "methodItemSftpLimitation": "Każdy plik korzysta z tego samego strumienia SFTP co kopiowanie pojedynczego pliku, jeden po drugim. Postęp jest sumowany dla wszystkich plików, więc przy dużych plikach pasek przesuwa się powoli.", + "methodLabel": "Metoda transferu", + "methodPreviewError": "Nie można wyświetlić podglądu metody transferu. Serwer i tak wybierze metodę po uruchomieniu.", + "methodPreviewLoading": "Obliczanie metody transferu…", + "methodPreviewScanSummary": "{{fileCount}} plików, łącznie {{totalSize}} (przeskanowano na hoście źródłowym).", + "methodPreviewWillUseItemSftp": "Zostanie użyte: SFTP dla każdego pliku", + "methodPreviewWillUseTar": "Zostanie użyte: archiwum tar", + "methodReason": { + "user_item_sftp": "Wybrano SFTP dla poszczególnych plików.", + "user_tar": "Wybrano archiwum tar.", + "tar_unavailable": "Tar nie jest dostępny na jednym lub obu hostach, zamiast niego zostanie użyty SFTP dla każdego pliku.", + "windows_host": "W transferze bierze udział host Windows, więc tar nie jest używany.", + "auto_multi_large": "Auto: wiele plików, w tym duży plik ({{largestSize}}) z kompresowalnymi danymi, tar pakuje je w jeden transfer.", + "auto_single_large_in_archive": "Auto: jeden duży plik ({{largestSize}}) w tym zestawie, SFTP dla każdego pliku.", + "auto_many_incompressible": "Auto: dane w większości niekompresowalne, SFTP dla każdego pliku.", + "auto_many_files": "Auto: wiele plików ({{fileCount}}), tar redukuje narzut na plik.", + "auto_default": "Auto: SFTP dla każdego pliku w tym zestawie." + }, + "methodTar": "Archiwum tar", + "methodTarHint": "Kompresja w źródle, transfer jednego archiwum, rozpakowanie w miejscu docelowym. Wymaga tar na obu hostach Unix.", + "metricsCompress": "Kompresja w źródle: {{duration}}", + "metricsExtract": "Rozpakowanie w miejscu docelowym: {{duration}}", + "metricsPrepare": "Przygotowanie miejsca docelowego: {{duration}}", + "metricsRouteBenchmark": "Sonda trasy. Bezpośrednia: {{direct}}, przez przekaźnik: {{relay}}", + "metricsSourceDelete": "Usunięcie ze źródła: {{duration}}", + "metricsTotal": "Razem: {{duration}}", + "metricsTransfer": "Całościowo: {{throughput}} ({{duration}})", + "metricsVerify": "Zweryfikowano SHA-256: {{duration}}", + "moveFolderToHost": "Przenieś folder do hosta…", + "moveItemsToHost": "Przenieś {{count}} elementów do hosta…", + "moveToHost": "Przenieś do hosta…", + "noHostsConnected": "Brak innych hostów z menedżerem plików.", + "noHostsConnectedHint": "Dodaj kolejny host SSH z włączonym Menedżerem plików w Menedżerze hostów.", + "parallelSegmentsHint": "Duże pliki są dzielone na fragmenty po 256 MB. Wiele pasów korzysta z osobnych połączeń (jak uruchomienie kilku transferów naraz), co daje większą łączną przepustowość.", + "parallelSegmentsLabel": "Równoległe pasy transferowe", + "parallelSegmentsOption": "{{count}} pasów", + "progressBenchmarking": "Wybór najszybszej trasy transferu…", + "progressBytes": "{{transferred}} / {{total}}", + "progressCancel": "Anuluj", + "progressCancelling": "Anulowanie…", + "progressCompressing": "Kompresja na hoście źródłowym…", + "progressExtracting": "Wyodrębnianie w miejscu docelowym…", + "progressItems": "{{current}} / {{total}} plików", + "progressReconnecting": "Ponowne łączenie…", + "progressStalled": "Utknął", + "progressTotalSpeed": "{{speed}} łącznie ({{lanes}} pasów)", + "progressTransferring": "Przesyłanie danych…", + "progressTransferringItems": "Przesyłanie plików ({{current}} z {{total}})…", + "progressVerifying": "Sprawdzanie integralności pliku…", + "recentDestinations": "Ostatnie miejsca docelowe", + "resumedHint": "Połączono ponownie z aktywnym transferem rozpoczętym w innym oknie.", + "retryTransfer": "Ponów", + "retryTransferError": "Ponowna próba nie powiodła się", + "selectDestinationHost": "Wybierz hosta docelowego", + "transferCancelled": "Transfer anulowany", + "transferCancelledCopyHint": "W miejscu docelowym mogą pozostać częściowe pliki.", + "transferCancelledMoveHint": "W miejscu docelowym mogą pozostać częściowe pliki. Pliki źródłowe nie zostały usunięte.", + "transferError": "Transfer nie powiódł się", + "transferFailedRetryHint": "W miejscu docelowym zachowano częściowe dane. Ponowna próba zostanie wznowiona po przywróceniu połączenia.", + "transferPartialHint": "Nie można przesłać: {{paths}}", + "transferSuccess": "Transfer zakończony" } } diff --git a/plugins/file-manager/locales/translated/pt_BR.json b/plugins/file-manager/locales/translated/pt_BR.json index f108ef109..862a11c58 100644 --- a/plugins/file-manager/locales/translated/pt_BR.json +++ b/plugins/file-manager/locales/translated/pt_BR.json @@ -382,7 +382,10 @@ "defaultPathLabel": "Caminho padrão", "fileManagerPathHint": "O diretório a ser aberto quando o gerenciador de arquivos for iniciado para este host.", "fileManagerUrlCopied": "URL do Gerenciador de Arquivos copiada", - "copyFileManagerUrlAction": "Copiar URL do Gerenciador de Arquivos" + "copyFileManagerUrlAction": "Copiar URL do Gerenciador de Arquivos", + "docsLink": "Ver documentos", + "hostNotFound": "Host não encontrado", + "loadingHost": "Carregando host..." }, "settings": { "host": { @@ -406,5 +409,105 @@ "nav": { "sftp": "SFTP", "files": "Arquivos" + }, + "onboarding": { + "feature_files": "Gerenciador de arquivos", + "feature_files_desc": "Navegue, carregue, baixe e edite arquivos via SFTP sem sair do aplicativo." + }, + "terminal": { + "runTitle": "Executando {{command}} - {{host}}", + "terminalTitle": "Terminal - {{host}}", + "terminalWithPath": "Terminal - {{host}}:{{path}}" + }, + "transfer": { + "browseFolders": "Procurar pastas de destino", + "browsePathError": "Não foi possível abrir este caminho no host de destino.", + "browsePathWillBeCreated": "Esta pasta ainda não existe. Ela será criada quando a transferência começar.", + "cancel": "Cancelar", + "cleanupDestFiles": "destino de limpeza", + "cleanupDestFilesError": "A limpeza falhou", + "cleanupDestFilesNothing": "Nada para limpar no destino.", + "cleanupDestFilesPartial": "Alguns arquivos parciais não puderam ser removidos.", + "cleanupDestFilesSuccess": "Arquivos parciais removidos do destino.", + "confirmCopy": "Cópia", + "confirmMove": "Mover", + "copyFolderToHost": "Copiar pasta para o host…", + "copyItemsToHost": "Copiar {{count}} itens para o host…", + "copyToHost": "Copiar para o host…", + "destinationPath": "Caminho de destino", + "destMustBeDirectory": "O destino deve ser um diretório para transferências de múltiplos itens.", + "goUp": "Subir", + "hostAuthRequired": "Autenticação necessária — abra o Gerenciador de Arquivos neste host primeiro.", + "hostConnecting": "Conectando…", + "hostConnectionFailed": "Falha na conexão", + "hostDisconnected": "Não conectado", + "hostReady": "Preparar", + "itemsSummary": "{{count}} itens", + "jumpHostLimitation": "Ambos os hosts devem ser acessíveis a partir do servidor Termix. O roteamento direto de host para host não é suportado.", + "methodAuto": "Auto", + "methodAutoHint": "Seleciona o método de compactação (tar) ou SFTP por arquivo com base na quantidade de arquivos, tamanho e compressibilidade. Arquivos individuais sempre utilizam SFTP de streaming.", + "methodItemSftp": "SFTP por arquivo", + "methodItemSftpHint": "Transfira cada arquivo individualmente via SFTP. Funciona em todos os hosts, incluindo Windows.", + "methodItemSftpLimitation": "Cada arquivo utiliza o mesmo fluxo SFTP como uma cópia de arquivo único, um após o outro. O progresso é combinado em todos os arquivos, portanto a barra se move lentamente durante a transferência de arquivos grandes.", + "methodLabel": "Método de transferência", + "methodPreviewError": "Não foi possível visualizar o método de transferência. O servidor ainda escolherá um método quando você iniciar o servidor.", + "methodPreviewLoading": "Calculando o método de transferência…", + "methodPreviewScanSummary": "{{fileCount}} arquivos, {{totalSize}} total (verificado no host de origem).", + "methodPreviewWillUseItemSftp": "Será utilizado: SFTP por arquivo", + "methodPreviewWillUseTar": "Será utilizado: Arquivo tar", + "methodReason": { + "user_item_sftp": "Você escolheu SFTP por arquivo.", + "user_tar": "Você escolheu o arquivo tar.", + "tar_unavailable": "O arquivo tar não está disponível em um ou ambos os hosts — em vez disso, será usado o SFTP por arquivo.", + "windows_host": "O sistema operacional host é Windows — o arquivo tar não é utilizado.", + "auto_multi_large": "Automático: vários arquivos, incluindo um arquivo grande ({{largestSize}}) com dados compressíveis — pacotes tar em uma única transferência.", + "auto_single_large_in_archive": "Automático: um arquivo grande ({{largestSize}}) neste conjunto — SFTP por arquivo.", + "auto_many_incompressible": "Automático: dados em sua maioria não compressíveis — SFTP por arquivo.", + "auto_many_files": "Automático: muitos arquivos ({{fileCount}}) — tar reduz a sobrecarga por arquivo.", + "auto_default": "Automático: SFTP por arquivo para este conjunto." + }, + "methodTar": "Arquivo Tar", + "methodTarHint": "Comprima na origem, transfira um único arquivo compactado e extraia no destino. Requer o uso do tar em ambos os hosts Unix.", + "metricsCompress": "Comprimir na origem: {{duration}}", + "metricsExtract": "Extrair no destino: {{duration}}", + "metricsPrepare": "Preparar destino: {{duration}}", + "metricsRouteBenchmark": "Sondagem de rota — direta: {{direct}}, retransmissão: {{relay}}", + "metricsSourceDelete": "Remover da fonte: {{duration}}", + "metricsTotal": "Total: {{duration}}", + "metricsTransfer": "De ponta a ponta: {{throughput}} ({{duration}})", + "metricsVerify": "Verificado por SHA-256: {{duration}}", + "moveFolderToHost": "Mover pasta para o host…", + "moveItemsToHost": "Mova {{count}} itens para o host…", + "moveToHost": "Mover para o host…", + "noHostsConnected": "Não há outros servidores de gerenciamento de arquivos disponíveis.", + "noHostsConnectedHint": "Adicione outro host SSH com o Gerenciador de Arquivos habilitado no Gerenciador de Hosts.", + "parallelSegmentsHint": "Arquivos grandes são divididos em partes de 256 MB. Várias vias utilizam conexões separadas (como iniciar várias transferências) para obter uma taxa de transferência total maior.", + "parallelSegmentsLabel": "Faixas de transferência paralelas", + "parallelSegmentsOption": "{{count}} faixas", + "progressBenchmarking": "Selecionando a rota de transferência mais rápida…", + "progressBytes": "{{transferred}} / {{total}}", + "progressCancel": "Cancelar", + "progressCancelling": "Cancelando…", + "progressCompressing": "Comprimindo no host de origem…", + "progressExtracting": "Extraindo no destino…", + "progressItems": "{{current}} / {{total}} arquivos", + "progressReconnecting": "Reconectando…", + "progressStalled": "Paralisado", + "progressTotalSpeed": "{{speed}} total ({{lanes}} faixas)", + "progressTransferring": "Transferindo dados…", + "progressTransferringItems": "Transferindo arquivos ({{current}} de {{total}})…", + "progressVerifying": "Verificando a integridade do arquivo…", + "recentDestinations": "Destinos recentes", + "resumedHint": "Reconectado a uma transferência ativa iniciada em outra janela.", + "retryTransfer": "Tentar novamente", + "retryTransferError": "A nova tentativa falhou.", + "selectDestinationHost": "Selecione o host de destino", + "transferCancelled": "Transferência cancelada", + "transferCancelledCopyHint": "Alguns arquivos podem permanecer no destino.", + "transferCancelledMoveHint": "É possível que alguns arquivos permaneçam no destino. Os arquivos de origem não foram removidos.", + "transferError": "A transferência falhou", + "transferFailedRetryHint": "Dados parciais foram mantidos no destino. A tentativa será retomada quando a conexão for restabelecida.", + "transferPartialHint": "Não foi possível transferir: {{paths}}", + "transferSuccess": "Transferência concluída" } } diff --git a/plugins/file-manager/locales/translated/pt_PT.json b/plugins/file-manager/locales/translated/pt_PT.json index f3e374dbf..c6c4b88fb 100644 --- a/plugins/file-manager/locales/translated/pt_PT.json +++ b/plugins/file-manager/locales/translated/pt_PT.json @@ -382,7 +382,10 @@ "defaultPathLabel": "Caminho Predefinido", "fileManagerPathHint": "O diretório a abrir quando o gestor de ficheiros for iniciado para este host", "fileManagerUrlCopied": "URL do gestor de ficheiros copiada", - "copyFileManagerUrlAction": "Copiar URL do Gestor de Ficheiros" + "copyFileManagerUrlAction": "Copiar URL do Gestor de Ficheiros", + "docsLink": "Ver documentação", + "hostNotFound": "Host não encontrado", + "loadingHost": "A carregar o host..." }, "settings": { "host": { @@ -406,5 +409,105 @@ "nav": { "sftp": "SFTP", "files": "Ficheiros" + }, + "onboarding": { + "feature_files": "Gestor de arquivos", + "feature_files_desc": "Navegue, carregue, descarregue e edite ficheiros via SFTP sem sair da aplicação." + }, + "terminal": { + "runTitle": "A executar {{command}} - {{host}}", + "terminalTitle": "Terminal - {{host}}", + "terminalWithPath": "Terminal - {{host}}:{{path}}" + }, + "transfer": { + "browseFolders": "Navegar pelas pastas de destino", + "browsePathError": "Não foi possível abrir este caminho no host de destino.", + "browsePathWillBeCreated": "Esta pasta ainda não existe. Será criada quando a transferência for iniciada.", + "cancel": "Cancelar", + "cleanupDestFiles": "Limpar destino", + "cleanupDestFilesError": "A limpeza falhou.", + "cleanupDestFilesNothing": "Nada a limpar no destino.", + "cleanupDestFilesPartial": "Não foi possível remover alguns ficheiros parciais.", + "cleanupDestFilesSuccess": "Ficheiros parciais removidos do destino.", + "confirmCopy": "Copiar", + "confirmMove": "Mover", + "copyFolderToHost": "Copiar pasta para o host…", + "copyItemsToHost": "Copiar {{count}} itens para o host…", + "copyToHost": "Copiar para o host…", + "destinationPath": "Caminho de destino", + "destMustBeDirectory": "O destino deve ser uma pasta para transferências de vários itens.", + "goUp": "Subir", + "hostAuthRequired": "Autenticação necessária — abra o Gestor de Ficheiros neste host primeiro", + "hostConnecting": "A ligar…", + "hostConnectionFailed": "Falha na ligação", + "hostDisconnected": "Desligado", + "hostReady": "Pronto", + "itemsSummary": "{{count}} itens", + "jumpHostLimitation": "Ambos os hosts têm de ser acessíveis a partir do servidor Termix. O encaminhamento direto entre hosts não é suportado.", + "methodAuto": "Automático", + "methodAutoHint": "Escolhe tar ou SFTP por ficheiro com base no número de ficheiros, tamanho e compressibilidade. Os ficheiros únicos usam sempre SFTP por streaming.", + "methodItemSftp": "SFTP por ficheiro", + "methodItemSftpHint": "Transfere cada ficheiro individualmente por SFTP. Funciona em todos os hosts, incluindo Windows.", + "methodItemSftpLimitation": "Cada ficheiro utiliza o mesmo stream SFTP como uma cópia de um único ficheiro, um após o outro. O progresso é combinado para todos os ficheiros, pelo que a barra se move lentamente durante ficheiros grandes.", + "methodLabel": "Método de transferência", + "methodPreviewError": "Não foi possível pré-visualizar o método de transferência. O servidor ainda escolherá um método quando iniciar.", + "methodPreviewLoading": "A calcular o método de transferência…", + "methodPreviewScanSummary": "{{fileCount}} ficheiros, {{totalSize}} no total (analisados no host de origem).", + "methodPreviewWillUseItemSftp": "Utilizará: SFTP por ficheiro", + "methodPreviewWillUseTar": "Utilizará: Arquivo Tar", + "methodReason": { + "user_item_sftp": "Optou por SFTP ficheiro a ficheiro.", + "user_tar": "Optou por ficheiro tar.", + "tar_unavailable": "O tar não está disponível num ou em ambos os anfitriões — será usado SFTP ficheiro a ficheiro.", + "windows_host": "Está envolvido um anfitrião Windows — o tar não é utilizado.", + "auto_multi_large": "Automático: vários ficheiros, incluindo um grande ({{largestSize}}) com dados compressíveis — o tar agrupa numa transferência única.", + "auto_single_large_in_archive": "Automático: um ficheiro grande ({{largestSize}}) neste conjunto — SFTP ficheiro a ficheiro.", + "auto_many_incompressible": "Automático: dados maioritariamente incompressíveis — SFTP ficheiro a ficheiro.", + "auto_many_files": "Automático: muitos ficheiros ({{fileCount}}) — o tar reduz a sobrecarga por ficheiro.", + "auto_default": "Automático: SFTP ficheiro a ficheiro para este conjunto." + }, + "methodTar": "Arquivo Tar", + "methodTarHint": "Comprime na origem, transfere um arquivo, extrai no destino. Requer tar em ambos os hosts Unix.", + "metricsCompress": "Compressão na origem: {{duration}}", + "metricsExtract": "Extração no destino: {{duration}}", + "metricsPrepare": "Preparar destino: {{duration}}", + "metricsRouteBenchmark": "Sondagem de percurso — direta: {{direct}}, retransmissão: {{relay}}", + "metricsSourceDelete": "Remoção da origem: {{duration}}", + "metricsTotal": "Total: {{duration}}", + "metricsTransfer": "Ponta a ponta: {{throughput}} ({{duration}})", + "metricsVerify": "Verificado por SHA-256: {{duration}}", + "moveFolderToHost": "Mover pasta para o host…", + "moveItemsToHost": "Mover {{count}} itens para o host…", + "moveToHost": "Mover para o host…", + "noHostsConnected": "Não há outros hosts do gestor de ficheiros disponíveis.", + "noHostsConnectedHint": "Adicione outro host SSH com o Gestor de Ficheiros ativado no Gestor de Hosts.", + "parallelSegmentsHint": "Os ficheiros grandes são divididos em partes de 256 MB. Múltiplas vias utilizam ligações separadas (como iniciar várias transferências) para um maior débito total.", + "parallelSegmentsLabel": "Vias de transferência paralelas", + "parallelSegmentsOption": "{{count}} vias", + "progressBenchmarking": "Selecionando a rota de transferência mais rápida…", + "progressBytes": "{{transferred}} / {{total}}", + "progressCancel": "Cancelar", + "progressCancelling": "A cancelar…", + "progressCompressing": "A comprimir no host de origem…", + "progressExtracting": "A extrair no destino…", + "progressItems": "{{current}} / {{total}} ficheiros", + "progressReconnecting": "A reconectar…", + "progressStalled": "Parado", + "progressTotalSpeed": "{{speed}} total ({{lanes}} vias)", + "progressTransferring": "A transferir dados…", + "progressTransferringItems": "A transferir ficheiros ({{current}} de {{total}})…", + "progressVerifying": "Verificação da integridade do ficheiro…", + "recentDestinations": "Destinos recentes", + "resumedHint": "Reconectado a uma transferência ativa iniciada noutra janela.", + "retryTransfer": "Repetir", + "retryTransferError": "A repetição falhou.", + "selectDestinationHost": "Selecionar host de destino", + "transferCancelled": "Transferência cancelada", + "transferCancelledCopyHint": "Poderão permanecer ficheiros parciais no destino.", + "transferCancelledMoveHint": "Poderão permanecer ficheiros parciais no destino. Os ficheiros de origem não foram removidos.", + "transferError": "Transferência falhou", + "transferFailedRetryHint": "Foram mantidos dados parciais no destino. A repetição será retomada quando a ligação for restabelecida.", + "transferPartialHint": "Não foi possível transferir: {{paths}}", + "transferSuccess": "Transferência concluída" } } diff --git a/plugins/file-manager/locales/translated/ro_RO.json b/plugins/file-manager/locales/translated/ro_RO.json index d0150f43d..7e86cfa07 100644 --- a/plugins/file-manager/locales/translated/ro_RO.json +++ b/plugins/file-manager/locales/translated/ro_RO.json @@ -382,7 +382,10 @@ "defaultPathLabel": "Calea implicită", "fileManagerPathHint": "Directorul care va fi deschis la lansarea managerului de fișiere pentru această gazdă.", "fileManagerUrlCopied": "Adresa URL a Managerului de fișiere a fost copiată", - "copyFileManagerUrlAction": "Copiați adresa URL a managerului de fișiere" + "copyFileManagerUrlAction": "Copiați adresa URL a managerului de fișiere", + "docsLink": "Vizualizați documentele", + "hostNotFound": "Gazdă negăsită", + "loadingHost": "Se încarcă gazda..." }, "settings": { "host": { @@ -406,5 +409,105 @@ "nav": { "sftp": "SFTP", "files": "Fișiere" + }, + "onboarding": { + "feature_files": "Manager de fișiere", + "feature_files_desc": "Răsfoiți, încărcați, descărcați și editați fișiere prin SFTP fără a părăsi aplicația." + }, + "terminal": { + "runTitle": "Rulează {{command}} - {{host}}", + "terminalTitle": "Terminal - {{host}}", + "terminalWithPath": "Terminal - {{host}}:{{path}}" + }, + "transfer": { + "browseFolders": "Răsfoiți folderele de destinație", + "browsePathError": "Nu s-a putut deschide această cale pe gazda destinație.", + "browsePathWillBeCreated": "Acest folder nu există încă. Va fi creat când va începe transferul.", + "cancel": "Anula", + "cleanupDestFiles": "Destinația de curățare", + "cleanupDestFilesError": "Curățarea a eșuat", + "cleanupDestFilesNothing": "Nimic de curățat la destinație", + "cleanupDestFilesPartial": "Unele fișiere parțiale nu au putut fi eliminate", + "cleanupDestFilesSuccess": "Fișiere parțiale eliminate din destinație", + "confirmCopy": "Copie", + "confirmMove": "Mişcare", + "copyFolderToHost": "Copiați folderul pe gazdă…", + "copyItemsToHost": "Copiați elementele {{count}} pe gazda…", + "copyToHost": "Copiați către gazdă…", + "destinationPath": "Calea de destinație", + "destMustBeDirectory": "Destinația trebuie să fie un director pentru transferurile cu mai multe elemente", + "goUp": "Mergi sus", + "hostAuthRequired": "Autentificare necesară — deschideți mai întâi File Manager pe această gazdă", + "hostConnecting": "Conectare…", + "hostConnectionFailed": "Conexiunea a eșuat", + "hostDisconnected": "Neconectat", + "hostReady": "Gata", + "itemsSummary": "{{count}} articole", + "jumpHostLimitation": "Ambele gazde trebuie să fie accesibile de pe serverul Termix. Rutarea directă de la gazdă la gazdă nu este acceptată.", + "methodAuto": "Auto", + "methodAutoHint": "Alege SFTP tar sau per fișier în funcție de numărul de fișiere, dimensiune și compresibilitate. Fișierele individuale utilizează întotdeauna SFTP în flux continuu.", + "methodItemSftp": "SFTP per fișier", + "methodItemSftpHint": "Transferă fiecare fișier individual prin SFTP. Funcționează pe toate gazdele, inclusiv Windows.", + "methodItemSftpLimitation": "Fiecare fișier folosește același flux SFTP ca o copie a unui singur fișier, una după alta. Progresul este combinat în toate fișierele, astfel încât bara se mișcă lent în timpul fișierelor mari.", + "methodLabel": "Metoda de transfer", + "methodPreviewError": "Nu s-a putut previzualiza metoda de transfer. Serverul va alege în continuare o metodă când porniți.", + "methodPreviewLoading": "Metoda de calcul a transferului…", + "methodPreviewScanSummary": "{{fileCount}} fișiere, {{totalSize}} în total (scanate pe gazda sursă).", + "methodPreviewWillUseItemSftp": "Se va utiliza: SFTP per fișier", + "methodPreviewWillUseTar": "Se va folosi: arhiva Tar", + "methodReason": { + "user_item_sftp": "Ai ales SFTP per fișier.", + "user_tar": "Ai ales arhiva tar.", + "tar_unavailable": "Tar nu este disponibil pe una sau ambele gazde — se va folosi în schimb SFTP per fișier.", + "windows_host": "Este implicată o gazdă Windows — nu se folosește fișierul tar.", + "auto_multi_large": "Automat: fișiere multiple, inclusiv un fișier mare ({{largestSize}}) cu date compresibile — pachete tar într-un singur transfer.", + "auto_single_large_in_archive": "Automat: un fișier mare ({{largestSize}}) în acest set — SFTP per fișier.", + "auto_many_incompressible": "Automat: date în mare parte incompresibile — SFTP per fișier.", + "auto_many_files": "Auto: multe fișiere ({{fileCount}}) — tar reduce costul per fișier.", + "auto_default": "Automat: SFTP per fișier pentru acest set." + }, + "methodTar": "Arhivă Tar", + "methodTarHint": "Comprimare la sursă, transfer o arhivă, extragere la destinație. Necesită tar pe ambele gazde Unix.", + "metricsCompress": "Comprimare pe sursă: {{duration}}", + "metricsExtract": "Extras la destinație: {{duration}}", + "metricsPrepare": "Pregătiți destinația: {{duration}}", + "metricsRouteBenchmark": "Sondă de rută — directă: {{direct}}, releu: {{relay}}", + "metricsSourceDelete": "Eliminare din sursă: {{duration}}", + "metricsTotal": "Total: {{duration}}", + "metricsTransfer": "De la un capăt la altul: {{throughput}} ({{duration}})", + "metricsVerify": "SHA-256 verificat: {{duration}}", + "moveFolderToHost": "Mută folderul pe gazdă…", + "moveItemsToHost": "Mută elementele {{count}} către gazda…", + "moveToHost": "Mutare la gazdă…", + "noHostsConnected": "Nu sunt disponibile alte gazde de gestionare a fișierelor.", + "noHostsConnectedHint": "Adăugați o altă gazdă SSH cu File Manager activat în Host Manager.", + "parallelSegmentsHint": "Fișierele mari sunt împărțite în blocuri de 256 MB. Mai multe benzi utilizează conexiuni separate (cum ar fi pornirea mai multor transferuri) pentru un debit total mai mare.", + "parallelSegmentsLabel": "Benzi de transfer paralele", + "parallelSegmentsOption": "{{count}} benzi", + "progressBenchmarking": "Selectarea celei mai rapide rute de transfer…", + "progressBytes": "{{transferred}} / {{total}}", + "progressCancel": "Anula", + "progressCancelling": "Anulare…", + "progressCompressing": "Comprimare pe gazda sursă…", + "progressExtracting": "Extragerea la destinație…", + "progressItems": "{{current}} / {{total}} fișiere", + "progressReconnecting": "Reconectare…", + "progressStalled": "Blocat", + "progressTotalSpeed": "{{speed}} total ({{lanes}} benzi)", + "progressTransferring": "Transferul datelor…", + "progressTransferringItems": "Transferarea fișierelor ({{current}} din {{total}})…", + "progressVerifying": "Verificarea integrității fișierului…", + "recentDestinations": "Destinații recente", + "resumedHint": "Reconectare la un transfer activ început într-o altă fereastră.", + "retryTransfer": "Reîncercați", + "retryTransferError": "Reîncercare eșuată", + "selectDestinationHost": "Selectați gazda de destinație", + "transferCancelled": "Transfer anulat", + "transferCancelledCopyHint": "Fișiere parțiale pot rămâne în destinație.", + "transferCancelledMoveHint": "Fișiere parțiale pot rămâne în destinație. Fișierele sursă nu au fost eliminate.", + "transferError": "Transferul a eșuat", + "transferFailedRetryHint": "Date parțiale au fost păstrate la destinație. Reîncercarea va fi reluată după restabilirea conexiunii.", + "transferPartialHint": "Nu s-a putut transfera: {{paths}}", + "transferSuccess": "Transfer finalizat" } } diff --git a/plugins/file-manager/locales/translated/ru_RU.json b/plugins/file-manager/locales/translated/ru_RU.json index 278205f14..1d1485dbb 100644 --- a/plugins/file-manager/locales/translated/ru_RU.json +++ b/plugins/file-manager/locales/translated/ru_RU.json @@ -382,7 +382,10 @@ "defaultPathLabel": "Путь по умолчанию", "fileManagerPathHint": "Каталог, который открывается при запуске файлового менеджера для этого хоста.", "fileManagerUrlCopied": "URL файлового менеджера скопирован", - "copyFileManagerUrlAction": "Копировать URL файлового менеджера" + "copyFileManagerUrlAction": "Копировать URL файлового менеджера", + "docsLink": "Документация", + "hostNotFound": "Хост не найден", + "loadingHost": "Загрузка хоста..." }, "settings": { "host": { @@ -406,5 +409,105 @@ "nav": { "sftp": "SFTP", "files": "Файлы" + }, + "onboarding": { + "feature_files": "Файловый менеджер", + "feature_files_desc": "Просматривайте, загружайте, скачивайте и редактируйте файлы по протоколу SFTP, не выходя из приложения." + }, + "terminal": { + "runTitle": "Выполнение {{command}} - {{host}}", + "terminalTitle": "Терминал - {{host}}", + "terminalWithPath": "Терминал - {{host}}:{{path}}" + }, + "transfer": { + "browseFolders": "Обзор папок назначения", + "browsePathError": "Не удалось открыть этот путь на целевом хосте.", + "browsePathWillBeCreated": "Эта папка ещё не существует. Она будет создана при запуске передачи.", + "cancel": "Отмена", + "cleanupDestFiles": "Очистить место назначения", + "cleanupDestFilesError": "Очистка не удалась", + "cleanupDestFilesNothing": "В месте назначения нечего очищать", + "cleanupDestFilesPartial": "Некоторые частично переданные файлы не удалось удалить", + "cleanupDestFilesSuccess": "Частично переданные файлы удалены из места назначения", + "confirmCopy": "Копировать", + "confirmMove": "Переместить", + "copyFolderToHost": "Копировать папку на хост…", + "copyItemsToHost": "Копировать {{count}} элементов на хост…", + "copyToHost": "Копировать на хост…", + "destinationPath": "Путь назначения", + "destMustBeDirectory": "Для передачи нескольких элементов путь назначения должен быть папкой", + "goUp": "Вверх", + "hostAuthRequired": "Требуется аутентификация — сначала откройте Файловый Менеджер на этом хосте", + "hostConnecting": "Подключение…", + "hostConnectionFailed": "Ошибка подключения", + "hostDisconnected": "Не подключен", + "hostReady": "Готов", + "itemsSummary": "{{count}} элементов", + "jumpHostLimitation": "Оба хоста должны быть доступны с сервера Termix. Прямая маршрутизация между хостами не поддерживается.", + "methodAuto": "Авто", + "methodAutoHint": "Выбирает tar или пофайловый SFTP в зависимости от количества файлов, размера и сжимаемости. Одиночные файлы всегда передаются потоковым SFTP.", + "methodItemSftp": "Пофайловый SFTP", + "methodItemSftpHint": "Передача каждого файла отдельно по SFTP. Работает на всех хостах, включая Windows.", + "methodItemSftpLimitation": "Каждый файл использует один и тот же поток SFTP, как при копировании одного файла, один за другим. Прогресс объединяется по всем файлам, поэтому индикатор движется медленно при больших файлах.", + "methodLabel": "Метод передачи", + "methodPreviewError": "Не удалось предварительно определить метод передачи. Сервер выберет метод при запуске.", + "methodPreviewLoading": "Расчёт метода передачи…", + "methodPreviewScanSummary": "{{fileCount}} файлов, {{totalSize}} всего (просканировано на исходном хосте).", + "methodPreviewWillUseItemSftp": "Будет использован: Пофайловый SFTP", + "methodPreviewWillUseTar": "Будет использован: Архив Tar", + "methodReason": { + "user_item_sftp": "Вы выбрали пофайловый SFTP.", + "user_tar": "Вы выбрали tar-архив.", + "tar_unavailable": "Tar недоступен на одном или обоих хостах — вместо этого будет использоваться пофайловый SFTP.", + "windows_host": "Участвует хост под Windows — tar не используется.", + "auto_multi_large": "Авто: несколько файлов, включая большой файл ({{largestSize}}) со сжимаемыми данными — tar объединяет в одну передачу.", + "auto_single_large_in_archive": "Авто: один большой файл ({{largestSize}}) в этом наборе — пофайловый SFTP.", + "auto_many_incompressible": "Авто: в основном несжимаемые данные — пофайловый SFTP.", + "auto_many_files": "Авто: много файлов ({{fileCount}}) — tar сокращает накладные расходы на каждый файл.", + "auto_default": "Авто: пофайловый SFTP для этого набора." + }, + "methodTar": "Архив Tar", + "methodTarHint": "Сжатие на источнике, передача одного архива, распаковка на назначении. Требует tar на обоих Unix-хостах.", + "metricsCompress": "Сжатие на источнике: {{duration}}", + "metricsExtract": "Распаковка на назначении: {{duration}}", + "metricsPrepare": "Подготовка назначения: {{duration}}", + "metricsRouteBenchmark": "Маршрутный зонд — прямой: {{direct}}, ретранслятор: {{relay}}", + "metricsSourceDelete": "Удаление с источника: {{duration}}", + "metricsTotal": "Всего: {{duration}}", + "metricsTransfer": "Сквозной: {{throughput}} ({{duration}})", + "metricsVerify": "SHA-256 проверен: {{duration}}", + "moveFolderToHost": "Переместить папку на хост…", + "moveItemsToHost": "Переместить {{count}} элементов на хост…", + "moveToHost": "Переместить на хост…", + "noHostsConnected": "Нет других доступных хостов с файловым менеджером.", + "noHostsConnectedHint": "Добавьте другой SSH-хост с включенным Файловым Менеджером в Менеджере Хостов.", + "parallelSegmentsHint": "Большие файлы разбиваются на фрагменты по 256 МБ. Несколько каналов используют отдельные соединения (как при запуске нескольких передач) для повышения общей пропускной способности.", + "parallelSegmentsLabel": "Параллельные каналы передачи", + "parallelSegmentsOption": "{{count}} каналов", + "progressBenchmarking": "Выбор самого быстрого маршрута пересадки…", + "progressBytes": "{{transferred}} / {{total}}", + "progressCancel": "Отмена", + "progressCancelling": "Отмена…", + "progressCompressing": "Сжатие на исходном хосте…", + "progressExtracting": "Распаковка на назначении…", + "progressItems": "{{current}} / {{total}} файлов", + "progressReconnecting": "Переподключение…", + "progressStalled": "Зависло", + "progressTotalSpeed": "{{speed}} всего ({{lanes}} каналов)", + "progressTransferring": "Передача данных…", + "progressTransferringItems": "Передача файлов ({{current}} из {{total}})…", + "progressVerifying": "Проверка целостности файла…", + "recentDestinations": "Недавние назначения", + "resumedHint": "Переподключено к активной передаче, запущенной в другом окне.", + "retryTransfer": "Повторить", + "retryTransferError": "Повтор не удался", + "selectDestinationHost": "Выберите целевой хост", + "transferCancelled": "Передача отменена", + "transferCancelledCopyHint": "Частично переданные файлы могут остаться в месте назначения.", + "transferCancelledMoveHint": "Частично переданные файлы могут остаться в месте назначения. Исходные файлы не были удалены.", + "transferError": "Ошибка передачи", + "transferFailedRetryHint": "Частичные данные сохранены в месте назначения. Повтор возобновится, когда соединение восстановится.", + "transferPartialHint": "Не удалось передать: {{paths}}", + "transferSuccess": "Передача завершена" } } diff --git a/plugins/file-manager/locales/translated/sr_SP.json b/plugins/file-manager/locales/translated/sr_SP.json index 70c8ee593..37e4ca8a6 100644 --- a/plugins/file-manager/locales/translated/sr_SP.json +++ b/plugins/file-manager/locales/translated/sr_SP.json @@ -382,7 +382,10 @@ "defaultPathLabel": "Подразумевана путања", "fileManagerPathHint": "Директоријум који треба отворити када се покрене менаџер датотека за овај хост.", "fileManagerUrlCopied": "URL менаџера датотека је копиран", - "copyFileManagerUrlAction": "Копирај URL менаџера датотека" + "copyFileManagerUrlAction": "Копирај URL менаџера датотека", + "docsLink": "Прикажи документе", + "hostNotFound": "Хост није пронађен", + "loadingHost": "Учитавање хоста..." }, "settings": { "host": { @@ -406,5 +409,105 @@ "nav": { "sftp": "СФТП", "files": "Датотеке" + }, + "onboarding": { + "feature_files": "Менаџер датотека", + "feature_files_desc": "Прегледајте, отпремајте, преузимајте и уређујте датотеке преко SFTP-а без напуштања апликације." + }, + "terminal": { + "runTitle": "Покреће се {{command}} - {{host}}", + "terminalTitle": "Терминал - {{host}}", + "terminalWithPath": "Терминал - {{host}}:{{path}}" + }, + "transfer": { + "browseFolders": "Прегледајте одредишне фасцикле", + "browsePathError": "Није могуће отворити ову путању на одредишном хосту.", + "browsePathWillBeCreated": "Ова фасцикла још увек не постоји. Биће креирана када пренос почне.", + "cancel": "Откажи", + "cleanupDestFiles": "Очистите одредиште", + "cleanupDestFilesError": "Чишћење није успело", + "cleanupDestFilesNothing": "Нема ништа за чишћење на одредишту", + "cleanupDestFilesPartial": "Неке делимичне датотеке нису могле бити уклоњене", + "cleanupDestFilesSuccess": "Уклоњене су делимичне датотеке са одредишта", + "confirmCopy": "Копија", + "confirmMove": "Помери", + "copyFolderToHost": "Копирај фасциклу на хост…", + "copyItemsToHost": "Копирај {{count}} ставке за хостовање…", + "copyToHost": "Копирај на хост…", + "destinationPath": "Путања одредишта", + "destMustBeDirectory": "Одредиште мора бити директоријум за преносе више ставки", + "goUp": "Иди горе", + "hostAuthRequired": "Потребна је аутентификација — прво отворите File Manager на овом хосту", + "hostConnecting": "Повезивање…", + "hostConnectionFailed": "Повезивање није успело", + "hostDisconnected": "Није повезано", + "hostReady": "Спреман", + "itemsSummary": "{{count}} ставке", + "jumpHostLimitation": "Оба хоста морају бити доступна са Termix сервера. Директно рутирање од хоста до хоста није подржано.", + "methodAuto": "Аутоматски", + "methodAutoHint": "Бира tar или SFTP за сваку датотеку на основу броја датотека, величине и компресибилности. Појединачне датотеке увек користе SFTP за стримовање.", + "methodItemSftp": "SFTP по датотеци", + "methodItemSftpHint": "Пренесите сваку датотеку појединачно преко SFTP-а. Ради на свим хостовима, укључујући Windows.", + "methodItemSftpLimitation": "Свака датотека користи исти SFTP ток као и копија појединачних датотека, једна за другом. Напредак се комбинује за све датотеке, тако да се трака помера споро током великих датотека.", + "methodLabel": "Метод преноса", + "methodPreviewError": "Није могуће прегледати метод преноса. Сервер ће ипак изабрати метод када покренете.", + "methodPreviewLoading": "Израчунавање методе преноса…", + "methodPreviewScanSummary": "{{fileCount}} датотека, {{totalSize}} укупно (скенирано на изворном хосту).", + "methodPreviewWillUseItemSftp": "Користиће се: SFTP за сваку датотеку", + "methodPreviewWillUseTar": "Користиће се: Тар архива", + "methodReason": { + "user_item_sftp": "Изабрали сте SFTP за сваку датотеку.", + "user_tar": "Изабрали сте tar архиву.", + "tar_unavailable": "Тар није доступан на једном или оба хоста — уместо тога ће се користити SFTP протокол за сваку датотеку.", + "windows_host": "Укључен је Windows хост — tar се не користи.", + "auto_multi_large": "Аутоматски: више датотека укључујући велику датотеку ({{largestSize}}) са компресибилним подацима — tar пакети у један пренос.", + "auto_single_large_in_archive": "Аутоматски: једна велика датотека ({{largestSize}}) у овом скупу — SFTP за сваку датотеку.", + "auto_many_incompressible": "Аутоматски: углавном несемпљиви подаци — SFTP по датотеци.", + "auto_many_files": "Аутоматски: много датотека ({{fileCount}}) — tar смањује оптерећење по датотеци.", + "auto_default": "Аутоматски: SFTP за сваку датотеку за овај скуп." + }, + "methodTar": "Тар архива", + "methodTarHint": "Компресуј на изворном нивоу, пренеси једну архиву, распакуј на одредишту. Потребан је tar на оба Unix хоста.", + "metricsCompress": "Компресуј на изворном коду: {{duration}}", + "metricsExtract": "Издвајање на одредишту: {{duration}}", + "metricsPrepare": "Припреми одредиште: {{duration}}", + "metricsRouteBenchmark": "Сонда руте — директна: {{direct}}, релеј: {{relay}}", + "metricsSourceDelete": "Уклони из извора: {{duration}}", + "metricsTotal": "Укупно: {{duration}}", + "metricsTransfer": "Од краја до краја: {{throughput}} ({{duration}})", + "metricsVerify": "SHA-256 верификован: {{duration}}", + "moveFolderToHost": "Премести фасциклу на хост…", + "moveItemsToHost": "Премести {{count}} ставке на хост…", + "moveToHost": "Премести на хост…", + "noHostsConnected": "Нема других доступних хостова за управљање датотекама.", + "noHostsConnectedHint": "Додајте још један SSH хост са омогућеним File Manager-ом у Host Manager-у.", + "parallelSegmentsHint": "Велике датотеке су подељене на делове од 256 MB. Вишеструке траке користе одвојене везе (као што је покретање неколико преноса) за већи укупни проток.", + "parallelSegmentsLabel": "Паралелне траке за прелазак", + "parallelSegmentsOption": "{{count}} траке", + "progressBenchmarking": "Избор најбрже руте за трансфер…", + "progressBytes": "{{transferred}} / {{total}}", + "progressCancel": "Откажи", + "progressCancelling": "Отказивање…", + "progressCompressing": "Компресија на изворном хосту…", + "progressExtracting": "Распакује се на одредишту…", + "progressItems": "{{current}} / {{total}} датотеке", + "progressReconnecting": "Поновно повезивање…", + "progressStalled": "Заустављено", + "progressTotalSpeed": "{{speed}} укупно ({{lanes}} трака)", + "progressTransferring": "Пренос података…", + "progressTransferringItems": "Пренос датотека ({{current}} од {{total}})…", + "progressVerifying": "Провера интегритета датотеке…", + "recentDestinations": "Недавне дестинације", + "resumedHint": "Поново повезано са активним преносом започетим у другом прозору.", + "retryTransfer": "Покушај поново", + "retryTransferError": "Поновни покушај није успео", + "selectDestinationHost": "Изаберите одредишни хост", + "transferCancelled": "Трансфер отказан", + "transferCancelledCopyHint": "Делимични фајлови могу остати на одредишту.", + "transferCancelledMoveHint": "Делимични фајлови могу остати на одредишту. Изворни фајлови нису уклоњени.", + "transferError": "Пренос није успео", + "transferFailedRetryHint": "Делимични подаци су сачувани на одредишту. Покушај ће бити настављен када се веза поново успостави.", + "transferPartialHint": "Није могуће пренети: {{paths}}", + "transferSuccess": "Пренос завршен" } } diff --git a/plugins/file-manager/locales/translated/sv_SE.json b/plugins/file-manager/locales/translated/sv_SE.json index 8aa5397ac..8e18fc1be 100644 --- a/plugins/file-manager/locales/translated/sv_SE.json +++ b/plugins/file-manager/locales/translated/sv_SE.json @@ -382,7 +382,10 @@ "defaultPathLabel": "Standardsökväg", "fileManagerPathHint": "Katalogen som ska öppnas när filhanteraren startas för den här värden.", "fileManagerUrlCopied": "Filhanterarens URL kopierad", - "copyFileManagerUrlAction": "Kopiera filhanterarens URL" + "copyFileManagerUrlAction": "Kopiera filhanterarens URL", + "docsLink": "Visa dokument", + "hostNotFound": "Värden hittades inte", + "loadingHost": "Laddar värd..." }, "settings": { "host": { @@ -406,5 +409,105 @@ "nav": { "sftp": "SFTP", "files": "Filer" + }, + "onboarding": { + "feature_files": "Filhanteraren", + "feature_files_desc": "Bläddra, ladda upp, ladda ner och redigera filer via SFTP utan att lämna appen." + }, + "terminal": { + "runTitle": "Kör {{command}} - {{host}}", + "terminalTitle": "Terminal - {{host}}", + "terminalWithPath": "Terminal - {{host}}:{{path}}" + }, + "transfer": { + "browseFolders": "Bläddra bland målmappar", + "browsePathError": "Kunde inte öppna den här sökvägen på målvärden.", + "browsePathWillBeCreated": "Den här mappen finns inte ännu. Den kommer att skapas när överföringen startar.", + "cancel": "Avboka", + "cleanupDestFiles": "Städa upp destinationen", + "cleanupDestFilesError": "Rensningen misslyckades", + "cleanupDestFilesNothing": "Inget att städa upp på destinationen", + "cleanupDestFilesPartial": "Vissa delfiler kunde inte tas bort", + "cleanupDestFilesSuccess": "Tog bort delvisa filer från destinationen", + "confirmCopy": "Kopiera", + "confirmMove": "Flytta", + "copyFolderToHost": "Kopiera mapp till värden…", + "copyItemsToHost": "Kopiera {{count}} objekt till…", + "copyToHost": "Kopiera till värd…", + "destinationPath": "Destinationsväg", + "destMustBeDirectory": "Destinationen måste vara en katalog för överföringar av flera objekt", + "goUp": "Gå upp", + "hostAuthRequired": "Autentisering krävs — öppna filhanteraren på den här värden först", + "hostConnecting": "Ansluter…", + "hostConnectionFailed": "Anslutningen misslyckades", + "hostDisconnected": "Inte ansluten", + "hostReady": "Redo", + "itemsSummary": "{{count}} objekt", + "jumpHostLimitation": "Båda värdarna måste vara nåbara från Termix-servern. Direkt routing mellan värdar stöds inte.", + "methodAuto": "Bil", + "methodAutoHint": "Väljer tar eller SFTP per fil baserat på filantal, storlek och komprimerbarhet. Enstaka filer använder alltid strömmande SFTP.", + "methodItemSftp": "SFTP per fil", + "methodItemSftpHint": "Överför varje fil individuellt via SFTP. Fungerar på alla värdar inklusive Windows.", + "methodItemSftpLimitation": "Varje fil använder samma SFTP-ström som en kopia av en enda fil, en efter en. Förloppet kombineras över alla filer, så stapeln rör sig långsamt vid stora filer.", + "methodLabel": "Överföringsmetod", + "methodPreviewError": "Kunde inte förhandsgranska överföringsmetoden. Servern kommer fortfarande att välja en metod när du startar.", + "methodPreviewLoading": "Beräkning av överföringsmetod…", + "methodPreviewScanSummary": "{{fileCount}} filer, {{totalSize}} totalt (skannat på källvärd).", + "methodPreviewWillUseItemSftp": "Kommer att använda: SFTP per fil", + "methodPreviewWillUseTar": "Kommer att använda: Tar-arkiv", + "methodReason": { + "user_item_sftp": "Du valde SFTP per fil.", + "user_tar": "Du valde tar-arkivet.", + "tar_unavailable": "Tar är inte tillgängligt på en eller båda värdarna — SFTP per fil kommer att användas istället.", + "windows_host": "En Windows-värd är inblandad — tar används inte.", + "auto_multi_large": "Auto: flera filer inklusive en stor fil ({{largestSize}}) med komprimerbar data — tar-paket samlas i en överföring.", + "auto_single_large_in_archive": "Auto: en stor fil ({{largestSize}}) i denna uppsättning — SFTP per fil.", + "auto_many_incompressible": "Auto: mestadels inkomprimerbar data — SFTP per fil.", + "auto_many_files": "Auto: många filer ({{fileCount}}) — tar minskar overhead per fil.", + "auto_default": "Auto: SFTP per fil för den här uppsättningen." + }, + "methodTar": "Tar-arkiv", + "methodTarHint": "Komprimera vid källan, överför ett arkiv, extrahera vid destinationen. Kräver tar på båda Unix-värdarna.", + "metricsCompress": "Komprimera på källan: {{duration}}", + "metricsExtract": "Extrahera på destination: {{duration}}", + "metricsPrepare": "Förbered destination: {{duration}}", + "metricsRouteBenchmark": "Ruttsond — direkt: {{direct}}, relä: {{relay}}", + "metricsSourceDelete": "Ta bort från källan: {{duration}}", + "metricsTotal": "Totalt: {{duration}}", + "metricsTransfer": "Från slut till slut: {{throughput}} ({{duration}})", + "metricsVerify": "SHA-256 verifierad: {{duration}}", + "moveFolderToHost": "Flytta mappen till värden…", + "moveItemsToHost": "Flytta {{count}} objekt till…", + "moveToHost": "Flytta till värd…", + "noHostsConnected": "Inga andra filhanterarvärdar tillgängliga.", + "noHostsConnectedHint": "Lägg till en annan SSH-värd med Filhanteraren aktiverad i Värdhanteraren.", + "parallelSegmentsHint": "Stora filer delas upp i bitar på 256 MB. Flera filer använder separata anslutningar (som att starta flera överföringar) för högre total dataflöde.", + "parallelSegmentsLabel": "Parallella överföringsfält", + "parallelSegmentsOption": "{{count}} körfält", + "progressBenchmarking": "Välja den snabbaste bytesvägen…", + "progressBytes": "{{transferred}} / {{total}}", + "progressCancel": "Avboka", + "progressCancelling": "Avbryter…", + "progressCompressing": "Komprimering på källvärd…", + "progressExtracting": "Extraherar på destination…", + "progressItems": "{{current}} / {{total}} filer", + "progressReconnecting": "Återansluter…", + "progressStalled": "Stannade", + "progressTotalSpeed": "{{speed}} totalt ({{lanes}} körfält)", + "progressTransferring": "Överför data…", + "progressTransferringItems": "Överföra filer ({{current}} av {{total}})…", + "progressVerifying": "Verifierar filintegritet…", + "recentDestinations": "Senaste destinationerna", + "resumedHint": "Återansluten till en aktiv överföring som startade i ett annat fönster.", + "retryTransfer": "Försöka igen", + "retryTransferError": "Återförsök misslyckades", + "selectDestinationHost": "Välj destinationsvärd", + "transferCancelled": "Överföringen avbruten", + "transferCancelledCopyHint": "Delvisa filer kan finnas kvar på destinationen.", + "transferCancelledMoveHint": "Delvisa filer kan finnas kvar på destinationen. Källfilerna togs inte bort.", + "transferError": "Överföringen misslyckades", + "transferFailedRetryHint": "Delvis data sparades på destinationen. Försöket återupptas när anslutningen är tillbaka.", + "transferPartialHint": "Kunde inte överföra: {{paths}}", + "transferSuccess": "Överföringen är klar" } } diff --git a/plugins/file-manager/locales/translated/th_TH.json b/plugins/file-manager/locales/translated/th_TH.json index 35b615290..0324499b0 100644 --- a/plugins/file-manager/locales/translated/th_TH.json +++ b/plugins/file-manager/locales/translated/th_TH.json @@ -382,7 +382,10 @@ "defaultPathLabel": "เส้นทางเริ่มต้น", "fileManagerPathHint": "โฟลเดอร์ที่จะเปิดเมื่อโปรแกรมจัดการไฟล์เริ่มทำงานสำหรับโฮสต์นี้", "fileManagerUrlCopied": "คัดลอก URL ของตัวจัดการไฟล์แล้ว", - "copyFileManagerUrlAction": "คัดลอก URL ของตัวจัดการไฟล์" + "copyFileManagerUrlAction": "คัดลอก URL ของตัวจัดการไฟล์", + "docsLink": "ดูเอกสาร", + "hostNotFound": "ไม่พบโฮสต์", + "loadingHost": "กำลังโหลดโฮสต์..." }, "settings": { "host": { @@ -406,5 +409,105 @@ "nav": { "sftp": "เอสเอฟทีพี", "files": "ไฟล์" + }, + "onboarding": { + "feature_files": "ตัวจัดการไฟล์", + "feature_files_desc": "เรียกดู อัปโหลด ดาวน์โหลด และแก้ไขไฟล์ผ่าน SFTP โดยไม่ต้องออกจากแอปพลิเคชัน" + }, + "terminal": { + "runTitle": "กำลังวิ่ง {{command}} - {{host}}", + "terminalTitle": "เทอร์มินัล - {{host}}", + "terminalWithPath": "เทอร์มินัล - {{host}}:{{path}}" + }, + "transfer": { + "browseFolders": "เรียกดูโฟลเดอร์ปลายทาง", + "browsePathError": "ไม่สามารถเปิดเส้นทางนี้บนโฮสต์ปลายทางได้", + "browsePathWillBeCreated": "โฟลเดอร์นี้ยังไม่มีอยู่ จะถูกสร้างขึ้นเมื่อการถ่ายโอนเริ่มต้นขึ้น", + "cancel": "ยกเลิก", + "cleanupDestFiles": "สถานที่ทำความสะอาด", + "cleanupDestFilesError": "การทำความสะอาดล้มเหลว", + "cleanupDestFilesNothing": "ไม่มีอะไรต้องทำความสะอาดที่ปลายทาง", + "cleanupDestFilesPartial": "ไม่สามารถลบไฟล์บางส่วนได้", + "cleanupDestFilesSuccess": "ลบไฟล์บางส่วนออกจากปลายทางแล้ว", + "confirmCopy": "สำเนา", + "confirmMove": "เคลื่อนไหว", + "copyFolderToHost": "คัดลอกโฟลเดอร์ไปยังโฮสต์…", + "copyItemsToHost": "คัดลอกรายการ {{count}} รายการไปยังโฮสต์…", + "copyToHost": "คัดลอกไปยังโฮสต์…", + "destinationPath": "เส้นทางปลายทาง", + "destMustBeDirectory": "สำหรับการโอนย้ายหลายรายการ ปลายทางต้องเป็นไดเร็กทอรี", + "goUp": "ขึ้นไป", + "hostAuthRequired": "ต้องมีการยืนยันตัวตน — โปรดเปิดตัวจัดการไฟล์บนโฮสต์นี้ก่อน", + "hostConnecting": "กำลังเชื่อมต่อ…", + "hostConnectionFailed": "การเชื่อมต่อล้มเหลว", + "hostDisconnected": "ไม่ได้เชื่อมต่อ", + "hostReady": "พร้อม", + "itemsSummary": "{{count}} รายการ", + "jumpHostLimitation": "โฮสต์ทั้งสองต้องสามารถเข้าถึงได้จากเซิร์ฟเวอร์ Termix การกำหนดเส้นทางโดยตรงระหว่างโฮสต์ไม่ได้รับการสนับสนุน", + "methodAuto": "อัตโนมัติ", + "methodAutoHint": "เลือกใช้ไฟล์บีบอัดแบบ tar หรือ SFTP แบบต่อไฟล์ โดยพิจารณาจากจำนวนไฟล์ ขนาดไฟล์ และความสามารถในการบีบอัด ไฟล์เดี่ยวจะใช้ SFTP แบบสตรีมมิ่งเสมอ", + "methodItemSftp": "SFTP ต่อไฟล์", + "methodItemSftpHint": "โอนไฟล์แต่ละไฟล์ทีละไฟล์ผ่าน SFTP ใช้งานได้กับทุกระบบปฏิบัติการ รวมถึง Windows", + "methodItemSftpLimitation": "แต่ละไฟล์จะใช้สตรีม SFTP เดียวกันในการคัดลอกไฟล์ทีละไฟล์ ความคืบหน้าจะถูกรวมเข้าด้วยกัน ทำให้แถบแสดงความคืบหน้าเคลื่อนที่ช้าลงเมื่อคัดลอกไฟล์ขนาดใหญ่", + "methodLabel": "วิธีการถ่ายโอน", + "methodPreviewError": "ไม่สามารถดูตัวอย่างวิธีการถ่ายโอนได้ เซิร์ฟเวอร์จะเลือกวิธีการเมื่อคุณเริ่มต้นใช้งาน", + "methodPreviewLoading": "กำลังคำนวณวิธีการโอน…", + "methodPreviewScanSummary": "ไฟล์ {{fileCount}} ไฟล์, รวม {{totalSize}} ไฟล์ (สแกนจากโฮสต์ต้นทาง)", + "methodPreviewWillUseItemSftp": "จะใช้: SFTP แบบแยกไฟล์", + "methodPreviewWillUseTar": "จะใช้: ไฟล์เก็บถาวร Tar", + "methodReason": { + "user_item_sftp": "คุณเลือกใช้ SFTP แบบต่อไฟล์", + "user_tar": "คุณเลือกไฟล์เก็บถาวรแบบ tar", + "tar_unavailable": "Tar ไม่สามารถใช้งานได้บนโฮสต์หนึ่งหรือทั้งสองโฮสต์ จึงจะใช้ SFTP แบบแยกไฟล์แทน", + "windows_host": "ระบบปฏิบัติการที่ใช้คือ Windows — ไม่ได้ใช้โปรแกรม tar", + "auto_multi_large": "อัตโนมัติ: ไฟล์หลายไฟล์ รวมถึงไฟล์ขนาดใหญ่ ({{largestSize}}) ที่มีข้อมูลที่สามารถบีบอัดได้ — tar จะรวมไฟล์เหล่านั้นไว้ในการถ่ายโอนครั้งเดียว", + "auto_single_large_in_archive": "อัตโนมัติ: ไฟล์ขนาดใหญ่หนึ่งไฟล์ ({{largestSize}}) ในชุดนี้ — SFTP ต่อไฟล์", + "auto_many_incompressible": "อัตโนมัติ: ข้อมูลส่วนใหญ่ไม่สามารถบีบอัดได้ — SFTP แบบแยกไฟล์", + "auto_many_files": "อัตโนมัติ: หลายไฟล์ ({{fileCount}}) — tar ช่วยลดภาระต่อไฟล์", + "auto_default": "อัตโนมัติ: ตั้งค่า SFTP สำหรับแต่ละไฟล์ในชุดนี้" + }, + "methodTar": "คลังข้อมูลทาร์", + "methodTarHint": "บีบอัดไฟล์ที่ต้นทาง ถ่ายโอนไฟล์เก็บถาวรหนึ่งไฟล์ และแตกไฟล์ที่ปลายทาง ต้องใช้ tar บนเครื่อง Unix ทั้งสองเครื่อง", + "metricsCompress": "บีบอัดจากแหล่งที่มา: {{duration}}", + "metricsExtract": "แตกไฟล์ที่ปลายทาง: {{duration}}", + "metricsPrepare": "เตรียมปลายทาง: {{duration}}", + "metricsRouteBenchmark": "การตรวจสอบเส้นทาง — โดยตรง: {{direct}}, ส่งต่อ: {{relay}}", + "metricsSourceDelete": "ลบออกจากแหล่งที่มา: {{duration}}", + "metricsTotal": "รวม: {{duration}}", + "metricsTransfer": "จากต้นทางถึงปลายทาง: {{throughput}} ({{duration}})", + "metricsVerify": "ตรวจสอบด้วย SHA-256 แล้ว: {{duration}}", + "moveFolderToHost": "ย้ายโฟลเดอร์ไปยังโฮสต์…", + "moveItemsToHost": "ย้ายรายการ {{count}} รายการไปยังโฮสต์…", + "moveToHost": "ย้ายไปยังโฮสต์…", + "noHostsConnected": "ไม่มีโฮสต์ตัวจัดการไฟล์อื่นให้บริการ", + "noHostsConnectedHint": "เพิ่มโฮสต์ SSH อีกตัวโดยเปิดใช้งานตัวจัดการไฟล์ในตัวจัดการโฮสต์", + "parallelSegmentsHint": "ไฟล์ขนาดใหญ่จะถูกแบ่งออกเป็นส่วนย่อยขนาด 256 MB การใช้หลายเลนจะใช้การเชื่อมต่อแยกกัน (เช่น การเริ่มการถ่ายโอนหลายรายการพร้อมกัน) เพื่อให้ได้ปริมาณงานโดยรวมที่สูงขึ้น", + "parallelSegmentsLabel": "ช่องทางเปลี่ยนถ่ายแบบขนาน", + "parallelSegmentsOption": "{{count}} เลน", + "progressBenchmarking": "เลือกเส้นทางการโอนย้ายที่เร็วที่สุด…", + "progressBytes": "{{transferred}} / {{total}}", + "progressCancel": "ยกเลิก", + "progressCancelling": "การยกเลิก…", + "progressCompressing": "กำลังบีบอัดบนโฮสต์ต้นทาง…", + "progressExtracting": "กำลังแตกไฟล์ที่ปลายทาง…", + "progressItems": "ไฟล์ {{current}} / {{total}}", + "progressReconnecting": "กำลังเชื่อมต่อใหม่…", + "progressStalled": "หยุดชะงัก", + "progressTotalSpeed": "{{speed}} รวม ({{lanes}} เลน)", + "progressTransferring": "กำลังถ่ายโอนข้อมูล…", + "progressTransferringItems": "กำลังถ่ายโอนไฟล์ ({{current}} จาก {{total}})…", + "progressVerifying": "กำลังตรวจสอบความสมบูรณ์ของไฟล์…", + "recentDestinations": "จุดหมายปลายทางล่าสุด", + "resumedHint": "เชื่อมต่อใหม่กับการถ่ายโอนที่เริ่มทำงานในหน้าต่างอื่นแล้ว", + "retryTransfer": "ลองใหม่อีกครั้ง", + "retryTransferError": "การลองใหม่ล้มเหลว", + "selectDestinationHost": "เลือกโฮสต์ปลายทาง", + "transferCancelled": "การโอนเงินถูกยกเลิก", + "transferCancelledCopyHint": "ไฟล์บางส่วนอาจยังคงอยู่ในปลายทาง", + "transferCancelledMoveHint": "ไฟล์บางส่วนอาจยังคงอยู่ในปลายทาง ไฟล์ต้นฉบับไม่ได้ถูกลบออก", + "transferError": "การโอนล้มเหลว", + "transferFailedRetryHint": "ข้อมูลบางส่วนถูกเก็บไว้ในปลายทาง การลองใหม่จะดำเนินการต่อเมื่อการเชื่อมต่อกลับมาใช้งานได้", + "transferPartialHint": "ไม่สามารถโอนเงินได้: {{paths}}", + "transferSuccess": "การโอนเสร็จสมบูรณ์" } } diff --git a/plugins/file-manager/locales/translated/tr_TR.json b/plugins/file-manager/locales/translated/tr_TR.json index f75a1c7c4..679fbb03a 100644 --- a/plugins/file-manager/locales/translated/tr_TR.json +++ b/plugins/file-manager/locales/translated/tr_TR.json @@ -382,7 +382,10 @@ "defaultPathLabel": "Varsayılan Yol", "fileManagerPathHint": "Dosya yöneticisi bu sunucu için başlatıldığında açılacak dizin.", "fileManagerUrlCopied": "Dosya Yöneticisi URL'si kopyalandı", - "copyFileManagerUrlAction": "Dosya Yöneticisi URL'sini Kopyala" + "copyFileManagerUrlAction": "Dosya Yöneticisi URL'sini Kopyala", + "docsLink": "Dokümanları görüntüle", + "hostNotFound": "Host bulunamadı", + "loadingHost": "Host yükleniyor..." }, "settings": { "host": { @@ -406,5 +409,105 @@ "nav": { "sftp": "SFTP", "files": "Dosyalar" + }, + "onboarding": { + "feature_files": "Dosya yöneticisi", + "feature_files_desc": "Uygulamadan çıkmadan SFTP üzerinden dosyalara göz atın, yükleyin, indirin ve düzenleyin." + }, + "terminal": { + "runTitle": "Çalıştırılıyor: {{command}} - {{host}}", + "terminalTitle": "Terminal - {{host}}", + "terminalWithPath": "Terminal - {{host}}:{{path}}" + }, + "transfer": { + "browseFolders": "Hedef klasörlere göz at", + "browsePathError": "Hedef ana bilgisayarda bu yol açılamadı.", + "browsePathWillBeCreated": "Bu klasör henüz mevcut değil. Aktarım başladığında oluşturulacak.", + "cancel": "İptal", + "cleanupDestFiles": "Hedefi temizle", + "cleanupDestFilesError": "Temizleme başarısız oldu", + "cleanupDestFilesNothing": "Hedefte temizlenecek bir şey yok", + "cleanupDestFilesPartial": "Bazı kısmi dosyalar kaldırılamadı", + "cleanupDestFilesSuccess": "Hedefteki kısmi dosyalar kaldırıldı", + "confirmCopy": "Kopyala", + "confirmMove": "Taşı", + "copyFolderToHost": "Klasörü ana bilgisayara kopyala…", + "copyItemsToHost": "{{count}} öğeyi sunucuya kopyala…", + "copyToHost": "Sunucuya kopyala…", + "destinationPath": "Hedef yol", + "destMustBeDirectory": "Çoklu öğe aktarımları için hedef bir dizin olmalıdır", + "goUp": "Yukarı", + "hostAuthRequired": "Kimlik doğrulama gerekli — önce bu ana bilgisayarda Dosya Yöneticisi'ni açın", + "hostConnecting": "Bağlanıyor…", + "hostConnectionFailed": "Bağlantı başarısız", + "hostDisconnected": "Bağlı değil", + "hostReady": "Hazır", + "itemsSummary": "{{count}} öğe", + "jumpHostLimitation": "Her iki sunucuya da Termix sunucusundan erişilebilir olmalıdır. Sunucular arası doğrudan yönlendirme desteklenmez.", + "methodAuto": "Otomatik", + "methodAutoHint": "Dosya sayısı, boyutu ve sıkıştırılabilirliğe bağlı olarak tar veya dosya başına SFTP seçer. Tek dosyalar her zaman akış SFTP'si kullanır.", + "methodItemSftp": "Dosya başına SFTP", + "methodItemSftpHint": "Her dosyayı SFTP üzerinden tek tek aktarır. Windows dahil tüm sunucularda çalışır.", + "methodItemSftpLimitation": "Her dosya, tek bir dosya kopyasıyla aynı SFTP akışını sırayla kullanır. İlerleme tüm dosyalar için birleştirilmiştir, bu nedenle büyük dosyalar sırasında çubuk yavaş hareket eder.", + "methodLabel": "Aktarım yöntemi", + "methodPreviewError": "Aktarım yöntemi önizlenemedi. Başlattığınızda sunucu yine de bir yöntem seçecektir.", + "methodPreviewLoading": "Aktarım yöntemi hesaplanıyor…", + "methodPreviewScanSummary": "{{fileCount}} dosya, toplam {{totalSize}} (kaynak sunucuda tarandı).", + "methodPreviewWillUseItemSftp": "Kullanılacak: Dosya başına SFTP", + "methodPreviewWillUseTar": "Kullanılacak: Tar arşivi", + "methodReason": { + "user_item_sftp": "Dosya bazında SFTP seçtiniz.", + "user_tar": "Tar arşivi seçtiniz.", + "tar_unavailable": "Bir veya her iki ana bilgisayarda Tar kullanılamıyor — bunun yerine dosya bazında SFTP kullanılacak.", + "windows_host": "Windows ana bilgisayarı söz konusu — tar kullanılmaz.", + "auto_multi_large": "Otomatik: sıkıştırılabilir veriye sahip büyük bir dosya ({{largestSize}}) dahil birden çok dosya — tar tek bir aktarımda birleştirir.", + "auto_single_large_in_archive": "Otomatik: bu kümede bir büyük dosya ({{largestSize}}) — dosya bazında SFTP.", + "auto_many_incompressible": "Otomatik: çoğunlukla sıkıştırılamayan veri — dosya bazında SFTP.", + "auto_many_files": "Otomatik: çok sayıda dosya ({{fileCount}}) — tar dosya başına ek yükü azaltır.", + "auto_default": "Otomatik: bu küme için dosya bazında SFTP." + }, + "methodTar": "Tar arşivi", + "methodTarHint": "Kaynakta sıkıştır, tek arşiv aktar, hedefte çıkar. Her iki Unix sunucuda tar gerektirir.", + "metricsCompress": "Kaynakta sıkıştırma: {{duration}}", + "metricsExtract": "Hedefte çıkarma: {{duration}}", + "metricsPrepare": "Hedefi hazırla: {{duration}}", + "metricsRouteBenchmark": "Rota sondası — doğrudan: {{direct}}, röle: {{relay}}", + "metricsSourceDelete": "Kaynaktan silme: {{duration}}", + "metricsTotal": "Toplam: {{duration}}", + "metricsTransfer": "Uçtan uca: {{throughput}} ({{duration}})", + "metricsVerify": "SHA-256 ile doğrulandı: {{duration}}", + "moveFolderToHost": "Klasörü ana bilgisayara taşı…", + "moveItemsToHost": "{{count}} öğeyi ana bilgisayara taşı…", + "moveToHost": "Sunucuya taşı…", + "noHostsConnected": "Kullanılabilir başka dosya yöneticisi ana bilgisayarı yok.", + "noHostsConnectedHint": "Ana Bilgisayar Yöneticisi'nde Dosya Yöneticisi etkinleştirilmiş başka bir SSH ana bilgisayarı ekleyin.", + "parallelSegmentsHint": "Büyük dosyalar 256 MB'lık parçalara bölünür. Çoklu yollar, daha yüksek toplam aktarım hızı için ayrı bağlantılar kullanır (birden fazla aktarım başlatmak gibi).", + "parallelSegmentsLabel": "Paralel aktarım yolları", + "parallelSegmentsOption": "{{count}} yol", + "progressBenchmarking": "En hızlı aktarma rotasını seçme…", + "progressBytes": "{{transferred}} / {{total}}", + "progressCancel": "İptal", + "progressCancelling": "İptal ediliyor…", + "progressCompressing": "Kaynak sunucuda sıkıştırılıyor…", + "progressExtracting": "Hedefte çıkarılıyor…", + "progressItems": "{{current}} / {{total}} dosya", + "progressReconnecting": "Yeniden bağlanılıyor…", + "progressStalled": "Askıda", + "progressTotalSpeed": "{{speed}} toplam ({{lanes}} yol)", + "progressTransferring": "Veri aktarılıyor…", + "progressTransferringItems": "Dosyalar aktarılıyor ({{current}} / {{total}})…", + "progressVerifying": "Dosya bütünlüğünün doğrulanması…", + "recentDestinations": "Son hedefler", + "resumedHint": "Başka bir pencerede başlatılan aktif bir aktarıma yeniden bağlanıldı.", + "retryTransfer": "Yeniden dene", + "retryTransferError": "Yeniden deneme başarısız oldu", + "selectDestinationHost": "Hedef ana bilgisayarı seçin", + "transferCancelled": "Aktarım iptal edildi", + "transferCancelledCopyHint": "Hedefte kısmi dosyalar kalabilir.", + "transferCancelledMoveHint": "Hedefte kısmi dosyalar kalabilir. Kaynak dosyalar silinmedi.", + "transferError": "Aktarım başarısız", + "transferFailedRetryHint": "Hedefte kısmi veri tutuldu. Bağlantı geri geldiğinde yeniden deneme devam edecek.", + "transferPartialHint": "Aktarılamadı: {{paths}}", + "transferSuccess": "Aktarım tamamlandı" } } diff --git a/plugins/file-manager/locales/translated/uk_UA.json b/plugins/file-manager/locales/translated/uk_UA.json index 2cfdef097..da589e37f 100644 --- a/plugins/file-manager/locales/translated/uk_UA.json +++ b/plugins/file-manager/locales/translated/uk_UA.json @@ -382,7 +382,10 @@ "defaultPathLabel": "Шлях за замовчуванням", "fileManagerPathHint": "Каталог, який потрібно відкрити під час запуску файлового менеджера для цього хоста.", "fileManagerUrlCopied": "URL-адресу файлового менеджера скопійовано", - "copyFileManagerUrlAction": "Копіювати URL-адресу файлового менеджера" + "copyFileManagerUrlAction": "Копіювати URL-адресу файлового менеджера", + "docsLink": "Переглянути документи", + "hostNotFound": "Хост не знайдено", + "loadingHost": "Завантаження хоста..." }, "settings": { "host": { @@ -406,5 +409,105 @@ "nav": { "sftp": "SFTP", "files": "Файли" + }, + "onboarding": { + "feature_files": "Файловий менеджер", + "feature_files_desc": "Переглядайте, завантажуйте, вивантажуйте та редагуйте файли через SFTP, не виходячи з програми." + }, + "terminal": { + "runTitle": "Запуск {{command}} - {{host}}", + "terminalTitle": "Термінал - {{host}}", + "terminalWithPath": "Термінал - {{host}}:{{path}}" + }, + "transfer": { + "browseFolders": "Перегляд папок призначення", + "browsePathError": "Не вдалося відкрити цей шлях на хості призначення.", + "browsePathWillBeCreated": "Цієї папки ще не існує. Вона буде створена, коли розпочнеться передача.", + "cancel": "Скасувати", + "cleanupDestFiles": "Прибирання місця призначення", + "cleanupDestFilesError": "Очищення не вдалося", + "cleanupDestFilesNothing": "Нічого прибирати на місці призначення", + "cleanupDestFilesPartial": "Не вдалося видалити деякі часткові файли", + "cleanupDestFilesSuccess": "Видалено часткові файли з місця призначення", + "confirmCopy": "Копіювати", + "confirmMove": "Перемістити", + "copyFolderToHost": "Копіювати папку на хост…", + "copyItemsToHost": "Копіювати елементи {{count}} для розміщення…", + "copyToHost": "Копіювати на хост…", + "destinationPath": "Шлях призначення", + "destMustBeDirectory": "Для перенесення кількох елементів місцем призначення має бути каталог", + "goUp": "Піднімися", + "hostAuthRequired": "Потрібна автентифікація — спочатку відкрийте Файловий менеджер на цьому хості", + "hostConnecting": "Підключення…", + "hostConnectionFailed": "Помилка підключення", + "hostDisconnected": "Не підключено", + "hostReady": "Готовий", + "itemsSummary": "{{count}} елементів", + "jumpHostLimitation": "Обидва хости мають бути доступні з сервера Termix. Пряма маршрутизація між хостами не підтримується.", + "methodAuto": "Авто", + "methodAutoHint": "Вибирає tar-файл або SFTP для кожного файлу на основі кількості файлів, розміру та стискальності. Окремі файли завжди використовують потоковий SFTP.", + "methodItemSftp": "SFTP для кожного файлу", + "methodItemSftpHint": "Передавайте кожен файл окремо через SFTP. Працює на всіх хостах, включаючи Windows.", + "methodItemSftpLimitation": "Кожен файл використовує той самий потік SFTP, що й копія окремого файлу, послідовно. Прогрес об'єднується для всіх файлів, тому шкала рухається повільно під час роботи з великими файлами.", + "methodLabel": "Спосіб переказу", + "methodPreviewError": "Не вдалося переглянути метод передачі. Сервер все одно вибере метод під час запуску.", + "methodPreviewLoading": "Розрахунок методу переказу…", + "methodPreviewScanSummary": "{{fileCount}} файлів, {{totalSize}} всього (проскановано на вихідному хості).", + "methodPreviewWillUseItemSftp": "Буде використовуватися: SFTP для кожного файлу", + "methodPreviewWillUseTar": "Буде використано: архів Tar", + "methodReason": { + "user_item_sftp": "Ви обрали SFTP для кожного файлу.", + "user_tar": "Ви обрали tar-архів.", + "tar_unavailable": "Архів TAR недоступний на одному або обох хостах — замість нього використовуватиметься SFTP для кожного файлу.", + "windows_host": "Задіяний хост Windows — tar не використовується.", + "auto_multi_large": "Авто: кілька файлів, включаючи великий файл ({{largestSize}}) зі стисливими даними — tar-пакети об'єднуються в одну передачу.", + "auto_single_large_in_archive": "Авто: один великий файл ({{largestSize}}) у цьому наборі — SFTP для кожного файлу.", + "auto_many_incompressible": "Авто: переважно нестисливі дані — SFTP для кожного файлу.", + "auto_many_files": "Авто: багато файлів ({{fileCount}}) — tar зменшує навантаження на кожен файл.", + "auto_default": "Авто: SFTP для кожного файлу для цього набору." + }, + "methodTar": "Архів Tar", + "methodTarHint": "Стиснення у вихідному коді, перенесення одного архіву, розпакування у кінцевому. Потрібен tar-архів на обох хостах Unix.", + "metricsCompress": "Стиснути у вихідному коді: {{duration}}", + "metricsExtract": "Вилучити в місці призначення: {{duration}}", + "metricsPrepare": "Підготувати пункт призначення: {{duration}}", + "metricsRouteBenchmark": "Зонд маршруту — прямий: {{direct}}, ретрансляція: {{relay}}", + "metricsSourceDelete": "Видалити з джерела: {{duration}}", + "metricsTotal": "Всього: {{duration}}", + "metricsTransfer": "Від кінця до кінця: {{throughput}} ({{duration}})", + "metricsVerify": "SHA-256 перевірено: {{duration}}", + "moveFolderToHost": "Перемістити папку на хост…", + "moveItemsToHost": "Перемістити {{count}} елементів на хост…", + "moveToHost": "Перемістити на хост…", + "noHostsConnected": "Інших хостів файлових менеджерів немає.", + "noHostsConnectedHint": "Додайте ще один SSH-хост з увімкненим файловим менеджером у Host Manager.", + "parallelSegmentsHint": "Великі файли розділяються на фрагменти по 256 МБ. Кілька ліній використовують окремі з’єднання (наприклад, запуск кількох передач) для підвищення загальної пропускної здатності.", + "parallelSegmentsLabel": "Паралельні пересадочні смуги", + "parallelSegmentsOption": "{{count}} смуги", + "progressBenchmarking": "Вибір найшвидшого маршруту пересадки…", + "progressBytes": "{{transferred}} / {{total}}", + "progressCancel": "Скасувати", + "progressCancelling": "Скасування…", + "progressCompressing": "Стиснення на вихідному хості…", + "progressExtracting": "Видобування в місці призначення…", + "progressItems": "{{current}} / {{total}} файли", + "progressReconnecting": "Повторне підключення…", + "progressStalled": "Зупинився", + "progressTotalSpeed": "{{speed}} всього ({{lanes}} смуг)", + "progressTransferring": "Передача даних…", + "progressTransferringItems": "Передача файлів ({{current}} з {{total}})…", + "progressVerifying": "Перевірка цілісності файлу…", + "recentDestinations": "Нещодавні напрямки", + "resumedHint": "Повторне підключення до активної передачі, розпочатої в іншому вікні.", + "retryTransfer": "Повторити спробу", + "retryTransferError": "Повторна спроба не вдалася", + "selectDestinationHost": "Виберіть хост призначення", + "transferCancelled": "Переказ скасовано", + "transferCancelledCopyHint": "Часткові файли можуть залишатися на пристрої призначення.", + "transferCancelledMoveHint": "Часткові файли можуть залишатися в місці призначення. Вихідні файли не видалено.", + "transferError": "Передача не вдалася", + "transferFailedRetryHint": "На місці призначення збережено частку даних. Повторна спроба відновиться після відновлення з’єднання.", + "transferPartialHint": "Не вдалося перенести: {{paths}}", + "transferSuccess": "Перенесення завершено" } } diff --git a/plugins/file-manager/locales/translated/vi_VN.json b/plugins/file-manager/locales/translated/vi_VN.json index 5a65c616b..9b0331b7d 100644 --- a/plugins/file-manager/locales/translated/vi_VN.json +++ b/plugins/file-manager/locales/translated/vi_VN.json @@ -382,7 +382,10 @@ "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.", "fileManagerUrlCopied": "Đã sao chép URL Trình quản lý tệp", - "copyFileManagerUrlAction": "Sao chép URL File Manager" + "copyFileManagerUrlAction": "Sao chép URL File Manager", + "docsLink": "Xem tài liệu", + "hostNotFound": "Không tìm thấy máy chủ", + "loadingHost": "Đang tải máy chủ..." }, "settings": { "host": { @@ -406,5 +409,105 @@ "nav": { "sftp": "SFTP", "files": "Tệp" + }, + "onboarding": { + "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." + }, + "terminal": { + "runTitle": "Đang chạy {{command}} - {{host}}", + "terminalTitle": "Terminal - {{host}}", + "terminalWithPath": "Terminal - {{host}}:{{path}}" + }, + "transfer": { + "browseFolders": "Duyệt thư mục đích", + "browsePathError": "Không thể mở đường dẫn này trên máy chủ đích.", + "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.", + "cancel": "Hủy", + "cleanupDestFiles": "Dọn dẹp đích", + "cleanupDestFilesError": "Dọn dẹp thất bại", + "cleanupDestFilesNothing": "Không có gì để dọn dẹp ở đích", + "cleanupDestFilesPartial": "Không thể xóa một số tệp chưa hoàn chỉnh", + "cleanupDestFilesSuccess": "Đã xóa các tệp chưa hoàn chỉnh ở đích", + "confirmCopy": "Sao chép", + "confirmMove": "Di chuyển", + "copyFolderToHost": "Sao chép thư mục tới máy chủ…", + "copyItemsToHost": "Sao chép {{count}} mục đến máy chủ…", + "copyToHost": "Sao chép đến máy chủ…", + "destinationPath": "Đường dẫn đích", + "destMustBeDirectory": "Đích phải là thư mục khi truyền tải nhiều mục", + "goUp": "Lên trên", + "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", + "hostConnecting": "Đang kết nối…", + "hostConnectionFailed": "Kết nối thất bại", + "hostDisconnected": "Chưa kết nối", + "hostReady": "Sẵn sàng", + "itemsSummary": "{{count}} mục", + "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.", + "methodAuto": "Tự động", + "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.", + "methodItemSftp": "SFTP từng tệp", + "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.", + "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.", + "methodLabel": "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.", + "methodPreviewLoading": "Đang tính toán phương thức truyền…", + "methodPreviewScanSummary": "{{fileCount}} tệp, tổng {{totalSize}} (đã quét trên máy nguồn).", + "methodPreviewWillUseItemSftp": "Sẽ dùng: SFTP từng tệp", + "methodPreviewWillUseTar": "Sẽ dùng: Lưu trữ tar", + "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." + }, + "methodTar": "Lưu trữ tar", + "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.", + "metricsCompress": "Nén tại nguồn: {{duration}}", + "metricsExtract": "Giải nén tại đích: {{duration}}", + "metricsPrepare": "Chuẩn bị đích: {{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}}", + "metricsTransfer": "Toàn trình: {{throughput}} ({{duration}})", + "metricsVerify": "Đã xác thực SHA-256: {{duration}}", + "moveFolderToHost": "Di chuyển thư mục tới máy chủ…", + "moveItemsToHost": "Di chuyển {{count}} mục tới máy chủ…", + "moveToHost": "Di chuyển đến 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ủ.", + "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.", + "parallelSegmentsLabel": "Làn truyền song song", + "parallelSegmentsOption": "{{count}} làn", + "progressBenchmarking": "Chọn tuyến đường chuyển tiếp nhanh nhất…", + "progressBytes": "{{transferred}} / {{total}}", + "progressCancel": "Hủy", + "progressCancelling": "Đang hủy…", + "progressCompressing": "Đang nén trên máy nguồn…", + "progressExtracting": "Đang giải nén tại đích…", + "progressItems": "{{current}} / {{total}} tệp", + "progressReconnecting": "Đang kết nối lại…", + "progressStalled": "Đình trệ", + "progressTotalSpeed": "{{speed}} tổng ({{lanes}} làn)", + "progressTransferring": "Đang truyền dữ liệu…", + "progressTransferringItems": "Đang truyền tệp ({{current}}/{{total}})…", + "progressVerifying": "Đang xác minh tính toàn vẹn của tệp…", + "recentDestinations": "Đích gần đây", + "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.", + "retryTransfer": "Thử lại", + "retryTransferError": "Thử lại thất bại", + "selectDestinationHost": "Chọn máy chủ đích", + "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.", + "transferError": "Truyền tả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.", + "transferPartialHint": "Không thể truyền tải: {{paths}}", + "transferSuccess": "Truyền tải hoàn tất" } } diff --git a/plugins/file-manager/locales/translated/zh_CN.json b/plugins/file-manager/locales/translated/zh_CN.json index ac0bce8fe..f701bda7d 100644 --- a/plugins/file-manager/locales/translated/zh_CN.json +++ b/plugins/file-manager/locales/translated/zh_CN.json @@ -382,7 +382,10 @@ "defaultPathLabel": "默认路径", "fileManagerPathHint": "为此主机启动文件管理器时要打开的目录。", "fileManagerUrlCopied": "文件管理器 URL 已复制", - "copyFileManagerUrlAction": "复制文件管理器 URL" + "copyFileManagerUrlAction": "复制文件管理器 URL", + "docsLink": "查看文档", + "hostNotFound": "未找到主机", + "loadingHost": "正在加载主机..." }, "settings": { "host": { @@ -406,5 +409,105 @@ "nav": { "sftp": "SFTP", "files": "文件" + }, + "onboarding": { + "feature_files": "文件管理器", + "feature_files_desc": "无需离开应用,即可通过 SFTP 浏览、上传、下载及编辑文件。" + }, + "terminal": { + "runTitle": "运行 {{command}} - {{host}}", + "terminalTitle": "终端 - {{host}}", + "terminalWithPath": "终端 - {{host}}:{{path}}" + }, + "transfer": { + "browseFolders": "浏览目标文件夹", + "browsePathError": "无法在目标主机上打开此路径。", + "browsePathWillBeCreated": "此文件夹尚不存在,将在传输开始时创建。", + "cancel": "取消", + "cleanupDestFiles": "清理目标位置", + "cleanupDestFilesError": "清理失败", + "cleanupDestFilesNothing": "目标位置无需清理", + "cleanupDestFilesPartial": "部分文件无法删除", + "cleanupDestFilesSuccess": "已从目标位置删除部分文件", + "confirmCopy": "复制", + "confirmMove": "移动", + "copyFolderToHost": "复制文件夹到主机…", + "copyItemsToHost": "复制 {{count}} 个项目到主机…", + "copyToHost": "复制到主机…", + "destinationPath": "目标路径", + "destMustBeDirectory": "对于多项目传输,目标必须是一个目录", + "goUp": "向上", + "hostAuthRequired": "需要身份验证 — 请先在此主机上打开文件管理器", + "hostConnecting": "连接中…", + "hostConnectionFailed": "连接失败", + "hostDisconnected": "未连接", + "hostReady": "就绪", + "itemsSummary": "{{count}} 个项目", + "jumpHostLimitation": "两个主机都必须能从 Termix 服务器访问。不支持直接的主机到主机路由。", + "methodAuto": "自动", + "methodAutoHint": "根据文件数量、大小和可压缩性选择 tar 或逐文件 SFTP。单个文件始终使用流式 SFTP。", + "methodItemSftp": "逐文件 SFTP", + "methodItemSftpHint": "通过 SFTP 逐个传输文件。适用于包括 Windows 在内的所有主机。", + "methodItemSftpLimitation": "每个文件使用相同的 SFTP 流(与单文件拷贝一样),一个接一个传输。所有文件的进度合并显示,因此大文件传输时进度条移动缓慢。", + "methodLabel": "传输方式", + "methodPreviewError": "无法预览传输方式。启动时服务器仍会选择方式。", + "methodPreviewLoading": "正在计算传输方式…", + "methodPreviewScanSummary": "{{fileCount}} 个文件,总计 {{totalSize}}(已在源主机上扫描)。", + "methodPreviewWillUseItemSftp": "将使用:逐文件 SFTP", + "methodPreviewWillUseTar": "将使用:Tar 归档", + "methodReason": { + "user_item_sftp": "您选择了逐文件 SFTP。", + "user_tar": "您选择了 Tar 归档。", + "tar_unavailable": "一个或多个主机上不可用 tar — 将转而使用逐文件 SFTP。", + "windows_host": "涉及 Windows 主机 — 不使用 tar。", + "auto_multi_large": "自动:多个文件,其中包括一个包含可压缩数据的大文件({{largestSize}})— tar 将其打包成一次传输。", + "auto_single_large_in_archive": "自动:此集合中有一个大文件({{largestSize}})— 使用逐文件 SFTP。", + "auto_many_incompressible": "自动:大部分为不可压缩数据 — 使用逐文件 SFTP。", + "auto_many_files": "自动:文件众多({{fileCount}})— tar 可减少逐文件开销。", + "auto_default": "自动:此集合使用逐文件 SFTP。" + }, + "methodTar": "Tar 归档", + "methodTarHint": "在源端压缩,传输单个归档文件,在目标端解压。要求两个 Unix 主机都有 tar。", + "metricsCompress": "源端压缩:{{duration}}", + "metricsExtract": "目标端解压:{{duration}}", + "metricsPrepare": "准备目标:{{duration}}", + "metricsRouteBenchmark": "路由探测 — 直接: {{direct}},中继: {{relay}}", + "metricsSourceDelete": "从源端删除:{{duration}}", + "metricsTotal": "总计:{{duration}}", + "metricsTransfer": "端到端:{{throughput}} ({{duration}})", + "metricsVerify": "SHA-256 已验证: {{duration}}", + "moveFolderToHost": "移动文件夹到主机…", + "moveItemsToHost": "移动 {{count}} 个项目到主机…", + "moveToHost": "移动到主机…", + "noHostsConnected": "没有其他可用的文件管理器主机。", + "noHostsConnectedHint": "在主机管理器中添加启用文件管理器的其他 SSH 主机。", + "parallelSegmentsHint": "大文件会被拆分为 256 MB 的块。多个通道使用独立连接(如同同时进行多个传输),以获得更高的总吞吐量。", + "parallelSegmentsLabel": "并行传输通道", + "parallelSegmentsOption": "{{count}} 个通道", + "progressBenchmarking": "选择最快的传输路线…", + "progressBytes": "{{transferred}} / {{total}}", + "progressCancel": "取消", + "progressCancelling": "正在取消…", + "progressCompressing": "正在源主机上压缩…", + "progressExtracting": "正在目标端解压…", + "progressItems": "{{current}} / {{total}} 个文件", + "progressReconnecting": "重新连接中…", + "progressStalled": "已停滞", + "progressTotalSpeed": "{{speed}} 总计({{lanes}} 通道)", + "progressTransferring": "正在传输数据…", + "progressTransferringItems": "正在传输文件({{current}}/{{total}})…", + "progressVerifying": "正在验证文件完整性…", + "recentDestinations": "最近目标", + "resumedHint": "已重新连接到在另一个窗口中启动的进行中的传输。", + "retryTransfer": "重试", + "retryTransferError": "重试失败", + "selectDestinationHost": "选择目标主机", + "transferCancelled": "传输已取消", + "transferCancelledCopyHint": "目标位置可能残留部分文件。", + "transferCancelledMoveHint": "目标位置可能残留部分文件。源文件未被删除。", + "transferError": "传输失败", + "transferFailedRetryHint": "部分数据已保留在目标位置。连接恢复后重试将继续。", + "transferPartialHint": "无法传输:{{paths}}", + "transferSuccess": "传输完成" } } diff --git a/plugins/file-manager/locales/translated/zh_TW.json b/plugins/file-manager/locales/translated/zh_TW.json index 8d6319b4a..a762a3a38 100644 --- a/plugins/file-manager/locales/translated/zh_TW.json +++ b/plugins/file-manager/locales/translated/zh_TW.json @@ -382,7 +382,10 @@ "defaultPathLabel": "預設路徑", "fileManagerPathHint": "啟動此主機的檔案管理員時開啟的目錄。", "fileManagerUrlCopied": "檔案管理員 URL 已複製", - "copyFileManagerUrlAction": "複製檔案管理員 URL" + "copyFileManagerUrlAction": "複製檔案管理員 URL", + "docsLink": "檢視文件", + "hostNotFound": "找不到主機", + "loadingHost": "正在載入主機..." }, "settings": { "host": { @@ -406,5 +409,105 @@ "nav": { "sftp": "SFTP", "files": "檔案" + }, + "onboarding": { + "feature_files": "文件管理器", + "feature_files_desc": "無需離開應用程序,即可透過 SFTP 瀏覽、上傳、下載和編輯檔案。" + }, + "terminal": { + "runTitle": "正在執行 {{command}} - {{host}}", + "terminalTitle": "終端機 - {{host}}", + "terminalWithPath": "終端機 - {{host}}:{{path}}" + }, + "transfer": { + "browseFolders": "瀏覽目標資料夾", + "browsePathError": "無法在目標主機上開啟此路徑。", + "browsePathWillBeCreated": "此資料夾尚不存在。傳送開始時將會建立。", + "cancel": "取消", + "cleanupDestFiles": "清理目的地", + "cleanupDestFilesError": "清理失敗", + "cleanupDestFilesNothing": "目的地無需清理", + "cleanupDestFilesPartial": "部分檔案無法移除", + "cleanupDestFilesSuccess": "已從目的地移除部分檔案", + "confirmCopy": "複製", + "confirmMove": "移動", + "copyFolderToHost": "複製資料夾至主機…", + "copyItemsToHost": "複製 {{count}} 個項目到主機…", + "copyToHost": "複製到主機…", + "destinationPath": "目標路徑", + "destMustBeDirectory": "多項目傳送時,目標必須是資料夾", + "goUp": "向上", + "hostAuthRequired": "需要驗證 — 請先在此主機上開啟檔案管理員", + "hostConnecting": "連線中…", + "hostConnectionFailed": "連線失敗", + "hostDisconnected": "未連線", + "hostReady": "就緒", + "itemsSummary": "{{count}} 個項目", + "jumpHostLimitation": "兩台主機都必須可從 Termix 伺服器連線。不支援主機對主機的直接路由。", + "methodAuto": "自動", + "methodAutoHint": "根據檔案數量、大小及可壓縮性選擇 tar 封存或逐檔 SFTP。單一檔案一律使用串流 SFTP。", + "methodItemSftp": "逐檔 SFTP", + "methodItemSftpHint": "透過 SFTP 逐一傳輸每個檔案。適用於所有主機,包括 Windows。", + "methodItemSftpLimitation": "每個檔案依序使用相同的 SFTP 串流作為單一檔案複製。進度會合併所有檔案,因此處理大型檔案時進度條會緩慢移動。", + "methodLabel": "傳輸方法", + "methodPreviewError": "無法預覽傳輸方法。啟動時伺服器仍會選擇一個方法。", + "methodPreviewLoading": "正在計算傳輸方法…", + "methodPreviewScanSummary": "{{fileCount}} 個檔案,總計 {{totalSize}}(已在來源主機掃描)。", + "methodPreviewWillUseItemSftp": "將使用:逐檔 SFTP", + "methodPreviewWillUseTar": "將使用:Tar 封存", + "methodReason": { + "user_item_sftp": "您選擇了逐檔 SFTP。", + "user_tar": "您選擇了 tar 封存。", + "tar_unavailable": "一或多部主機無法使用 tar,將改用逐檔 SFTP。", + "windows_host": "涉及 Windows 主機,因此不使用 tar。", + "auto_multi_large": "自動:多個檔案中包含一個具可壓縮資料的大型檔案 ({{largestSize}}),tar 會將所有檔案封裝成單一傳輸。", + "auto_single_large_in_archive": "自動:此集合中有一個大型檔案 ({{largestSize}}) — 逐檔 SFTP。", + "auto_many_incompressible": "自動:多為不可壓縮資料 — 逐檔 SFTP。", + "auto_many_files": "自動:多個檔案 ({{fileCount}}) — tar 可減少逐檔傳輸的額外負擔。", + "auto_default": "自動:此集合使用逐檔 SFTP。" + }, + "methodTar": "Tar 封存", + "methodTarHint": "在來源主機壓縮,傳輸一個封存檔,在目標主機解壓縮。需兩台 Unix 主機皆安裝 tar。", + "metricsCompress": "在來源主機壓縮: {{duration}}", + "metricsExtract": "在目標主機解壓縮: {{duration}}", + "metricsPrepare": "準備目標:{{duration}}", + "metricsRouteBenchmark": "路由探測 — 直接: {{direct}},中繼: {{relay}}", + "metricsSourceDelete": "從來源主機刪除: {{duration}}", + "metricsTotal": "總計: {{duration}}", + "metricsTransfer": "端對端: {{throughput}} ({{duration}})", + "metricsVerify": "SHA-256 已驗證: {{duration}}", + "moveFolderToHost": "移動資料夾至主機…", + "moveItemsToHost": "將 {{count}} 個項目移至主機…", + "moveToHost": "移動到主機…", + "noHostsConnected": "無其他可用的檔案管理員主機。", + "noHostsConnectedHint": "在主機管理員中新增另一個已啟用檔案管理員的 SSH 主機。", + "parallelSegmentsHint": "大型檔案會分割成 256 MB 區塊。多個通道會使用獨立的連線(如同啟動多個傳輸作業)以獲取更高的總傳輸速率。", + "parallelSegmentsLabel": "平行傳輸通道", + "parallelSegmentsOption": "{{count}} 個通道", + "progressBenchmarking": "選擇最快的傳輸路線…", + "progressBytes": "{{transferred}} / {{total}}", + "progressCancel": "取消", + "progressCancelling": "正在取消…", + "progressCompressing": "在來源主機壓縮中…", + "progressExtracting": "在目標主機解壓縮中…", + "progressItems": "{{current}} / {{total}} 個檔案", + "progressReconnecting": "重新連線中…", + "progressStalled": "停滯", + "progressTotalSpeed": "總計 {{speed}}({{lanes}} 個通道)", + "progressTransferring": "傳輸資料中…", + "progressTransferringItems": "傳輸檔案中({{current}} / {{total}})…", + "progressVerifying": "正在驗證檔案完整性…", + "recentDestinations": "最近使用的目的地", + "resumedHint": "已重新連線至在另一個視窗中啟動的進行中傳輸。", + "retryTransfer": "重試", + "retryTransferError": "重試失敗", + "selectDestinationHost": "選擇目標主機", + "transferCancelled": "傳輸已取消", + "transferCancelledCopyHint": "部分檔案可能仍留在目的地。", + "transferCancelledMoveHint": "部分檔案可能仍留在目的地,來源檔案未被移除。", + "transferError": "傳送失敗", + "transferFailedRetryHint": "部分資料已保留在目的地。重新連線後,重試將從斷點繼續。", + "transferPartialHint": "無法傳送:{{paths}}", + "transferSuccess": "傳送完成" } } diff --git a/plugins/fleets/locales/en.json b/plugins/fleets/locales/en.json index 0fe7a94dc..18ffb4fa6 100644 --- a/plugins/fleets/locales/en.json +++ b/plugins/fleets/locales/en.json @@ -106,5 +106,45 @@ }, "nav": { "fleets": "Fleets" + }, + "hosts": { + "docsLink": "View docs", + "sharing": { + "customHoursPlaceholder": "Hours until access expires", + "expiry": { + "never": "Never", + "oneHour": "1 hour", + "oneDay": "24 hours", + "sevenDays": "7 days", + "thirtyDays": "30 days", + "custom": "Custom" + }, + "expiryLabel": "Access expiry", + "levels": { + "connect": { + "label": "Connect", + "description": "Open sessions only: terminal, remote desktop, file manager, tunnels and Docker. No access to the host configuration." + }, + "view": { + "label": "View", + "description": "Connect, plus see the host configuration. Secrets are never shown." + }, + "edit": { + "label": "Edit", + "description": "View, plus modify non-authentication host settings. The owner's SSH authentication stays private and owner-only." + }, + "manage": { + "label": "Manage", + "description": "Edit, plus share the host with others, change permission levels and revoke access." + } + }, + "noMatches": "No matches found", + "permissionLevelLabel": "Permission level", + "rolesTab": "Roles", + "searchPlaceholder": "Search users or roles...", + "shareButton": "Share", + "shareWithCount": "Share ({{count}})", + "usersTab": "Users" + } } } diff --git a/plugins/fleets/locales/translated/af_ZA.json b/plugins/fleets/locales/translated/af_ZA.json index e0d6d4904..f8a428ba9 100644 --- a/plugins/fleets/locales/translated/af_ZA.json +++ b/plugins/fleets/locales/translated/af_ZA.json @@ -85,5 +85,45 @@ }, "nav": { "fleets": "Vlote" + }, + "hosts": { + "docsLink": "Bekyk dokumente", + "sharing": { + "customHoursPlaceholder": "Ure totdat toegang verval", + "expiry": { + "never": "Nooit", + "oneHour": "1 uur", + "oneDay": "24 uur", + "sevenDays": "7 dae", + "thirtyDays": "30 dae", + "custom": "Pasgemaak" + }, + "expiryLabel": "Toegang verval", + "levels": { + "connect": { + "label": "Verbind", + "description": "Slegs oop sessies: terminaal, afstandwerkskerm, lêerbestuurder, tonnels en Docker. Geen toegang tot die gasheerkonfigurasie nie." + }, + "view": { + "label": "Bekyk", + "description": "Verbind, plus sien die gasheerkonfigurasie. Geheime word nooit gewys nie." + }, + "edit": { + "label": "Wysig", + "description": "Bekyk, plus wysig nie-verifikasie gasheerinstellings. Die eienaar se SSH-verifikasie bly privaat en slegs vir die eienaar." + }, + "manage": { + "label": "Bestuur", + "description": "Wysig, plus deel die gasheer met ander, verander toestemmingsvlakke en herroep toegang." + } + }, + "noMatches": "Geen ooreenstemmings gevind nie", + "permissionLevelLabel": "Toestemmingsvlak", + "rolesTab": "Rolle", + "searchPlaceholder": "Soek gebruikers of rolle...", + "shareButton": "Deel", + "shareWithCount": "Deel ({{count}})", + "usersTab": "Gebruikers" + } } } diff --git a/plugins/fleets/locales/translated/ar_SA.json b/plugins/fleets/locales/translated/ar_SA.json index 9a941645e..5e2c1d03e 100644 --- a/plugins/fleets/locales/translated/ar_SA.json +++ b/plugins/fleets/locales/translated/ar_SA.json @@ -85,5 +85,45 @@ }, "nav": { "fleets": "الأساطيل" + }, + "hosts": { + "docsLink": "عرض المستندات", + "sharing": { + "customHoursPlaceholder": "عدد الساعات حتى انتهاء صلاحية الوصول", + "expiry": { + "never": "أبدًا", + "oneHour": "ساعة واحدة", + "oneDay": "24 ساعة", + "sevenDays": "7 أيام", + "thirtyDays": "30 يومًا", + "custom": "مخصص" + }, + "expiryLabel": "انتهاء صلاحية الوصول", + "levels": { + "connect": { + "label": "اتصال", + "description": "فتح الجلسات فقط: الطرفية، سطح المكتب البعيد، مدير الملفات، الأنفاق وDocker. لا يمكن الوصول إلى إعدادات المضيف." + }, + "view": { + "label": "عرض", + "description": "الاتصال، بالإضافة إلى عرض إعدادات المضيف. لا تظهر الأسرار أبدًا." + }, + "edit": { + "label": "تعديل", + "description": "يمكنك عرض وتعديل إعدادات المضيف غير المتعلقة بالمصادقة. تبقى مصادقة SSH الخاصة بالمالك سرية ومخصصة له فقط." + }, + "manage": { + "label": "إدارة", + "description": "التعديل، بالإضافة إلى مشاركة المضيف مع الآخرين، وتغيير مستويات الصلاحية وإلغاء الوصول." + } + }, + "noMatches": "لا توجد نتائج مطابقة", + "permissionLevelLabel": "مستوى الصلاحية", + "rolesTab": "الأدوار", + "searchPlaceholder": "البحث عن مستخدمين أو أدوار...", + "shareButton": "مشاركة", + "shareWithCount": "مشاركة ({{count}})", + "usersTab": "المستخدمون" + } } } diff --git a/plugins/fleets/locales/translated/bg_BG.json b/plugins/fleets/locales/translated/bg_BG.json index 204400954..41029c287 100644 --- a/plugins/fleets/locales/translated/bg_BG.json +++ b/plugins/fleets/locales/translated/bg_BG.json @@ -85,5 +85,45 @@ }, "nav": { "fleets": "Флотили" + }, + "hosts": { + "docsLink": "Преглед на документи", + "sharing": { + "customHoursPlaceholder": "Часове до изтичане на срока на достъп", + "expiry": { + "never": "Никога", + "oneHour": "1 час", + "oneDay": "24 часа", + "sevenDays": "7 дни", + "thirtyDays": "30 дни", + "custom": "Персонализирано" + }, + "expiryLabel": "Изтичане на достъпа", + "levels": { + "connect": { + "label": "Свържете се", + "description": "Само отворени сесии: терминал, отдалечен работен плот, файлов мениджър, тунели и Docker. Няма достъп до конфигурацията на хоста." + }, + "view": { + "label": "Преглед", + "description": "Свържете се, плюс вижте конфигурацията на хоста. Тайните никога не се показват." + }, + "edit": { + "label": "Редактиране", + "description": "Преглеждайте и променяйте настройките на хоста без удостоверяване. SSH удостоверяването на собственика остава частно и само за собственика." + }, + "manage": { + "label": "Управление", + "description": "Редактирайте, плюс споделяйте хоста с други, променяйте нивата на разрешения и отменяйте достъпа." + } + }, + "noMatches": "Няма намерени съвпадения", + "permissionLevelLabel": "Ниво на разрешение", + "rolesTab": "Роли", + "searchPlaceholder": "Търсене на потребители или роли...", + "shareButton": "Споделяне", + "shareWithCount": "Споделяне ({{count}})", + "usersTab": "Потребители" + } } } diff --git a/plugins/fleets/locales/translated/bn_BD.json b/plugins/fleets/locales/translated/bn_BD.json index 98b071fbc..f399b73c5 100644 --- a/plugins/fleets/locales/translated/bn_BD.json +++ b/plugins/fleets/locales/translated/bn_BD.json @@ -85,5 +85,45 @@ }, "nav": { "fleets": "ফ্লিট" + }, + "hosts": { + "docsLink": "নথি দেখুন", + "sharing": { + "customHoursPlaceholder": "অ্যাক্সেসের মেয়াদ শেষ হতে বাকি ঘন্টা", + "expiry": { + "never": "কখনো না", + "oneHour": "১ ঘন্টা", + "oneDay": "২৪ ঘন্টা", + "sevenDays": "৭ দিন", + "thirtyDays": "৩০ দিন", + "custom": "কাস্টম" + }, + "expiryLabel": "অ্যাক্সেসের মেয়াদ শেষ", + "levels": { + "connect": { + "label": "সংযোগ করুন", + "description": "শুধুমাত্র টার্মিনাল, রিমোট ডেস্কটপ, ফাইল ম্যানেজার, টানেল এবং ডকার সেশনগুলো খোলা থাকবে। হোস্ট কনফিগারেশনে কোনো অ্যাক্সেস নেই।" + }, + "view": { + "label": "দেখুন", + "description": "সংযোগ করুন, এবং হোস্ট কনফিগারেশন দেখুন। গোপনীয় তথ্য কখনোই দেখানো হয় না।" + }, + "edit": { + "label": "সম্পাদনা", + "description": "নন-অথেনটিকেশন হোস্ট সেটিংস দেখুন এবং পরিবর্তন করুন। মালিকের SSH অথেনটিকেশন ব্যক্তিগত এবং শুধুমাত্র মালিকের জন্যই সংরক্ষিত থাকে।" + }, + "manage": { + "label": "পরিচালনা করুন", + "description": "সম্পাদনা করুন, সেইসাথে অন্যদের সাথে হোস্টটি শেয়ার করুন, অনুমতির স্তর পরিবর্তন করুন এবং অ্যাক্সেস প্রত্যাহার করুন।" + } + }, + "noMatches": "কোনো মিল খুঁজে পাওয়া যায়নি", + "permissionLevelLabel": "অনুমতি স্তর", + "rolesTab": "ভূমিকা", + "searchPlaceholder": "ব্যবহারকারী বা ভূমিকা অনুসন্ধান করুন...", + "shareButton": "শেয়ার", + "shareWithCount": "শেয়ার করুন ({{count}})", + "usersTab": "ব্যবহারকারীরা" + } } } diff --git a/plugins/fleets/locales/translated/ca_ES.json b/plugins/fleets/locales/translated/ca_ES.json index 895227ddb..9906e2a2a 100644 --- a/plugins/fleets/locales/translated/ca_ES.json +++ b/plugins/fleets/locales/translated/ca_ES.json @@ -85,5 +85,45 @@ }, "nav": { "fleets": "Flotes" + }, + "hosts": { + "docsLink": "Veure documents", + "sharing": { + "customHoursPlaceholder": "Hores fins que caduca l'accés", + "expiry": { + "never": "Mai", + "oneHour": "1 hora", + "oneDay": "24 hores", + "sevenDays": "7 dies", + "thirtyDays": "30 dies", + "custom": "Personalitzat" + }, + "expiryLabel": "Caducitat de l'accés", + "levels": { + "connect": { + "label": "Connecta", + "description": "Només sessions obertes: terminal, escriptori remot, gestor de fitxers, túnels i Docker. No hi ha accés a la configuració de l'amfitrió." + }, + "view": { + "label": "Vista", + "description": "Connecta't i consulta la configuració de l'amfitrió. Els secrets no es mostren mai." + }, + "edit": { + "label": "Edita", + "description": "Visualitza i modifica la configuració de l'amfitrió que no és d'autenticació. L'autenticació SSH del propietari es manté privada i només del propietari." + }, + "manage": { + "label": "Gestiona", + "description": "Edita i comparteix l'amfitrió amb altres persones, canvia els nivells de permisos i revoca l'accés." + } + }, + "noMatches": "No s'han trobat coincidències", + "permissionLevelLabel": "Nivell de permís", + "rolesTab": "Rols", + "searchPlaceholder": "Cerca usuaris o rols...", + "shareButton": "Comparteix", + "shareWithCount": "Comparteix ({{count}})", + "usersTab": "Usuaris" + } } } diff --git a/plugins/fleets/locales/translated/cs_CZ.json b/plugins/fleets/locales/translated/cs_CZ.json index 3e440db53..42b7d5318 100644 --- a/plugins/fleets/locales/translated/cs_CZ.json +++ b/plugins/fleets/locales/translated/cs_CZ.json @@ -85,5 +85,45 @@ }, "nav": { "fleets": "Flotily" + }, + "hosts": { + "docsLink": "Zobrazit dokumenty", + "sharing": { + "customHoursPlaceholder": "Hodiny do vypršení přístupu", + "expiry": { + "never": "Nikdy", + "oneHour": "1 hodina", + "oneDay": "24 hodin", + "sevenDays": "7 dní", + "thirtyDays": "30 dní", + "custom": "Zvyk" + }, + "expiryLabel": "Vypršení přístupu", + "levels": { + "connect": { + "label": "Připojit", + "description": "Pouze otevřené relace: terminál, vzdálená plocha, správce souborů, tunely a Docker. Bez přístupu ke konfiguraci hostitele." + }, + "view": { + "label": "Pohled", + "description": "Připojte se a podívejte se na konfiguraci hostitele. Tajné kódy se nikdy nezobrazují." + }, + "edit": { + "label": "Upravit", + "description": "Zobrazení a úprava nastavení hostitele bez ověřování. Ověřování vlastníka přes SSH zůstává soukromé a pouze pro vlastníka." + }, + "manage": { + "label": "Spravovat", + "description": "Upravovat a sdílet hostitele s ostatními, měnit úrovně oprávnění a odebírat přístup." + } + }, + "noMatches": "Nenalezeny žádné shody", + "permissionLevelLabel": "Úroveň oprávnění", + "rolesTab": "Role", + "searchPlaceholder": "Hledat uživatele nebo role...", + "shareButton": "Podíl", + "shareWithCount": "Sdílet ({{count}})", + "usersTab": "Uživatelé" + } } } diff --git a/plugins/fleets/locales/translated/da_DK.json b/plugins/fleets/locales/translated/da_DK.json index c5d65e1a1..609429c7f 100644 --- a/plugins/fleets/locales/translated/da_DK.json +++ b/plugins/fleets/locales/translated/da_DK.json @@ -85,5 +85,45 @@ }, "nav": { "fleets": "Flåder" + }, + "hosts": { + "docsLink": "Se dokumenter", + "sharing": { + "customHoursPlaceholder": "Timer indtil adgangen udløber", + "expiry": { + "never": "Aldrig", + "oneHour": "1 time", + "oneDay": "24 timer", + "sevenDays": "7 dage", + "thirtyDays": "30 dage", + "custom": "Skik" + }, + "expiryLabel": "Udløb af adgang", + "levels": { + "connect": { + "label": "Forbinde", + "description": "Kun åbne sessioner: terminal, fjernskrivebord, filhåndtering, tunneler og Docker. Ingen adgang til værtkonfigurationen." + }, + "view": { + "label": "Udsigt", + "description": "Opret forbindelse, plus se værtkonfigurationen. Hemmeligheder vises aldrig." + }, + "edit": { + "label": "Redigere", + "description": "Se og rediger ikke-godkendelseshostindstillinger. Ejerens SSH-godkendelse forbliver privat og kun for ejeren." + }, + "manage": { + "label": "Styre", + "description": "Rediger, plus del værten med andre, skift tilladelsesniveauer og tilbagekald adgang." + } + }, + "noMatches": "Ingen matches fundet", + "permissionLevelLabel": "Tilladelsesniveau", + "rolesTab": "Roller", + "searchPlaceholder": "Søg efter brugere eller roller...", + "shareButton": "Dele", + "shareWithCount": "Del ({{count}})", + "usersTab": "Brugere" + } } } diff --git a/plugins/fleets/locales/translated/de_DE.json b/plugins/fleets/locales/translated/de_DE.json index 7fa332345..a411e05af 100644 --- a/plugins/fleets/locales/translated/de_DE.json +++ b/plugins/fleets/locales/translated/de_DE.json @@ -85,5 +85,45 @@ }, "nav": { "fleets": "Flotten" + }, + "hosts": { + "docsLink": "Dokumentation anzeigen", + "sharing": { + "customHoursPlaceholder": "Stunden bis zum Zugriffsablauf", + "expiry": { + "never": "Nie", + "oneHour": "1 Stunde", + "oneDay": "24 Stunden", + "sevenDays": "7 Tage", + "thirtyDays": "30 Tage", + "custom": "Benutzerdefiniert" + }, + "expiryLabel": "Zugriffsablauf", + "levels": { + "connect": { + "label": "Verbinden", + "description": "Nur Sitzungen öffnen: Terminal, Remotedesktop, Dateimanager, Tunnel und Docker. Kein Zugriff auf die Hostkonfiguration." + }, + "view": { + "label": "Anzeigen", + "description": "Verbinden sowie Hostkonfiguration anzeigen. Geheimnisse werden nie angezeigt." + }, + "edit": { + "label": "Bearbeiten", + "description": "Sie können die Einstellungen für Hosts ohne Authentifizierung anzeigen und bearbeiten. Die SSH-Authentifizierung des Besitzers bleibt privat und ist nur für den Besitzer zugänglich." + }, + "manage": { + "label": "Verwalten", + "description": "Bearbeiten sowie Host für andere freigeben, Berechtigungsstufen ändern und Zugriff entziehen." + } + }, + "noMatches": "Keine Treffer gefunden", + "permissionLevelLabel": "Berechtigungsstufe", + "rolesTab": "Rollen", + "searchPlaceholder": "Benutzer oder Rollen suchen...", + "shareButton": "Teilen", + "shareWithCount": "Teilen ({{count}})", + "usersTab": "Benutzer" + } } } diff --git a/plugins/fleets/locales/translated/el_GR.json b/plugins/fleets/locales/translated/el_GR.json index 2c822690f..b4667290e 100644 --- a/plugins/fleets/locales/translated/el_GR.json +++ b/plugins/fleets/locales/translated/el_GR.json @@ -85,5 +85,45 @@ }, "nav": { "fleets": "Στόλοι" + }, + "hosts": { + "docsLink": "Προβολή εγγράφων", + "sharing": { + "customHoursPlaceholder": "Ώρες μέχρι τη λήξη της πρόσβασης", + "expiry": { + "never": "Ποτέ", + "oneHour": "1 ώρα", + "oneDay": "24 ώρες", + "sevenDays": "7 ημέρες", + "thirtyDays": "30 ημέρες", + "custom": "Εθιμο" + }, + "expiryLabel": "Λήξη πρόσβασης", + "levels": { + "connect": { + "label": "Συνδέω", + "description": "Μόνο ανοιχτές συνεδρίες: τερματικό, απομακρυσμένη επιφάνεια εργασίας, διαχειριστής αρχείων, σήραγγες και Docker. Δεν υπάρχει πρόσβαση στη διαμόρφωση του κεντρικού υπολογιστή." + }, + "view": { + "label": "Θέα", + "description": "Συνδεθείτε και δείτε τη διαμόρφωση του κεντρικού υπολογιστή. Τα μυστικά δεν εμφανίζονται ποτέ." + }, + "edit": { + "label": "Εκδίδω", + "description": "Προβολή και τροποποίηση ρυθμίσεων κεντρικού υπολογιστή που δεν απαιτούν έλεγχο ταυτότητας. Ο έλεγχος ταυτότητας SSH του κατόχου παραμένει ιδιωτικός και μόνο για τον κάτοχο." + }, + "manage": { + "label": "Διαχειρίζομαι", + "description": "Επεξεργαστείτε και μοιραστείτε τον κεντρικό υπολογιστή με άλλους, αλλάξτε τα επίπεδα δικαιωμάτων και ανακαλέστε την πρόσβαση." + } + }, + "noMatches": "Δεν βρέθηκαν αντιστοιχίσεις", + "permissionLevelLabel": "Επίπεδο δικαιωμάτων", + "rolesTab": "Ρόλοι", + "searchPlaceholder": "Αναζήτηση χρηστών ή ρόλων...", + "shareButton": "Μερίδιο", + "shareWithCount": "Κοινή χρήση ({{count}})", + "usersTab": "Χρήστες" + } } } diff --git a/plugins/fleets/locales/translated/es_ES.json b/plugins/fleets/locales/translated/es_ES.json index 5f7439657..47888c03d 100644 --- a/plugins/fleets/locales/translated/es_ES.json +++ b/plugins/fleets/locales/translated/es_ES.json @@ -85,5 +85,45 @@ }, "nav": { "fleets": "Flotas" + }, + "hosts": { + "docsLink": "Ver documentación", + "sharing": { + "customHoursPlaceholder": "Horas hasta que caduque el acceso", + "expiry": { + "never": "Nunca", + "oneHour": "1 hora", + "oneDay": "24 horas", + "sevenDays": "7 días", + "thirtyDays": "30 días", + "custom": "Personalizado" + }, + "expiryLabel": "Caducidad del acceso", + "levels": { + "connect": { + "label": "Conectar", + "description": "Abrir solo sesiones: terminal, escritorio remoto, gestor de archivos, túneles y Docker. Sin acceso a la configuración del host." + }, + "view": { + "label": "Ver", + "description": "Conectar, además de ver la configuración del host. Los secretos nunca se muestran." + }, + "edit": { + "label": "Editar", + "description": "Visualice y modifique la configuración del host que no requiere autenticación. La autenticación SSH del propietario permanece privada y solo accesible para él." + }, + "manage": { + "label": "Gestionar", + "description": "Editar, además de compartir el host con otros, cambiar niveles de permiso y revocar el acceso." + } + }, + "noMatches": "No se han encontrado coincidencias", + "permissionLevelLabel": "Nivel de permiso", + "rolesTab": "Roles", + "searchPlaceholder": "Buscar usuarios o roles...", + "shareButton": "Compartir", + "shareWithCount": "Compartir ({{count}})", + "usersTab": "Usuarios" + } } } diff --git a/plugins/fleets/locales/translated/fi_FI.json b/plugins/fleets/locales/translated/fi_FI.json index 5992f0469..536a93516 100644 --- a/plugins/fleets/locales/translated/fi_FI.json +++ b/plugins/fleets/locales/translated/fi_FI.json @@ -85,5 +85,45 @@ }, "nav": { "fleets": "Laivastot" + }, + "hosts": { + "docsLink": "Näytä dokumentit", + "sharing": { + "customHoursPlaceholder": "Tuntia käyttöoikeuden vanhenemiseen", + "expiry": { + "never": "Ei koskaan", + "oneHour": "1 tunti", + "oneDay": "24 tuntia", + "sevenDays": "7 päivää", + "thirtyDays": "30 päivää", + "custom": "Mukautettu" + }, + "expiryLabel": "Käyttöoikeuden päättyminen", + "levels": { + "connect": { + "label": "Yhdistä", + "description": "Vain avoimet istunnot: pääte, etätyöpöytä, tiedostonhallinta, tunnelit ja Docker. Ei pääsyä isäntäkokoonpanoon." + }, + "view": { + "label": "Näytä", + "description": "Yhdistä ja katso isäntäkokoonpano. Salaisuuksia ei koskaan näytetä." + }, + "edit": { + "label": "Muokata", + "description": "Näytä ja muokkaa ei-todennukseen perustuvia isäntäasetuksia. Omistajan SSH-todennus pysyy yksityisenä ja vain omistajalle tarkoitettuna." + }, + "manage": { + "label": "Hallitse", + "description": "Muokkaa ja jaa isäntä muiden kanssa, muuta käyttöoikeustasoja ja peruuta käyttöoikeuksia." + } + }, + "noMatches": "Ei osumia", + "permissionLevelLabel": "Käyttöoikeustaso", + "rolesTab": "Roolit", + "searchPlaceholder": "Hae käyttäjiä tai rooleja...", + "shareButton": "Jakaa", + "shareWithCount": "Jaa ({{count}})", + "usersTab": "Käyttäjät" + } } } diff --git a/plugins/fleets/locales/translated/fr_FR.json b/plugins/fleets/locales/translated/fr_FR.json index a79e7a324..09c3279d8 100644 --- a/plugins/fleets/locales/translated/fr_FR.json +++ b/plugins/fleets/locales/translated/fr_FR.json @@ -85,5 +85,45 @@ }, "nav": { "fleets": "Flottes" + }, + "hosts": { + "docsLink": "Voir la documentation", + "sharing": { + "customHoursPlaceholder": "Heures jusqu'à l'expiration de l'accès", + "expiry": { + "never": "Jamais", + "oneHour": "1 heure", + "oneDay": "24 heures", + "sevenDays": "7 jours", + "thirtyDays": "30 jours", + "custom": "Personnalisé" + }, + "expiryLabel": "Expiration de l’accès", + "levels": { + "connect": { + "label": "Connexion", + "description": "Ouverture de sessions uniquement : terminal, bureau à distance, gestionnaire de fichiers, tunnels et Docker. Aucun accès à la configuration de l'hôte." + }, + "view": { + "label": "Consultation", + "description": "Connexion, plus consultation de la configuration de l’hôte. Les secrets ne sont jamais affichés." + }, + "edit": { + "label": "Modification", + "description": "Consultez et modifiez les paramètres de l'hôte sans authentification. L'authentification SSH du propriétaire reste privée et accessible uniquement à ce dernier." + }, + "manage": { + "label": "Gestion", + "description": "Modification, plus partager l'hôte avec d'autres utilisateurs, modifier les niveaux de permission et révoquer l'accès." + } + }, + "noMatches": "Aucun résultat trouvé", + "permissionLevelLabel": "Niveau de permission", + "rolesTab": "Rôles", + "searchPlaceholder": "Rechercher des utilisateurs ou des rôles…", + "shareButton": "Partager", + "shareWithCount": "Partager ({{count}})", + "usersTab": "Utilisateurs" + } } } diff --git a/plugins/fleets/locales/translated/he_IL.json b/plugins/fleets/locales/translated/he_IL.json index aacc267c5..4a515854d 100644 --- a/plugins/fleets/locales/translated/he_IL.json +++ b/plugins/fleets/locales/translated/he_IL.json @@ -85,5 +85,45 @@ }, "nav": { "fleets": "ציי רכב" + }, + "hosts": { + "docsLink": "הצג מסמכים", + "sharing": { + "customHoursPlaceholder": "שעות עד לפקיעת הגישה", + "expiry": { + "never": "לְעוֹלָם לֹא", + "oneHour": "שעה אחת", + "oneDay": "24 שעות", + "sevenDays": "7 ימים", + "thirtyDays": "30 ימים", + "custom": "מִנְהָג" + }, + "expiryLabel": "פקיעת גישה", + "levels": { + "connect": { + "label": "לְחַבֵּר", + "description": "הפעלות פתוחות בלבד: טרמינל, שולחן עבודה מרוחק, מנהל קבצים, מנהרות ו-Docker. אין גישה לתצורת המארח." + }, + "view": { + "label": "נוֹף", + "description": "התחבר, בנוסף ראה את תצורת המארח. סודות לעולם אינם מוצגים." + }, + "edit": { + "label": "לַעֲרוֹך", + "description": "הצג ושנה הגדרות של מארח שאינו קשור לאימות. אימות ה-SSH של הבעלים נשאר פרטי ולבעלים בלבד." + }, + "manage": { + "label": "לְנַהֵל", + "description": "עריכה, בנוסף לשיתוף המארח עם אחרים, שינוי רמות הרשאה וביטול גישה." + } + }, + "noMatches": "לא נמצאו התאמות", + "permissionLevelLabel": "רמת הרשאה", + "rolesTab": "תפקידים", + "searchPlaceholder": "חיפוש משתמשים או תפקידים...", + "shareButton": "לַחֲלוֹק", + "shareWithCount": "שתף ({{count}})", + "usersTab": "משתמשים" + } } } diff --git a/plugins/fleets/locales/translated/hi_IN.json b/plugins/fleets/locales/translated/hi_IN.json index 1b9e94e18..6b06d0547 100644 --- a/plugins/fleets/locales/translated/hi_IN.json +++ b/plugins/fleets/locales/translated/hi_IN.json @@ -85,5 +85,45 @@ }, "nav": { "fleets": "बेड़े" + }, + "hosts": { + "docsLink": "दस्तावेज़ देखें", + "sharing": { + "customHoursPlaceholder": "पहुँच समाप्त होने तक के घंटे", + "expiry": { + "never": "कभी नहीं", + "oneHour": "1 घंटा", + "oneDay": "24 घंटे", + "sevenDays": "7 दिन", + "thirtyDays": "30 दिन", + "custom": "कस्टम" + }, + "expiryLabel": "पहुँच समाप्ति", + "levels": { + "connect": { + "label": "कनेक्ट", + "description": "केवल सत्र खोलें: टर्मिनल, रिमोट डेस्कटॉप, फ़ाइल प्रबंधक, टनल और Docker। होस्ट कॉन्फ़िगरेशन तक पहुँच नहीं।" + }, + "view": { + "label": "देखें", + "description": "कनेक्ट करें, साथ ही होस्ट कॉन्फ़िगरेशन देखें। सीक्रेट कभी नहीं दिखाए जाते।" + }, + "edit": { + "label": "संपादित करें", + "description": "आप बिना प्रमाणीकरण वाले होस्ट की सेटिंग्स देख सकते हैं और उनमें बदलाव कर सकते हैं। मालिक का SSH प्रमाणीकरण गोपनीय रहता है और केवल मालिक के लिए ही उपलब्ध होता है।" + }, + "manage": { + "label": "प्रबंधित करें", + "description": "संपादित करें, और दूसरों के साथ होस्ट साझा करें, अनुमति स्तर बदलें और पहुँच रद्द करें।" + } + }, + "noMatches": "कोई मिलान नहीं मिला", + "permissionLevelLabel": "अनुमति स्तर", + "rolesTab": "भूमिकाएँ", + "searchPlaceholder": "उपयोगकर्ता या भूमिकाएँ खोजें...", + "shareButton": "साझा करें", + "shareWithCount": "साझा करें ({{count}})", + "usersTab": "उपयोगकर्ता" + } } } diff --git a/plugins/fleets/locales/translated/hu_HU.json b/plugins/fleets/locales/translated/hu_HU.json index 100656064..d44a8dabb 100644 --- a/plugins/fleets/locales/translated/hu_HU.json +++ b/plugins/fleets/locales/translated/hu_HU.json @@ -85,5 +85,45 @@ }, "nav": { "fleets": "Flották" + }, + "hosts": { + "docsLink": "Dokumentumok megtekintése", + "sharing": { + "customHoursPlaceholder": "Órák a hozzáférés lejártáig", + "expiry": { + "never": "Soha", + "oneHour": "1 óra", + "oneDay": "24 óra", + "sevenDays": "7 nap", + "thirtyDays": "30 nap", + "custom": "Szokás" + }, + "expiryLabel": "Hozzáférés lejárata", + "levels": { + "connect": { + "label": "Csatlakozás", + "description": "Csak nyitott munkamenetek: terminál, távoli asztal, fájlkezelő, alagutak és Docker. Nincs hozzáférés a gazdagép konfigurációjához." + }, + "view": { + "label": "Kilátás", + "description": "Csatlakozás, valamint a gazdagép konfigurációjának megtekintése. A titkos kódok soha nem jelennek meg." + }, + "edit": { + "label": "Szerkesztés", + "description": "A nem hitelesítési hosztbeállítások megtekintése és módosítása. A tulajdonos SSH-hitelesítése privát és csak a tulajdonos számára elérhető marad." + }, + "manage": { + "label": "Kezelés", + "description": "Szerkeszd, és oszd meg a gazdagépet másokkal, módosítsd a jogosultsági szinteket és vond vissza a hozzáférést." + } + }, + "noMatches": "Nincs találat", + "permissionLevelLabel": "Jogosultsági szint", + "rolesTab": "Szerepkörök", + "searchPlaceholder": "Felhasználók vagy szerepkörök keresése...", + "shareButton": "Részesedés", + "shareWithCount": "Megosztás ({{count}})", + "usersTab": "Felhasználók" + } } } diff --git a/plugins/fleets/locales/translated/id_ID.json b/plugins/fleets/locales/translated/id_ID.json index fcc949634..9fc9dc2d4 100644 --- a/plugins/fleets/locales/translated/id_ID.json +++ b/plugins/fleets/locales/translated/id_ID.json @@ -85,5 +85,45 @@ }, "nav": { "fleets": "Armada" + }, + "hosts": { + "docsLink": "Lihat dokumen", + "sharing": { + "customHoursPlaceholder": "Waktu hingga akses berakhir", + "expiry": { + "never": "Tidak pernah", + "oneHour": "1 jam", + "oneDay": "24 jam", + "sevenDays": "7 hari", + "thirtyDays": "30 hari", + "custom": "Kebiasaan" + }, + "expiryLabel": "Kedaluwarsa akses", + "levels": { + "connect": { + "label": "Menghubungkan", + "description": "Hanya sesi yang diizinkan untuk dibuka: terminal, desktop jarak jauh, pengelola file, terowongan, dan Docker. Tidak ada akses ke konfigurasi host." + }, + "view": { + "label": "Melihat", + "description": "Hubungkan, dan lihat konfigurasi host. Rahasia tidak akan pernah ditampilkan." + }, + "edit": { + "label": "Edit", + "description": "Lihat, dan ubah pengaturan host non-autentikasi. Autentikasi SSH pemilik tetap bersifat pribadi dan hanya untuk pemilik." + }, + "manage": { + "label": "Mengelola", + "description": "Edit, bagikan host dengan orang lain, ubah tingkat izin, dan cabut akses." + } + }, + "noMatches": "Tidak ditemukan kecocokan.", + "permissionLevelLabel": "Tingkat izin", + "rolesTab": "Peran", + "searchPlaceholder": "Cari pengguna atau peran...", + "shareButton": "Membagikan", + "shareWithCount": "Bagikan ({{count}})", + "usersTab": "Pengguna" + } } } diff --git a/plugins/fleets/locales/translated/it_IT.json b/plugins/fleets/locales/translated/it_IT.json index e5a2a6319..58ae5aa58 100644 --- a/plugins/fleets/locales/translated/it_IT.json +++ b/plugins/fleets/locales/translated/it_IT.json @@ -85,5 +85,45 @@ }, "nav": { "fleets": "Flotte" + }, + "hosts": { + "docsLink": "Visualizza documentazione", + "sharing": { + "customHoursPlaceholder": "Ore fino alla scadenza dell'accesso", + "expiry": { + "never": "Mai", + "oneHour": "1 ora", + "oneDay": "24 ore", + "sevenDays": "7 giorni", + "thirtyDays": "30 giorni", + "custom": "Personalizzato" + }, + "expiryLabel": "Scadenza accesso", + "levels": { + "connect": { + "label": "Connetti", + "description": "Apri solo sessioni: terminale, desktop remoto, gestione file, tunnel e Docker. Nessun accesso alla configurazione dell'host." + }, + "view": { + "label": "Visualizza", + "description": "Connetti, più visualizza la configurazione dell'host. I segreti non vengono mai mostrati." + }, + "edit": { + "label": "Modifica", + "description": "Visualizza e modifica le impostazioni host senza autenticazione. L'autenticazione SSH del proprietario rimane privata e accessibile solo al proprietario." + }, + "manage": { + "label": "Gestisci", + "description": "Modifica, più condividi l'host con altri, modifica i livelli di autorizzazione e revoca l'accesso." + } + }, + "noMatches": "Nessuna corrispondenza trovata", + "permissionLevelLabel": "Livello di autorizzazione", + "rolesTab": "Ruoli", + "searchPlaceholder": "Cerca utenti o ruoli...", + "shareButton": "Condividi", + "shareWithCount": "Condividi ({{count}})", + "usersTab": "Utenti" + } } } diff --git a/plugins/fleets/locales/translated/ja_JP.json b/plugins/fleets/locales/translated/ja_JP.json index cde1ead7b..0fbd8aed6 100644 --- a/plugins/fleets/locales/translated/ja_JP.json +++ b/plugins/fleets/locales/translated/ja_JP.json @@ -85,5 +85,45 @@ }, "nav": { "fleets": "艦隊" + }, + "hosts": { + "docsLink": "ドキュメントを表示", + "sharing": { + "customHoursPlaceholder": "アクセス期限までの時間数", + "expiry": { + "never": "無期限", + "oneHour": "1時間", + "oneDay": "24時間", + "sevenDays": "7日間", + "thirtyDays": "30日間", + "custom": "カスタム" + }, + "expiryLabel": "アクセス期限", + "levels": { + "connect": { + "label": "接続", + "description": "セッションのみ開く: ターミナル、リモートデスクトップ、ファイルマネージャー、トンネル、Docker。ホスト設定へのアクセスはありません。" + }, + "view": { + "label": "表示", + "description": "接続に加え、ホスト設定を表示できます。シークレットは表示されません。" + }, + "edit": { + "label": "編集", + "description": "認証不要のホスト設定を表示および変更できます。所有者のSSH認証情報は非公開で、所有者のみがアクセスできます。" + }, + "manage": { + "label": "管理", + "description": "編集に加え、ホストを他者と共有し、権限レベルを変更、アクセスを取り消すことができます。" + } + }, + "noMatches": "一致する結果がありません", + "permissionLevelLabel": "権限レベル", + "rolesTab": "ロール", + "searchPlaceholder": "ユーザーまたはロールを検索...", + "shareButton": "共有", + "shareWithCount": "共有 ({{count}})", + "usersTab": "ユーザー" + } } } diff --git a/plugins/fleets/locales/translated/ko_KR.json b/plugins/fleets/locales/translated/ko_KR.json index 5c6015ac5..71ca1f048 100644 --- a/plugins/fleets/locales/translated/ko_KR.json +++ b/plugins/fleets/locales/translated/ko_KR.json @@ -85,5 +85,45 @@ }, "nav": { "fleets": "함대" + }, + "hosts": { + "docsLink": "문서 보기", + "sharing": { + "customHoursPlaceholder": "액세스 만료까지 시간", + "expiry": { + "never": "안 함", + "oneHour": "1시간", + "oneDay": "24시간", + "sevenDays": "7일", + "thirtyDays": "30일", + "custom": "사용자 지정" + }, + "expiryLabel": "액세스 만료", + "levels": { + "connect": { + "label": "연결", + "description": "세션 열기만: 터미널, 원격 데스크톱, 파일 관리자, 터널 및 Docker. 호스트 구성에 액세스할 수 없습니다." + }, + "view": { + "label": "보기", + "description": "연결 및 호스트 구성 보기. 비밀 정보는 표시되지 않습니다." + }, + "edit": { + "label": "편집", + "description": "인증이 필요하지 않은 호스트 설정을 보고 수정할 수 있습니다. 소유자의 SSH 인증 정보는 비공개로 유지되며 소유자만 볼 수 있습니다." + }, + "manage": { + "label": "관리", + "description": "편집, 호스트 공유, 권한 수준 변경, 액세스 해지." + } + }, + "noMatches": "일치하는 항목이 없습니다.", + "permissionLevelLabel": "권한 수준", + "rolesTab": "역할", + "searchPlaceholder": "사용자 또는 역할 검색...", + "shareButton": "공유", + "shareWithCount": "공유 ({{count}})", + "usersTab": "사용자" + } } } diff --git a/plugins/fleets/locales/translated/nl_NL.json b/plugins/fleets/locales/translated/nl_NL.json index 7c8f4311f..18399634c 100644 --- a/plugins/fleets/locales/translated/nl_NL.json +++ b/plugins/fleets/locales/translated/nl_NL.json @@ -85,5 +85,45 @@ }, "nav": { "fleets": "Vloten" + }, + "hosts": { + "docsLink": "Documenten bekijken", + "sharing": { + "customHoursPlaceholder": "Aantal uren tot de toegang verloopt", + "expiry": { + "never": "Nooit", + "oneHour": "1 uur", + "oneDay": "24 uur", + "sevenDays": "7 dagen", + "thirtyDays": "30 dagen", + "custom": "Aangepast" + }, + "expiryLabel": "Toegang verloopt", + "levels": { + "connect": { + "label": "Verbinden", + "description": "Alleen open sessies: terminal, extern bureaublad, bestandsbeheer, tunnels en Docker. Geen toegang tot de hostconfiguratie." + }, + "view": { + "label": "Weergave", + "description": "Maak verbinding en bekijk de hostconfiguratie. Geheime gegevens worden nooit weergegeven." + }, + "edit": { + "label": "Bewerking", + "description": "Bekijk en wijzig de instellingen van de host die geen authenticatie vereist. De SSH-authenticatie van de eigenaar blijft privé en alleen toegankelijk voor de eigenaar." + }, + "manage": { + "label": "Beheren", + "description": "Bewerken, de host delen met anderen, toegangsrechten wijzigen en toegang intrekken." + } + }, + "noMatches": "Geen overeenkomsten gevonden", + "permissionLevelLabel": "Toegangsniveau", + "rolesTab": "Rollen", + "searchPlaceholder": "Gebruikers of rollen zoeken...", + "shareButton": "Deel", + "shareWithCount": "Delen ({{count}})", + "usersTab": "Gebruikers" + } } } diff --git a/plugins/fleets/locales/translated/no_NO.json b/plugins/fleets/locales/translated/no_NO.json index a5e77e726..9dcc31581 100644 --- a/plugins/fleets/locales/translated/no_NO.json +++ b/plugins/fleets/locales/translated/no_NO.json @@ -85,5 +85,45 @@ }, "nav": { "fleets": "Flåter" + }, + "hosts": { + "docsLink": "Vis dokumenter", + "sharing": { + "customHoursPlaceholder": "Timer til tilgangen utløper", + "expiry": { + "never": "Aldri", + "oneHour": "1 time", + "oneDay": "24 timer", + "sevenDays": "7 dager", + "thirtyDays": "30 dager", + "custom": "Skikk" + }, + "expiryLabel": "Utløpsdato for tilgang", + "levels": { + "connect": { + "label": "Koble til", + "description": "Kun åpne økter: terminal, eksternt skrivebord, filbehandler, tunneler og Docker. Ingen tilgang til vertskonfigurasjonen." + }, + "view": { + "label": "Utsikt", + "description": "Koble til, pluss se vertskonfigurasjonen. Hemmeligheter vises aldri." + }, + "edit": { + "label": "Redigere", + "description": "Vis og endre innstillinger for verter uten autentisering. Eierens SSH-autentisering forblir privat og kun for eieren." + }, + "manage": { + "label": "Administrer", + "description": "Rediger, pluss del verten med andre, endre tillatelsesnivåer og tilbakekall tilgang." + } + }, + "noMatches": "Ingen treff funnet", + "permissionLevelLabel": "Tillatelsesnivå", + "rolesTab": "Roller", + "searchPlaceholder": "Søk etter brukere eller roller...", + "shareButton": "Dele", + "shareWithCount": "Del ({{count}})", + "usersTab": "Brukere" + } } } diff --git a/plugins/fleets/locales/translated/pl_PL.json b/plugins/fleets/locales/translated/pl_PL.json index 8ad196328..6634ddc65 100644 --- a/plugins/fleets/locales/translated/pl_PL.json +++ b/plugins/fleets/locales/translated/pl_PL.json @@ -85,5 +85,45 @@ }, "nav": { "fleets": "Floty" + }, + "hosts": { + "docsLink": "Zobacz dokumentację", + "sharing": { + "customHoursPlaceholder": "Godziny do wygaśnięcia dostępu", + "expiry": { + "never": "Nigdy", + "oneHour": "1 godzina", + "oneDay": "24 godziny", + "sevenDays": "7 dni", + "thirtyDays": "30 dni", + "custom": "Niestandardowy" + }, + "expiryLabel": "Wygaśnięcie dostępu", + "levels": { + "connect": { + "label": "Połączenie", + "description": "Tylko otwieranie sesji: terminal, pulpit zdalny, menedżer plików, tunele i Docker. Bez dostępu do konfiguracji hosta." + }, + "view": { + "label": "Podgląd", + "description": "Jak Połączenie, plus podgląd konfiguracji hosta. Sekrety nigdy nie są pokazywane." + }, + "edit": { + "label": "Edycja", + "description": "Jak Podgląd, plus zmiana ustawień hosta niezwiązanych z uwierzytelnianiem. Uwierzytelnianie SSH właściciela pozostaje prywatne i dostępne tylko dla niego." + }, + "manage": { + "label": "Zarządzanie", + "description": "Jak Edycja, plus udostępnianie hosta innym, zmiana poziomów uprawnień i unieważnianie dostępu." + } + }, + "noMatches": "Nie znaleziono wyników", + "permissionLevelLabel": "Poziom uprawnień", + "rolesTab": "Role", + "searchPlaceholder": "Wyszukaj użytkowników lub role...", + "shareButton": "Udostępnij", + "shareWithCount": "Udostępnij ({{count}})", + "usersTab": "Użytkownicy" + } } } diff --git a/plugins/fleets/locales/translated/pt_BR.json b/plugins/fleets/locales/translated/pt_BR.json index 700850bc1..bab04d4ce 100644 --- a/plugins/fleets/locales/translated/pt_BR.json +++ b/plugins/fleets/locales/translated/pt_BR.json @@ -85,5 +85,45 @@ }, "nav": { "fleets": "Frotas" + }, + "hosts": { + "docsLink": "Ver documentos", + "sharing": { + "customHoursPlaceholder": "Horas restantes até o acesso expirar", + "expiry": { + "never": "Nunca", + "oneHour": "1 hora", + "oneDay": "24 horas", + "sevenDays": "7 dias", + "thirtyDays": "30 dias", + "custom": "Personalizado" + }, + "expiryLabel": "Expiração do acesso", + "levels": { + "connect": { + "label": "Conectar", + "description": "Somente sessões abertas: terminal, área de trabalho remota, gerenciador de arquivos, túneis e Docker. Sem acesso à configuração do host." + }, + "view": { + "label": "Visualizar", + "description": "Conecte-se e veja a configuração do host. Os segredos nunca são exibidos." + }, + "edit": { + "label": "Editar", + "description": "Visualize e modifique as configurações do host que não exigem autenticação. A autenticação SSH do proprietário permanece privada e restrita ao proprietário." + }, + "manage": { + "label": "Gerenciar", + "description": "Edite, compartilhe o host com outras pessoas, altere os níveis de permissão e revogue o acesso." + } + }, + "noMatches": "Nenhuma correspondência encontrada", + "permissionLevelLabel": "Nível de permissão", + "rolesTab": "Funções", + "searchPlaceholder": "Pesquisar usuários ou funções...", + "shareButton": "Compartilhar", + "shareWithCount": "Compartilhar ({{count}})", + "usersTab": "Usuários" + } } } diff --git a/plugins/fleets/locales/translated/pt_PT.json b/plugins/fleets/locales/translated/pt_PT.json index f2b8a7050..ee9667283 100644 --- a/plugins/fleets/locales/translated/pt_PT.json +++ b/plugins/fleets/locales/translated/pt_PT.json @@ -85,5 +85,45 @@ }, "nav": { "fleets": "Frotas" + }, + "hosts": { + "docsLink": "Ver documentação", + "sharing": { + "customHoursPlaceholder": "Horas até à expiração do acesso", + "expiry": { + "never": "Nunca", + "oneHour": "1 hora", + "oneDay": "24 horas", + "sevenDays": "7 dias", + "thirtyDays": "30 dias", + "custom": "Personalizado" + }, + "expiryLabel": "Expiração do acesso", + "levels": { + "connect": { + "label": "Ligar", + "description": "Abrir apenas sessões: terminal, ambiente de trabalho remoto, gestor de ficheiros, túneis e Docker. Sem acesso à configuração do anfitrião." + }, + "view": { + "label": "Ver", + "description": "Ligar e ver a configuração do anfitrião. Os segredos nunca são mostrados." + }, + "edit": { + "label": "Editar", + "description": "Visualize e modifique as definições do host que não requerem autenticação. A autenticação SSH do proprietário permanece privada e restrita ao proprietário." + }, + "manage": { + "label": "Gerir", + "description": "Editar, além de partilhar o anfitrião com outras pessoas, alterar os níveis de permissão e revogar o acesso." + } + }, + "noMatches": "Nenhuma correspondência encontrada", + "permissionLevelLabel": "Nível de permissão", + "rolesTab": "Funções", + "searchPlaceholder": "Procurar utilizadores ou funções...", + "shareButton": "Partilhar", + "shareWithCount": "Partilhar ({{count}})", + "usersTab": "Utilizadores" + } } } diff --git a/plugins/fleets/locales/translated/ro_RO.json b/plugins/fleets/locales/translated/ro_RO.json index 66a220f01..ecbc40b83 100644 --- a/plugins/fleets/locales/translated/ro_RO.json +++ b/plugins/fleets/locales/translated/ro_RO.json @@ -85,5 +85,45 @@ }, "nav": { "fleets": "Flote" + }, + "hosts": { + "docsLink": "Vizualizați documentele", + "sharing": { + "customHoursPlaceholder": "Ore până la expirarea accesului", + "expiry": { + "never": "Nu", + "oneHour": "1 oră", + "oneDay": "24 de ore", + "sevenDays": "7 zile", + "thirtyDays": "30 de zile", + "custom": "Personalizat" + }, + "expiryLabel": "Expirarea accesului", + "levels": { + "connect": { + "label": "Conectează-te", + "description": "Deschideți doar sesiunile: terminal, desktop la distanță, manager de fișiere, tuneluri și Docker. Fără acces la configurația gazdei." + }, + "view": { + "label": "Vedere", + "description": "Conectează-te și vezi configurația gazdei. Secretele nu sunt afișate niciodată." + }, + "edit": { + "label": "Edita", + "description": "Vizualizați și modificați setările gazdei fără autentificare. Autentificarea SSH a proprietarului rămâne privată și exclusiv pentru proprietar." + }, + "manage": { + "label": "Gestionează", + "description": "Editați, plus partajați gazda cu alții, modificați nivelurile de permisiune și revocați accesul." + } + }, + "noMatches": "Nu s-au găsit potriviri", + "permissionLevelLabel": "Nivel de permisiune", + "rolesTab": "Roluri", + "searchPlaceholder": "Căutați utilizatori sau roluri...", + "shareButton": "Distribuie", + "shareWithCount": "Distribuie ({{count}})", + "usersTab": "Utilizatori" + } } } diff --git a/plugins/fleets/locales/translated/ru_RU.json b/plugins/fleets/locales/translated/ru_RU.json index 1fcb75998..fdc5d652e 100644 --- a/plugins/fleets/locales/translated/ru_RU.json +++ b/plugins/fleets/locales/translated/ru_RU.json @@ -85,5 +85,45 @@ }, "nav": { "fleets": "Флоты" + }, + "hosts": { + "docsLink": "Документация", + "sharing": { + "customHoursPlaceholder": "Часов до окончания срока доступа", + "expiry": { + "never": "Никогда", + "oneHour": "1 час", + "oneDay": "24 часа", + "sevenDays": "7 дней", + "thirtyDays": "30 дней", + "custom": "Настроить" + }, + "expiryLabel": "Срок действия доступа", + "levels": { + "connect": { + "label": "Подключение", + "description": "Только открытие сеансов: терминал, удалённый рабочий стол, файловый менеджер, туннели и Docker. Без доступа к конфигурации хоста." + }, + "view": { + "label": "Просмотр", + "description": "Подключение и просмотр конфигурации хоста. Секреты не отображаются." + }, + "edit": { + "label": "Редактирование", + "description": "Просмотр и изменение настроек хоста без аутентификации. SSH-аутентификация владельца остается конфиденциальной и доступна только владельцу." + }, + "manage": { + "label": "Управление", + "description": "Редактирование, а также предоставление доступа другим, изменение уровней доступа и отзыв доступа." + } + }, + "noMatches": "Совпадений не найдено", + "permissionLevelLabel": "Уровень доступа", + "rolesTab": "Роли", + "searchPlaceholder": "Поиск пользователей или ролей...", + "shareButton": "Поделиться", + "shareWithCount": "Поделиться ({{count}})", + "usersTab": "Пользователи" + } } } diff --git a/plugins/fleets/locales/translated/sr_SP.json b/plugins/fleets/locales/translated/sr_SP.json index 8578f48aa..29926b140 100644 --- a/plugins/fleets/locales/translated/sr_SP.json +++ b/plugins/fleets/locales/translated/sr_SP.json @@ -85,5 +85,45 @@ }, "nav": { "fleets": "Флоте" + }, + "hosts": { + "docsLink": "Прикажи документе", + "sharing": { + "customHoursPlaceholder": "Сати до истека приступа", + "expiry": { + "never": "Никад", + "oneHour": "1 сат", + "oneDay": "24 сата", + "sevenDays": "7 дана", + "thirtyDays": "30 дана", + "custom": "Прилагођено" + }, + "expiryLabel": "Истек приступа", + "levels": { + "connect": { + "label": "Повежи се", + "description": "Само отворене сесије: терминал, удаљена радна површина, менаџер датотека, тунели и Докер. Нема приступа конфигурацији хоста." + }, + "view": { + "label": "Поглед", + "description": "Повежите се, плус погледајте конфигурацију хоста. Тајне се никада не приказују." + }, + "edit": { + "label": "Измени", + "description": "Прегледајте и мењајте подешавања хоста која не захтевају аутентификацију. SSH аутентификација власника остаје приватна и доступна само власнику." + }, + "manage": { + "label": "Управљај", + "description": "Уредите, плус делите хост са другима, мењајте нивое дозвола и опозовите приступ." + } + }, + "noMatches": "Није пронађено ниједно подударање", + "permissionLevelLabel": "Ниво дозволе", + "rolesTab": "Улоге", + "searchPlaceholder": "Претражите кориснике или улоге...", + "shareButton": "Дели", + "shareWithCount": "Подели ({{count}})", + "usersTab": "Корисници" + } } } diff --git a/plugins/fleets/locales/translated/sv_SE.json b/plugins/fleets/locales/translated/sv_SE.json index 5542f9ba3..844457231 100644 --- a/plugins/fleets/locales/translated/sv_SE.json +++ b/plugins/fleets/locales/translated/sv_SE.json @@ -85,5 +85,45 @@ }, "nav": { "fleets": "Flottor" + }, + "hosts": { + "docsLink": "Visa dokument", + "sharing": { + "customHoursPlaceholder": "Timmar tills åtkomsten upphör", + "expiry": { + "never": "Aldrig", + "oneHour": "1 timme", + "oneDay": "24 timmar", + "sevenDays": "7 dagar", + "thirtyDays": "30 dagar", + "custom": "Beställnings" + }, + "expiryLabel": "Åtkomstutgång", + "levels": { + "connect": { + "label": "Ansluta", + "description": "Endast öppna sessioner: terminal, fjärrskrivbord, filhanterare, tunnlar och Docker. Ingen åtkomst till värdkonfigurationen." + }, + "view": { + "label": "Se", + "description": "Anslut, plus se värdkonfigurationen. Hemligheter visas aldrig." + }, + "edit": { + "label": "Redigera", + "description": "Visa och ändra inställningar för icke-autentiseringsvärdar. Ägarens SSH-autentisering förblir privat och endast för ägaren." + }, + "manage": { + "label": "Hantera", + "description": "Redigera, plus dela värden med andra, ändra behörighetsnivåer och återkalla åtkomst." + } + }, + "noMatches": "Inga träffar hittades", + "permissionLevelLabel": "Behörighetsnivå", + "rolesTab": "Roller", + "searchPlaceholder": "Sök användare eller roller...", + "shareButton": "Dela", + "shareWithCount": "Dela ({{count}})", + "usersTab": "Användare" + } } } diff --git a/plugins/fleets/locales/translated/th_TH.json b/plugins/fleets/locales/translated/th_TH.json index 6171c8f9d..cc89cedeb 100644 --- a/plugins/fleets/locales/translated/th_TH.json +++ b/plugins/fleets/locales/translated/th_TH.json @@ -85,5 +85,45 @@ }, "nav": { "fleets": "กองเรือ" + }, + "hosts": { + "docsLink": "ดูเอกสาร", + "sharing": { + "customHoursPlaceholder": "เหลือเวลาอีกกี่ชั่วโมงก่อนที่สิทธิ์การเข้าถึงจะหมดอายุ", + "expiry": { + "never": "ไม่เคย", + "oneHour": "1 ชั่วโมง", + "oneDay": "24 ชั่วโมง", + "sevenDays": "7 วัน", + "thirtyDays": "30 วัน", + "custom": "กำหนดเอง" + }, + "expiryLabel": "วันหมดอายุการเข้าถึง", + "levels": { + "connect": { + "label": "เชื่อมต่อ", + "description": "อนุญาตเฉพาะเซสชันที่เปิดใช้งานเท่านั้น: เทอร์มินัล, เดสก์ท็อประยะไกล, ตัวจัดการไฟล์, อุโมงค์ และ Docker ไม่สามารถเข้าถึงการกำหนดค่าโฮสต์ได้" + }, + "view": { + "label": "ดู", + "description": "เชื่อมต่อและดูการตั้งค่าโฮสต์ ข้อมูลลับจะไม่ถูกเปิดเผย" + }, + "edit": { + "label": "แก้ไข", + "description": "ดูและแก้ไขการตั้งค่าโฮสต์ที่ไม่ต้องยืนยันตัวตน การยืนยันตัวตน SSH ของเจ้าของจะยังคงเป็นส่วนตัวและเข้าถึงได้เฉพาะเจ้าของเท่านั้น" + }, + "manage": { + "label": "จัดการ", + "description": "แก้ไข รวมถึงแชร์โฮสต์กับผู้อื่น เปลี่ยนระดับสิทธิ์ และเพิกถอนการเข้าถึงได้" + } + }, + "noMatches": "ไม่พบผลลัพธ์ที่ตรงกัน", + "permissionLevelLabel": "ระดับการอนุญาต", + "rolesTab": "บทบาท", + "searchPlaceholder": "ค้นหาผู้ใช้หรือบทบาท...", + "shareButton": "แบ่งปัน", + "shareWithCount": "แชร์ ({{count}})", + "usersTab": "ผู้ใช้" + } } } diff --git a/plugins/fleets/locales/translated/tr_TR.json b/plugins/fleets/locales/translated/tr_TR.json index c9be967cc..f79a16d34 100644 --- a/plugins/fleets/locales/translated/tr_TR.json +++ b/plugins/fleets/locales/translated/tr_TR.json @@ -85,5 +85,45 @@ }, "nav": { "fleets": "Filolar" + }, + "hosts": { + "docsLink": "Dokümanları görüntüle", + "sharing": { + "customHoursPlaceholder": "Erişim süresi (saat)", + "expiry": { + "never": "Süresiz", + "oneHour": "1 saat", + "oneDay": "24 saat", + "sevenDays": "7 gün", + "thirtyDays": "30 gün", + "custom": "Özel" + }, + "expiryLabel": "Erişim süresi sonu", + "levels": { + "connect": { + "label": "Bağlan", + "description": "Yalnızca oturum açar: terminal, uzak masaüstü, dosya yöneticisi, tüneller ve Docker. Sunucu yapılandırmasına erişim yok." + }, + "view": { + "label": "Görüntüle", + "description": "Bağlan iznine ek olarak sunucu yapılandırmasını görebilir. Gizli bilgiler asla gösterilmez." + }, + "edit": { + "label": "Düzenle", + "description": "Kimlik doğrulaması gerektirmeyen sunucu ayarlarını görüntüleyin ve değiştirin. Sahibin SSH kimlik doğrulaması gizli kalır ve yalnızca sahibine özeldir." + }, + "manage": { + "label": "Yönet", + "description": "Düzenleme iznine ek olarak sunucuyu başkalarıyla paylaşabilir, izin düzeylerini değiştirebilir ve erişimi iptal edebilir." + } + }, + "noMatches": "Eşleşme bulunamadı", + "permissionLevelLabel": "İzin düzeyi", + "rolesTab": "Roller", + "searchPlaceholder": "Kullanıcı veya rol ara...", + "shareButton": "Paylaş", + "shareWithCount": "Paylaş ({{count}})", + "usersTab": "Kullanıcılar" + } } } diff --git a/plugins/fleets/locales/translated/uk_UA.json b/plugins/fleets/locales/translated/uk_UA.json index 8f49109bb..9f019732c 100644 --- a/plugins/fleets/locales/translated/uk_UA.json +++ b/plugins/fleets/locales/translated/uk_UA.json @@ -85,5 +85,45 @@ }, "nav": { "fleets": "Флоти" + }, + "hosts": { + "docsLink": "Переглянути документи", + "sharing": { + "customHoursPlaceholder": "Години до закінчення терміну дії доступу", + "expiry": { + "never": "Ніколи", + "oneHour": "1 година", + "oneDay": "24 години", + "sevenDays": "7 днів", + "thirtyDays": "30 днів", + "custom": "Користувацька" + }, + "expiryLabel": "Термін дії доступу", + "levels": { + "connect": { + "label": "Підключитися", + "description": "Тільки відкриті сеанси: термінал, віддалений робочий стіл, файловий менеджер, тунелі та Docker. Без доступу до конфігурації хоста." + }, + "view": { + "label": "Переглянути", + "description": "Підключитися, а також переглянути конфігурацію хоста. Секрети ніколи не відображаються." + }, + "edit": { + "label": "Редагувати", + "description": "Переглядайте та змінюйте налаштування хоста без автентифікації. SSH-автентифікація власника залишається приватною та доступною лише для власника." + }, + "manage": { + "label": "Керувати", + "description": "Редагувати, а також ділитися хостом з іншими, змінювати рівні дозволів та скасовувати доступ." + } + }, + "noMatches": "Збігів не знайдено", + "permissionLevelLabel": "Рівень дозволів", + "rolesTab": "Ролі", + "searchPlaceholder": "Пошук користувачів або ролей...", + "shareButton": "Поділитися", + "shareWithCount": "Поділитися ({{count}})", + "usersTab": "Користувачі" + } } } diff --git a/plugins/fleets/locales/translated/vi_VN.json b/plugins/fleets/locales/translated/vi_VN.json index 072a6eb42..4a206c866 100644 --- a/plugins/fleets/locales/translated/vi_VN.json +++ b/plugins/fleets/locales/translated/vi_VN.json @@ -85,5 +85,45 @@ }, "nav": { "fleets": "Hạm đội" + }, + "hosts": { + "docsLink": "Xem tài liệu", + "sharing": { + "customHoursPlaceholder": "Số giờ cho đến khi 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" + }, + "expiryLabel": "Hết hạn truy cập", + "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." + } + }, + "noMatches": "Không tìm thấy kết quả phù hợp", + "permissionLevelLabel": "Cấp độ quyền", + "rolesTab": "Vai trò", + "searchPlaceholder": "Tìm kiếm người dùng hoặc vai trò...", + "shareButton": "Chia sẻ", + "shareWithCount": "Chia sẻ ({{count}})", + "usersTab": "Người dùng" + } } } diff --git a/plugins/fleets/locales/translated/zh_CN.json b/plugins/fleets/locales/translated/zh_CN.json index c4968c954..1fb6e8cd4 100644 --- a/plugins/fleets/locales/translated/zh_CN.json +++ b/plugins/fleets/locales/translated/zh_CN.json @@ -85,5 +85,45 @@ }, "nav": { "fleets": "舰队" + }, + "hosts": { + "docsLink": "查看文档", + "sharing": { + "customHoursPlaceholder": "过期前的小时数", + "expiry": { + "never": "永不过期", + "oneHour": "1 小时", + "oneDay": "24 小时", + "sevenDays": "7 天", + "thirtyDays": "30 天", + "custom": "自定义" + }, + "expiryLabel": "访问有效期", + "levels": { + "connect": { + "label": "连接", + "description": "仅打开会话:终端、远程桌面、文件管理器、隧道和 Docker。无权访问主机配置。" + }, + "view": { + "label": "查看", + "description": "连接,并查看主机配置。凭据信息从不显示。" + }, + "edit": { + "label": "编辑", + "description": "查看并修改无需身份验证的主机设置。所有者的 SSH 身份验证信息将保持私密,仅限所有者本人查看。" + }, + "manage": { + "label": "管理", + "description": "编辑,并与其他用户共享主机、更改权限级别及撤销访问。" + } + }, + "noMatches": "未找到匹配项", + "permissionLevelLabel": "权限级别", + "rolesTab": "角色", + "searchPlaceholder": "搜索用户或角色...", + "shareButton": "共享", + "shareWithCount": "共享({{count}})", + "usersTab": "用户" + } } } diff --git a/plugins/fleets/locales/translated/zh_TW.json b/plugins/fleets/locales/translated/zh_TW.json index 34e2bd7bc..e43d969d2 100644 --- a/plugins/fleets/locales/translated/zh_TW.json +++ b/plugins/fleets/locales/translated/zh_TW.json @@ -85,5 +85,45 @@ }, "nav": { "fleets": "艦隊" + }, + "hosts": { + "docsLink": "檢視文件", + "sharing": { + "customHoursPlaceholder": "存取到期前的小時數", + "expiry": { + "never": "永不", + "oneHour": "1 小時", + "oneDay": "24 小時", + "sevenDays": "7 天", + "thirtyDays": "30 天", + "custom": "自訂" + }, + "expiryLabel": "存取期限", + "levels": { + "connect": { + "label": "連線", + "description": "僅開啟工作階段:終端機、遠端桌面、檔案管理員、通道和 Docker。無法存取主機設定。" + }, + "view": { + "label": "檢視", + "description": "連線,並可查看主機設定。機密資料絕不顯示。" + }, + "edit": { + "label": "編輯", + "description": "查看並修改無需身份驗證的主機設定。所有者的 SSH 身份驗證資訊將保持私密,僅限所有者本人查看。" + }, + "manage": { + "label": "管理", + "description": "編輯,並可與他人分享主機、變更權限層級及撤銷存取權。" + } + }, + "noMatches": "找不到符合項目", + "permissionLevelLabel": "權限層級", + "rolesTab": "角色", + "searchPlaceholder": "搜尋使用者或角色...", + "shareButton": "分享", + "shareWithCount": "分享 ({{count}})", + "usersTab": "使用者" + } } } diff --git a/plugins/network-topology/locales/en.json b/plugins/network-topology/locales/en.json index 3c761a9b4..a27badca9 100644 --- a/plugins/network-topology/locales/en.json +++ b/plugins/network-topology/locales/en.json @@ -57,5 +57,8 @@ "title": "Use network graph", "description": "View and edit the network topology graph." } + }, + "hosts": { + "docsLink": "View docs" } } diff --git a/plugins/network-topology/locales/translated/af_ZA.json b/plugins/network-topology/locales/translated/af_ZA.json index e7c2b95b1..c70c8dc44 100644 --- a/plugins/network-topology/locales/translated/af_ZA.json +++ b/plugins/network-topology/locales/translated/af_ZA.json @@ -56,5 +56,8 @@ }, "dashboardTab": { "nodes": "{{count}} nodusse" + }, + "hosts": { + "docsLink": "Bekyk dokumente" } } diff --git a/plugins/network-topology/locales/translated/ar_SA.json b/plugins/network-topology/locales/translated/ar_SA.json index 2f158ae5a..1b4c4eed1 100644 --- a/plugins/network-topology/locales/translated/ar_SA.json +++ b/plugins/network-topology/locales/translated/ar_SA.json @@ -56,5 +56,8 @@ }, "dashboardTab": { "nodes": "{{count}} عقدة" + }, + "hosts": { + "docsLink": "عرض المستندات" } } diff --git a/plugins/network-topology/locales/translated/bg_BG.json b/plugins/network-topology/locales/translated/bg_BG.json index d35506d4c..69495b9ec 100644 --- a/plugins/network-topology/locales/translated/bg_BG.json +++ b/plugins/network-topology/locales/translated/bg_BG.json @@ -56,5 +56,8 @@ }, "dashboardTab": { "nodes": "{{count}} възли" + }, + "hosts": { + "docsLink": "Преглед на документи" } } diff --git a/plugins/network-topology/locales/translated/bn_BD.json b/plugins/network-topology/locales/translated/bn_BD.json index 105122add..af98770bb 100644 --- a/plugins/network-topology/locales/translated/bn_BD.json +++ b/plugins/network-topology/locales/translated/bn_BD.json @@ -56,5 +56,8 @@ }, "dashboardTab": { "nodes": "{{count}} নোড" + }, + "hosts": { + "docsLink": "নথি দেখুন" } } diff --git a/plugins/network-topology/locales/translated/ca_ES.json b/plugins/network-topology/locales/translated/ca_ES.json index 06757edb0..39c460629 100644 --- a/plugins/network-topology/locales/translated/ca_ES.json +++ b/plugins/network-topology/locales/translated/ca_ES.json @@ -56,5 +56,8 @@ }, "dashboardTab": { "nodes": "nodes {{count}}" + }, + "hosts": { + "docsLink": "Veure documents" } } diff --git a/plugins/network-topology/locales/translated/cs_CZ.json b/plugins/network-topology/locales/translated/cs_CZ.json index ecd6d5f7b..df344cd12 100644 --- a/plugins/network-topology/locales/translated/cs_CZ.json +++ b/plugins/network-topology/locales/translated/cs_CZ.json @@ -56,5 +56,8 @@ }, "dashboardTab": { "nodes": "{{count}} uzlů" + }, + "hosts": { + "docsLink": "Zobrazit dokumenty" } } diff --git a/plugins/network-topology/locales/translated/da_DK.json b/plugins/network-topology/locales/translated/da_DK.json index dbd9f83a7..f5d60d87d 100644 --- a/plugins/network-topology/locales/translated/da_DK.json +++ b/plugins/network-topology/locales/translated/da_DK.json @@ -56,5 +56,8 @@ }, "dashboardTab": { "nodes": "{{count}} noder" + }, + "hosts": { + "docsLink": "Se dokumenter" } } diff --git a/plugins/network-topology/locales/translated/de_DE.json b/plugins/network-topology/locales/translated/de_DE.json index 4b4df93ec..2e2ba9d08 100644 --- a/plugins/network-topology/locales/translated/de_DE.json +++ b/plugins/network-topology/locales/translated/de_DE.json @@ -56,5 +56,8 @@ }, "dashboardTab": { "nodes": "{{count}} Knoten" + }, + "hosts": { + "docsLink": "Dokumentation anzeigen" } } diff --git a/plugins/network-topology/locales/translated/el_GR.json b/plugins/network-topology/locales/translated/el_GR.json index 20f323859..2f2819ad4 100644 --- a/plugins/network-topology/locales/translated/el_GR.json +++ b/plugins/network-topology/locales/translated/el_GR.json @@ -56,5 +56,8 @@ }, "dashboardTab": { "nodes": "{{count}} κόμβοι" + }, + "hosts": { + "docsLink": "Προβολή εγγράφων" } } diff --git a/plugins/network-topology/locales/translated/es_ES.json b/plugins/network-topology/locales/translated/es_ES.json index a4b041cfa..cab73b0bb 100644 --- a/plugins/network-topology/locales/translated/es_ES.json +++ b/plugins/network-topology/locales/translated/es_ES.json @@ -56,5 +56,8 @@ }, "dashboardTab": { "nodes": "{{count}} nodos" + }, + "hosts": { + "docsLink": "Ver documentación" } } diff --git a/plugins/network-topology/locales/translated/fi_FI.json b/plugins/network-topology/locales/translated/fi_FI.json index 1cdf961eb..8f5f19cc8 100644 --- a/plugins/network-topology/locales/translated/fi_FI.json +++ b/plugins/network-topology/locales/translated/fi_FI.json @@ -56,5 +56,8 @@ }, "dashboardTab": { "nodes": "{{count}} solmut" + }, + "hosts": { + "docsLink": "Näytä dokumentit" } } diff --git a/plugins/network-topology/locales/translated/fr_FR.json b/plugins/network-topology/locales/translated/fr_FR.json index 3865a5abc..1a76a53c4 100644 --- a/plugins/network-topology/locales/translated/fr_FR.json +++ b/plugins/network-topology/locales/translated/fr_FR.json @@ -56,5 +56,8 @@ }, "dashboardTab": { "nodes": "{{count}} nœuds" + }, + "hosts": { + "docsLink": "Voir la documentation" } } diff --git a/plugins/network-topology/locales/translated/he_IL.json b/plugins/network-topology/locales/translated/he_IL.json index c8a6c46f3..b38359f87 100644 --- a/plugins/network-topology/locales/translated/he_IL.json +++ b/plugins/network-topology/locales/translated/he_IL.json @@ -56,5 +56,8 @@ }, "dashboardTab": { "nodes": "צמתים {{count}}" + }, + "hosts": { + "docsLink": "הצג מסמכים" } } diff --git a/plugins/network-topology/locales/translated/hi_IN.json b/plugins/network-topology/locales/translated/hi_IN.json index 0dc02c8c0..0d4b1166d 100644 --- a/plugins/network-topology/locales/translated/hi_IN.json +++ b/plugins/network-topology/locales/translated/hi_IN.json @@ -56,5 +56,8 @@ }, "dashboardTab": { "nodes": "{{count}} नोड्स" + }, + "hosts": { + "docsLink": "दस्तावेज़ देखें" } } diff --git a/plugins/network-topology/locales/translated/hu_HU.json b/plugins/network-topology/locales/translated/hu_HU.json index 528ef2538..96101bbde 100644 --- a/plugins/network-topology/locales/translated/hu_HU.json +++ b/plugins/network-topology/locales/translated/hu_HU.json @@ -56,5 +56,8 @@ }, "dashboardTab": { "nodes": "{{count}} csomópontok" + }, + "hosts": { + "docsLink": "Dokumentumok megtekintése" } } diff --git a/plugins/network-topology/locales/translated/id_ID.json b/plugins/network-topology/locales/translated/id_ID.json index 6873a62fa..43c261f43 100644 --- a/plugins/network-topology/locales/translated/id_ID.json +++ b/plugins/network-topology/locales/translated/id_ID.json @@ -56,5 +56,8 @@ }, "dashboardTab": { "nodes": "{{count}} node" + }, + "hosts": { + "docsLink": "Lihat dokumen" } } diff --git a/plugins/network-topology/locales/translated/it_IT.json b/plugins/network-topology/locales/translated/it_IT.json index 0eae51798..3ebfd9baf 100644 --- a/plugins/network-topology/locales/translated/it_IT.json +++ b/plugins/network-topology/locales/translated/it_IT.json @@ -56,5 +56,8 @@ }, "dashboardTab": { "nodes": "{{count}} nodi" + }, + "hosts": { + "docsLink": "Visualizza documentazione" } } diff --git a/plugins/network-topology/locales/translated/ja_JP.json b/plugins/network-topology/locales/translated/ja_JP.json index ee8b9f0db..4d1fb771c 100644 --- a/plugins/network-topology/locales/translated/ja_JP.json +++ b/plugins/network-topology/locales/translated/ja_JP.json @@ -56,5 +56,8 @@ }, "dashboardTab": { "nodes": "{{count}} ノード" + }, + "hosts": { + "docsLink": "ドキュメントを表示" } } diff --git a/plugins/network-topology/locales/translated/ko_KR.json b/plugins/network-topology/locales/translated/ko_KR.json index ede805526..15ccf3b8e 100644 --- a/plugins/network-topology/locales/translated/ko_KR.json +++ b/plugins/network-topology/locales/translated/ko_KR.json @@ -56,5 +56,8 @@ }, "dashboardTab": { "nodes": "{{count}}개 노드" + }, + "hosts": { + "docsLink": "문서 보기" } } diff --git a/plugins/network-topology/locales/translated/nl_NL.json b/plugins/network-topology/locales/translated/nl_NL.json index fe8845e27..81152a8e0 100644 --- a/plugins/network-topology/locales/translated/nl_NL.json +++ b/plugins/network-topology/locales/translated/nl_NL.json @@ -56,5 +56,8 @@ }, "dashboardTab": { "nodes": "{{count}} knooppunten" + }, + "hosts": { + "docsLink": "Documenten bekijken" } } diff --git a/plugins/network-topology/locales/translated/no_NO.json b/plugins/network-topology/locales/translated/no_NO.json index d2e92f0f2..a519638bf 100644 --- a/plugins/network-topology/locales/translated/no_NO.json +++ b/plugins/network-topology/locales/translated/no_NO.json @@ -56,5 +56,8 @@ }, "dashboardTab": { "nodes": "{{count}} noder" + }, + "hosts": { + "docsLink": "Vis dokumenter" } } diff --git a/plugins/network-topology/locales/translated/pl_PL.json b/plugins/network-topology/locales/translated/pl_PL.json index d839f7608..72a8225b2 100644 --- a/plugins/network-topology/locales/translated/pl_PL.json +++ b/plugins/network-topology/locales/translated/pl_PL.json @@ -56,5 +56,8 @@ }, "dashboardTab": { "nodes": "{{count}} węzłów" + }, + "hosts": { + "docsLink": "Zobacz dokumentację" } } diff --git a/plugins/network-topology/locales/translated/pt_BR.json b/plugins/network-topology/locales/translated/pt_BR.json index 4b43ca6ba..d184a752b 100644 --- a/plugins/network-topology/locales/translated/pt_BR.json +++ b/plugins/network-topology/locales/translated/pt_BR.json @@ -56,5 +56,8 @@ }, "dashboardTab": { "nodes": "{{count}} nós" + }, + "hosts": { + "docsLink": "Ver documentos" } } diff --git a/plugins/network-topology/locales/translated/pt_PT.json b/plugins/network-topology/locales/translated/pt_PT.json index 97bbce375..99ffcde4a 100644 --- a/plugins/network-topology/locales/translated/pt_PT.json +++ b/plugins/network-topology/locales/translated/pt_PT.json @@ -56,5 +56,8 @@ }, "dashboardTab": { "nodes": "{{count}} nós" + }, + "hosts": { + "docsLink": "Ver documentação" } } diff --git a/plugins/network-topology/locales/translated/ro_RO.json b/plugins/network-topology/locales/translated/ro_RO.json index 0c220fc2a..6f6f44fb6 100644 --- a/plugins/network-topology/locales/translated/ro_RO.json +++ b/plugins/network-topology/locales/translated/ro_RO.json @@ -56,5 +56,8 @@ }, "dashboardTab": { "nodes": "noduri {{count}}" + }, + "hosts": { + "docsLink": "Vizualizați documentele" } } diff --git a/plugins/network-topology/locales/translated/ru_RU.json b/plugins/network-topology/locales/translated/ru_RU.json index e21ea374d..dca4fa403 100644 --- a/plugins/network-topology/locales/translated/ru_RU.json +++ b/plugins/network-topology/locales/translated/ru_RU.json @@ -56,5 +56,8 @@ }, "dashboardTab": { "nodes": "{{count}} узлов" + }, + "hosts": { + "docsLink": "Документация" } } diff --git a/plugins/network-topology/locales/translated/sr_SP.json b/plugins/network-topology/locales/translated/sr_SP.json index d08230b39..581215357 100644 --- a/plugins/network-topology/locales/translated/sr_SP.json +++ b/plugins/network-topology/locales/translated/sr_SP.json @@ -56,5 +56,8 @@ }, "dashboardTab": { "nodes": "{{count}} чворова" + }, + "hosts": { + "docsLink": "Прикажи документе" } } diff --git a/plugins/network-topology/locales/translated/sv_SE.json b/plugins/network-topology/locales/translated/sv_SE.json index 259924f1d..01288e9f6 100644 --- a/plugins/network-topology/locales/translated/sv_SE.json +++ b/plugins/network-topology/locales/translated/sv_SE.json @@ -56,5 +56,8 @@ }, "dashboardTab": { "nodes": "{{count}} noder" + }, + "hosts": { + "docsLink": "Visa dokument" } } diff --git a/plugins/network-topology/locales/translated/th_TH.json b/plugins/network-topology/locales/translated/th_TH.json index b9a2b1d19..bc5220842 100644 --- a/plugins/network-topology/locales/translated/th_TH.json +++ b/plugins/network-topology/locales/translated/th_TH.json @@ -56,5 +56,8 @@ }, "dashboardTab": { "nodes": "โหนด {{count}}" + }, + "hosts": { + "docsLink": "ดูเอกสาร" } } diff --git a/plugins/network-topology/locales/translated/tr_TR.json b/plugins/network-topology/locales/translated/tr_TR.json index a2d9ed8cc..3df3b8610 100644 --- a/plugins/network-topology/locales/translated/tr_TR.json +++ b/plugins/network-topology/locales/translated/tr_TR.json @@ -56,5 +56,8 @@ }, "dashboardTab": { "nodes": "{{count}} düğüm" + }, + "hosts": { + "docsLink": "Dokümanları görüntüle" } } diff --git a/plugins/network-topology/locales/translated/uk_UA.json b/plugins/network-topology/locales/translated/uk_UA.json index 452c1efe0..63084f473 100644 --- a/plugins/network-topology/locales/translated/uk_UA.json +++ b/plugins/network-topology/locales/translated/uk_UA.json @@ -56,5 +56,8 @@ }, "dashboardTab": { "nodes": "{{count}} вузлів" + }, + "hosts": { + "docsLink": "Переглянути документи" } } diff --git a/plugins/network-topology/locales/translated/vi_VN.json b/plugins/network-topology/locales/translated/vi_VN.json index ef5643515..c1dd23167 100644 --- a/plugins/network-topology/locales/translated/vi_VN.json +++ b/plugins/network-topology/locales/translated/vi_VN.json @@ -56,5 +56,8 @@ }, "dashboardTab": { "nodes": "{{count}} node" + }, + "hosts": { + "docsLink": "Xem tài liệu" } } diff --git a/plugins/network-topology/locales/translated/zh_CN.json b/plugins/network-topology/locales/translated/zh_CN.json index 623594b87..e1e0bd8f0 100644 --- a/plugins/network-topology/locales/translated/zh_CN.json +++ b/plugins/network-topology/locales/translated/zh_CN.json @@ -56,5 +56,8 @@ }, "dashboardTab": { "nodes": "{{count}} 个节点" + }, + "hosts": { + "docsLink": "查看文档" } } diff --git a/plugins/network-topology/locales/translated/zh_TW.json b/plugins/network-topology/locales/translated/zh_TW.json index 90d571430..3edceae72 100644 --- a/plugins/network-topology/locales/translated/zh_TW.json +++ b/plugins/network-topology/locales/translated/zh_TW.json @@ -56,5 +56,8 @@ }, "dashboardTab": { "nodes": "{{count}} 個節點" + }, + "hosts": { + "docsLink": "檢視文件" } } diff --git a/plugins/opkssh/locales/en.json b/plugins/opkssh/locales/en.json index 2e87c7423..ff2307890 100644 --- a/plugins/opkssh/locales/en.json +++ b/plugins/opkssh/locales/en.json @@ -25,5 +25,8 @@ "label": "Use the old redirect URI", "description": "Keep sending /host/opkssh-callback, the redirect URI used before 2.9. Turn this off once your identity providers allow the new one." } + }, + "hosts": { + "filterAuthOpkssh": "OPKSSH" } } diff --git a/plugins/opkssh/locales/translated/af_ZA.json b/plugins/opkssh/locales/translated/af_ZA.json index ec4a314d0..e2e8329f9 100644 --- a/plugins/opkssh/locales/translated/af_ZA.json +++ b/plugins/opkssh/locales/translated/af_ZA.json @@ -15,5 +15,8 @@ "errors": { "authFailed": "Verifikasie het misluk. Kontroleer asseblief jou geloofsbriewe en probeer weer.", "timeout": "Verifikasie het verstryk. Probeer asseblief weer." + }, + "hosts": { + "filterAuthOpkssh": "OPKSSH" } } diff --git a/plugins/opkssh/locales/translated/ar_SA.json b/plugins/opkssh/locales/translated/ar_SA.json index 5662a7625..cdcd2b447 100644 --- a/plugins/opkssh/locales/translated/ar_SA.json +++ b/plugins/opkssh/locales/translated/ar_SA.json @@ -15,5 +15,8 @@ "errors": { "authFailed": "فشلت المصادقة. يرجى التحقق من بيانات الاعتماد والمحاولة مرة أخرى.", "timeout": "انتهت مهلة المصادقة. يرجى المحاولة مرة أخرى." + }, + "hosts": { + "filterAuthOpkssh": "OPKSSH" } } diff --git a/plugins/opkssh/locales/translated/bg_BG.json b/plugins/opkssh/locales/translated/bg_BG.json index cd4aff9b2..0f69cf4a4 100644 --- a/plugins/opkssh/locales/translated/bg_BG.json +++ b/plugins/opkssh/locales/translated/bg_BG.json @@ -15,5 +15,8 @@ "errors": { "authFailed": "Удостоверяването не бе успешно. Моля, проверете идентификационните си данни и опитайте отново.", "timeout": "Времето за изчакване на удостоверяването изтече. Моля, опитайте отново." + }, + "hosts": { + "filterAuthOpkssh": "ОПКСШ" } } diff --git a/plugins/opkssh/locales/translated/bn_BD.json b/plugins/opkssh/locales/translated/bn_BD.json index 1c1f5cdc8..362e3da21 100644 --- a/plugins/opkssh/locales/translated/bn_BD.json +++ b/plugins/opkssh/locales/translated/bn_BD.json @@ -15,5 +15,8 @@ "errors": { "authFailed": "প্রমাণীকরণ ব্যর্থ হয়েছে। অনুগ্রহ করে আপনার পরিচয়পত্র যাচাই করে আবার চেষ্টা করুন।", "timeout": "প্রমাণীকরণের সময়সীমা শেষ হয়ে গেছে। অনুগ্রহ করে আবার চেষ্টা করুন।" + }, + "hosts": { + "filterAuthOpkssh": "OPKSSH" } } diff --git a/plugins/opkssh/locales/translated/ca_ES.json b/plugins/opkssh/locales/translated/ca_ES.json index 237ad32e0..4715a47f0 100644 --- a/plugins/opkssh/locales/translated/ca_ES.json +++ b/plugins/opkssh/locales/translated/ca_ES.json @@ -15,5 +15,8 @@ "errors": { "authFailed": "L'autenticació ha fallat. Si us plau, comproveu les vostres credencials i torneu-ho a intentar.", "timeout": "S'ha esgotat el temps d'autenticació. Torna-ho a provar." + }, + "hosts": { + "filterAuthOpkssh": "OPKSSH" } } diff --git a/plugins/opkssh/locales/translated/cs_CZ.json b/plugins/opkssh/locales/translated/cs_CZ.json index 939ff7f65..2b06a325f 100644 --- a/plugins/opkssh/locales/translated/cs_CZ.json +++ b/plugins/opkssh/locales/translated/cs_CZ.json @@ -15,5 +15,8 @@ "errors": { "authFailed": "Ověření se nezdařilo. Zkontrolujte prosím své přihlašovací údaje a zkuste to znovu.", "timeout": "Časový limit ověření vypršel. Zkuste to prosím znovu." + }, + "hosts": { + "filterAuthOpkssh": "OPKSSH" } } diff --git a/plugins/opkssh/locales/translated/da_DK.json b/plugins/opkssh/locales/translated/da_DK.json index f79ba777e..8721f1d5a 100644 --- a/plugins/opkssh/locales/translated/da_DK.json +++ b/plugins/opkssh/locales/translated/da_DK.json @@ -15,5 +15,8 @@ "errors": { "authFailed": "Godkendelse mislykkedes. Tjek dine loginoplysninger, og prøv igen.", "timeout": "Godkendelsen udløb. Prøv igen." + }, + "hosts": { + "filterAuthOpkssh": "OPKSSH" } } diff --git a/plugins/opkssh/locales/translated/de_DE.json b/plugins/opkssh/locales/translated/de_DE.json index ee7ef02aa..3bdc5034e 100644 --- a/plugins/opkssh/locales/translated/de_DE.json +++ b/plugins/opkssh/locales/translated/de_DE.json @@ -15,5 +15,8 @@ "errors": { "authFailed": "Authentifizierung fehlgeschlagen. Bitte überprüfen Sie Ihre Anmeldeinformationen und versuchen Sie es erneut.", "timeout": "Authentifizierung abgelaufen. Bitte versuchen Sie es erneut." + }, + "hosts": { + "filterAuthOpkssh": "OPKSSH" } } diff --git a/plugins/opkssh/locales/translated/el_GR.json b/plugins/opkssh/locales/translated/el_GR.json index cb756b130..03dcc7376 100644 --- a/plugins/opkssh/locales/translated/el_GR.json +++ b/plugins/opkssh/locales/translated/el_GR.json @@ -15,5 +15,8 @@ "errors": { "authFailed": "Ο έλεγχος ταυτότητας απέτυχε. Ελέγξτε τα διαπιστευτήριά σας και προσπαθήστε ξανά.", "timeout": "Το χρονικό όριο ελέγχου ταυτότητας έληξε. Δοκιμάστε ξανά." + }, + "hosts": { + "filterAuthOpkssh": "OPKSSH" } } diff --git a/plugins/opkssh/locales/translated/es_ES.json b/plugins/opkssh/locales/translated/es_ES.json index 6e6209101..d4d7997be 100644 --- a/plugins/opkssh/locales/translated/es_ES.json +++ b/plugins/opkssh/locales/translated/es_ES.json @@ -15,5 +15,8 @@ "errors": { "authFailed": "La autenticación falló. Revisa tus credenciales e inténtalo de nuevo.", "timeout": "La autenticación expiró. Inténtalo de nuevo." + }, + "hosts": { + "filterAuthOpkssh": "OPKSSH" } } diff --git a/plugins/opkssh/locales/translated/fi_FI.json b/plugins/opkssh/locales/translated/fi_FI.json index 071eadf03..68884fcb5 100644 --- a/plugins/opkssh/locales/translated/fi_FI.json +++ b/plugins/opkssh/locales/translated/fi_FI.json @@ -15,5 +15,8 @@ "errors": { "authFailed": "Todennus epäonnistui. Tarkista tunnistetietosi ja yritä uudelleen.", "timeout": "Todennus aikakatkaistiin. Yritä uudelleen." + }, + "hosts": { + "filterAuthOpkssh": "OPKSSH" } } diff --git a/plugins/opkssh/locales/translated/fr_FR.json b/plugins/opkssh/locales/translated/fr_FR.json index 147231b93..eebb28cac 100644 --- a/plugins/opkssh/locales/translated/fr_FR.json +++ b/plugins/opkssh/locales/translated/fr_FR.json @@ -15,5 +15,8 @@ "errors": { "authFailed": "Échec de l'authentification. Veuillez vérifier vos identifiants et réessayer.", "timeout": "L'authentification a expiré. Veuillez réessayer." + }, + "hosts": { + "filterAuthOpkssh": "OPKSSH" } } diff --git a/plugins/opkssh/locales/translated/he_IL.json b/plugins/opkssh/locales/translated/he_IL.json index d3e0722a7..e084e8819 100644 --- a/plugins/opkssh/locales/translated/he_IL.json +++ b/plugins/opkssh/locales/translated/he_IL.json @@ -15,5 +15,8 @@ "errors": { "authFailed": "האימות נכשל. אנא בדוק את פרטי הגישה שלך ונסה שוב.", "timeout": "הזמן שהוקצב לאימות הסתיים. אנא נסה שוב." + }, + "hosts": { + "filterAuthOpkssh": "אופקש" } } diff --git a/plugins/opkssh/locales/translated/hi_IN.json b/plugins/opkssh/locales/translated/hi_IN.json index 41373417f..fb59e0e1b 100644 --- a/plugins/opkssh/locales/translated/hi_IN.json +++ b/plugins/opkssh/locales/translated/hi_IN.json @@ -15,5 +15,8 @@ "errors": { "authFailed": "प्रमाणीकरण विफल। कृपया अपने क्रेडेंशियल जाँचें और पुनः प्रयास करें।", "timeout": "प्रमाणीकरण का समय समाप्त हो गया। कृपया पुनः प्रयास करें।" + }, + "hosts": { + "filterAuthOpkssh": "OPKSSH" } } diff --git a/plugins/opkssh/locales/translated/hu_HU.json b/plugins/opkssh/locales/translated/hu_HU.json index 12da5401e..641c12010 100644 --- a/plugins/opkssh/locales/translated/hu_HU.json +++ b/plugins/opkssh/locales/translated/hu_HU.json @@ -15,5 +15,8 @@ "errors": { "authFailed": "Sikertelen hitelesítés. Kérjük, ellenőrizze a hitelesítő adatait, és próbálja újra.", "timeout": "A hitelesítés időtúllépést okozott. Kérjük, próbálja újra." + }, + "hosts": { + "filterAuthOpkssh": "OPKSSH" } } diff --git a/plugins/opkssh/locales/translated/id_ID.json b/plugins/opkssh/locales/translated/id_ID.json index bcb00d38b..7b2a84cca 100644 --- a/plugins/opkssh/locales/translated/id_ID.json +++ b/plugins/opkssh/locales/translated/id_ID.json @@ -15,5 +15,8 @@ "errors": { "authFailed": "Autentikasi gagal. Harap periksa kredensial Anda dan coba lagi.", "timeout": "Autentikasi habis waktu. Silakan coba lagi." + }, + "hosts": { + "filterAuthOpkssh": "OPKSSH" } } diff --git a/plugins/opkssh/locales/translated/it_IT.json b/plugins/opkssh/locales/translated/it_IT.json index 8861c7fde..075f70dd9 100644 --- a/plugins/opkssh/locales/translated/it_IT.json +++ b/plugins/opkssh/locales/translated/it_IT.json @@ -15,5 +15,8 @@ "errors": { "authFailed": "Autenticazione fallita. Controlla le credenziali e riprova.", "timeout": "Autenticazione scaduta. Riprova." + }, + "hosts": { + "filterAuthOpkssh": "OPKSSH" } } diff --git a/plugins/opkssh/locales/translated/ja_JP.json b/plugins/opkssh/locales/translated/ja_JP.json index be382e31d..fd750e798 100644 --- a/plugins/opkssh/locales/translated/ja_JP.json +++ b/plugins/opkssh/locales/translated/ja_JP.json @@ -15,5 +15,8 @@ "errors": { "authFailed": "認証に失敗しました。資格情報を確認して再試行してください。", "timeout": "認証がタイムアウトしました。もう一度お試しください。" + }, + "hosts": { + "filterAuthOpkssh": "OPKSSH" } } diff --git a/plugins/opkssh/locales/translated/ko_KR.json b/plugins/opkssh/locales/translated/ko_KR.json index 7d1f54f09..5536d9223 100644 --- a/plugins/opkssh/locales/translated/ko_KR.json +++ b/plugins/opkssh/locales/translated/ko_KR.json @@ -15,5 +15,8 @@ "errors": { "authFailed": "인증에 실패했습니다. 자격 증명을 확인하고 다시 시도하세요.", "timeout": "인증 시간이 초과되었습니다. 다시 시도하세요." + }, + "hosts": { + "filterAuthOpkssh": "OPKSSH" } } diff --git a/plugins/opkssh/locales/translated/nl_NL.json b/plugins/opkssh/locales/translated/nl_NL.json index ab76954f0..af031e500 100644 --- a/plugins/opkssh/locales/translated/nl_NL.json +++ b/plugins/opkssh/locales/translated/nl_NL.json @@ -15,5 +15,8 @@ "errors": { "authFailed": "Authenticatie mislukt. Controleer uw inloggegevens en probeer het opnieuw.", "timeout": "De authenticatie is mislukt vanwege een time-out. Probeer het opnieuw." + }, + "hosts": { + "filterAuthOpkssh": "OPKSSH" } } diff --git a/plugins/opkssh/locales/translated/no_NO.json b/plugins/opkssh/locales/translated/no_NO.json index b54b421ba..6ff95d70a 100644 --- a/plugins/opkssh/locales/translated/no_NO.json +++ b/plugins/opkssh/locales/translated/no_NO.json @@ -15,5 +15,8 @@ "errors": { "authFailed": "Autentiseringen mislyktes. Sjekk legitimasjonen din og prøv på nytt.", "timeout": "Autentiseringen ble tidsavbrutt. Prøv på nytt." + }, + "hosts": { + "filterAuthOpkssh": "OPKSSH" } } diff --git a/plugins/opkssh/locales/translated/pl_PL.json b/plugins/opkssh/locales/translated/pl_PL.json index cbd41c311..b698eae57 100644 --- a/plugins/opkssh/locales/translated/pl_PL.json +++ b/plugins/opkssh/locales/translated/pl_PL.json @@ -15,5 +15,8 @@ "errors": { "authFailed": "Uwierzytelnienie nie powiodło się. Sprawdź poświadczenia i spróbuj ponownie.", "timeout": "Upłynął limit czasu uwierzytelniania. Spróbuj ponownie." + }, + "hosts": { + "filterAuthOpkssh": "OPKSSH" } } diff --git a/plugins/opkssh/locales/translated/pt_BR.json b/plugins/opkssh/locales/translated/pt_BR.json index 4ce01fd5b..0804523d5 100644 --- a/plugins/opkssh/locales/translated/pt_BR.json +++ b/plugins/opkssh/locales/translated/pt_BR.json @@ -15,5 +15,8 @@ "errors": { "authFailed": "A autenticação falhou. Verifique suas credenciais e tente novamente.", "timeout": "A autenticação expirou. Tente novamente." + }, + "hosts": { + "filterAuthOpkssh": "OPKSSH" } } diff --git a/plugins/opkssh/locales/translated/pt_PT.json b/plugins/opkssh/locales/translated/pt_PT.json index ce63db0cf..8165edf54 100644 --- a/plugins/opkssh/locales/translated/pt_PT.json +++ b/plugins/opkssh/locales/translated/pt_PT.json @@ -15,5 +15,8 @@ "errors": { "authFailed": "A autenticação falhou. Verifique as suas credenciais e tente novamente.", "timeout": "A autenticação expirou. Tente novamente." + }, + "hosts": { + "filterAuthOpkssh": "OPKSSH" } } diff --git a/plugins/opkssh/locales/translated/ro_RO.json b/plugins/opkssh/locales/translated/ro_RO.json index 156d9d04b..c51218705 100644 --- a/plugins/opkssh/locales/translated/ro_RO.json +++ b/plugins/opkssh/locales/translated/ro_RO.json @@ -15,5 +15,8 @@ "errors": { "authFailed": "Autentificarea a eșuat. Verificați acreditările și încercați din nou.", "timeout": "Autentificarea a expirat. Vă rugăm să încercați din nou." + }, + "hosts": { + "filterAuthOpkssh": "OPKSSH" } } diff --git a/plugins/opkssh/locales/translated/ru_RU.json b/plugins/opkssh/locales/translated/ru_RU.json index 7bbfb3376..995de2662 100644 --- a/plugins/opkssh/locales/translated/ru_RU.json +++ b/plugins/opkssh/locales/translated/ru_RU.json @@ -15,5 +15,8 @@ "errors": { "authFailed": "Аутентификация не удалась. Проверьте учётные данные и попробуйте снова.", "timeout": "Время аутентификации истекло. Попробуйте снова." + }, + "hosts": { + "filterAuthOpkssh": "OPKSSH" } } diff --git a/plugins/opkssh/locales/translated/sr_SP.json b/plugins/opkssh/locales/translated/sr_SP.json index 80c9f3bb1..568286d0a 100644 --- a/plugins/opkssh/locales/translated/sr_SP.json +++ b/plugins/opkssh/locales/translated/sr_SP.json @@ -15,5 +15,8 @@ "errors": { "authFailed": "Аутентификација није успела. Проверите своје акредитиве и покушајте поново.", "timeout": "Временско ограничење за аутентификацију је истекло. Молимо покушајте поново." + }, + "hosts": { + "filterAuthOpkssh": "ОПКШ" } } diff --git a/plugins/opkssh/locales/translated/sv_SE.json b/plugins/opkssh/locales/translated/sv_SE.json index 038b2a398..49c1eea03 100644 --- a/plugins/opkssh/locales/translated/sv_SE.json +++ b/plugins/opkssh/locales/translated/sv_SE.json @@ -15,5 +15,8 @@ "errors": { "authFailed": "Autentiseringen misslyckades. Kontrollera dina inloggningsuppgifter och försök igen.", "timeout": "Autentiseringen har gått ut. Försök igen." + }, + "hosts": { + "filterAuthOpkssh": "OPKSSH" } } diff --git a/plugins/opkssh/locales/translated/th_TH.json b/plugins/opkssh/locales/translated/th_TH.json index a3126f930..f8ac6287a 100644 --- a/plugins/opkssh/locales/translated/th_TH.json +++ b/plugins/opkssh/locales/translated/th_TH.json @@ -15,5 +15,8 @@ "errors": { "authFailed": "การตรวจสอบสิทธิ์ล้มเหลว โปรดตรวจสอบข้อมูลประจำตัวของคุณและลองอีกครั้ง", "timeout": "การตรวจสอบสิทธิ์หมดเวลา โปรดลองอีกครั้ง" + }, + "hosts": { + "filterAuthOpkssh": "โอพีเคเอสเอช" } } diff --git a/plugins/opkssh/locales/translated/tr_TR.json b/plugins/opkssh/locales/translated/tr_TR.json index c58f6abdd..36f756291 100644 --- a/plugins/opkssh/locales/translated/tr_TR.json +++ b/plugins/opkssh/locales/translated/tr_TR.json @@ -15,5 +15,8 @@ "errors": { "authFailed": "Kimlik doğrulaması başarısız oldu. Lütfen kimlik bilgilerinizi kontrol edip tekrar deneyin.", "timeout": "Kimlik doğrulaması zaman aşımına uğradı. Lütfen tekrar deneyin." + }, + "hosts": { + "filterAuthOpkssh": "OPKSSH" } } diff --git a/plugins/opkssh/locales/translated/uk_UA.json b/plugins/opkssh/locales/translated/uk_UA.json index 92b21ff86..17dfb2db9 100644 --- a/plugins/opkssh/locales/translated/uk_UA.json +++ b/plugins/opkssh/locales/translated/uk_UA.json @@ -15,5 +15,8 @@ "errors": { "authFailed": "Помилка автентифікації. Перевірте свої облікові дані та спробуйте ще раз.", "timeout": "Час очікування автентифікації минув. Спробуйте ще раз." + }, + "hosts": { + "filterAuthOpkssh": "ОПКШ" } } diff --git a/plugins/opkssh/locales/translated/vi_VN.json b/plugins/opkssh/locales/translated/vi_VN.json index b8a30beea..b11b224a9 100644 --- a/plugins/opkssh/locales/translated/vi_VN.json +++ b/plugins/opkssh/locales/translated/vi_VN.json @@ -15,5 +15,8 @@ "errors": { "authFailed": "Xác thực thất bại. Vui lòng kiểm tra thông tin đăng nhập và thử lại.", "timeout": "Xác thực đã hết thời gian chờ. Vui lòng thử lại." + }, + "hosts": { + "filterAuthOpkssh": "OPKSSH" } } diff --git a/plugins/opkssh/locales/translated/zh_CN.json b/plugins/opkssh/locales/translated/zh_CN.json index c616d736b..efc7c3ad1 100644 --- a/plugins/opkssh/locales/translated/zh_CN.json +++ b/plugins/opkssh/locales/translated/zh_CN.json @@ -15,5 +15,8 @@ "errors": { "authFailed": "认证失败,请检查凭据并重试。", "timeout": "认证超时,请重试。" + }, + "hosts": { + "filterAuthOpkssh": "OPKSSH" } } diff --git a/plugins/opkssh/locales/translated/zh_TW.json b/plugins/opkssh/locales/translated/zh_TW.json index 677847ac4..f8383e4e3 100644 --- a/plugins/opkssh/locales/translated/zh_TW.json +++ b/plugins/opkssh/locales/translated/zh_TW.json @@ -15,5 +15,8 @@ "errors": { "authFailed": "驗證失敗。請檢查您的憑證並再試一次。", "timeout": "驗證逾時。請再試一次。" + }, + "hosts": { + "filterAuthOpkssh": "OPKSSH" } } diff --git a/plugins/proxmox/locales/en.json b/plugins/proxmox/locales/en.json index acb88bb1c..e3258666c 100644 --- a/plugins/proxmox/locales/en.json +++ b/plugins/proxmox/locales/en.json @@ -104,6 +104,17 @@ "proxmoxResultFailed": "{{count}} failed", "proxmoxImportComplete": "Proxmox import complete: {{summary}}", "proxmoxDiscoveryFailed": "Discovery failed", - "proxmoxImportFailed": "Import failed" + "proxmoxImportFailed": "Import failed", + "docsLink": "View docs", + "hostNotFound": "Host not found", + "loadingHost": "Loading host...", + "none": "None", + "proxmoxGuestsSelected_one": "{{count}} guest — {{selected}} selected", + "proxmoxGuestsSelected_other": "{{count}} guests — {{selected}} selected", + "proxmoxImportButton_one": "Import {{count}} host", + "proxmoxImportButton_other": "Import {{count}} hosts" + }, + "terminal": { + "connected": "Connected" } } diff --git a/plugins/proxmox/locales/translated/af_ZA.json b/plugins/proxmox/locales/translated/af_ZA.json index 6c7241587..1409d4d8d 100644 --- a/plugins/proxmox/locales/translated/af_ZA.json +++ b/plugins/proxmox/locales/translated/af_ZA.json @@ -55,7 +55,15 @@ "proxmoxStatsPollIntervalDesc": "Minimum 15 sekondes. Hoe gereeld om Proxmox-nodusstatistieke te verfris.", "proxmoxStatsNodeOverride": "Nodenaam-oorskrywing", "proxmoxStatsNodeOverrideDesc": "Ignoreer outomatiese opsporing van die Proxmox-nodusnaam (standaard opgespoor via gasheernaam).", - "proxmoxStatsNodeOverridePlaceholder": "Outomaties opgespoor vanaf gasheernaam" + "proxmoxStatsNodeOverridePlaceholder": "Outomaties opgespoor vanaf gasheernaam", + "docsLink": "Bekyk dokumente", + "hostNotFound": "Gasheer nie gevind nie", + "loadingHost": "Laai gasheer...", + "none": "Geen", + "proxmoxGuestsSelected_one": "{{count}} gas — {{selected}} gekies", + "proxmoxGuestsSelected_other": "{{count}} gaste — {{selected}} gekies", + "proxmoxImportButton_one": "Voer {{count}} gasheer in", + "proxmoxImportButton_other": "Voer {{count}} gashere in" }, "proxmoxStats": { "tabTitle": "Proxmox-statistieke", @@ -102,5 +110,8 @@ "filterLxc": "LXC", "noGuests": "Geen VM'e of LXC-houers is op hierdie node gevind nie.", "noGuestsMatch": "Geen gaste stem ooreen met die huidige filters nie." + }, + "terminal": { + "connected": "Verbonde" } } diff --git a/plugins/proxmox/locales/translated/ar_SA.json b/plugins/proxmox/locales/translated/ar_SA.json index 1bc496c2f..035e45b18 100644 --- a/plugins/proxmox/locales/translated/ar_SA.json +++ b/plugins/proxmox/locales/translated/ar_SA.json @@ -55,7 +55,15 @@ "proxmoxStatsPollIntervalDesc": "الحد الأدنى 15 ثانية. عدد مرات تحديث إحصائيات عقدة Proxmox.", "proxmoxStatsNodeOverride": "تجاوز اسم العقدة", "proxmoxStatsNodeOverrideDesc": "تجاوز الكشف التلقائي عن اسم عقدة Proxmox (يتم الكشف عنه عبر اسم المضيف افتراضيًا).", - "proxmoxStatsNodeOverridePlaceholder": "تم اكتشافه تلقائيًا من اسم المضيف" + "proxmoxStatsNodeOverridePlaceholder": "تم اكتشافه تلقائيًا من اسم المضيف", + "docsLink": "عرض المستندات", + "hostNotFound": "المضيف غير موجود", + "loadingHost": "جارٍ تحميل المضيف...", + "none": "لا يوجد", + "proxmoxGuestsSelected_one": "{{count}} جهاز ضيف — {{selected}} مُحدد", + "proxmoxGuestsSelected_other": "{{count}} أجهزة ضيفة — {{selected}} مُحددة", + "proxmoxImportButton_one": "استيراد {{count}} مضيف", + "proxmoxImportButton_other": "استيراد {{count}} مضيفين" }, "proxmoxStats": { "tabTitle": "إحصائيات Proxmox", @@ -102,5 +110,8 @@ "filterLxc": "LXC", "noGuests": "لم يتم العثور على أي أجهزة افتراضية أو حاويات LXC على هذه العقدة.", "noGuestsMatch": "لا يوجد ضيوف يطابقون المعايير الحالية." + }, + "terminal": { + "connected": "متصل" } } diff --git a/plugins/proxmox/locales/translated/bg_BG.json b/plugins/proxmox/locales/translated/bg_BG.json index 7878a60cb..05b291e12 100644 --- a/plugins/proxmox/locales/translated/bg_BG.json +++ b/plugins/proxmox/locales/translated/bg_BG.json @@ -55,7 +55,15 @@ "proxmoxStatsPollIntervalDesc": "Минимум 15 секунди. Колко често да се обновяват статистическите данни за възлите на Proxmox.", "proxmoxStatsNodeOverride": "Замяна на името на възела", "proxmoxStatsNodeOverrideDesc": "Игнориране на автоматичното откриване на името на възела Proxmox (по подразбиране се открива чрез името на хоста).", - "proxmoxStatsNodeOverridePlaceholder": "Автоматично разпознато от името на хоста" + "proxmoxStatsNodeOverridePlaceholder": "Автоматично разпознато от името на хоста", + "docsLink": "Преглед на документи", + "hostNotFound": "Хостът не е намерен", + "loadingHost": "Зареждане на хоста...", + "none": "Няма", + "proxmoxGuestsSelected_one": "{{count}} гост — {{selected}} избран", + "proxmoxGuestsSelected_other": "{{count}} гости — {{selected}} избрани", + "proxmoxImportButton_one": "Импортиране на хост {{count}}", + "proxmoxImportButton_other": "Импортиране на {{count}} хостове" }, "proxmoxStats": { "tabTitle": "Статистика на Proxmox", @@ -102,5 +110,8 @@ "filterLxc": "LXC", "noGuests": "На този възел не са намерени виртуални машини или LXC контейнери.", "noGuestsMatch": "Няма гости, които да отговарят на текущите филтри." + }, + "terminal": { + "connected": "Свързан" } } diff --git a/plugins/proxmox/locales/translated/bn_BD.json b/plugins/proxmox/locales/translated/bn_BD.json index 64713d660..d2a2d618b 100644 --- a/plugins/proxmox/locales/translated/bn_BD.json +++ b/plugins/proxmox/locales/translated/bn_BD.json @@ -55,7 +55,15 @@ "proxmoxStatsPollIntervalDesc": "সর্বনিম্ন ১৫ সেকেন্ড। কত ঘন ঘন প্রক্সমক্স নোড স্ট্যাটস রিফ্রেশ করতে হবে।", "proxmoxStatsNodeOverride": "নোডের নাম ওভাররাইড", "proxmoxStatsNodeOverrideDesc": "প্রক্সমক্স নোডের নামের স্বয়ংক্রিয় সনাক্তকরণকে অগ্রাহ্য করুন (যা ডিফল্টরূপে হোস্টনেমের মাধ্যমে সনাক্ত করা হয়)।", - "proxmoxStatsNodeOverridePlaceholder": "হোস্টনেম থেকে স্বয়ংক্রিয়ভাবে শনাক্ত করা হয়েছে" + "proxmoxStatsNodeOverridePlaceholder": "হোস্টনেম থেকে স্বয়ংক্রিয়ভাবে শনাক্ত করা হয়েছে", + "docsLink": "নথি দেখুন", + "hostNotFound": "হোস্ট খুঁজে পাওয়া যায়নি", + "loadingHost": "হোস্ট লোড হচ্ছে...", + "none": "কোনোটিই না", + "proxmoxGuestsSelected_one": "{{count}} অতিথি — {{selected}} নির্বাচিত", + "proxmoxGuestsSelected_other": "{{count}} জন অতিথি — {{selected}} জন নির্বাচিত", + "proxmoxImportButton_one": "{{count}} হোস্ট আমদানি করুন", + "proxmoxImportButton_other": "{{count}} হোস্ট আমদানি করুন" }, "proxmoxStats": { "tabTitle": "প্রক্সমক্স পরিসংখ্যান", @@ -102,5 +110,8 @@ "filterLxc": "এলএক্সসি", "noGuests": "এই নোডে কোনো ভিএম বা এলএক্সসি কন্টেইনার খুঁজে পাওয়া যায়নি।", "noGuestsMatch": "বর্তমান ফিল্টারগুলোর সাথে কোনো অতিথি মেলে না।" + }, + "terminal": { + "connected": "সংযুক্ত" } } diff --git a/plugins/proxmox/locales/translated/ca_ES.json b/plugins/proxmox/locales/translated/ca_ES.json index 73dab5281..1255097de 100644 --- a/plugins/proxmox/locales/translated/ca_ES.json +++ b/plugins/proxmox/locales/translated/ca_ES.json @@ -55,7 +55,15 @@ "proxmoxStatsPollIntervalDesc": "Mínim 15 segons. Amb quina freqüència s'han d'actualitzar les estadístiques del node Proxmox.", "proxmoxStatsNodeOverride": "Substitució del nom del node", "proxmoxStatsNodeOverrideDesc": "Anul·la la detecció automàtica del nom del node Proxmox (detectat per defecte mitjançant el nom de l'amfitrió).", - "proxmoxStatsNodeOverridePlaceholder": "Detectat automàticament des del nom d'amfitrió" + "proxmoxStatsNodeOverridePlaceholder": "Detectat automàticament des del nom d'amfitrió", + "docsLink": "Veure documents", + "hostNotFound": "No s'ha trobat l'amfitrió", + "loadingHost": "S'està carregant l'amfitrió...", + "none": "Cap", + "proxmoxGuestsSelected_one": "{{count}} convidat — {{selected}} seleccionat", + "proxmoxGuestsSelected_other": "{{count}} convidats — {{selected}} seleccionats", + "proxmoxImportButton_one": "Importa l'amfitrió {{count}}", + "proxmoxImportButton_other": "Importa els amfitrions {{count}}" }, "proxmoxStats": { "tabTitle": "Estadístiques de Proxmox", @@ -102,5 +110,8 @@ "filterLxc": "LXC", "noGuests": "No s'han trobat màquines virtuals ni contenidors LXC en aquest node.", "noGuestsMatch": "No hi ha convidats que coincideixin amb els filtres actuals." + }, + "terminal": { + "connected": "Connectat" } } diff --git a/plugins/proxmox/locales/translated/cs_CZ.json b/plugins/proxmox/locales/translated/cs_CZ.json index 6d45f144a..de6ce696a 100644 --- a/plugins/proxmox/locales/translated/cs_CZ.json +++ b/plugins/proxmox/locales/translated/cs_CZ.json @@ -55,7 +55,15 @@ "proxmoxStatsPollIntervalDesc": "Minimálně 15 sekund. Jak často aktualizovat statistiky uzlu Proxmox.", "proxmoxStatsNodeOverride": "Přepsání názvu uzlu", "proxmoxStatsNodeOverrideDesc": "Přepsat automatickou detekci názvu uzlu Proxmox (ve výchozím nastavení detekováno pomocí názvu hostitele).", - "proxmoxStatsNodeOverridePlaceholder": "Automaticky detekováno z názvu hostitele" + "proxmoxStatsNodeOverridePlaceholder": "Automaticky detekováno z názvu hostitele", + "docsLink": "Zobrazit dokumenty", + "hostNotFound": "Hostitel nenalezen", + "loadingHost": "Načítání hostitele...", + "none": "Žádný", + "proxmoxGuestsSelected_one": "{{count}} host — {{selected}} vybráno", + "proxmoxGuestsSelected_other": "{{count}} hosté — {{selected}} vybráno", + "proxmoxImportButton_one": "Importovat hostitele {{count}}", + "proxmoxImportButton_other": "Importovat hostitele {{count}}" }, "proxmoxStats": { "tabTitle": "Statistiky Proxmoxu", @@ -102,5 +110,8 @@ "filterLxc": "LXC", "noGuests": "Na tomto uzlu nebyly nalezeny žádné virtuální počítače ani kontejnery LXC.", "noGuestsMatch": "Aktuálním filtrům neodpovídají žádní hosté." + }, + "terminal": { + "connected": "Připojeno" } } diff --git a/plugins/proxmox/locales/translated/da_DK.json b/plugins/proxmox/locales/translated/da_DK.json index 25d769cdf..3afbd4dbb 100644 --- a/plugins/proxmox/locales/translated/da_DK.json +++ b/plugins/proxmox/locales/translated/da_DK.json @@ -55,7 +55,15 @@ "proxmoxStatsPollIntervalDesc": "Minimum 15 sekunder. Hvor ofte skal Proxmox-nodestatistikker opdateres.", "proxmoxStatsNodeOverride": "Tilsidesættelse af nodenavn", "proxmoxStatsNodeOverrideDesc": "Tilsidesæt automatisk detektion af Proxmox-nodenavnet (registreres som standard via værtsnavn).", - "proxmoxStatsNodeOverridePlaceholder": "Automatisk registreret fra værtsnavn" + "proxmoxStatsNodeOverridePlaceholder": "Automatisk registreret fra værtsnavn", + "docsLink": "Se dokumenter", + "hostNotFound": "Værten blev ikke fundet", + "loadingHost": "Indlæser vært...", + "none": "Ingen", + "proxmoxGuestsSelected_one": "{{count}} gæst — {{selected}} valgt", + "proxmoxGuestsSelected_other": "{{count}} gæster — {{selected}} valgt", + "proxmoxImportButton_one": "Importér {{count}} vært", + "proxmoxImportButton_other": "Importér {{count}} værter" }, "proxmoxStats": { "tabTitle": "Proxmox-statistik", @@ -102,5 +110,8 @@ "filterLxc": "LXC", "noGuests": "Der blev ikke fundet nogen VM'er eller LXC-containere på denne node.", "noGuestsMatch": "Ingen gæster matcher de nuværende filtre." + }, + "terminal": { + "connected": "Forbundet" } } diff --git a/plugins/proxmox/locales/translated/de_DE.json b/plugins/proxmox/locales/translated/de_DE.json index d77489348..873f9dad1 100644 --- a/plugins/proxmox/locales/translated/de_DE.json +++ b/plugins/proxmox/locales/translated/de_DE.json @@ -55,7 +55,15 @@ "proxmoxStatsPollIntervalDesc": "Mindestens 15 Sekunden. Wie oft sollen die Proxmox-Knotenstatistiken aktualisiert werden?", "proxmoxStatsNodeOverride": "Knotennamen überschreiben", "proxmoxStatsNodeOverrideDesc": "Die automatische Erkennung des Proxmox-Knotennamens (standardmäßig über den Hostnamen ermittelt) kann deaktiviert werden.", - "proxmoxStatsNodeOverridePlaceholder": "Automatisch anhand des Hostnamens erkannt" + "proxmoxStatsNodeOverridePlaceholder": "Automatisch anhand des Hostnamens erkannt", + "docsLink": "Dokumentation anzeigen", + "hostNotFound": "Host nicht gefunden", + "loadingHost": "Host wird geladen...", + "none": "Keine", + "proxmoxGuestsSelected_one": "{{count}} Gast — {{selected}} ausgewählt", + "proxmoxGuestsSelected_other": "{{count}} Gäste — {{selected}} ausgewählt", + "proxmoxImportButton_one": "{{count}} Host importieren", + "proxmoxImportButton_other": "{{count}} Hosts importieren" }, "proxmoxStats": { "tabTitle": "Proxmox-Statistiken", @@ -102,5 +110,8 @@ "filterLxc": "LXC", "noGuests": "Auf diesem Knoten wurden keine VMs oder LXC-Container gefunden.", "noGuestsMatch": "Es gibt keine Gäste, die den aktuellen Filtern entsprechen." + }, + "terminal": { + "connected": "Verbunden" } } diff --git a/plugins/proxmox/locales/translated/el_GR.json b/plugins/proxmox/locales/translated/el_GR.json index 195111255..9ded5f4e5 100644 --- a/plugins/proxmox/locales/translated/el_GR.json +++ b/plugins/proxmox/locales/translated/el_GR.json @@ -55,7 +55,15 @@ "proxmoxStatsPollIntervalDesc": "Ελάχιστο 15 δευτερόλεπτα. Πόσο συχνά θα ανανεώνονται τα στατιστικά στοιχεία του κόμβου Proxmox.", "proxmoxStatsNodeOverride": "Παράκαμψη ονόματος κόμβου", "proxmoxStatsNodeOverrideDesc": "Παράκαμψη αυτόματης ανίχνευσης του ονόματος κόμβου Proxmox (εντοπίζεται μέσω του ονόματος κεντρικού υπολογιστή από προεπιλογή).", - "proxmoxStatsNodeOverridePlaceholder": "Αυτόματη ανίχνευση από το όνομα κεντρικού υπολογιστή" + "proxmoxStatsNodeOverridePlaceholder": "Αυτόματη ανίχνευση από το όνομα κεντρικού υπολογιστή", + "docsLink": "Προβολή εγγράφων", + "hostNotFound": "Δεν βρέθηκε κεντρικός υπολογιστής", + "loadingHost": "Φόρτωση κεντρικού υπολογιστή...", + "none": "Κανένας", + "proxmoxGuestsSelected_one": "{{count}} επισκέπτης — {{selected}} επιλεγμένος", + "proxmoxGuestsSelected_other": "{{count}} επισκέπτες — {{selected}} επιλεγμένοι", + "proxmoxImportButton_one": "Εισαγωγή κεντρικού υπολογιστή {{count}}", + "proxmoxImportButton_other": "Εισαγωγή {{count}} κεντρικών υπολογιστών" }, "proxmoxStats": { "tabTitle": "Στατιστικά Proxmox", @@ -102,5 +110,8 @@ "filterLxc": "LXC", "noGuests": "Δεν βρέθηκαν εικονικές μηχανές ή κοντέινερ LXC σε αυτόν τον κόμβο.", "noGuestsMatch": "Δεν υπάρχουν επισκέπτες που να αντιστοιχούν στα τρέχοντα φίλτρα." + }, + "terminal": { + "connected": "Συνδεδεμένος" } } diff --git a/plugins/proxmox/locales/translated/es_ES.json b/plugins/proxmox/locales/translated/es_ES.json index 66557f325..a933220ba 100644 --- a/plugins/proxmox/locales/translated/es_ES.json +++ b/plugins/proxmox/locales/translated/es_ES.json @@ -55,7 +55,15 @@ "proxmoxStatsPollIntervalDesc": "Mínimo 15 segundos. Con qué frecuencia se actualizan las estadísticas del nodo Proxmox.", "proxmoxStatsNodeOverride": "Anulación del nombre del nodo", "proxmoxStatsNodeOverrideDesc": "Anular la detección automática del nombre del nodo Proxmox (detectado por defecto mediante el nombre de host).", - "proxmoxStatsNodeOverridePlaceholder": "Detectado automáticamente a partir del nombre de host." + "proxmoxStatsNodeOverridePlaceholder": "Detectado automáticamente a partir del nombre de host.", + "docsLink": "Ver documentación", + "hostNotFound": "Host no encontrado", + "loadingHost": "Cargando host...", + "none": "Ninguno", + "proxmoxGuestsSelected_one": "{{count}} invitado — {{selected}} seleccionado", + "proxmoxGuestsSelected_other": "{{count}} invitados — {{selected}} seleccionados", + "proxmoxImportButton_one": "Importar {{count}} host", + "proxmoxImportButton_other": "Importar {{count}} hosts" }, "proxmoxStats": { "tabTitle": "Estadísticas de Proxmox", @@ -102,5 +110,8 @@ "filterLxc": "LXC", "noGuests": "No se encontraron máquinas virtuales ni contenedores LXC en este nodo.", "noGuestsMatch": "No hay huéspedes que coincidan con los filtros actuales." + }, + "terminal": { + "connected": "Conectado" } } diff --git a/plugins/proxmox/locales/translated/fi_FI.json b/plugins/proxmox/locales/translated/fi_FI.json index 349004f23..c1a0a88cd 100644 --- a/plugins/proxmox/locales/translated/fi_FI.json +++ b/plugins/proxmox/locales/translated/fi_FI.json @@ -55,7 +55,15 @@ "proxmoxStatsPollIntervalDesc": "Vähintään 15 sekuntia. Kuinka usein Proxmox-solmun tilastot päivitetään.", "proxmoxStatsNodeOverride": "Solmun nimen ohitus", "proxmoxStatsNodeOverrideDesc": "Ohita Proxmox-solmun nimen automaattinen tunnistus (tunnistetaan oletusarvoisesti isäntänimen kautta).", - "proxmoxStatsNodeOverridePlaceholder": "Automaattisesti tunnistettu isäntänimestä" + "proxmoxStatsNodeOverridePlaceholder": "Automaattisesti tunnistettu isäntänimestä", + "docsLink": "Näytä dokumentit", + "hostNotFound": "Isäntää ei löydy", + "loadingHost": "Ladataan isäntää...", + "none": "Ei mitään", + "proxmoxGuestsSelected_one": "{{count}} vieras — {{selected}} valittu", + "proxmoxGuestsSelected_other": "{{count}} vieraat — {{selected}} valittu", + "proxmoxImportButton_one": "Tuo {{count}} isäntä", + "proxmoxImportButton_other": "Tuo {{count}} isäntiä" }, "proxmoxStats": { "tabTitle": "Proxmox-tilastot", @@ -102,5 +110,8 @@ "filterLxc": "LXC", "noGuests": "Tältä solmulta ei löytynyt virtuaalikoneita tai LXC-säilöjä.", "noGuestsMatch": "Yksikään vieras ei vastaa nykyisiä suodattimia." + }, + "terminal": { + "connected": "Yhdistetty" } } diff --git a/plugins/proxmox/locales/translated/fr_FR.json b/plugins/proxmox/locales/translated/fr_FR.json index 1ce86e0c9..206209137 100644 --- a/plugins/proxmox/locales/translated/fr_FR.json +++ b/plugins/proxmox/locales/translated/fr_FR.json @@ -55,7 +55,15 @@ "proxmoxStatsPollIntervalDesc": "Minimum 15 secondes. Fréquence d'actualisation des statistiques du nœud Proxmox.", "proxmoxStatsNodeOverride": "Remplacement du nom du nœud", "proxmoxStatsNodeOverrideDesc": "Désactiver la détection automatique du nom du nœud Proxmox (détecté par défaut via le nom d'hôte).", - "proxmoxStatsNodeOverridePlaceholder": "Détection automatique à partir du nom d'hôte" + "proxmoxStatsNodeOverridePlaceholder": "Détection automatique à partir du nom d'hôte", + "docsLink": "Voir la documentation", + "hostNotFound": "Hôte introuvable", + "loadingHost": "Chargement de l'hôte...", + "none": "Aucun", + "proxmoxGuestsSelected_one": "{{count}} invité — {{selected}} sélectionné", + "proxmoxGuestsSelected_other": "{{count}} invités — {{selected}} sélectionnés", + "proxmoxImportButton_one": "Importer {{count}} hôte", + "proxmoxImportButton_other": "Importer {{count}} hôtes" }, "proxmoxStats": { "tabTitle": "Statistiques Proxmox", @@ -102,5 +110,8 @@ "filterLxc": "LXC", "noGuests": "Aucune machine virtuelle ni conteneur LXC n'a été trouvé sur ce nœud.", "noGuestsMatch": "Aucun invité ne correspond aux filtres actuels." + }, + "terminal": { + "connected": "Connecté" } } diff --git a/plugins/proxmox/locales/translated/he_IL.json b/plugins/proxmox/locales/translated/he_IL.json index 7b8552949..9c7e49590 100644 --- a/plugins/proxmox/locales/translated/he_IL.json +++ b/plugins/proxmox/locales/translated/he_IL.json @@ -55,7 +55,15 @@ "proxmoxStatsPollIntervalDesc": "מינימום 15 שניות. באיזו תדירות לרענן את סטטיסטיקות הצומת של Proxmox.", "proxmoxStatsNodeOverride": "עקיפת שם הצומת", "proxmoxStatsNodeOverrideDesc": "עקיפת זיהוי אוטומטי של שם הצומת Proxmox (מזוהה דרך שם המארח כברירת מחדל).", - "proxmoxStatsNodeOverridePlaceholder": "זוהה אוטומטית משם המארח" + "proxmoxStatsNodeOverridePlaceholder": "זוהה אוטומטית משם המארח", + "docsLink": "הצג מסמכים", + "hostNotFound": "המארח לא נמצא", + "loadingHost": "טוען מארח...", + "none": "אַף לֹא אֶחָד", + "proxmoxGuestsSelected_one": "{{count}} אורח — {{selected}} נבחר", + "proxmoxGuestsSelected_other": "{{count}} אורחים — {{selected}} נבחרו", + "proxmoxImportButton_one": "ייבוא מארח {{count}}", + "proxmoxImportButton_other": "ייבוא מארחים {{count}}" }, "proxmoxStats": { "tabTitle": "סטטיסטיקות פרוקסמוקס", @@ -102,5 +110,8 @@ "filterLxc": "LXC", "noGuests": "לא נמצאו מכונות וירטואליות או מכולות LXC בצומת זה.", "noGuestsMatch": "אין אורחים התואמים את המסננים הנוכחיים." + }, + "terminal": { + "connected": "מְחוּבָּר" } } diff --git a/plugins/proxmox/locales/translated/hi_IN.json b/plugins/proxmox/locales/translated/hi_IN.json index d9b2c21ac..32869d126 100644 --- a/plugins/proxmox/locales/translated/hi_IN.json +++ b/plugins/proxmox/locales/translated/hi_IN.json @@ -55,7 +55,15 @@ "proxmoxStatsPollIntervalDesc": "कम से कम 15 सेकंड। प्रोक्समॉक्स नोड के आंकड़ों को कितनी बार रीफ्रेश करना है?", "proxmoxStatsNodeOverride": "नोड नाम ओवरराइड", "proxmoxStatsNodeOverrideDesc": "Proxmox नोड नाम की स्वतः पहचान को ओवरराइड करें (जो डिफ़ॉल्ट रूप से होस्टनाम के माध्यम से पता लगाया जाता है)।", - "proxmoxStatsNodeOverridePlaceholder": "होस्टनाम से स्वतः पता लगाया गया" + "proxmoxStatsNodeOverridePlaceholder": "होस्टनाम से स्वतः पता लगाया गया", + "docsLink": "दस्तावेज़ देखें", + "hostNotFound": "होस्ट नहीं मिला", + "loadingHost": "होस्ट लोड हो रहा है...", + "none": "कोई नहीं", + "proxmoxGuestsSelected_one": "{{count}} अतिथि — {{selected}} चयनित", + "proxmoxGuestsSelected_other": "{{count}} अतिथि — {{selected}} चयनित", + "proxmoxImportButton_one": "{{count}} होस्ट आयात करें", + "proxmoxImportButton_other": "{{count}} होस्ट आयात करें" }, "proxmoxStats": { "tabTitle": "प्रॉक्समॉक्स आँकड़े", @@ -102,5 +110,8 @@ "filterLxc": "एलएक्ससी", "noGuests": "इस नोड पर कोई वीएम या एलएक्ससी कंटेनर नहीं मिला।", "noGuestsMatch": "वर्तमान फ़िल्टरों से कोई अतिथि मेल नहीं खाता।" + }, + "terminal": { + "connected": "कनेक्टेड" } } diff --git a/plugins/proxmox/locales/translated/hu_HU.json b/plugins/proxmox/locales/translated/hu_HU.json index 7be88ab7f..50eae2a2b 100644 --- a/plugins/proxmox/locales/translated/hu_HU.json +++ b/plugins/proxmox/locales/translated/hu_HU.json @@ -55,7 +55,15 @@ "proxmoxStatsPollIntervalDesc": "Minimum 15 másodperc. A Proxmox csomópont statisztikáinak frissítési gyakorisága.", "proxmoxStatsNodeOverride": "Csomópont nevének felülbírálása", "proxmoxStatsNodeOverrideDesc": "A Proxmox csomópont nevének automatikus észlelésének felülbírálása (alapértelmezés szerint a gazdagépnév alapján észlelhető).", - "proxmoxStatsNodeOverridePlaceholder": "Automatikusan felismerve a gazdagépnév alapján" + "proxmoxStatsNodeOverridePlaceholder": "Automatikusan felismerve a gazdagépnév alapján", + "docsLink": "Dokumentumok megtekintése", + "hostNotFound": "Nem található gazdagép", + "loadingHost": "Gazdagép betöltése...", + "none": "Egyik sem", + "proxmoxGuestsSelected_one": "{{count}} vendég — {{selected}} kiválasztva", + "proxmoxGuestsSelected_other": "{{count}} vendégek — {{selected}} kiválasztva", + "proxmoxImportButton_one": "Importálja a {{count}} gazdagépet", + "proxmoxImportButton_other": "{{count}} hosztok importálása" }, "proxmoxStats": { "tabTitle": "Proxmox statisztikák", @@ -102,5 +110,8 @@ "filterLxc": "LXC", "noGuests": "Nem találhatók virtuális gépek vagy LXC konténerek ezen a csomóponton.", "noGuestsMatch": "Egyik vendég sem felel meg a jelenlegi szűrőknek." + }, + "terminal": { + "connected": "Csatlakoztatva" } } diff --git a/plugins/proxmox/locales/translated/id_ID.json b/plugins/proxmox/locales/translated/id_ID.json index 001100688..2fe7d9efd 100644 --- a/plugins/proxmox/locales/translated/id_ID.json +++ b/plugins/proxmox/locales/translated/id_ID.json @@ -55,7 +55,15 @@ "proxmoxStatsPollIntervalDesc": "Minimal 15 detik. Seberapa sering statistik node Proxmox diperbarui.", "proxmoxStatsNodeOverride": "Penggantian nama node", "proxmoxStatsNodeOverrideDesc": "Ganti deteksi otomatis nama node Proxmox (yang secara default dideteksi melalui nama host).", - "proxmoxStatsNodeOverridePlaceholder": "Terdeteksi secara otomatis dari nama host" + "proxmoxStatsNodeOverridePlaceholder": "Terdeteksi secara otomatis dari nama host", + "docsLink": "Lihat dokumen", + "hostNotFound": "Host tidak ditemukan", + "loadingHost": "Memuat host...", + "none": "Tidak ada", + "proxmoxGuestsSelected_one": "{{count}} tamu — {{selected}} terpilih", + "proxmoxGuestsSelected_other": "{{count}} tamu — {{selected}} terpilih", + "proxmoxImportButton_one": "Impor {{count}} host", + "proxmoxImportButton_other": "Impor {{count}} host" }, "proxmoxStats": { "tabTitle": "Statistik Proxmox", @@ -102,5 +110,8 @@ "filterLxc": "LXC", "noGuests": "Tidak ditemukan VM atau kontainer LXC pada node ini.", "noGuestsMatch": "Tidak ada tamu yang sesuai dengan filter saat ini." + }, + "terminal": { + "connected": "Terhubung" } } diff --git a/plugins/proxmox/locales/translated/it_IT.json b/plugins/proxmox/locales/translated/it_IT.json index ac5c450ff..51ea4c806 100644 --- a/plugins/proxmox/locales/translated/it_IT.json +++ b/plugins/proxmox/locales/translated/it_IT.json @@ -55,7 +55,15 @@ "proxmoxStatsPollIntervalDesc": "Minimo 15 secondi. Frequenza di aggiornamento delle statistiche dei nodi Proxmox.", "proxmoxStatsNodeOverride": "Sovrascrittura del nome del nodo", "proxmoxStatsNodeOverrideDesc": "Ignora il rilevamento automatico del nome del nodo Proxmox (rilevato tramite nome host per impostazione predefinita).", - "proxmoxStatsNodeOverridePlaceholder": "Rilevato automaticamente dal nome host" + "proxmoxStatsNodeOverridePlaceholder": "Rilevato automaticamente dal nome host", + "docsLink": "Visualizza documentazione", + "hostNotFound": "Host non trovato", + "loadingHost": "Caricamento host...", + "none": "Nessuna", + "proxmoxGuestsSelected_one": "{{count}} guest — {{selected}} selezionato", + "proxmoxGuestsSelected_other": "{{count}} guest — {{selected}} selezionati", + "proxmoxImportButton_one": "Importa {{count}} host", + "proxmoxImportButton_other": "Importa {{count}} host" }, "proxmoxStats": { "tabTitle": "Statistiche di Proxmox", @@ -102,5 +110,8 @@ "filterLxc": "LXC", "noGuests": "Nessuna macchina virtuale o container LXC trovato su questo nodo.", "noGuestsMatch": "Nessun ospite corrisponde ai filtri attualmente attivi." + }, + "terminal": { + "connected": "Connesso" } } diff --git a/plugins/proxmox/locales/translated/ja_JP.json b/plugins/proxmox/locales/translated/ja_JP.json index 8bfac618b..ea254859b 100644 --- a/plugins/proxmox/locales/translated/ja_JP.json +++ b/plugins/proxmox/locales/translated/ja_JP.json @@ -55,7 +55,15 @@ "proxmoxStatsPollIntervalDesc": "最低15秒。Proxmoxノードの統計情報を更新する頻度。", "proxmoxStatsNodeOverride": "ノード名の上書き", "proxmoxStatsNodeOverrideDesc": "Proxmoxノード名の自動検出(デフォルトではホスト名で検出)を上書きします。", - "proxmoxStatsNodeOverridePlaceholder": "ホスト名から自動検出" + "proxmoxStatsNodeOverridePlaceholder": "ホスト名から自動検出", + "docsLink": "ドキュメントを表示", + "hostNotFound": "ホストが見つかりません", + "loadingHost": "ホストを読み込み中...", + "none": "なし", + "proxmoxGuestsSelected_one": "{{count}} ゲスト — {{selected}} 選択中", + "proxmoxGuestsSelected_other": "{{count}} ゲスト — {{selected}} 選択中", + "proxmoxImportButton_one": "{{count}} ホストをインポート", + "proxmoxImportButton_other": "{{count}} 台のホストをインポート" }, "proxmoxStats": { "tabTitle": "Proxmox統計情報", @@ -102,5 +110,8 @@ "filterLxc": "LXC", "noGuests": "このノード上にはVMまたはLXCコンテナは見つかりませんでした。", "noGuestsMatch": "現在の検索条件に一致するゲストはいません。" + }, + "terminal": { + "connected": "接続中" } } diff --git a/plugins/proxmox/locales/translated/ko_KR.json b/plugins/proxmox/locales/translated/ko_KR.json index bd607d42a..2e5679a1f 100644 --- a/plugins/proxmox/locales/translated/ko_KR.json +++ b/plugins/proxmox/locales/translated/ko_KR.json @@ -55,7 +55,15 @@ "proxmoxStatsPollIntervalDesc": "최소 15초. Proxmox 노드 통계를 새로 고치는 빈도.", "proxmoxStatsNodeOverride": "노드 이름 재정의", "proxmoxStatsNodeOverrideDesc": "Proxmox 노드 이름 자동 감지 기능을 재정의합니다(기본적으로 호스트 이름을 통해 감지됨).", - "proxmoxStatsNodeOverridePlaceholder": "호스트 이름에서 자동 감지됨" + "proxmoxStatsNodeOverridePlaceholder": "호스트 이름에서 자동 감지됨", + "docsLink": "문서 보기", + "hostNotFound": "호스트를 찾을 수 없습니다", + "loadingHost": "호스트 로드 중...", + "none": "없음", + "proxmoxGuestsSelected_one": "게스트 {{count}}개 — {{selected}}개 선택됨", + "proxmoxGuestsSelected_other": "게스트 {{count}}개 — {{selected}}개 선택됨", + "proxmoxImportButton_one": "호스트 {{count}}개 가져오기", + "proxmoxImportButton_other": "{{count}}개 호스트 가져오기" }, "proxmoxStats": { "tabTitle": "프록스목스 통계", @@ -102,5 +110,8 @@ "filterLxc": "LXC", "noGuests": "이 노드에서 VM 또는 LXC 컨테이너를 찾을 수 없습니다.", "noGuestsMatch": "현재 필터 조건에 맞는 투숙객이 없습니다." + }, + "terminal": { + "connected": "연결됨" } } diff --git a/plugins/proxmox/locales/translated/nl_NL.json b/plugins/proxmox/locales/translated/nl_NL.json index e15d8c12b..3c6379634 100644 --- a/plugins/proxmox/locales/translated/nl_NL.json +++ b/plugins/proxmox/locales/translated/nl_NL.json @@ -55,7 +55,15 @@ "proxmoxStatsPollIntervalDesc": "Minimaal 15 seconden. Hoe vaak moeten de Proxmox-node-statistieken worden vernieuwd?", "proxmoxStatsNodeOverride": "Knooppuntnaam overschrijven", "proxmoxStatsNodeOverrideDesc": "Schakel de automatische detectie van de Proxmox-knooppuntnaam uit (deze wordt standaard gedetecteerd via de hostnaam).", - "proxmoxStatsNodeOverridePlaceholder": "Automatisch gedetecteerd op basis van hostnaam" + "proxmoxStatsNodeOverridePlaceholder": "Automatisch gedetecteerd op basis van hostnaam", + "docsLink": "Documenten bekijken", + "hostNotFound": "Host niet gevonden", + "loadingHost": "Host wordt geladen...", + "none": "Geen", + "proxmoxGuestsSelected_one": "{{count}} gast — {{selected}} geselecteerd", + "proxmoxGuestsSelected_other": "{{count}} gasten — {{selected}} geselecteerd", + "proxmoxImportButton_one": "Importeer {{count}} host", + "proxmoxImportButton_other": "Importeer {{count}} hosts" }, "proxmoxStats": { "tabTitle": "Proxmox-statistieken", @@ -102,5 +110,8 @@ "filterLxc": "LXC", "noGuests": "Er zijn geen VM's of LXC-containers gevonden op dit knooppunt.", "noGuestsMatch": "Er zijn geen gasten die aan de huidige filters voldoen." + }, + "terminal": { + "connected": "Aangesloten" } } diff --git a/plugins/proxmox/locales/translated/no_NO.json b/plugins/proxmox/locales/translated/no_NO.json index e20694519..8f50355d4 100644 --- a/plugins/proxmox/locales/translated/no_NO.json +++ b/plugins/proxmox/locales/translated/no_NO.json @@ -55,7 +55,15 @@ "proxmoxStatsPollIntervalDesc": "Minimum 15 sekunder. Hvor ofte Proxmox-nodestatistikken skal oppdateres.", "proxmoxStatsNodeOverride": "Overstyring av nodenavn", "proxmoxStatsNodeOverrideDesc": "Overstyr automatisk deteksjon av Proxmox-nodenavnet (detekteres via vertsnavn som standard).", - "proxmoxStatsNodeOverridePlaceholder": "Automatisk oppdaget fra vertsnavn" + "proxmoxStatsNodeOverridePlaceholder": "Automatisk oppdaget fra vertsnavn", + "docsLink": "Vis dokumenter", + "hostNotFound": "Verten ble ikke funnet", + "loadingHost": "Laster inn vert ...", + "none": "Ingen", + "proxmoxGuestsSelected_one": "{{count}} gjest — {{selected}} valgt", + "proxmoxGuestsSelected_other": "{{count}} gjester — {{selected}} valgt", + "proxmoxImportButton_one": "Importer {{count}} vert", + "proxmoxImportButton_other": "Importer {{count}} verter" }, "proxmoxStats": { "tabTitle": "Proxmox-statistikk", @@ -102,5 +110,8 @@ "filterLxc": "LXC", "noGuests": "Ingen virtuelle maskiner eller LXC-containere funnet på denne noden.", "noGuestsMatch": "Ingen gjester samsvarer med de gjeldende filtrene." + }, + "terminal": { + "connected": "Tilkoblet" } } diff --git a/plugins/proxmox/locales/translated/pl_PL.json b/plugins/proxmox/locales/translated/pl_PL.json index 6953e8b00..ec0cd7db9 100644 --- a/plugins/proxmox/locales/translated/pl_PL.json +++ b/plugins/proxmox/locales/translated/pl_PL.json @@ -55,7 +55,15 @@ "proxmoxStatsPollIntervalDesc": "Minimum 15 sekund. Jak często odświeżać statystyki węzła Proxmox.", "proxmoxStatsNodeOverride": "Nadpisanie nazwy węzła", "proxmoxStatsNodeOverrideDesc": "Zastąp automatyczne wykrywanie nazwy węzła Proxmox (domyślnie wykrywane za pomocą nazwy hosta).", - "proxmoxStatsNodeOverridePlaceholder": "Automatycznie wykryto na podstawie nazwy hosta" + "proxmoxStatsNodeOverridePlaceholder": "Automatycznie wykryto na podstawie nazwy hosta", + "docsLink": "Zobacz dokumentację", + "hostNotFound": "Nie znaleziono hosta", + "loadingHost": "Ładowanie hosta...", + "none": "Brak", + "proxmoxGuestsSelected_one": "{{count}} gość, wybrano {{selected}}", + "proxmoxGuestsSelected_other": "{{count}} gości, wybrano {{selected}}", + "proxmoxImportButton_one": "Importuj {{count}} host", + "proxmoxImportButton_other": "Importuj {{count}} hostów" }, "proxmoxStats": { "tabTitle": "Statystyki Proxmox", @@ -102,5 +110,8 @@ "filterLxc": "LXC", "noGuests": "Nie znaleziono maszyn wirtualnych ani kontenerów LXC na tym węźle.", "noGuestsMatch": "Żaden gość nie pasuje do bieżących filtrów." + }, + "terminal": { + "connected": "Połączono" } } diff --git a/plugins/proxmox/locales/translated/pt_BR.json b/plugins/proxmox/locales/translated/pt_BR.json index 86d134549..5fcc35b2f 100644 --- a/plugins/proxmox/locales/translated/pt_BR.json +++ b/plugins/proxmox/locales/translated/pt_BR.json @@ -55,7 +55,15 @@ "proxmoxStatsPollIntervalDesc": "Mínimo de 15 segundos. Com que frequência as estatísticas do nó Proxmox devem ser atualizadas.", "proxmoxStatsNodeOverride": "Substituição do nome do nó", "proxmoxStatsNodeOverrideDesc": "Substituir a detecção automática do nome do nó Proxmox (detectado por padrão através do nome do host).", - "proxmoxStatsNodeOverridePlaceholder": "Detectado automaticamente a partir do nome do host" + "proxmoxStatsNodeOverridePlaceholder": "Detectado automaticamente a partir do nome do host", + "docsLink": "Ver documentos", + "hostNotFound": "Host não encontrado", + "loadingHost": "Carregando host...", + "none": "Nenhum", + "proxmoxGuestsSelected_one": "{{count}} convidado — {{selected}} selecionado", + "proxmoxGuestsSelected_other": "{{count}} convidados — {{selected}} selecionados", + "proxmoxImportButton_one": "Importar {{count}} host", + "proxmoxImportButton_other": "Importar {{count}} hosts" }, "proxmoxStats": { "tabTitle": "Estatísticas do Proxmox", @@ -102,5 +110,8 @@ "filterLxc": "LXC", "noGuests": "Nenhuma máquina virtual ou contêiner LXC foi encontrado neste nó.", "noGuestsMatch": "Nenhum hóspede corresponde aos filtros atuais." + }, + "terminal": { + "connected": "Conectado" } } diff --git a/plugins/proxmox/locales/translated/pt_PT.json b/plugins/proxmox/locales/translated/pt_PT.json index 19292e184..2819c13f6 100644 --- a/plugins/proxmox/locales/translated/pt_PT.json +++ b/plugins/proxmox/locales/translated/pt_PT.json @@ -55,7 +55,15 @@ "proxmoxStatsPollIntervalDesc": "Mínimo de 15 segundos. Com que frequência as estatísticas do nó Proxmox devem ser atualizadas.", "proxmoxStatsNodeOverride": "Substituição do nome do nó", "proxmoxStatsNodeOverrideDesc": "Substituir a deteção automática do nome do nó Proxmox (detetado por defeito através do nome do host).", - "proxmoxStatsNodeOverridePlaceholder": "Detetado automaticamente a partir do nome do host" + "proxmoxStatsNodeOverridePlaceholder": "Detetado automaticamente a partir do nome do host", + "docsLink": "Ver documentação", + "hostNotFound": "Host não encontrado", + "loadingHost": "A carregar o host...", + "none": "Nenhum", + "proxmoxGuestsSelected_one": "{{count}} convidado — {{selected}} selecionado", + "proxmoxGuestsSelected_other": "{{count}} convidados — {{selected}} selecionados", + "proxmoxImportButton_one": "Importar {{count}} host", + "proxmoxImportButton_other": "Importar {{count}} hosts" }, "proxmoxStats": { "tabTitle": "Estatísticas do Proxmox", @@ -102,5 +110,8 @@ "filterLxc": "LXC", "noGuests": "Nenhuma máquina virtual ou contentor LXC foi encontrado neste nó.", "noGuestsMatch": "Nenhum hóspede corresponde aos filtros atuais." + }, + "terminal": { + "connected": "Ligado" } } diff --git a/plugins/proxmox/locales/translated/ro_RO.json b/plugins/proxmox/locales/translated/ro_RO.json index 3615ea1c6..afd19b71c 100644 --- a/plugins/proxmox/locales/translated/ro_RO.json +++ b/plugins/proxmox/locales/translated/ro_RO.json @@ -55,7 +55,15 @@ "proxmoxStatsPollIntervalDesc": "Minim 15 secunde. Cât de des se actualizează statisticile nodului Proxmox.", "proxmoxStatsNodeOverride": "Suprascriere nume nod", "proxmoxStatsNodeOverrideDesc": "Suprascrie detectarea automată a numelui nodului Proxmox (detectat implicit prin numele de gazdă).", - "proxmoxStatsNodeOverridePlaceholder": "Detectat automat de la numele de gazdă" + "proxmoxStatsNodeOverridePlaceholder": "Detectat automat de la numele de gazdă", + "docsLink": "Vizualizați documentele", + "hostNotFound": "Gazdă negăsită", + "loadingHost": "Se încarcă gazda...", + "none": "Nici unul", + "proxmoxGuestsSelected_one": "{{count}} invitat — {{selected}} selectat", + "proxmoxGuestsSelected_other": "{{count}} invitați — {{selected}} selectați", + "proxmoxImportButton_one": "Importați gazda {{count}}", + "proxmoxImportButton_other": "Importați gazde {{count}}" }, "proxmoxStats": { "tabTitle": "Statistici Proxmox", @@ -102,5 +110,8 @@ "filterLxc": "LXC", "noGuests": "Nu s-au găsit mașini virtuale sau containere LXC pe acest nod.", "noGuestsMatch": "Niciun invitat nu corespunde filtrelor actuale." + }, + "terminal": { + "connected": "Conectat" } } diff --git a/plugins/proxmox/locales/translated/ru_RU.json b/plugins/proxmox/locales/translated/ru_RU.json index fc39749db..441a3c274 100644 --- a/plugins/proxmox/locales/translated/ru_RU.json +++ b/plugins/proxmox/locales/translated/ru_RU.json @@ -55,7 +55,15 @@ "proxmoxStatsPollIntervalDesc": "Минимум 15 секунд. Как часто обновлять статистику узлов Proxmox.", "proxmoxStatsNodeOverride": "Переопределение имени узла", "proxmoxStatsNodeOverrideDesc": "Отключить автоматическое определение имени узла Proxmox (по умолчанию определяется по имени хоста).", - "proxmoxStatsNodeOverridePlaceholder": "Автоматически определено по имени хоста" + "proxmoxStatsNodeOverridePlaceholder": "Автоматически определено по имени хоста", + "docsLink": "Документация", + "hostNotFound": "Хост не найден", + "loadingHost": "Загрузка хоста...", + "none": "Нет", + "proxmoxGuestsSelected_one": "{{count}} гость — {{selected}} выбрано", + "proxmoxGuestsSelected_other": "{{count}} гостей — {{selected}} выбрано", + "proxmoxImportButton_one": "Импортировать {{count}} хост", + "proxmoxImportButton_other": "Импортировать {{count}} хостов" }, "proxmoxStats": { "tabTitle": "Статистика Proxmox", @@ -102,5 +110,8 @@ "filterLxc": "ЛХС", "noGuests": "На этом узле не обнаружено виртуальных машин или контейнеров LXC.", "noGuestsMatch": "Ни один из гостей не соответствует текущим фильтрам." + }, + "terminal": { + "connected": "Подключено" } } diff --git a/plugins/proxmox/locales/translated/sr_SP.json b/plugins/proxmox/locales/translated/sr_SP.json index da3ac0c0a..fc8c261fd 100644 --- a/plugins/proxmox/locales/translated/sr_SP.json +++ b/plugins/proxmox/locales/translated/sr_SP.json @@ -55,7 +55,15 @@ "proxmoxStatsPollIntervalDesc": "Минимум 15 секунди. Колико често освежавати статистику Proxmox чвора.", "proxmoxStatsNodeOverride": "Замена имена чвора", "proxmoxStatsNodeOverrideDesc": "Поништи аутоматско откривање имена Proxmox чвора (подразумевано се открива преко имена хоста).", - "proxmoxStatsNodeOverridePlaceholder": "Аутоматски детектовано на основу имена хоста" + "proxmoxStatsNodeOverridePlaceholder": "Аутоматски детектовано на основу имена хоста", + "docsLink": "Прикажи документе", + "hostNotFound": "Хост није пронађен", + "loadingHost": "Учитавање хоста...", + "none": "Ниједан", + "proxmoxGuestsSelected_one": "{{count}} гост — {{selected}} изабрано", + "proxmoxGuestsSelected_other": "{{count}} гости — {{selected}} изабрано", + "proxmoxImportButton_one": "Увоз {{count}} хоста", + "proxmoxImportButton_other": "Увези {{count}} хостова" }, "proxmoxStats": { "tabTitle": "Proxmox статистика", @@ -102,5 +110,8 @@ "filterLxc": "LXC", "noGuests": "На овом чвору нису пронађене виртуелне машине или LXC контејнери.", "noGuestsMatch": "Ниједан гост не одговара тренутним филтерима." + }, + "terminal": { + "connected": "Повезано" } } diff --git a/plugins/proxmox/locales/translated/sv_SE.json b/plugins/proxmox/locales/translated/sv_SE.json index 61e122ab2..34c34f974 100644 --- a/plugins/proxmox/locales/translated/sv_SE.json +++ b/plugins/proxmox/locales/translated/sv_SE.json @@ -55,7 +55,15 @@ "proxmoxStatsPollIntervalDesc": "Minst 15 sekunder. Hur ofta Proxmox-nodstatistik ska uppdateras.", "proxmoxStatsNodeOverride": "Åsidosättning av nodnamn", "proxmoxStatsNodeOverrideDesc": "Åsidosätt automatisk detektering av Proxmox-nodnamnet (detekteras via värdnamn som standard).", - "proxmoxStatsNodeOverridePlaceholder": "Automatiskt identifierad från värdnamn" + "proxmoxStatsNodeOverridePlaceholder": "Automatiskt identifierad från värdnamn", + "docsLink": "Visa dokument", + "hostNotFound": "Värden hittades inte", + "loadingHost": "Laddar värd...", + "none": "Ingen", + "proxmoxGuestsSelected_one": "{{count}} gäst — {{selected}} vald", + "proxmoxGuestsSelected_other": "{{count}} gäster — {{selected}} vald", + "proxmoxImportButton_one": "Importera {{count}} värd", + "proxmoxImportButton_other": "Importera {{count}} värdar" }, "proxmoxStats": { "tabTitle": "Proxmox-statistik", @@ -102,5 +110,8 @@ "filterLxc": "LXC", "noGuests": "Inga virtuella maskiner eller LXC-behållare hittades på den här noden.", "noGuestsMatch": "Inga gäster matchar de aktuella filtren." + }, + "terminal": { + "connected": "Ansluten" } } diff --git a/plugins/proxmox/locales/translated/th_TH.json b/plugins/proxmox/locales/translated/th_TH.json index 733a5c847..fb9ea8b3f 100644 --- a/plugins/proxmox/locales/translated/th_TH.json +++ b/plugins/proxmox/locales/translated/th_TH.json @@ -55,7 +55,15 @@ "proxmoxStatsPollIntervalDesc": "อย่างน้อย 15 วินาที ความถี่ในการอัปเดตสถิติโหนด Proxmox", "proxmoxStatsNodeOverride": "การแทนที่ชื่อโหนด", "proxmoxStatsNodeOverrideDesc": "ยกเลิกการตรวจจับชื่อโหนด Proxmox อัตโนมัติ (โดยค่าเริ่มต้นจะตรวจจับผ่านชื่อโฮสต์)", - "proxmoxStatsNodeOverridePlaceholder": "ตรวจจับอัตโนมัติจากชื่อโฮสต์" + "proxmoxStatsNodeOverridePlaceholder": "ตรวจจับอัตโนมัติจากชื่อโฮสต์", + "docsLink": "ดูเอกสาร", + "hostNotFound": "ไม่พบโฮสต์", + "loadingHost": "กำลังโหลดโฮสต์...", + "none": "ไม่มี", + "proxmoxGuestsSelected_one": "{{count}} แขก — {{selected}} เลือกแล้ว", + "proxmoxGuestsSelected_other": "แขก {{count}} คน — แขก {{selected}} คน ที่เลือก", + "proxmoxImportButton_one": "นำเข้าโฮสต์ {{count}}", + "proxmoxImportButton_other": "นำเข้าโฮสต์ {{count}}" }, "proxmoxStats": { "tabTitle": "สถิติ Proxmox", @@ -102,5 +110,8 @@ "filterLxc": "LXC", "noGuests": "ไม่พบเครื่องเสมือน (VM) หรือคอนเทนเนอร์ LXC บนโหนดนี้", "noGuestsMatch": "ไม่มีแขกท่านใดตรงกับตัวกรองที่มีอยู่ในขณะนี้" + }, + "terminal": { + "connected": "เชื่อมต่อแล้ว" } } diff --git a/plugins/proxmox/locales/translated/tr_TR.json b/plugins/proxmox/locales/translated/tr_TR.json index 13a902aa1..7b5e9a8f0 100644 --- a/plugins/proxmox/locales/translated/tr_TR.json +++ b/plugins/proxmox/locales/translated/tr_TR.json @@ -55,7 +55,15 @@ "proxmoxStatsPollIntervalDesc": "En az 15 saniye. Proxmox düğüm istatistiklerinin ne sıklıkla yenilenmesi gerektiği.", "proxmoxStatsNodeOverride": "Düğüm adı geçersiz kılma", "proxmoxStatsNodeOverrideDesc": "Proxmox düğüm adının otomatik olarak algılanmasını (varsayılan olarak ana bilgisayar adı üzerinden algılanır) geçersiz kılın.", - "proxmoxStatsNodeOverridePlaceholder": "Ana bilgisayar adından otomatik olarak algılandı" + "proxmoxStatsNodeOverridePlaceholder": "Ana bilgisayar adından otomatik olarak algılandı", + "docsLink": "Dokümanları görüntüle", + "hostNotFound": "Host bulunamadı", + "loadingHost": "Host yükleniyor...", + "none": "Hiçbiri", + "proxmoxGuestsSelected_one": "{{count}} misafir — {{selected}} seçili", + "proxmoxGuestsSelected_other": "{{count}} misafir — {{selected}} seçili", + "proxmoxImportButton_one": "{{count}} ana makineyi içe aktar", + "proxmoxImportButton_other": "{{count}} sunucuyu içe aktar" }, "proxmoxStats": { "tabTitle": "Proxmox İstatistikleri", @@ -102,5 +110,8 @@ "filterLxc": "LXC", "noGuests": "Bu düğümde hiçbir sanal makine veya LXC kapsayıcısı bulunamadı.", "noGuestsMatch": "Mevcut filtrelere uyan konuk bulunamadı." + }, + "terminal": { + "connected": "Bağlandı" } } diff --git a/plugins/proxmox/locales/translated/uk_UA.json b/plugins/proxmox/locales/translated/uk_UA.json index 146aa7b9a..386fc396b 100644 --- a/plugins/proxmox/locales/translated/uk_UA.json +++ b/plugins/proxmox/locales/translated/uk_UA.json @@ -55,7 +55,15 @@ "proxmoxStatsPollIntervalDesc": "Мінімум 15 секунд. Як часто оновлювати статистику вузла Proxmox.", "proxmoxStatsNodeOverride": "Перевизначення назви вузла", "proxmoxStatsNodeOverrideDesc": "Перевизначити автоматичне визначення імені вузла Proxmox (за замовчуванням визначається через ім'я хоста).", - "proxmoxStatsNodeOverridePlaceholder": "Автоматично визначено за назвою хоста" + "proxmoxStatsNodeOverridePlaceholder": "Автоматично визначено за назвою хоста", + "docsLink": "Переглянути документи", + "hostNotFound": "Хост не знайдено", + "loadingHost": "Завантаження хоста...", + "none": "Жоден", + "proxmoxGuestsSelected_one": "{{count}} гість — {{selected}} вибрано", + "proxmoxGuestsSelected_other": "{{count}} гостей — {{selected}} вибрано", + "proxmoxImportButton_one": "Імпортувати хост {{count}}", + "proxmoxImportButton_other": "Імпортувати {{count}} хостів" }, "proxmoxStats": { "tabTitle": "Статистика Proxmox", @@ -102,5 +110,8 @@ "filterLxc": "LXC", "noGuests": "На цьому вузлі не знайдено віртуальних машин або контейнерів LXC.", "noGuestsMatch": "Немає гостей, які відповідають поточним фільтрам." + }, + "terminal": { + "connected": "Підключено" } } diff --git a/plugins/proxmox/locales/translated/vi_VN.json b/plugins/proxmox/locales/translated/vi_VN.json index baa6e5cd3..a0fef47a1 100644 --- a/plugins/proxmox/locales/translated/vi_VN.json +++ b/plugins/proxmox/locales/translated/vi_VN.json @@ -55,7 +55,15 @@ "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ủ" + "proxmoxStatsNodeOverridePlaceholder": "Tự động nhận diện từ tên máy chủ", + "docsLink": "Xem tài liệu", + "hostNotFound": "Không tìm thấy máy chủ", + "loadingHost": "Đang tải máy chủ...", + "none": "Không có", + "proxmoxGuestsSelected_one": "{{count}} máy khách — đã chọn {{selected}}", + "proxmoxGuestsSelected_other": "{{count}} máy khách — đã chọn {{selected}}", + "proxmoxImportButton_one": "Nhập {{count}} máy chủ", + "proxmoxImportButton_other": "Nhập {{count}} máy chủ" }, "proxmoxStats": { "tabTitle": "Thống kê Proxmox", @@ -102,5 +110,8 @@ "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." + }, + "terminal": { + "connected": "Đã kết nối" } } diff --git a/plugins/proxmox/locales/translated/zh_CN.json b/plugins/proxmox/locales/translated/zh_CN.json index 7b8a81763..fb36c40c6 100644 --- a/plugins/proxmox/locales/translated/zh_CN.json +++ b/plugins/proxmox/locales/translated/zh_CN.json @@ -55,7 +55,15 @@ "proxmoxStatsPollIntervalDesc": "最短间隔 15 秒。Proxmox 节点统计信息刷新频率。", "proxmoxStatsNodeOverride": "覆盖节点名称", "proxmoxStatsNodeOverrideDesc": "覆盖自动检测的 Proxmox 节点名称(默认情况下通过主机名检测)。", - "proxmoxStatsNodeOverridePlaceholder": "从主机名自动检测" + "proxmoxStatsNodeOverridePlaceholder": "从主机名自动检测", + "docsLink": "查看文档", + "hostNotFound": "未找到主机", + "loadingHost": "正在加载主机...", + "none": "无", + "proxmoxGuestsSelected_one": "{{count}} 个客户主机 — 已选择 {{selected}} 个", + "proxmoxGuestsSelected_other": "{{count}} 个客户主机 — 已选择 {{selected}} 个", + "proxmoxImportButton_one": "导入 {{count}} 个主机", + "proxmoxImportButton_other": "导入 {{count}} 个主机" }, "proxmoxStats": { "tabTitle": "Proxmox 统计数据", @@ -102,5 +110,8 @@ "filterLxc": "LXC", "noGuests": "此节点上未找到虚拟机或 LXC 容器。", "noGuestsMatch": "没有符合当前筛选条件的客户主机。" + }, + "terminal": { + "connected": "已连接" } } diff --git a/plugins/proxmox/locales/translated/zh_TW.json b/plugins/proxmox/locales/translated/zh_TW.json index 933907589..8225f1dd9 100644 --- a/plugins/proxmox/locales/translated/zh_TW.json +++ b/plugins/proxmox/locales/translated/zh_TW.json @@ -55,7 +55,15 @@ "proxmoxStatsPollIntervalDesc": "最短間隔 15 秒。 Proxmox 節點統計資訊刷新頻率。", "proxmoxStatsNodeOverride": "節點名稱覆蓋", "proxmoxStatsNodeOverrideDesc": "覆蓋 Proxmox 節點名稱的自動偵測(預設透過主機名稱偵測)。", - "proxmoxStatsNodeOverridePlaceholder": "從主機名稱自動偵測" + "proxmoxStatsNodeOverridePlaceholder": "從主機名稱自動偵測", + "docsLink": "檢視文件", + "hostNotFound": "找不到主機", + "loadingHost": "正在載入主機...", + "none": "無", + "proxmoxGuestsSelected_one": "{{count}} 個訪客主機 — 已選取 {{selected}}", + "proxmoxGuestsSelected_other": "{{count}} 個訪客主機 — 已選取 {{selected}}", + "proxmoxImportButton_one": "匯入 {{count}} 台主機", + "proxmoxImportButton_other": "匯入 {{count}} 台主機" }, "proxmoxStats": { "tabTitle": "Proxmox 統計數據", @@ -102,5 +110,8 @@ "filterLxc": "LXC", "noGuests": "此節點上未發現虛擬機器或 LXC 容器。", "noGuestsMatch": "沒有符合目前篩選條件的客人。" + }, + "terminal": { + "connected": "已連線" } } diff --git a/plugins/proxmox/src/backend/guest-sync.ts b/plugins/proxmox/src/backend/guest-sync.ts index d39021748..53ab1558f 100644 --- a/plugins/proxmox/src/backend/guest-sync.ts +++ b/plugins/proxmox/src/backend/guest-sync.ts @@ -49,8 +49,8 @@ export function proxmoxSourceKey(source: { return `${source.sourceHostId}:${source.node}:${source.type}:${source.vmid}`; } -export interface ImportedGuest { - host: Record; +export interface ImportedGuest> { + host: H; config: Record; source: ProxmoxSource; } @@ -60,13 +60,13 @@ export interface ImportedGuest { * source lives in each guest's proxmoxConfig host setting, not on the host * row, so the caller passes both. */ -export function indexImportedGuests( - hosts: Record[], +export function indexImportedGuests( + hosts: H[], configs: Array<{ hostId: number; value: unknown }>, sourceHostId: number, -): Map { +): Map> { const configById = new Map(configs.map((c) => [c.hostId, c.value])); - const out = new Map(); + const out = new Map>(); for (const host of hosts) { const config = parseJsonObject(configById.get(Number(host.id))); const source = getProxmoxSource(config); diff --git a/plugins/proxmox/src/backend/proxmox-jump-hosts.ts b/plugins/proxmox/src/backend/proxmox-jump-hosts.ts index a71453127..c9cd753a1 100644 --- a/plugins/proxmox/src/backend/proxmox-jump-hosts.ts +++ b/plugins/proxmox/src/backend/proxmox-jump-hosts.ts @@ -10,8 +10,3 @@ export function parseProxmoxJumpHosts(raw: unknown): unknown[] | null { return null; } } - -export function serializeProxmoxJumpHosts(raw: unknown): string | null { - const parsed = parseProxmoxJumpHosts(raw); - return parsed ? JSON.stringify(parsed) : null; -} diff --git a/plugins/proxmox/src/backend/routes.ts b/plugins/proxmox/src/backend/routes.ts index 10efd9a93..23d9c256c 100644 --- a/plugins/proxmox/src/backend/routes.ts +++ b/plugins/proxmox/src/backend/routes.ts @@ -3,16 +3,14 @@ import type { Client as SSHClient } from "ssh2"; import { execElevated } from "@termix/plugin-sdk/host-commands"; import type { PluginHostCreateInput, - PluginHostRecord, + PluginHostJumpHost, PluginHostUpdateInput, + PluginSshHost, } from "@termix/plugin-sdk/backend"; import { connectSsh } from "./ssh.js"; import { pluginCtx } from "./plugin-ctx.js"; import { resolveProxmoxImportAuth } from "./proxmox-import-auth.js"; -import { - parseProxmoxJumpHosts, - serializeProxmoxJumpHosts, -} from "./proxmox-jump-hosts.js"; +import { parseProxmoxJumpHosts } from "./proxmox-jump-hosts.js"; import { isSafeNodeName } from "./proxmox-shared.js"; import { indexImportedGuests, @@ -190,7 +188,7 @@ type ProxmoxGuest = { }; /** The resolved host ctx.ssh.connect hands back, plus the sudo secret proxmox needs for pvesh. */ -type PluginSshHostWithSudo = PluginHostRecord & { sudoPassword?: string }; +type PluginSshHostWithSudo = PluginSshHost & { sudoPassword?: string }; type ProxmoxSyncResult = { created: number; @@ -215,6 +213,22 @@ function guestTags(guest: ProxmoxGuest): string[] { ]; } +/** + * The switches another plugin keeps for an imported guest. An entry for a + * plugin that is not running is skipped by core. + */ +export function guestPluginSettings( + connectionType: "ssh" | "rdp", + enableDocker: boolean, +): Record> { + return { + ...(connectionType === "rdp" + ? { "remote-desktop": { enableRdp: true, rdpPort: 3389 } } + : {}), + ...(enableDocker ? { docker: { enableDocker: true } } : {}), + }; +} + function mergeTags( existing: unknown, additions: string[], @@ -261,7 +275,7 @@ async function discoverProxmoxGuestsForHost( timeoutMs: 35000, overrides: { tryKeyboard: false, readyTimeout: 30000 }, }); - const hostWithSudo = host as PluginSshHostWithSudo; + const hostWithSudo: PluginSshHostWithSudo = host; const hostCredentialId = (hostWithSudo.credentialId as number | null) ?? null; try { @@ -498,7 +512,7 @@ async function syncProxmoxHost( try { const discovery = await discoverProxmoxGuestsForHost(userId, sourceHostId); - const sourceHostName = discovery.host.name || "Proxmox"; + const sourceHostName = String(discovery.host.name || "Proxmox"); const defaultCredentialId = discovery.config.defaultCredentialId ?? discovery.credentialId ?? null; const importAuth = resolveProxmoxImportAuth( @@ -507,12 +521,8 @@ async function syncProxmoxHost( ); const now = new Date().toISOString(); - const existingHosts = (await ctx.hosts.listOwned()) as unknown as Record< - string, - unknown - >[]; const existingBySource = indexImportedGuests( - existingHosts, + await ctx.hosts.listOwned(), await ctx.settings.listHostValues("proxmoxConfig"), sourceHostId, ); @@ -560,7 +570,7 @@ async function syncProxmoxHost( : connectionType === "rdp" ? "" : "root"; - const update: Record = { + const update: PluginHostUpdateInput = { name: guest.name, ip: guest.ip || existing?.ip || "0.0.0.0", port, @@ -568,7 +578,7 @@ async function syncProxmoxHost( connectionType, folder: existing?.folder || sourceHostName, tags: mergeTags(existing?.tags, guestTags(guest), ["proxmox-missing"]), - updatedAt: now, + pluginSettings: { [ctx.pluginId]: { proxmoxConfig } }, }; if (existing) { @@ -576,69 +586,46 @@ async function syncProxmoxHost( update.credentialId = importAuth.credentialId; update.overrideCredentialUsername = false; } - await ctx.hosts.update( - existing.id as number, - update as PluginHostUpdateInput, - ); - await ctx.settings.setHost( - existing.id as number, - "proxmoxConfig", - proxmoxConfig, - ); + await ctx.hosts.update(existing.id, update); result.updated++; continue; } - Object.assign(update, { - enableDocker: guest.enableDocker, - enableSsh: connectionType === "ssh", - enableRdp: connectionType === "rdp", - }); - - const created = await ctx.hosts.create({ + await ctx.hosts.create({ ...update, - createdAt: now, + name: guest.name, + ip: update.ip!, + port, + username, + enableSsh: connectionType === "ssh", pin: false, authType: connectionType === "rdp" ? "password" : importAuth.authType, credentialId: connectionType === "ssh" ? importAuth.credentialId : null, - overrideCredentialUsername: importAuth.overrideCredentialUsername, - password: null, - key: null, - keyPassword: null, - keyType: null, - rdpPort: connectionType === "rdp" ? 3389 : null, - jumpHosts: serializeProxmoxJumpHosts(discovery.jumpHosts), - quickActions: null, - forceKeyboardInteractive: "false", - useSocks5: 0, - socks5Host: null, - socks5Port: null, - socks5Username: null, - socks5Password: null, - socks5ProxyChain: null, - portKnockSequence: null, - } as unknown as PluginHostCreateInput); - await ctx.settings.setHost( - Number(created.id), - "proxmoxConfig", - proxmoxConfig, - ); + overrideCredentialUsername: !!importAuth.overrideCredentialUsername, + jumpHosts: (parseProxmoxJumpHosts(discovery.jumpHosts) ?? + []) as PluginHostJumpHost[], + forceKeyboardInteractive: false, + pluginSettings: { + ...update.pluginSettings, + ...guestPluginSettings(connectionType, guest.enableDocker), + }, + }); result.created++; } if (discovery.config.markMissingGuests) { for (const [key, { host, config, source }] of existingBySource) { if (seen.has(key)) continue; - await ctx.hosts.update( - host.id as number, - { - tags: mergeTags(host.tags, ["proxmox-missing"]), - updatedAt: now, - } as PluginHostUpdateInput, - ); - await ctx.settings.setHost(host.id as number, "proxmoxConfig", { - ...config, - source: { ...source, missingSince: source.missingSince || now }, + await ctx.hosts.update(host.id, { + tags: mergeTags(host.tags, ["proxmox-missing"]), + pluginSettings: { + [ctx.pluginId]: { + proxmoxConfig: { + ...config, + source: { ...source, missingSince: source.missingSince || now }, + }, + }, + }, }); result.markedMissing++; } @@ -984,22 +971,15 @@ router.post("/import", async (req, res) => { return res.status(400).json({ error: "No hosts to import" }); } const result = { success: 0, failed: 0, errors: [] as string[] }; - for (const entry of hosts as Array>) { - const { pluginSettings, ...input } = entry; + for (const entry of hosts as PluginHostCreateInput[]) { try { - const created = await ctx.hosts.create( - input as unknown as PluginHostCreateInput, - ); - const own = (pluginSettings as Record | undefined)?.[ - ctx.pluginId - ] as Record | undefined; - for (const [key, value] of Object.entries(own ?? {})) { - await ctx.settings.setHost(Number(created.id), key, value); - } + // Core refuses any field it does not take, and any host setting its + // plugin does not declare. + await ctx.hosts.create(entry); result.success++; } catch (err: unknown) { result.failed++; - result.errors.push(`${String(input.name)}: ${getErrorMessage(err)}`); + result.errors.push(`${String(entry?.name)}: ${getErrorMessage(err)}`); } } return res.json(result); diff --git a/plugins/proxmox/src/frontend/ProxmoxDiscoverDialog.tsx b/plugins/proxmox/src/frontend/ProxmoxDiscoverDialog.tsx index 14c25fda8..a6e9c3c5c 100644 --- a/plugins/proxmox/src/frontend/ProxmoxDiscoverDialog.tsx +++ b/plugins/proxmox/src/frontend/ProxmoxDiscoverDialog.tsx @@ -158,8 +158,6 @@ export function ProxmoxDiscoverDialog({ jumpHosts: discoveredJumpHosts ?? undefined, ...importAuth, enableSsh: g.connectionType !== "rdp", - enableRdp: g.connectionType === "rdp", - enableDocker: g.enableDocker, connectionType: g.connectionType, tags: [ "proxmox", @@ -168,8 +166,13 @@ export function ProxmoxDiscoverDialog({ g.type === "lxc" ? `ct-${g.vmid}` : `vm-${g.vmid}`, ...(g.enableDocker ? ["docker"] : []), ], - // This plugin's host settings travel with the import like an export's. + // Host settings travel with the import like an export's, keyed by + // the plugin that keeps them. pluginSettings: { + ...(g.connectionType === "rdp" + ? { "remote-desktop": { enableRdp: true, rdpPort: 3389 } } + : {}), + ...(g.enableDocker ? { docker: { enableDocker: true } } : {}), proxmox: { proxmoxConfig: { source: { diff --git a/plugins/proxmox/src/frontend/index.tsx b/plugins/proxmox/src/frontend/index.tsx index 640cebd41..b8a6ff499 100644 --- a/plugins/proxmox/src/frontend/index.tsx +++ b/plugins/proxmox/src/frontend/index.tsx @@ -92,6 +92,13 @@ function ProxmoxStatsStandalone({ hostId }: StandaloneViewProps) { return ; } +/** This plugin's host settings, as they arrive on the host record. */ +export function proxmoxSettings( + host: Pick, +): Record { + return host.pluginSettings?.proxmox ?? {}; +} + export function activate(app: TermixApp): void { setProxmoxApp(app); app.onDispose(() => setProxmoxApp(null)); @@ -136,7 +143,7 @@ export function activate(app: TermixApp): void { return ( openDiscover({})} - disabled={!hosts.some((host) => host.enableProxmox)} + disabled={!hosts.some((host) => proxmoxSettings(host).enableProxmox)} > {t("hosts.proxmoxImportTitle")} @@ -166,9 +173,9 @@ export function activate(app: TermixApp): void { icon: Boxes, kind: "open", order: 90, - when: (host) => !!host.enableProxmox, + when: (host) => !!proxmoxSettings(host).enableProxmox, run: (host) => { - const config = host.proxmoxConfig as + const config = proxmoxSettings(host).proxmoxConfig as | { defaultCredentialId?: number | null; defaultAuthType?: string } | undefined; openDiscover({ @@ -205,6 +212,6 @@ export function activate(app: TermixApp): void { order: 60, tabType: "proxmox-stats", copyUrlView: "proxmox-stats", - when: (host) => host.enableProxmoxStats === true, + when: (host) => proxmoxSettings(host).enableProxmoxStats === true, }); } diff --git a/plugins/proxmox/tests/backend/proxmox-jump-hosts.test.ts b/plugins/proxmox/tests/backend/proxmox-jump-hosts.test.ts index 083a4ef25..e57743b6a 100644 --- a/plugins/proxmox/tests/backend/proxmox-jump-hosts.test.ts +++ b/plugins/proxmox/tests/backend/proxmox-jump-hosts.test.ts @@ -1,26 +1,14 @@ import { describe, expect, it } from "vitest"; -import { - parseProxmoxJumpHosts, - serializeProxmoxJumpHosts, -} from "../../src/backend/proxmox-jump-hosts.js"; +import { parseProxmoxJumpHosts } from "../../src/backend/proxmox-jump-hosts.js"; describe("Proxmox jump-host persistence", () => { - const jumpHosts = [{ hostId: 7 }, { hostId: 9 }]; - - it("serializes resolved arrays before inserting a synced guest", () => { - expect(serializeProxmoxJumpHosts(jumpHosts)).toBe( - '[{"hostId":7},{"hostId":9}]', - ); - }); - - it("keeps stored JSON strings stable", () => { - const stored = '[{"hostId":7}]'; - expect(serializeProxmoxJumpHosts(stored)).toBe(stored); - expect(parseProxmoxJumpHosts(stored)).toEqual([{ hostId: 7 }]); + it("reads a resolved array or a stored JSON string", () => { + expect(parseProxmoxJumpHosts([{ hostId: 7 }])).toEqual([{ hostId: 7 }]); + expect(parseProxmoxJumpHosts('[{"hostId":7}]')).toEqual([{ hostId: 7 }]); }); it("turns missing or malformed values into null", () => { - expect(serializeProxmoxJumpHosts(null)).toBeNull(); - expect(serializeProxmoxJumpHosts("invalid")).toBeNull(); + expect(parseProxmoxJumpHosts(null)).toBeNull(); + expect(parseProxmoxJumpHosts("invalid")).toBeNull(); }); }); diff --git a/plugins/proxmox/tests/backend/routes.test.ts b/plugins/proxmox/tests/backend/routes.test.ts new file mode 100644 index 000000000..c959e4f1d --- /dev/null +++ b/plugins/proxmox/tests/backend/routes.test.ts @@ -0,0 +1,12 @@ +import { describe, expect, it } from "vitest"; +import { guestPluginSettings } from "../../src/backend/routes.js"; + +describe("guestPluginSettings", () => { + it("names the plugin that keeps each switch an imported guest needs", () => { + expect(guestPluginSettings("rdp", true)).toEqual({ + "remote-desktop": { enableRdp: true, rdpPort: 3389 }, + docker: { enableDocker: true }, + }); + expect(guestPluginSettings("ssh", false)).toEqual({}); + }); +}); diff --git a/plugins/proxmox/tests/frontend/activate.test.tsx b/plugins/proxmox/tests/frontend/activate.test.tsx index 814097280..9c693739d 100644 --- a/plugins/proxmox/tests/frontend/activate.test.tsx +++ b/plugins/proxmox/tests/frontend/activate.test.tsx @@ -38,6 +38,25 @@ describe(`${manifest.id} activate`, () => { } }); + it("reads its switches from its own host settings", async () => { + rendered = await renderWithApp(plugin, { manifest, locales }); + const host = (settings: Record) => ({ + id: "1", + name: "pve", + ip: "10.0.0.1", + port: 22, + pluginSettings: { proxmox: settings }, + }); + const ids = (settings: Record) => + rendered!.registered.hostActionsFor(host(settings)).map((a) => a.id); + expect(ids({ enableProxmox: true })).toContain("proxmox-discover"); + expect(ids({})).not.toContain("proxmox-discover"); + expect(ids({ enableProxmoxStats: true })).toContain("proxmox-stats"); + expect(plugin.proxmoxSettings(host({ enableProxmoxStats: true }))).toEqual({ + enableProxmoxStats: true, + }); + }); + it("removes everything it registered on deactivate", async () => { const app = await renderWithApp(plugin, { manifest, locales }); await app.deactivate(); diff --git a/plugins/remote-desktop/locales/en.json b/plugins/remote-desktop/locales/en.json index 137915b61..dd0e35a59 100644 --- a/plugins/remote-desktop/locales/en.json +++ b/plugins/remote-desktop/locales/en.json @@ -218,7 +218,8 @@ "unencryptedShell": "Unencrypted shell", "remoteDesktopNotes": "Notes", "userDefaultsNote": "Settings left on their default use your Remote Desktop defaults from Settings.", - "connectionOriginNote": "On the desktop app, RDP, VNC and Telnet use the remote server unless the host is set to This device, which needs a guacd this machine can reach. Set one in the Remote Desktop settings, or per host under guacd Proxy." + "connectionOriginNote": "On the desktop app, RDP, VNC and Telnet use the remote server unless the host is set to This device, which needs a guacd this machine can reach. Set one in the Remote Desktop settings, or per host under guacd Proxy.", + "docsLink": "View docs" }, "onboarding": { "feature_desktop": "Remote desktop", @@ -335,5 +336,8 @@ "title": "Share remote desktop sessions", "description": "Let session sharing and collab rooms show this user's RDP, VNC and Telnet sessions to others." } + }, + "errors": { + "remoteServerRequired": "Remote server required. Connect a remote server in Settings to use this connection type." } } diff --git a/plugins/remote-desktop/locales/translated/af_ZA.json b/plugins/remote-desktop/locales/translated/af_ZA.json index 30b2f3296..e3c295caa 100644 --- a/plugins/remote-desktop/locales/translated/af_ZA.json +++ b/plugins/remote-desktop/locales/translated/af_ZA.json @@ -213,7 +213,8 @@ "tabVnc": "VNC", "tabTelnet": "Telnet", "virtualNetwork": "Virtuele Netwerk", - "unencryptedShell": "Ongeënkripteerde dop" + "unencryptedShell": "Ongeënkripteerde dop", + "docsLink": "Bekyk dokumente" }, "onboarding": { "feature_desktop": "Afstandlessenaar", @@ -274,5 +275,8 @@ "label": "guacd-URL" } } + }, + "errors": { + "remoteServerRequired": "Afstandbediener word benodig. Koppel 'n afstandbediener in Instellings om hierdie verbindingstipe te gebruik." } } diff --git a/plugins/remote-desktop/locales/translated/ar_SA.json b/plugins/remote-desktop/locales/translated/ar_SA.json index 158c02d59..67f679a9b 100644 --- a/plugins/remote-desktop/locales/translated/ar_SA.json +++ b/plugins/remote-desktop/locales/translated/ar_SA.json @@ -213,7 +213,8 @@ "tabVnc": "VNC", "tabTelnet": "Telnet", "virtualNetwork": "الشبكة الافتراضية", - "unencryptedShell": "shell غير مشفر" + "unencryptedShell": "shell غير مشفر", + "docsLink": "عرض المستندات" }, "onboarding": { "feature_desktop": "سطح المكتب البعيد", @@ -274,5 +275,8 @@ "label": "رابط guacd" } } + }, + "errors": { + "remoteServerRequired": "يلزم وجود خادم بعيد. قم بتوصيل خادم بعيد في الإعدادات لاستخدام نوع الاتصال هذا." } } diff --git a/plugins/remote-desktop/locales/translated/bg_BG.json b/plugins/remote-desktop/locales/translated/bg_BG.json index 1e69af9d3..fc48b0091 100644 --- a/plugins/remote-desktop/locales/translated/bg_BG.json +++ b/plugins/remote-desktop/locales/translated/bg_BG.json @@ -213,7 +213,8 @@ "tabVnc": "VNC", "tabTelnet": "Телнет", "virtualNetwork": "Виртуална мрежа", - "unencryptedShell": "Некриптирана обвивка" + "unencryptedShell": "Некриптирана обвивка", + "docsLink": "Преглед на документи" }, "onboarding": { "feature_desktop": "Отдалечен работен плот", @@ -274,5 +275,8 @@ "label": "URL адрес на GUACD" } } + }, + "errors": { + "remoteServerRequired": "Изисква се отдалечен сървър. Свържете се с отдалечен сървър в „Настройки“, за да използвате този тип връзка." } } diff --git a/plugins/remote-desktop/locales/translated/bn_BD.json b/plugins/remote-desktop/locales/translated/bn_BD.json index 0de4a78c3..382c2d427 100644 --- a/plugins/remote-desktop/locales/translated/bn_BD.json +++ b/plugins/remote-desktop/locales/translated/bn_BD.json @@ -213,7 +213,8 @@ "tabVnc": "ভিএনসি", "tabTelnet": "টেলনেট", "virtualNetwork": "ভার্চুয়াল নেটওয়ার্ক", - "unencryptedShell": "এনক্রিপ্টবিহীন শেল" + "unencryptedShell": "এনক্রিপ্টবিহীন শেল", + "docsLink": "নথি দেখুন" }, "onboarding": { "feature_desktop": "রিমোট ডেস্কটপ", @@ -274,5 +275,8 @@ "label": "guacd URL" } } + }, + "errors": { + "remoteServerRequired": "রিমোট সার্ভার প্রয়োজন। এই সংযোগের ধরণটি ব্যবহার করতে সেটিংস-এ একটি রিমোট সার্ভার সংযুক্ত করুন।" } } diff --git a/plugins/remote-desktop/locales/translated/ca_ES.json b/plugins/remote-desktop/locales/translated/ca_ES.json index ebb07cd61..82073cb88 100644 --- a/plugins/remote-desktop/locales/translated/ca_ES.json +++ b/plugins/remote-desktop/locales/translated/ca_ES.json @@ -213,7 +213,8 @@ "tabVnc": "VNC", "tabTelnet": "Telnet", "virtualNetwork": "Xarxa virtual", - "unencryptedShell": "Shell sense xifrar" + "unencryptedShell": "Shell sense xifrar", + "docsLink": "Veure documents" }, "onboarding": { "feature_desktop": "Escriptori remot", @@ -274,5 +275,8 @@ "label": "URL de guacd" } } + }, + "errors": { + "remoteServerRequired": "Cal un servidor remot. Connecteu un servidor remot a Configuració per utilitzar aquest tipus de connexió." } } diff --git a/plugins/remote-desktop/locales/translated/cs_CZ.json b/plugins/remote-desktop/locales/translated/cs_CZ.json index f366bda87..31f2d2726 100644 --- a/plugins/remote-desktop/locales/translated/cs_CZ.json +++ b/plugins/remote-desktop/locales/translated/cs_CZ.json @@ -213,7 +213,8 @@ "tabVnc": "VNC", "tabTelnet": "Telnet", "virtualNetwork": "Virtuální síť", - "unencryptedShell": "Nešifrovaný shell" + "unencryptedShell": "Nešifrovaný shell", + "docsLink": "Zobrazit dokumenty" }, "onboarding": { "feature_desktop": "Vzdálená plocha", @@ -274,5 +275,8 @@ "label": "URL GUACD" } } + }, + "errors": { + "remoteServerRequired": "Je vyžadován vzdálený server. Pro použití tohoto typu připojení se připojte ke vzdálenému serveru v Nastavení." } } diff --git a/plugins/remote-desktop/locales/translated/da_DK.json b/plugins/remote-desktop/locales/translated/da_DK.json index 8c70099bc..f61dc5137 100644 --- a/plugins/remote-desktop/locales/translated/da_DK.json +++ b/plugins/remote-desktop/locales/translated/da_DK.json @@ -213,7 +213,8 @@ "tabVnc": "VNC", "tabTelnet": "Telnet", "virtualNetwork": "Virtuelt netværk", - "unencryptedShell": "Ukrypteret skal" + "unencryptedShell": "Ukrypteret skal", + "docsLink": "Se dokumenter" }, "onboarding": { "feature_desktop": "Fjernskrivebord", @@ -274,5 +275,8 @@ "label": "guacd-URL" } } + }, + "errors": { + "remoteServerRequired": "Fjernserver kræves. Opret forbindelse til en fjernserver i Indstillinger for at bruge denne forbindelsestype." } } diff --git a/plugins/remote-desktop/locales/translated/de_DE.json b/plugins/remote-desktop/locales/translated/de_DE.json index c2793a1d4..27b915588 100644 --- a/plugins/remote-desktop/locales/translated/de_DE.json +++ b/plugins/remote-desktop/locales/translated/de_DE.json @@ -213,7 +213,8 @@ "tabVnc": "VNC", "tabTelnet": "Telnet", "virtualNetwork": "Virtuelles Netzwerk", - "unencryptedShell": "Unverschlüsselte Shell" + "unencryptedShell": "Unverschlüsselte Shell", + "docsLink": "Dokumentation anzeigen" }, "onboarding": { "feature_desktop": "Remote-Desktop", @@ -274,5 +275,8 @@ "label": "guacd-URL" } } + }, + "errors": { + "remoteServerRequired": "Remote-Server erforderlich. Um diesen Verbindungstyp zu verwenden, verbinden Sie einen Remote-Server in den Einstellungen." } } diff --git a/plugins/remote-desktop/locales/translated/el_GR.json b/plugins/remote-desktop/locales/translated/el_GR.json index 17b1e8720..642f6206c 100644 --- a/plugins/remote-desktop/locales/translated/el_GR.json +++ b/plugins/remote-desktop/locales/translated/el_GR.json @@ -213,7 +213,8 @@ "tabVnc": "VNC", "tabTelnet": "Τέλνετ", "virtualNetwork": "Εικονικό Δίκτυο", - "unencryptedShell": "Μη κρυπτογραφημένο κέλυφος" + "unencryptedShell": "Μη κρυπτογραφημένο κέλυφος", + "docsLink": "Προβολή εγγράφων" }, "onboarding": { "feature_desktop": "Απομακρυσμένη επιφάνεια εργασίας", @@ -274,5 +275,8 @@ "label": "URL guacd" } } + }, + "errors": { + "remoteServerRequired": "Απαιτείται απομακρυσμένος διακομιστής. Συνδέστε έναν απομακρυσμένο διακομιστή στις Ρυθμίσεις για να χρησιμοποιήσετε αυτόν τον τύπο σύνδεσης." } } diff --git a/plugins/remote-desktop/locales/translated/es_ES.json b/plugins/remote-desktop/locales/translated/es_ES.json index 8ff80cc7b..66ae4ca4a 100644 --- a/plugins/remote-desktop/locales/translated/es_ES.json +++ b/plugins/remote-desktop/locales/translated/es_ES.json @@ -213,7 +213,8 @@ "tabVnc": "VNC", "tabTelnet": "Telnet", "virtualNetwork": "Red virtual", - "unencryptedShell": "Shell sin cifrar" + "unencryptedShell": "Shell sin cifrar", + "docsLink": "Ver documentación" }, "onboarding": { "feature_desktop": "Escritorio remoto", @@ -274,5 +275,8 @@ "label": "URL de guacd" } } + }, + "errors": { + "remoteServerRequired": "Se requiere un servidor remoto. Conecte un servidor remoto en Configuración para usar este tipo de conexión." } } diff --git a/plugins/remote-desktop/locales/translated/fi_FI.json b/plugins/remote-desktop/locales/translated/fi_FI.json index 7f7d5e0ab..a423dd255 100644 --- a/plugins/remote-desktop/locales/translated/fi_FI.json +++ b/plugins/remote-desktop/locales/translated/fi_FI.json @@ -213,7 +213,8 @@ "tabVnc": "VNC", "tabTelnet": "Telnet", "virtualNetwork": "Virtuaaliverkko", - "unencryptedShell": "Salaamaton kuori" + "unencryptedShell": "Salaamaton kuori", + "docsLink": "Näytä dokumentit" }, "onboarding": { "feature_desktop": "Etätyöpöytä", @@ -274,5 +275,8 @@ "label": "guacd-URL-osoite" } } + }, + "errors": { + "remoteServerRequired": "Etäpalvelin vaaditaan. Yhdistä etäpalvelin asetuksissa käyttääksesi tätä yhteystyyppiä." } } diff --git a/plugins/remote-desktop/locales/translated/fr_FR.json b/plugins/remote-desktop/locales/translated/fr_FR.json index 9ce0b3e45..bb4ca29c6 100644 --- a/plugins/remote-desktop/locales/translated/fr_FR.json +++ b/plugins/remote-desktop/locales/translated/fr_FR.json @@ -213,7 +213,8 @@ "tabVnc": "VNC", "tabTelnet": "Telnet", "virtualNetwork": "Réseau virtuel", - "unencryptedShell": "Shell non chiffré" + "unencryptedShell": "Shell non chiffré", + "docsLink": "Voir la documentation" }, "onboarding": { "feature_desktop": "Bureau à distance", @@ -274,5 +275,8 @@ "label": "URL guacd" } } + }, + "errors": { + "remoteServerRequired": "Serveur distant requis. Connectez un serveur distant dans les paramètres pour utiliser ce type de connexion." } } diff --git a/plugins/remote-desktop/locales/translated/he_IL.json b/plugins/remote-desktop/locales/translated/he_IL.json index 138621c32..5cfb0ed4f 100644 --- a/plugins/remote-desktop/locales/translated/he_IL.json +++ b/plugins/remote-desktop/locales/translated/he_IL.json @@ -213,7 +213,8 @@ "tabVnc": "VNC", "tabTelnet": "טלנט", "virtualNetwork": "רשת וירטואלית", - "unencryptedShell": "מעטפת לא מוצפנת" + "unencryptedShell": "מעטפת לא מוצפנת", + "docsLink": "הצג מסמכים" }, "onboarding": { "feature_desktop": "שולחן עבודה מרוחק", @@ -274,5 +275,8 @@ "label": "כתובת אתר של guacd" } } + }, + "errors": { + "remoteServerRequired": "נדרש שרת מרוחק. יש להתחבר לשרת מרוחק בהגדרות כדי להשתמש בסוג חיבור זה." } } diff --git a/plugins/remote-desktop/locales/translated/hi_IN.json b/plugins/remote-desktop/locales/translated/hi_IN.json index ae056109e..01c980838 100644 --- a/plugins/remote-desktop/locales/translated/hi_IN.json +++ b/plugins/remote-desktop/locales/translated/hi_IN.json @@ -213,7 +213,8 @@ "tabVnc": "VNC", "tabTelnet": "Telnet", "virtualNetwork": "वर्चुअल नेटवर्क", - "unencryptedShell": "अनएन्क्रिप्टेड शेल" + "unencryptedShell": "अनएन्क्रिप्टेड शेल", + "docsLink": "दस्तावेज़ देखें" }, "onboarding": { "feature_desktop": "दूरवर्ती डेस्कटॉप", @@ -274,5 +275,8 @@ "label": "guacd URL" } } + }, + "errors": { + "remoteServerRequired": "रिमोट सर्वर आवश्यक है। इस कनेक्शन प्रकार का उपयोग करने के लिए सेटिंग्स में जाकर रिमोट सर्वर कनेक्ट करें।" } } diff --git a/plugins/remote-desktop/locales/translated/hu_HU.json b/plugins/remote-desktop/locales/translated/hu_HU.json index fe5ce1a82..e1b110dc8 100644 --- a/plugins/remote-desktop/locales/translated/hu_HU.json +++ b/plugins/remote-desktop/locales/translated/hu_HU.json @@ -213,7 +213,8 @@ "tabVnc": "VNC", "tabTelnet": "Telnet", "virtualNetwork": "Virtuális hálózat", - "unencryptedShell": "Titkosítatlan shell" + "unencryptedShell": "Titkosítatlan shell", + "docsLink": "Dokumentumok megtekintése" }, "onboarding": { "feature_desktop": "Távoli asztal", @@ -274,5 +275,8 @@ "label": "guacd URL" } } + }, + "errors": { + "remoteServerRequired": "Távoli szerver szükséges. Csatlakoztasson egy távoli szervert a Beállításokban a kapcsolattípus használatához." } } diff --git a/plugins/remote-desktop/locales/translated/id_ID.json b/plugins/remote-desktop/locales/translated/id_ID.json index eae6679d4..6f1214d0c 100644 --- a/plugins/remote-desktop/locales/translated/id_ID.json +++ b/plugins/remote-desktop/locales/translated/id_ID.json @@ -213,7 +213,8 @@ "tabVnc": "VNC", "tabTelnet": "Telnet", "virtualNetwork": "Jaringan Virtual", - "unencryptedShell": "Shell yang tidak terenkripsi" + "unencryptedShell": "Shell yang tidak terenkripsi", + "docsLink": "Lihat dokumen" }, "onboarding": { "feature_desktop": "Desktop jarak jauh", @@ -274,5 +275,8 @@ "label": "URL guacd" } } + }, + "errors": { + "remoteServerRequired": "Diperlukan server jarak jauh. Hubungkan server jarak jauh di Pengaturan untuk menggunakan jenis koneksi ini." } } diff --git a/plugins/remote-desktop/locales/translated/it_IT.json b/plugins/remote-desktop/locales/translated/it_IT.json index 341e77543..54d1a438f 100644 --- a/plugins/remote-desktop/locales/translated/it_IT.json +++ b/plugins/remote-desktop/locales/translated/it_IT.json @@ -213,7 +213,8 @@ "tabVnc": "VNC", "tabTelnet": "Telnet", "virtualNetwork": "Rete virtuale", - "unencryptedShell": "Shell non crittografata" + "unencryptedShell": "Shell non crittografata", + "docsLink": "Visualizza documentazione" }, "onboarding": { "feature_desktop": "Desktop remoto", @@ -274,5 +275,8 @@ "label": "URL guacd" } } + }, + "errors": { + "remoteServerRequired": "È necessario un server remoto. Per utilizzare questo tipo di connessione, collega un server remoto nelle Impostazioni." } } diff --git a/plugins/remote-desktop/locales/translated/ja_JP.json b/plugins/remote-desktop/locales/translated/ja_JP.json index 3d19d7639..5e5e52833 100644 --- a/plugins/remote-desktop/locales/translated/ja_JP.json +++ b/plugins/remote-desktop/locales/translated/ja_JP.json @@ -213,7 +213,8 @@ "tabVnc": "VNC", "tabTelnet": "Telnet", "virtualNetwork": "仮想ネットワーク", - "unencryptedShell": "暗号化されていないシェル" + "unencryptedShell": "暗号化されていないシェル", + "docsLink": "ドキュメントを表示" }, "onboarding": { "feature_desktop": "リモートデスクトップ", @@ -274,5 +275,8 @@ "label": "guacd URL" } } + }, + "errors": { + "remoteServerRequired": "リモートサーバーが必要です。この接続タイプを使用するには、設定でリモートサーバーを接続してください。" } } diff --git a/plugins/remote-desktop/locales/translated/ko_KR.json b/plugins/remote-desktop/locales/translated/ko_KR.json index 542b4417f..f8049c59f 100644 --- a/plugins/remote-desktop/locales/translated/ko_KR.json +++ b/plugins/remote-desktop/locales/translated/ko_KR.json @@ -213,7 +213,8 @@ "tabVnc": "VNC", "tabTelnet": "텔넷", "virtualNetwork": "가상 네트워크", - "unencryptedShell": "암호화되지 않은 셸" + "unencryptedShell": "암호화되지 않은 셸", + "docsLink": "문서 보기" }, "onboarding": { "feature_desktop": "원격 데스크톱", @@ -274,5 +275,8 @@ "label": "guacd URL" } } + }, + "errors": { + "remoteServerRequired": "원격 서버가 필요합니다. 이 연결 유형을 사용하려면 설정에서 원격 서버를 연결하세요." } } diff --git a/plugins/remote-desktop/locales/translated/nl_NL.json b/plugins/remote-desktop/locales/translated/nl_NL.json index d24adb82b..1a398ee1f 100644 --- a/plugins/remote-desktop/locales/translated/nl_NL.json +++ b/plugins/remote-desktop/locales/translated/nl_NL.json @@ -213,7 +213,8 @@ "tabVnc": "VNC", "tabTelnet": "Telnet", "virtualNetwork": "Virtueel netwerk", - "unencryptedShell": "Niet-versleutelde shell" + "unencryptedShell": "Niet-versleutelde shell", + "docsLink": "Documenten bekijken" }, "onboarding": { "feature_desktop": "Extern bureaublad", @@ -274,5 +275,8 @@ "label": "guacd URL" } } + }, + "errors": { + "remoteServerRequired": "Externe server vereist. Verbind een externe server in de instellingen om dit verbindingstype te gebruiken." } } diff --git a/plugins/remote-desktop/locales/translated/no_NO.json b/plugins/remote-desktop/locales/translated/no_NO.json index 343a53bb9..53d72e5c5 100644 --- a/plugins/remote-desktop/locales/translated/no_NO.json +++ b/plugins/remote-desktop/locales/translated/no_NO.json @@ -213,7 +213,8 @@ "tabVnc": "VNC", "tabTelnet": "Telnet", "virtualNetwork": "Virtuelt nettverk", - "unencryptedShell": "Ukryptert skall" + "unencryptedShell": "Ukryptert skall", + "docsLink": "Vis dokumenter" }, "onboarding": { "feature_desktop": "Eksternt skrivebord", @@ -274,5 +275,8 @@ "label": "guacd-URL" } } + }, + "errors": { + "remoteServerRequired": "Ekstern server kreves. Koble til en ekstern server i Innstillinger for å bruke denne tilkoblingstypen." } } diff --git a/plugins/remote-desktop/locales/translated/pl_PL.json b/plugins/remote-desktop/locales/translated/pl_PL.json index 2b1e4ae62..eeff4c507 100644 --- a/plugins/remote-desktop/locales/translated/pl_PL.json +++ b/plugins/remote-desktop/locales/translated/pl_PL.json @@ -213,7 +213,8 @@ "tabVnc": "VNC", "tabTelnet": "Telnet", "virtualNetwork": "Sieć wirtualna", - "unencryptedShell": "Niezaszyfrowana powłoka" + "unencryptedShell": "Niezaszyfrowana powłoka", + "docsLink": "Zobacz dokumentację" }, "onboarding": { "feature_desktop": "Zdalny pulpit", @@ -274,5 +275,8 @@ "label": "Adres URL guacd" } } + }, + "errors": { + "remoteServerRequired": "Wymagany jest serwer zdalny. Połącz się z serwerem zdalnym w Ustawieniach, aby korzystać z tego typu połączenia." } } diff --git a/plugins/remote-desktop/locales/translated/pt_BR.json b/plugins/remote-desktop/locales/translated/pt_BR.json index aefa99433..0cc9d1237 100644 --- a/plugins/remote-desktop/locales/translated/pt_BR.json +++ b/plugins/remote-desktop/locales/translated/pt_BR.json @@ -213,7 +213,8 @@ "tabVnc": "VNC", "tabTelnet": "Telnet", "virtualNetwork": "Rede Virtual", - "unencryptedShell": "Shell não criptografado" + "unencryptedShell": "Shell não criptografado", + "docsLink": "Ver documentos" }, "onboarding": { "feature_desktop": "Área de trabalho remota", @@ -274,5 +275,8 @@ "label": "URL do guacd" } } + }, + "errors": { + "remoteServerRequired": "É necessário um servidor remoto. Conecte um servidor remoto nas Configurações para usar este tipo de conexão." } } diff --git a/plugins/remote-desktop/locales/translated/pt_PT.json b/plugins/remote-desktop/locales/translated/pt_PT.json index c330096a6..63e1a318b 100644 --- a/plugins/remote-desktop/locales/translated/pt_PT.json +++ b/plugins/remote-desktop/locales/translated/pt_PT.json @@ -213,7 +213,8 @@ "tabVnc": "VNC", "tabTelnet": "Telnet", "virtualNetwork": "Rede Virtual", - "unencryptedShell": "Shell não encriptado" + "unencryptedShell": "Shell não encriptado", + "docsLink": "Ver documentação" }, "onboarding": { "feature_desktop": "Área de trabalho remota", @@ -274,5 +275,8 @@ "label": "URL do guacd" } } + }, + "errors": { + "remoteServerRequired": "É necessário um servidor remoto. Ligue um servidor remoto nas Definições para utilizar este tipo de ligação." } } diff --git a/plugins/remote-desktop/locales/translated/ro_RO.json b/plugins/remote-desktop/locales/translated/ro_RO.json index 97c5fa2ea..b7c82935f 100644 --- a/plugins/remote-desktop/locales/translated/ro_RO.json +++ b/plugins/remote-desktop/locales/translated/ro_RO.json @@ -213,7 +213,8 @@ "tabVnc": "VNC", "tabTelnet": "Telnet", "virtualNetwork": "Rețea virtuală", - "unencryptedShell": "Shell necriptat" + "unencryptedShell": "Shell necriptat", + "docsLink": "Vizualizați documentele" }, "onboarding": { "feature_desktop": "Desktop la distanță", @@ -274,5 +275,8 @@ "label": "URL-ul guacd" } } + }, + "errors": { + "remoteServerRequired": "Este necesar un server la distanță. Conectați un server la distanță în Setări pentru a utiliza acest tip de conexiune." } } diff --git a/plugins/remote-desktop/locales/translated/ru_RU.json b/plugins/remote-desktop/locales/translated/ru_RU.json index a95facd9c..44f644d93 100644 --- a/plugins/remote-desktop/locales/translated/ru_RU.json +++ b/plugins/remote-desktop/locales/translated/ru_RU.json @@ -213,7 +213,8 @@ "tabVnc": "VNC", "tabTelnet": "Telnet", "virtualNetwork": "Виртуальная сеть", - "unencryptedShell": "Незашифрованная оболочка" + "unencryptedShell": "Незашифрованная оболочка", + "docsLink": "Документация" }, "onboarding": { "feature_desktop": "Удаленный рабочий стол", @@ -274,5 +275,8 @@ "label": "URL guacd" } } + }, + "errors": { + "remoteServerRequired": "Требуется удаленный сервер. Для использования этого типа подключения подключите удаленный сервер в настройках." } } diff --git a/plugins/remote-desktop/locales/translated/sr_SP.json b/plugins/remote-desktop/locales/translated/sr_SP.json index 01ccd69d6..10820f368 100644 --- a/plugins/remote-desktop/locales/translated/sr_SP.json +++ b/plugins/remote-desktop/locales/translated/sr_SP.json @@ -213,7 +213,8 @@ "tabVnc": "VNC", "tabTelnet": "Телнет", "virtualNetwork": "Виртуелна мрежа", - "unencryptedShell": "Нешифрована љуска" + "unencryptedShell": "Нешифрована љуска", + "docsLink": "Прикажи документе" }, "onboarding": { "feature_desktop": "Удаљена радна површина", @@ -274,5 +275,8 @@ "label": "URL адреса guacd-а" } } + }, + "errors": { + "remoteServerRequired": "Потребан је удаљени сервер. Повежите се са удаљеним сервером у Подешавањима да бисте користили овај тип везе." } } diff --git a/plugins/remote-desktop/locales/translated/sv_SE.json b/plugins/remote-desktop/locales/translated/sv_SE.json index f6d5195ab..a80481b24 100644 --- a/plugins/remote-desktop/locales/translated/sv_SE.json +++ b/plugins/remote-desktop/locales/translated/sv_SE.json @@ -213,7 +213,8 @@ "tabVnc": "VNC", "tabTelnet": "Telnet", "virtualNetwork": "Virtuellt nätverk", - "unencryptedShell": "Okrypterat skal" + "unencryptedShell": "Okrypterat skal", + "docsLink": "Visa dokument" }, "onboarding": { "feature_desktop": "Fjärrskrivbord", @@ -274,5 +275,8 @@ "label": "guacd-URL" } } + }, + "errors": { + "remoteServerRequired": "Fjärrserver krävs. Anslut en fjärrserver i Inställningar för att använda den här anslutningstypen." } } diff --git a/plugins/remote-desktop/locales/translated/th_TH.json b/plugins/remote-desktop/locales/translated/th_TH.json index 0972086be..6e9ab925c 100644 --- a/plugins/remote-desktop/locales/translated/th_TH.json +++ b/plugins/remote-desktop/locales/translated/th_TH.json @@ -213,7 +213,8 @@ "tabVnc": "วีเอ็นซี", "tabTelnet": "เทลเน็ต", "virtualNetwork": "เครือข่ายเสมือน", - "unencryptedShell": "เชลล์ที่ไม่ได้เข้ารหัส" + "unencryptedShell": "เชลล์ที่ไม่ได้เข้ารหัส", + "docsLink": "ดูเอกสาร" }, "onboarding": { "feature_desktop": "การเข้าถึงเดสก์ท็อประยะไกล", @@ -274,5 +275,8 @@ "label": "URL guacd" } } + }, + "errors": { + "remoteServerRequired": "จำเป็นต้องใช้เซิร์ฟเวอร์ระยะไกล เชื่อมต่อเซิร์ฟเวอร์ระยะไกลในการตั้งค่าเพื่อใช้ประเภทการเชื่อมต่อนี้" } } diff --git a/plugins/remote-desktop/locales/translated/tr_TR.json b/plugins/remote-desktop/locales/translated/tr_TR.json index 3dad71693..de08a97a5 100644 --- a/plugins/remote-desktop/locales/translated/tr_TR.json +++ b/plugins/remote-desktop/locales/translated/tr_TR.json @@ -213,7 +213,8 @@ "tabVnc": "VNC", "tabTelnet": "Telnet", "virtualNetwork": "Sanal Ağ", - "unencryptedShell": "Şifrelenmemiş Shell" + "unencryptedShell": "Şifrelenmemiş Shell", + "docsLink": "Dokümanları görüntüle" }, "onboarding": { "feature_desktop": "Uzaktan masaüstü", @@ -274,5 +275,8 @@ "label": "guacd URL'si" } } + }, + "errors": { + "remoteServerRequired": "Uzak sunucu gereklidir. Bu bağlantı türünü kullanmak için Ayarlar'dan bir uzak sunucu bağlayın." } } diff --git a/plugins/remote-desktop/locales/translated/uk_UA.json b/plugins/remote-desktop/locales/translated/uk_UA.json index d81173337..8e2326e85 100644 --- a/plugins/remote-desktop/locales/translated/uk_UA.json +++ b/plugins/remote-desktop/locales/translated/uk_UA.json @@ -213,7 +213,8 @@ "tabVnc": "VNC", "tabTelnet": "Телнет", "virtualNetwork": "Віртуальна мережа", - "unencryptedShell": "Незашифрована оболонка" + "unencryptedShell": "Незашифрована оболонка", + "docsLink": "Переглянути документи" }, "onboarding": { "feature_desktop": "Віддалений робочий стіл", @@ -274,5 +275,8 @@ "label": "URL-адреса GUACD" } } + }, + "errors": { + "remoteServerRequired": "Потрібен віддалений сервер. Підключіться до віддаленого сервера в налаштуваннях, щоб використовувати цей тип підключення." } } diff --git a/plugins/remote-desktop/locales/translated/vi_VN.json b/plugins/remote-desktop/locales/translated/vi_VN.json index 8a443127e..f00813bc0 100644 --- a/plugins/remote-desktop/locales/translated/vi_VN.json +++ b/plugins/remote-desktop/locales/translated/vi_VN.json @@ -213,7 +213,8 @@ "tabVnc": "VNC", "tabTelnet": "Telnet", "virtualNetwork": "Mạng ảo", - "unencryptedShell": "Shell không mã hóa" + "unencryptedShell": "Shell không mã hóa", + "docsLink": "Xem tài liệu" }, "onboarding": { "feature_desktop": "Máy tính từ xa", @@ -274,5 +275,8 @@ "label": "URL guacd" } } + }, + "errors": { + "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." } } diff --git a/plugins/remote-desktop/locales/translated/zh_CN.json b/plugins/remote-desktop/locales/translated/zh_CN.json index 71fef9727..4a9e2b062 100644 --- a/plugins/remote-desktop/locales/translated/zh_CN.json +++ b/plugins/remote-desktop/locales/translated/zh_CN.json @@ -213,7 +213,8 @@ "tabVnc": "VNC", "tabTelnet": "Telnet", "virtualNetwork": "虚拟网络", - "unencryptedShell": "未加密 Shell" + "unencryptedShell": "未加密 Shell", + "docsLink": "查看文档" }, "onboarding": { "feature_desktop": "远程桌面", @@ -274,5 +275,8 @@ "label": "guacd URL" } } + }, + "errors": { + "remoteServerRequired": "需要远程服务器。请在“设置”中连接远程服务器以使用此连接类型。" } } diff --git a/plugins/remote-desktop/locales/translated/zh_TW.json b/plugins/remote-desktop/locales/translated/zh_TW.json index 519e1e6cd..85b3d3163 100644 --- a/plugins/remote-desktop/locales/translated/zh_TW.json +++ b/plugins/remote-desktop/locales/translated/zh_TW.json @@ -213,7 +213,8 @@ "tabVnc": "VNC", "tabTelnet": "Telnet", "virtualNetwork": "虛擬網路", - "unencryptedShell": "未加密殼層" + "unencryptedShell": "未加密殼層", + "docsLink": "檢視文件" }, "onboarding": { "feature_desktop": "遠端桌面", @@ -274,5 +275,8 @@ "label": "guacd URL" } } + }, + "errors": { + "remoteServerRequired": "需要遠端伺服器。請在「設定」中連接遠端伺服器以使用此連線類型。" } } diff --git a/plugins/remote-desktop/src/frontend/index.tsx b/plugins/remote-desktop/src/frontend/index.tsx index 4bd41612e..9bb5f14f1 100644 --- a/plugins/remote-desktop/src/frontend/index.tsx +++ b/plugins/remote-desktop/src/frontend/index.tsx @@ -92,7 +92,7 @@ const PROTOCOLS: { ]; function RemoteDesktopTab({ tab, host, isVisible, handleRef }: TabProps) { - const record = host as unknown as RemoteHostLogin | undefined; + const record: RemoteHostLogin | undefined = host; return ( } @@ -175,6 +175,12 @@ function ToolbarCard({ ); } +/** The Wake-on-LAN address a host keeps, the default for a session's wake packet. */ +function wakeOnLanMac(host: PluginHostRecord | undefined): string | null { + const value = host?.pluginSettings?.["wake-on-lan"]?.macAddress; + return typeof value === "string" && value ? value : null; +} + function RdpSection(props: HostEditorSectionProps) { const { form, setField, setGuacField } = remoteDesktopForm(props); return ( @@ -183,7 +189,7 @@ function RdpSection(props: HostEditorSectionProps) { form={form} setField={setField} setGuacField={setGuacField} - host={props.host as { macAddress?: string | null } | undefined} + host={{ macAddress: wakeOnLanMac(props.host) }} credentials={props.credentials as never} /> @@ -200,7 +206,7 @@ function VncSection(props: HostEditorSectionProps) { form={form} setField={setField} setGuacField={setGuacField} - host={props.host as { macAddress?: string | null } | undefined} + host={{ macAddress: wakeOnLanMac(props.host) }} credentials={props.credentials as never} /> @@ -246,7 +252,7 @@ function registerNativeRdp(app: TermixApp): void { order: 105, when: (host) => protocolEnabled(host, "rdp"), run: (host) => { - const record = host as unknown as RemoteHostLogin; + const record: RemoteHostLogin = host; void openNativeRdp({ host: String(record.ip ?? ""), port: hostRemoteOptions(record).rdpPort, diff --git a/plugins/session-sharing/locales/en.json b/plugins/session-sharing/locales/en.json index 49540e3b4..540573925 100644 --- a/plugins/session-sharing/locales/en.json +++ b/plugins/session-sharing/locales/en.json @@ -156,5 +156,17 @@ "title": "Share sessions and join rooms", "description": "Share live sessions by link or with other users, and create and join collaboration rooms." } + }, + "hosts": { + "sharing": { + "expiry": { + "never": "Never", + "oneHour": "1 hour", + "oneDay": "24 hours", + "sevenDays": "7 days", + "thirtyDays": "30 days", + "custom": "Custom" + } + } } } diff --git a/plugins/session-sharing/locales/translated/af_ZA.json b/plugins/session-sharing/locales/translated/af_ZA.json index f8cfe77a8..79cb857ed 100644 --- a/plugins/session-sharing/locales/translated/af_ZA.json +++ b/plugins/session-sharing/locales/translated/af_ZA.json @@ -148,5 +148,17 @@ "description": "Laat regstreekse sessies op hierdie gasheer via skakel of met ander gebruikers gedeel word" } } + }, + "hosts": { + "sharing": { + "expiry": { + "never": "Nooit", + "oneHour": "1 uur", + "oneDay": "24 uur", + "sevenDays": "7 dae", + "thirtyDays": "30 dae", + "custom": "Pasgemaak" + } + } } } diff --git a/plugins/session-sharing/locales/translated/ar_SA.json b/plugins/session-sharing/locales/translated/ar_SA.json index c79b35711..437120a97 100644 --- a/plugins/session-sharing/locales/translated/ar_SA.json +++ b/plugins/session-sharing/locales/translated/ar_SA.json @@ -148,5 +148,17 @@ "description": "يمكن مشاركة الجلسات المباشرة على هذا المضيف عبر رابط أو مع مستخدمين آخرين" } } + }, + "hosts": { + "sharing": { + "expiry": { + "never": "أبدًا", + "oneHour": "ساعة واحدة", + "oneDay": "24 ساعة", + "sevenDays": "7 أيام", + "thirtyDays": "30 يومًا", + "custom": "مخصص" + } + } } } diff --git a/plugins/session-sharing/locales/translated/bg_BG.json b/plugins/session-sharing/locales/translated/bg_BG.json index d5409b0e7..8409a8e8b 100644 --- a/plugins/session-sharing/locales/translated/bg_BG.json +++ b/plugins/session-sharing/locales/translated/bg_BG.json @@ -148,5 +148,17 @@ "description": "Позволете споделянето на сесиите на живо на този хост чрез линк или с други потребители" } } + }, + "hosts": { + "sharing": { + "expiry": { + "never": "Никога", + "oneHour": "1 час", + "oneDay": "24 часа", + "sevenDays": "7 дни", + "thirtyDays": "30 дни", + "custom": "Персонализирано" + } + } } } diff --git a/plugins/session-sharing/locales/translated/bn_BD.json b/plugins/session-sharing/locales/translated/bn_BD.json index 5d3c417ad..a118f817b 100644 --- a/plugins/session-sharing/locales/translated/bn_BD.json +++ b/plugins/session-sharing/locales/translated/bn_BD.json @@ -148,5 +148,17 @@ "description": "এই হোস্টের লাইভ সেশনগুলো লিঙ্কের মাধ্যমে বা অন্যান্য ব্যবহারকারীদের সাথে শেয়ার করা যাবে।" } } + }, + "hosts": { + "sharing": { + "expiry": { + "never": "কখনো না", + "oneHour": "১ ঘন্টা", + "oneDay": "২৪ ঘন্টা", + "sevenDays": "৭ দিন", + "thirtyDays": "৩০ দিন", + "custom": "কাস্টম" + } + } } } diff --git a/plugins/session-sharing/locales/translated/ca_ES.json b/plugins/session-sharing/locales/translated/ca_ES.json index ba27dd651..08e967d7d 100644 --- a/plugins/session-sharing/locales/translated/ca_ES.json +++ b/plugins/session-sharing/locales/translated/ca_ES.json @@ -148,5 +148,17 @@ "description": "Permet que les sessions en directe d'aquest amfitrió es comparteixin mitjançant un enllaç o amb altres usuaris" } } + }, + "hosts": { + "sharing": { + "expiry": { + "never": "Mai", + "oneHour": "1 hora", + "oneDay": "24 hores", + "sevenDays": "7 dies", + "thirtyDays": "30 dies", + "custom": "Personalitzat" + } + } } } diff --git a/plugins/session-sharing/locales/translated/cs_CZ.json b/plugins/session-sharing/locales/translated/cs_CZ.json index de3921f28..401a19a40 100644 --- a/plugins/session-sharing/locales/translated/cs_CZ.json +++ b/plugins/session-sharing/locales/translated/cs_CZ.json @@ -148,5 +148,17 @@ "description": "Umožnit sdílení živých relací na tomto hostiteli prostřednictvím odkazu nebo s ostatními uživateli" } } + }, + "hosts": { + "sharing": { + "expiry": { + "never": "Nikdy", + "oneHour": "1 hodina", + "oneDay": "24 hodin", + "sevenDays": "7 dní", + "thirtyDays": "30 dní", + "custom": "Zvyk" + } + } } } diff --git a/plugins/session-sharing/locales/translated/da_DK.json b/plugins/session-sharing/locales/translated/da_DK.json index 44027251a..258ba2b29 100644 --- a/plugins/session-sharing/locales/translated/da_DK.json +++ b/plugins/session-sharing/locales/translated/da_DK.json @@ -148,5 +148,17 @@ "description": "Tillad live-sessioner på denne vært at blive delt via link eller med andre brugere" } } + }, + "hosts": { + "sharing": { + "expiry": { + "never": "Aldrig", + "oneHour": "1 time", + "oneDay": "24 timer", + "sevenDays": "7 dage", + "thirtyDays": "30 dage", + "custom": "Skik" + } + } } } diff --git a/plugins/session-sharing/locales/translated/de_DE.json b/plugins/session-sharing/locales/translated/de_DE.json index 5bda3e920..418f37629 100644 --- a/plugins/session-sharing/locales/translated/de_DE.json +++ b/plugins/session-sharing/locales/translated/de_DE.json @@ -148,5 +148,17 @@ "description": "Ermöglichen Sie es, Live-Sitzungen auf diesem Host per Link oder mit anderen Benutzern zu teilen." } } + }, + "hosts": { + "sharing": { + "expiry": { + "never": "Nie", + "oneHour": "1 Stunde", + "oneDay": "24 Stunden", + "sevenDays": "7 Tage", + "thirtyDays": "30 Tage", + "custom": "Benutzerdefiniert" + } + } } } diff --git a/plugins/session-sharing/locales/translated/el_GR.json b/plugins/session-sharing/locales/translated/el_GR.json index df41288a3..f7f660854 100644 --- a/plugins/session-sharing/locales/translated/el_GR.json +++ b/plugins/session-sharing/locales/translated/el_GR.json @@ -148,5 +148,17 @@ "description": "Να επιτρέπεται η κοινοποίηση ζωντανών συνεδριών σε αυτόν τον πάροχο μέσω συνδέσμου ή με άλλους χρήστες" } } + }, + "hosts": { + "sharing": { + "expiry": { + "never": "Ποτέ", + "oneHour": "1 ώρα", + "oneDay": "24 ώρες", + "sevenDays": "7 ημέρες", + "thirtyDays": "30 ημέρες", + "custom": "Εθιμο" + } + } } } diff --git a/plugins/session-sharing/locales/translated/es_ES.json b/plugins/session-sharing/locales/translated/es_ES.json index d3f05d5f2..330277025 100644 --- a/plugins/session-sharing/locales/translated/es_ES.json +++ b/plugins/session-sharing/locales/translated/es_ES.json @@ -148,5 +148,17 @@ "description": "Permitir que las sesiones en vivo en este servidor se compartan mediante un enlace o con otros usuarios." } } + }, + "hosts": { + "sharing": { + "expiry": { + "never": "Nunca", + "oneHour": "1 hora", + "oneDay": "24 horas", + "sevenDays": "7 días", + "thirtyDays": "30 días", + "custom": "Personalizado" + } + } } } diff --git a/plugins/session-sharing/locales/translated/fi_FI.json b/plugins/session-sharing/locales/translated/fi_FI.json index a841deecf..fd1472eeb 100644 --- a/plugins/session-sharing/locales/translated/fi_FI.json +++ b/plugins/session-sharing/locales/translated/fi_FI.json @@ -148,5 +148,17 @@ "description": "Salli live-istuntojen jakaminen tällä isännällä linkin kautta tai muiden käyttäjien kanssa" } } + }, + "hosts": { + "sharing": { + "expiry": { + "never": "Ei koskaan", + "oneHour": "1 tunti", + "oneDay": "24 tuntia", + "sevenDays": "7 päivää", + "thirtyDays": "30 päivää", + "custom": "Mukautettu" + } + } } } diff --git a/plugins/session-sharing/locales/translated/fr_FR.json b/plugins/session-sharing/locales/translated/fr_FR.json index 3b3f4178b..481233034 100644 --- a/plugins/session-sharing/locales/translated/fr_FR.json +++ b/plugins/session-sharing/locales/translated/fr_FR.json @@ -148,5 +148,17 @@ "description": "Autoriser le partage des sessions en direct sur cet hébergeur via un lien ou avec d'autres utilisateurs" } } + }, + "hosts": { + "sharing": { + "expiry": { + "never": "Jamais", + "oneHour": "1 heure", + "oneDay": "24 heures", + "sevenDays": "7 jours", + "thirtyDays": "30 jours", + "custom": "Personnalisé" + } + } } } diff --git a/plugins/session-sharing/locales/translated/he_IL.json b/plugins/session-sharing/locales/translated/he_IL.json index a05781856..3a97ea1ec 100644 --- a/plugins/session-sharing/locales/translated/he_IL.json +++ b/plugins/session-sharing/locales/translated/he_IL.json @@ -148,5 +148,17 @@ "description": "אפשר שיתוף של מפגשים חיים במארח זה באמצעות קישור או עם משתמשים אחרים" } } + }, + "hosts": { + "sharing": { + "expiry": { + "never": "לְעוֹלָם לֹא", + "oneHour": "שעה אחת", + "oneDay": "24 שעות", + "sevenDays": "7 ימים", + "thirtyDays": "30 ימים", + "custom": "מִנְהָג" + } + } } } diff --git a/plugins/session-sharing/locales/translated/hi_IN.json b/plugins/session-sharing/locales/translated/hi_IN.json index 3464f12a5..0ff06e93c 100644 --- a/plugins/session-sharing/locales/translated/hi_IN.json +++ b/plugins/session-sharing/locales/translated/hi_IN.json @@ -148,5 +148,17 @@ "description": "इस होस्ट पर होने वाले लाइव सेशन को लिंक के माध्यम से या अन्य उपयोगकर्ताओं के साथ साझा किया जा सकता है।" } } + }, + "hosts": { + "sharing": { + "expiry": { + "never": "कभी नहीं", + "oneHour": "1 घंटा", + "oneDay": "24 घंटे", + "sevenDays": "7 दिन", + "thirtyDays": "30 दिन", + "custom": "कस्टम" + } + } } } diff --git a/plugins/session-sharing/locales/translated/hu_HU.json b/plugins/session-sharing/locales/translated/hu_HU.json index a0832e55a..17a9d9c57 100644 --- a/plugins/session-sharing/locales/translated/hu_HU.json +++ b/plugins/session-sharing/locales/translated/hu_HU.json @@ -148,5 +148,17 @@ "description": "Engedélyezi az élő munkamenetek megosztását ezen a gazdagépen linken vagy más felhasználókkal" } } + }, + "hosts": { + "sharing": { + "expiry": { + "never": "Soha", + "oneHour": "1 óra", + "oneDay": "24 óra", + "sevenDays": "7 nap", + "thirtyDays": "30 nap", + "custom": "Szokás" + } + } } } diff --git a/plugins/session-sharing/locales/translated/id_ID.json b/plugins/session-sharing/locales/translated/id_ID.json index 5022c36e8..6a11e5a41 100644 --- a/plugins/session-sharing/locales/translated/id_ID.json +++ b/plugins/session-sharing/locales/translated/id_ID.json @@ -148,5 +148,17 @@ "description": "Izinkan sesi langsung di host ini dibagikan melalui tautan atau dengan pengguna lain." } } + }, + "hosts": { + "sharing": { + "expiry": { + "never": "Tidak pernah", + "oneHour": "1 jam", + "oneDay": "24 jam", + "sevenDays": "7 hari", + "thirtyDays": "30 hari", + "custom": "Kebiasaan" + } + } } } diff --git a/plugins/session-sharing/locales/translated/it_IT.json b/plugins/session-sharing/locales/translated/it_IT.json index 7858aa6c8..c488d957f 100644 --- a/plugins/session-sharing/locales/translated/it_IT.json +++ b/plugins/session-sharing/locales/translated/it_IT.json @@ -148,5 +148,17 @@ "description": "Consenti la condivisione delle sessioni live su questo host tramite link o con altri utenti" } } + }, + "hosts": { + "sharing": { + "expiry": { + "never": "Mai", + "oneHour": "1 ora", + "oneDay": "24 ore", + "sevenDays": "7 giorni", + "thirtyDays": "30 giorni", + "custom": "Personalizzato" + } + } } } diff --git a/plugins/session-sharing/locales/translated/ja_JP.json b/plugins/session-sharing/locales/translated/ja_JP.json index b7630383b..8e4f62b68 100644 --- a/plugins/session-sharing/locales/translated/ja_JP.json +++ b/plugins/session-sharing/locales/translated/ja_JP.json @@ -148,5 +148,17 @@ "description": "このホスト上のライブセッションをリンクまたは他のユーザーと共有できるようにします。" } } + }, + "hosts": { + "sharing": { + "expiry": { + "never": "無期限", + "oneHour": "1時間", + "oneDay": "24時間", + "sevenDays": "7日間", + "thirtyDays": "30日間", + "custom": "カスタム" + } + } } } diff --git a/plugins/session-sharing/locales/translated/ko_KR.json b/plugins/session-sharing/locales/translated/ko_KR.json index 619883609..245699600 100644 --- a/plugins/session-sharing/locales/translated/ko_KR.json +++ b/plugins/session-sharing/locales/translated/ko_KR.json @@ -148,5 +148,17 @@ "description": "이 호스트에서 진행되는 라이브 세션을 링크 또는 다른 사용자와 공유하세요." } } + }, + "hosts": { + "sharing": { + "expiry": { + "never": "안 함", + "oneHour": "1시간", + "oneDay": "24시간", + "sevenDays": "7일", + "thirtyDays": "30일", + "custom": "사용자 지정" + } + } } } diff --git a/plugins/session-sharing/locales/translated/nl_NL.json b/plugins/session-sharing/locales/translated/nl_NL.json index c39027383..443473b39 100644 --- a/plugins/session-sharing/locales/translated/nl_NL.json +++ b/plugins/session-sharing/locales/translated/nl_NL.json @@ -148,5 +148,17 @@ "description": "Sta toe dat live sessies op deze host via een link of met andere gebruikers worden gedeeld." } } + }, + "hosts": { + "sharing": { + "expiry": { + "never": "Nooit", + "oneHour": "1 uur", + "oneDay": "24 uur", + "sevenDays": "7 dagen", + "thirtyDays": "30 dagen", + "custom": "Aangepast" + } + } } } diff --git a/plugins/session-sharing/locales/translated/no_NO.json b/plugins/session-sharing/locales/translated/no_NO.json index b6c23a07e..c41a721b1 100644 --- a/plugins/session-sharing/locales/translated/no_NO.json +++ b/plugins/session-sharing/locales/translated/no_NO.json @@ -148,5 +148,17 @@ "description": "La direktesendte økter på denne verten deles via lenke eller med andre brukere" } } + }, + "hosts": { + "sharing": { + "expiry": { + "never": "Aldri", + "oneHour": "1 time", + "oneDay": "24 timer", + "sevenDays": "7 dager", + "thirtyDays": "30 dager", + "custom": "Skikk" + } + } } } diff --git a/plugins/session-sharing/locales/translated/pl_PL.json b/plugins/session-sharing/locales/translated/pl_PL.json index 479fc5d06..d39b6fab5 100644 --- a/plugins/session-sharing/locales/translated/pl_PL.json +++ b/plugins/session-sharing/locales/translated/pl_PL.json @@ -148,5 +148,17 @@ "description": "Zezwól na udostępnianie sesji na żywo na tym hoście przez link lub innym użytkownikom" } } + }, + "hosts": { + "sharing": { + "expiry": { + "never": "Nigdy", + "oneHour": "1 godzina", + "oneDay": "24 godziny", + "sevenDays": "7 dni", + "thirtyDays": "30 dni", + "custom": "Niestandardowy" + } + } } } diff --git a/plugins/session-sharing/locales/translated/pt_BR.json b/plugins/session-sharing/locales/translated/pt_BR.json index 3c1d56878..847f5dcc6 100644 --- a/plugins/session-sharing/locales/translated/pt_BR.json +++ b/plugins/session-sharing/locales/translated/pt_BR.json @@ -148,5 +148,17 @@ "description": "Permitir que as sessões ao vivo neste servidor sejam compartilhadas por meio de link ou com outros usuários." } } + }, + "hosts": { + "sharing": { + "expiry": { + "never": "Nunca", + "oneHour": "1 hora", + "oneDay": "24 horas", + "sevenDays": "7 dias", + "thirtyDays": "30 dias", + "custom": "Personalizado" + } + } } } diff --git a/plugins/session-sharing/locales/translated/pt_PT.json b/plugins/session-sharing/locales/translated/pt_PT.json index 9258aa6c4..fa4379908 100644 --- a/plugins/session-sharing/locales/translated/pt_PT.json +++ b/plugins/session-sharing/locales/translated/pt_PT.json @@ -148,5 +148,17 @@ "description": "Permitir que as sessões em direto neste servidor sejam partilhadas através de link ou com outros utilizadores." } } + }, + "hosts": { + "sharing": { + "expiry": { + "never": "Nunca", + "oneHour": "1 hora", + "oneDay": "24 horas", + "sevenDays": "7 dias", + "thirtyDays": "30 dias", + "custom": "Personalizado" + } + } } } diff --git a/plugins/session-sharing/locales/translated/ro_RO.json b/plugins/session-sharing/locales/translated/ro_RO.json index 9cc89af1e..e43ccbb5e 100644 --- a/plugins/session-sharing/locales/translated/ro_RO.json +++ b/plugins/session-sharing/locales/translated/ro_RO.json @@ -148,5 +148,17 @@ "description": "Permiteți partajarea sesiunilor live de pe această gazdă prin link sau cu alți utilizatori" } } + }, + "hosts": { + "sharing": { + "expiry": { + "never": "Nu", + "oneHour": "1 oră", + "oneDay": "24 de ore", + "sevenDays": "7 zile", + "thirtyDays": "30 de zile", + "custom": "Personalizat" + } + } } } diff --git a/plugins/session-sharing/locales/translated/ru_RU.json b/plugins/session-sharing/locales/translated/ru_RU.json index b42df8796..3114282fa 100644 --- a/plugins/session-sharing/locales/translated/ru_RU.json +++ b/plugins/session-sharing/locales/translated/ru_RU.json @@ -148,5 +148,17 @@ "description": "Разрешите делиться записями онлайн-сессий на этом хостинге по ссылке или с другими пользователями." } } + }, + "hosts": { + "sharing": { + "expiry": { + "never": "Никогда", + "oneHour": "1 час", + "oneDay": "24 часа", + "sevenDays": "7 дней", + "thirtyDays": "30 дней", + "custom": "Настроить" + } + } } } diff --git a/plugins/session-sharing/locales/translated/sr_SP.json b/plugins/session-sharing/locales/translated/sr_SP.json index c5cfe9ad8..07dd86365 100644 --- a/plugins/session-sharing/locales/translated/sr_SP.json +++ b/plugins/session-sharing/locales/translated/sr_SP.json @@ -148,5 +148,17 @@ "description": "Дозволите дељење сесија уживо на овом хосту путем линка или са другим корисницима" } } + }, + "hosts": { + "sharing": { + "expiry": { + "never": "Никад", + "oneHour": "1 сат", + "oneDay": "24 сата", + "sevenDays": "7 дана", + "thirtyDays": "30 дана", + "custom": "Прилагођено" + } + } } } diff --git a/plugins/session-sharing/locales/translated/sv_SE.json b/plugins/session-sharing/locales/translated/sv_SE.json index 9eb3e364d..6e581b86c 100644 --- a/plugins/session-sharing/locales/translated/sv_SE.json +++ b/plugins/session-sharing/locales/translated/sv_SE.json @@ -148,5 +148,17 @@ "description": "Tillåt att livesessioner på den här värden delas via länk eller med andra användare" } } + }, + "hosts": { + "sharing": { + "expiry": { + "never": "Aldrig", + "oneHour": "1 timme", + "oneDay": "24 timmar", + "sevenDays": "7 dagar", + "thirtyDays": "30 dagar", + "custom": "Beställnings" + } + } } } diff --git a/plugins/session-sharing/locales/translated/th_TH.json b/plugins/session-sharing/locales/translated/th_TH.json index 776790ff8..4b056154c 100644 --- a/plugins/session-sharing/locales/translated/th_TH.json +++ b/plugins/session-sharing/locales/translated/th_TH.json @@ -148,5 +148,17 @@ "description": "อนุญาตให้แชร์เซสชันสดบนโฮสต์นี้ผ่านลิงก์หรือกับผู้ใช้รายอื่น" } } + }, + "hosts": { + "sharing": { + "expiry": { + "never": "ไม่เคย", + "oneHour": "1 ชั่วโมง", + "oneDay": "24 ชั่วโมง", + "sevenDays": "7 วัน", + "thirtyDays": "30 วัน", + "custom": "กำหนดเอง" + } + } } } diff --git a/plugins/session-sharing/locales/translated/tr_TR.json b/plugins/session-sharing/locales/translated/tr_TR.json index f77953bbd..d1380a435 100644 --- a/plugins/session-sharing/locales/translated/tr_TR.json +++ b/plugins/session-sharing/locales/translated/tr_TR.json @@ -148,5 +148,17 @@ "description": "Bu sunucudaki canlı oturumların bağlantı yoluyla veya diğer kullanıcılarla paylaşılmasına izin verin." } } + }, + "hosts": { + "sharing": { + "expiry": { + "never": "Süresiz", + "oneHour": "1 saat", + "oneDay": "24 saat", + "sevenDays": "7 gün", + "thirtyDays": "30 gün", + "custom": "Özel" + } + } } } diff --git a/plugins/session-sharing/locales/translated/uk_UA.json b/plugins/session-sharing/locales/translated/uk_UA.json index 0a3d4358d..f249f7847 100644 --- a/plugins/session-sharing/locales/translated/uk_UA.json +++ b/plugins/session-sharing/locales/translated/uk_UA.json @@ -148,5 +148,17 @@ "description": "Дозволити ділитися прямими трансляціями на цьому хості через посилання або з іншими користувачами" } } + }, + "hosts": { + "sharing": { + "expiry": { + "never": "Ніколи", + "oneHour": "1 година", + "oneDay": "24 години", + "sevenDays": "7 днів", + "thirtyDays": "30 днів", + "custom": "Користувацька" + } + } } } diff --git a/plugins/session-sharing/locales/translated/vi_VN.json b/plugins/session-sharing/locales/translated/vi_VN.json index 024b2f571..7655c4e23 100644 --- a/plugins/session-sharing/locales/translated/vi_VN.json +++ b/plugins/session-sharing/locales/translated/vi_VN.json @@ -148,5 +148,17 @@ "description": "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." } } + }, + "hosts": { + "sharing": { + "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" + } + } } } diff --git a/plugins/session-sharing/locales/translated/zh_CN.json b/plugins/session-sharing/locales/translated/zh_CN.json index 84f9bec59..98cf71239 100644 --- a/plugins/session-sharing/locales/translated/zh_CN.json +++ b/plugins/session-sharing/locales/translated/zh_CN.json @@ -148,5 +148,17 @@ "description": "允许通过链接或其他方式共享此主机上的实时会话。" } } + }, + "hosts": { + "sharing": { + "expiry": { + "never": "永不过期", + "oneHour": "1 小时", + "oneDay": "24 小时", + "sevenDays": "7 天", + "thirtyDays": "30 天", + "custom": "自定义" + } + } } } diff --git a/plugins/session-sharing/locales/translated/zh_TW.json b/plugins/session-sharing/locales/translated/zh_TW.json index 03a23b6a6..36fa4161c 100644 --- a/plugins/session-sharing/locales/translated/zh_TW.json +++ b/plugins/session-sharing/locales/translated/zh_TW.json @@ -148,5 +148,17 @@ "description": "允許透過連結或其他方式分享此主機上的即時會話。" } } + }, + "hosts": { + "sharing": { + "expiry": { + "never": "永不", + "oneHour": "1 小時", + "oneDay": "24 小時", + "sevenDays": "7 天", + "thirtyDays": "30 天", + "custom": "自訂" + } + } } } diff --git a/plugins/ssh-terminal/locales/en.json b/plugins/ssh-terminal/locales/en.json index 816b3b7b2..1130f99aa 100644 --- a/plugins/ssh-terminal/locales/en.json +++ b/plugins/ssh-terminal/locales/en.json @@ -668,5 +668,8 @@ }, "seconds": "seconds", "secondsShort": "{{count}}s" + }, + "errors": { + "remoteServerRequired": "Remote server required. Connect a remote server in Settings to use this connection type." } } diff --git a/plugins/ssh-terminal/locales/translated/af_ZA.json b/plugins/ssh-terminal/locales/translated/af_ZA.json index 2530ce4c1..441b1e710 100644 --- a/plugins/ssh-terminal/locales/translated/af_ZA.json +++ b/plugins/ssh-terminal/locales/translated/af_ZA.json @@ -470,5 +470,8 @@ }, "seconds": "sekondes", "secondsShort": "{{count}}s" + }, + "errors": { + "remoteServerRequired": "Afstandbediener word benodig. Koppel 'n afstandbediener in Instellings om hierdie verbindingstipe te gebruik." } } diff --git a/plugins/ssh-terminal/locales/translated/ar_SA.json b/plugins/ssh-terminal/locales/translated/ar_SA.json index 33fb6bc1c..3444fc0ce 100644 --- a/plugins/ssh-terminal/locales/translated/ar_SA.json +++ b/plugins/ssh-terminal/locales/translated/ar_SA.json @@ -470,5 +470,8 @@ }, "seconds": "ثوانٍ", "secondsShort": "{{count}}s" + }, + "errors": { + "remoteServerRequired": "يلزم وجود خادم بعيد. قم بتوصيل خادم بعيد في الإعدادات لاستخدام نوع الاتصال هذا." } } diff --git a/plugins/ssh-terminal/locales/translated/bg_BG.json b/plugins/ssh-terminal/locales/translated/bg_BG.json index 5f367021d..90748d62c 100644 --- a/plugins/ssh-terminal/locales/translated/bg_BG.json +++ b/plugins/ssh-terminal/locales/translated/bg_BG.json @@ -470,5 +470,8 @@ }, "seconds": "секунди", "secondsShort": "{{count}}с" + }, + "errors": { + "remoteServerRequired": "Изисква се отдалечен сървър. Свържете се с отдалечен сървър в „Настройки“, за да използвате този тип връзка." } } diff --git a/plugins/ssh-terminal/locales/translated/bn_BD.json b/plugins/ssh-terminal/locales/translated/bn_BD.json index 7417ec0f1..967a366ef 100644 --- a/plugins/ssh-terminal/locales/translated/bn_BD.json +++ b/plugins/ssh-terminal/locales/translated/bn_BD.json @@ -470,5 +470,8 @@ }, "seconds": "সেকেন্ড", "secondsShort": "{{count}}s" + }, + "errors": { + "remoteServerRequired": "রিমোট সার্ভার প্রয়োজন। এই সংযোগের ধরণটি ব্যবহার করতে সেটিংস-এ একটি রিমোট সার্ভার সংযুক্ত করুন।" } } diff --git a/plugins/ssh-terminal/locales/translated/ca_ES.json b/plugins/ssh-terminal/locales/translated/ca_ES.json index 5967cd855..d70d69b0d 100644 --- a/plugins/ssh-terminal/locales/translated/ca_ES.json +++ b/plugins/ssh-terminal/locales/translated/ca_ES.json @@ -470,5 +470,8 @@ }, "seconds": "segons", "secondsShort": "{{count}}s" + }, + "errors": { + "remoteServerRequired": "Cal un servidor remot. Connecteu un servidor remot a Configuració per utilitzar aquest tipus de connexió." } } diff --git a/plugins/ssh-terminal/locales/translated/cs_CZ.json b/plugins/ssh-terminal/locales/translated/cs_CZ.json index 86d0728b1..b9f21e1bd 100644 --- a/plugins/ssh-terminal/locales/translated/cs_CZ.json +++ b/plugins/ssh-terminal/locales/translated/cs_CZ.json @@ -470,5 +470,8 @@ }, "seconds": "sekundy", "secondsShort": "{{count}}s" + }, + "errors": { + "remoteServerRequired": "Je vyžadován vzdálený server. Pro použití tohoto typu připojení se připojte ke vzdálenému serveru v Nastavení." } } diff --git a/plugins/ssh-terminal/locales/translated/da_DK.json b/plugins/ssh-terminal/locales/translated/da_DK.json index c64990186..d8ad39acb 100644 --- a/plugins/ssh-terminal/locales/translated/da_DK.json +++ b/plugins/ssh-terminal/locales/translated/da_DK.json @@ -470,5 +470,8 @@ }, "seconds": "sekunder", "secondsShort": "{{count}}s" + }, + "errors": { + "remoteServerRequired": "Fjernserver kræves. Opret forbindelse til en fjernserver i Indstillinger for at bruge denne forbindelsestype." } } diff --git a/plugins/ssh-terminal/locales/translated/de_DE.json b/plugins/ssh-terminal/locales/translated/de_DE.json index c33d9c3c7..b95c8fcaa 100644 --- a/plugins/ssh-terminal/locales/translated/de_DE.json +++ b/plugins/ssh-terminal/locales/translated/de_DE.json @@ -470,5 +470,8 @@ }, "seconds": "Sekunden", "secondsShort": "{{count}}s" + }, + "errors": { + "remoteServerRequired": "Remote-Server erforderlich. Um diesen Verbindungstyp zu verwenden, verbinden Sie einen Remote-Server in den Einstellungen." } } diff --git a/plugins/ssh-terminal/locales/translated/el_GR.json b/plugins/ssh-terminal/locales/translated/el_GR.json index f277f94ad..39ec4d0e9 100644 --- a/plugins/ssh-terminal/locales/translated/el_GR.json +++ b/plugins/ssh-terminal/locales/translated/el_GR.json @@ -470,5 +470,8 @@ }, "seconds": "δευτερόλεπτα", "secondsShort": "{{count}}s" + }, + "errors": { + "remoteServerRequired": "Απαιτείται απομακρυσμένος διακομιστής. Συνδέστε έναν απομακρυσμένο διακομιστή στις Ρυθμίσεις για να χρησιμοποιήσετε αυτόν τον τύπο σύνδεσης." } } diff --git a/plugins/ssh-terminal/locales/translated/es_ES.json b/plugins/ssh-terminal/locales/translated/es_ES.json index 714f4b69c..8951550d6 100644 --- a/plugins/ssh-terminal/locales/translated/es_ES.json +++ b/plugins/ssh-terminal/locales/translated/es_ES.json @@ -470,5 +470,8 @@ }, "seconds": "artículos de segunda clase", "secondsShort": "{{count}}s" + }, + "errors": { + "remoteServerRequired": "Se requiere un servidor remoto. Conecte un servidor remoto en Configuración para usar este tipo de conexión." } } diff --git a/plugins/ssh-terminal/locales/translated/fi_FI.json b/plugins/ssh-terminal/locales/translated/fi_FI.json index e104fd4b4..d2d1c1b42 100644 --- a/plugins/ssh-terminal/locales/translated/fi_FI.json +++ b/plugins/ssh-terminal/locales/translated/fi_FI.json @@ -470,5 +470,8 @@ }, "seconds": "sekuntia", "secondsShort": "{{count}}s" + }, + "errors": { + "remoteServerRequired": "Etäpalvelin vaaditaan. Yhdistä etäpalvelin asetuksissa käyttääksesi tätä yhteystyyppiä." } } diff --git a/plugins/ssh-terminal/locales/translated/fr_FR.json b/plugins/ssh-terminal/locales/translated/fr_FR.json index 316a3b3e5..0a1ef1943 100644 --- a/plugins/ssh-terminal/locales/translated/fr_FR.json +++ b/plugins/ssh-terminal/locales/translated/fr_FR.json @@ -470,5 +470,8 @@ }, "seconds": "secondes", "secondsShort": "{{count}}s" + }, + "errors": { + "remoteServerRequired": "Serveur distant requis. Connectez un serveur distant dans les paramètres pour utiliser ce type de connexion." } } diff --git a/plugins/ssh-terminal/locales/translated/he_IL.json b/plugins/ssh-terminal/locales/translated/he_IL.json index 02aa4b14f..df4e28e6e 100644 --- a/plugins/ssh-terminal/locales/translated/he_IL.json +++ b/plugins/ssh-terminal/locales/translated/he_IL.json @@ -470,5 +470,8 @@ }, "seconds": "שניות", "secondsShort": "{{count}}ים" + }, + "errors": { + "remoteServerRequired": "נדרש שרת מרוחק. יש להתחבר לשרת מרוחק בהגדרות כדי להשתמש בסוג חיבור זה." } } diff --git a/plugins/ssh-terminal/locales/translated/hi_IN.json b/plugins/ssh-terminal/locales/translated/hi_IN.json index a5054561c..aba6a6b9b 100644 --- a/plugins/ssh-terminal/locales/translated/hi_IN.json +++ b/plugins/ssh-terminal/locales/translated/hi_IN.json @@ -470,5 +470,8 @@ }, "seconds": "सेकंड", "secondsShort": "{{count}}s" + }, + "errors": { + "remoteServerRequired": "रिमोट सर्वर आवश्यक है। इस कनेक्शन प्रकार का उपयोग करने के लिए सेटिंग्स में जाकर रिमोट सर्वर कनेक्ट करें।" } } diff --git a/plugins/ssh-terminal/locales/translated/hu_HU.json b/plugins/ssh-terminal/locales/translated/hu_HU.json index f4787cdef..7588fc2c1 100644 --- a/plugins/ssh-terminal/locales/translated/hu_HU.json +++ b/plugins/ssh-terminal/locales/translated/hu_HU.json @@ -470,5 +470,8 @@ }, "seconds": "másodperc", "secondsShort": "{{count}}s" + }, + "errors": { + "remoteServerRequired": "Távoli szerver szükséges. Csatlakoztasson egy távoli szervert a Beállításokban a kapcsolattípus használatához." } } diff --git a/plugins/ssh-terminal/locales/translated/id_ID.json b/plugins/ssh-terminal/locales/translated/id_ID.json index bba785c0d..26c1886fe 100644 --- a/plugins/ssh-terminal/locales/translated/id_ID.json +++ b/plugins/ssh-terminal/locales/translated/id_ID.json @@ -470,5 +470,8 @@ }, "seconds": "detik", "secondsShort": "{{count}}s" + }, + "errors": { + "remoteServerRequired": "Diperlukan server jarak jauh. Hubungkan server jarak jauh di Pengaturan untuk menggunakan jenis koneksi ini." } } diff --git a/plugins/ssh-terminal/locales/translated/it_IT.json b/plugins/ssh-terminal/locales/translated/it_IT.json index 09bb8c4f7..fcde03269 100644 --- a/plugins/ssh-terminal/locales/translated/it_IT.json +++ b/plugins/ssh-terminal/locales/translated/it_IT.json @@ -470,5 +470,8 @@ }, "seconds": "secondi", "secondsShort": "{{count}}s" + }, + "errors": { + "remoteServerRequired": "È necessario un server remoto. Per utilizzare questo tipo di connessione, collega un server remoto nelle Impostazioni." } } diff --git a/plugins/ssh-terminal/locales/translated/ja_JP.json b/plugins/ssh-terminal/locales/translated/ja_JP.json index 227500592..7010bb45b 100644 --- a/plugins/ssh-terminal/locales/translated/ja_JP.json +++ b/plugins/ssh-terminal/locales/translated/ja_JP.json @@ -470,5 +470,8 @@ }, "seconds": "秒", "secondsShort": "{{count}}s" + }, + "errors": { + "remoteServerRequired": "リモートサーバーが必要です。この接続タイプを使用するには、設定でリモートサーバーを接続してください。" } } diff --git a/plugins/ssh-terminal/locales/translated/ko_KR.json b/plugins/ssh-terminal/locales/translated/ko_KR.json index 480f52609..b55130114 100644 --- a/plugins/ssh-terminal/locales/translated/ko_KR.json +++ b/plugins/ssh-terminal/locales/translated/ko_KR.json @@ -470,5 +470,8 @@ }, "seconds": "초", "secondsShort": "{{count}}s" + }, + "errors": { + "remoteServerRequired": "원격 서버가 필요합니다. 이 연결 유형을 사용하려면 설정에서 원격 서버를 연결하세요." } } diff --git a/plugins/ssh-terminal/locales/translated/nl_NL.json b/plugins/ssh-terminal/locales/translated/nl_NL.json index b83d0c1bf..e53fe44cf 100644 --- a/plugins/ssh-terminal/locales/translated/nl_NL.json +++ b/plugins/ssh-terminal/locales/translated/nl_NL.json @@ -470,5 +470,8 @@ }, "seconds": "seconden", "secondsShort": "{{count}}s" + }, + "errors": { + "remoteServerRequired": "Externe server vereist. Verbind een externe server in de instellingen om dit verbindingstype te gebruiken." } } diff --git a/plugins/ssh-terminal/locales/translated/no_NO.json b/plugins/ssh-terminal/locales/translated/no_NO.json index 0d5baf002..44318b120 100644 --- a/plugins/ssh-terminal/locales/translated/no_NO.json +++ b/plugins/ssh-terminal/locales/translated/no_NO.json @@ -470,5 +470,8 @@ }, "seconds": "sekunder", "secondsShort": "{{count}}s" + }, + "errors": { + "remoteServerRequired": "Ekstern server kreves. Koble til en ekstern server i Innstillinger for å bruke denne tilkoblingstypen." } } diff --git a/plugins/ssh-terminal/locales/translated/pl_PL.json b/plugins/ssh-terminal/locales/translated/pl_PL.json index e2637385d..91750c547 100644 --- a/plugins/ssh-terminal/locales/translated/pl_PL.json +++ b/plugins/ssh-terminal/locales/translated/pl_PL.json @@ -470,5 +470,8 @@ }, "seconds": "sekundy", "secondsShort": "{{count}}s" + }, + "errors": { + "remoteServerRequired": "Wymagany jest serwer zdalny. Połącz się z serwerem zdalnym w Ustawieniach, aby korzystać z tego typu połączenia." } } diff --git a/plugins/ssh-terminal/locales/translated/pt_BR.json b/plugins/ssh-terminal/locales/translated/pt_BR.json index 6f090bbd9..6943c129c 100644 --- a/plugins/ssh-terminal/locales/translated/pt_BR.json +++ b/plugins/ssh-terminal/locales/translated/pt_BR.json @@ -470,5 +470,8 @@ }, "seconds": "segundos", "secondsShort": "{{count}}s" + }, + "errors": { + "remoteServerRequired": "É necessário um servidor remoto. Conecte um servidor remoto nas Configurações para usar este tipo de conexão." } } diff --git a/plugins/ssh-terminal/locales/translated/pt_PT.json b/plugins/ssh-terminal/locales/translated/pt_PT.json index 2272d97fe..3d3c9a9d6 100644 --- a/plugins/ssh-terminal/locales/translated/pt_PT.json +++ b/plugins/ssh-terminal/locales/translated/pt_PT.json @@ -470,5 +470,8 @@ }, "seconds": "segundos", "secondsShort": "{{count}}s" + }, + "errors": { + "remoteServerRequired": "É necessário um servidor remoto. Ligue um servidor remoto nas Definições para utilizar este tipo de ligação." } } diff --git a/plugins/ssh-terminal/locales/translated/ro_RO.json b/plugins/ssh-terminal/locales/translated/ro_RO.json index 8033eed19..4f272d533 100644 --- a/plugins/ssh-terminal/locales/translated/ro_RO.json +++ b/plugins/ssh-terminal/locales/translated/ro_RO.json @@ -470,5 +470,8 @@ }, "seconds": "secunde", "secondsShort": "{{count}}s" + }, + "errors": { + "remoteServerRequired": "Este necesar un server la distanță. Conectați un server la distanță în Setări pentru a utiliza acest tip de conexiune." } } diff --git a/plugins/ssh-terminal/locales/translated/ru_RU.json b/plugins/ssh-terminal/locales/translated/ru_RU.json index 052eb34fd..4cec39680 100644 --- a/plugins/ssh-terminal/locales/translated/ru_RU.json +++ b/plugins/ssh-terminal/locales/translated/ru_RU.json @@ -470,5 +470,8 @@ }, "seconds": "секунд", "secondsShort": "{{count}}с" + }, + "errors": { + "remoteServerRequired": "Требуется удаленный сервер. Для использования этого типа подключения подключите удаленный сервер в настройках." } } diff --git a/plugins/ssh-terminal/locales/translated/sr_SP.json b/plugins/ssh-terminal/locales/translated/sr_SP.json index 4bd320e6b..f6556238f 100644 --- a/plugins/ssh-terminal/locales/translated/sr_SP.json +++ b/plugins/ssh-terminal/locales/translated/sr_SP.json @@ -470,5 +470,8 @@ }, "seconds": "секунде", "secondsShort": "{{count}}с" + }, + "errors": { + "remoteServerRequired": "Потребан је удаљени сервер. Повежите се са удаљеним сервером у Подешавањима да бисте користили овај тип везе." } } diff --git a/plugins/ssh-terminal/locales/translated/sv_SE.json b/plugins/ssh-terminal/locales/translated/sv_SE.json index b43e55ac7..9010a28cc 100644 --- a/plugins/ssh-terminal/locales/translated/sv_SE.json +++ b/plugins/ssh-terminal/locales/translated/sv_SE.json @@ -470,5 +470,8 @@ }, "seconds": "sekunder", "secondsShort": "{{count}}s" + }, + "errors": { + "remoteServerRequired": "Fjärrserver krävs. Anslut en fjärrserver i Inställningar för att använda den här anslutningstypen." } } diff --git a/plugins/ssh-terminal/locales/translated/th_TH.json b/plugins/ssh-terminal/locales/translated/th_TH.json index 0c7f44f81..7ce39c75f 100644 --- a/plugins/ssh-terminal/locales/translated/th_TH.json +++ b/plugins/ssh-terminal/locales/translated/th_TH.json @@ -470,5 +470,8 @@ }, "seconds": "วินาที", "secondsShort": "{{count}}s" + }, + "errors": { + "remoteServerRequired": "จำเป็นต้องใช้เซิร์ฟเวอร์ระยะไกล เชื่อมต่อเซิร์ฟเวอร์ระยะไกลในการตั้งค่าเพื่อใช้ประเภทการเชื่อมต่อนี้" } } diff --git a/plugins/ssh-terminal/locales/translated/tr_TR.json b/plugins/ssh-terminal/locales/translated/tr_TR.json index df200a3fa..ff3906158 100644 --- a/plugins/ssh-terminal/locales/translated/tr_TR.json +++ b/plugins/ssh-terminal/locales/translated/tr_TR.json @@ -470,5 +470,8 @@ }, "seconds": "saniyeler", "secondsShort": "{{count}}s" + }, + "errors": { + "remoteServerRequired": "Uzak sunucu gereklidir. Bu bağlantı türünü kullanmak için Ayarlar'dan bir uzak sunucu bağlayın." } } diff --git a/plugins/ssh-terminal/locales/translated/uk_UA.json b/plugins/ssh-terminal/locales/translated/uk_UA.json index a827e523b..ea34b8ece 100644 --- a/plugins/ssh-terminal/locales/translated/uk_UA.json +++ b/plugins/ssh-terminal/locales/translated/uk_UA.json @@ -470,5 +470,8 @@ }, "seconds": "секунди", "secondsShort": "{{count}}с" + }, + "errors": { + "remoteServerRequired": "Потрібен віддалений сервер. Підключіться до віддаленого сервера в налаштуваннях, щоб використовувати цей тип підключення." } } diff --git a/plugins/ssh-terminal/locales/translated/vi_VN.json b/plugins/ssh-terminal/locales/translated/vi_VN.json index 6ee7139c4..f2a941b49 100644 --- a/plugins/ssh-terminal/locales/translated/vi_VN.json +++ b/plugins/ssh-terminal/locales/translated/vi_VN.json @@ -470,5 +470,8 @@ }, "seconds": "giây", "secondsShort": "{{count}}s" + }, + "errors": { + "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." } } diff --git a/plugins/ssh-terminal/locales/translated/zh_CN.json b/plugins/ssh-terminal/locales/translated/zh_CN.json index 7a25aefab..1958320f3 100644 --- a/plugins/ssh-terminal/locales/translated/zh_CN.json +++ b/plugins/ssh-terminal/locales/translated/zh_CN.json @@ -470,5 +470,8 @@ }, "seconds": "秒", "secondsShort": "{{count}}s" + }, + "errors": { + "remoteServerRequired": "需要远程服务器。请在“设置”中连接远程服务器以使用此连接类型。" } } diff --git a/plugins/ssh-terminal/locales/translated/zh_TW.json b/plugins/ssh-terminal/locales/translated/zh_TW.json index f3c8af95a..123d64b39 100644 --- a/plugins/ssh-terminal/locales/translated/zh_TW.json +++ b/plugins/ssh-terminal/locales/translated/zh_TW.json @@ -470,5 +470,8 @@ }, "seconds": "秒", "secondsShort": "{{count}}s" + }, + "errors": { + "remoteServerRequired": "需要遠端伺服器。請在「設定」中連接遠端伺服器以使用此連線類型。" } } diff --git a/plugins/tailscale/locales/en.json b/plugins/tailscale/locales/en.json index ab9ae0ae0..706848e1c 100644 --- a/plugins/tailscale/locales/en.json +++ b/plugins/tailscale/locales/en.json @@ -46,7 +46,8 @@ "tailscaleAddHost": "Add host", "tailscaleCopyIp": "Copy Tailscale IP", "tailscaleIpCopied": "IP copied", - "tailscaleIpCopyFailed": "Could not copy the IP" + "tailscaleIpCopyFailed": "Could not copy the IP", + "filterAuthTailscale": "Tailscale" }, "terminal": { "tailscaleCheckRequired": "Tailscale Authentication Required", @@ -73,5 +74,13 @@ "tsDisabled": "Tailscale disconnected", "tsExitNode": "Exit node", "tsExitNodeActive": "Exit node active" + }, + "newUi": { + "sidebar": { + "quickConnect": { + "connectToTerminal": "Connect to Terminal", + "usernameLabel": "Username" + } + } } } diff --git a/plugins/tailscale/locales/translated/af_ZA.json b/plugins/tailscale/locales/translated/af_ZA.json index ec17d3c6d..b1377eed6 100644 --- a/plugins/tailscale/locales/translated/af_ZA.json +++ b/plugins/tailscale/locales/translated/af_ZA.json @@ -16,5 +16,13 @@ "tailscaleCheckOpenBrowser": "Maak blaaier oop om te verifieer", "tailscaleCheckWaiting": "Wag vir Tailscale-verifikasie...", "tailscaleCheckTimeout": "Tailscale-verifikasie het verstryk. Probeer asseblief weer." + }, + "newUi": { + "sidebar": { + "quickConnect": { + "connectToTerminal": "Koppel aan terminaal", + "usernameLabel": "Gebruikersnaam" + } + } } } diff --git a/plugins/tailscale/locales/translated/ar_SA.json b/plugins/tailscale/locales/translated/ar_SA.json index de8fd7557..f0325f90e 100644 --- a/plugins/tailscale/locales/translated/ar_SA.json +++ b/plugins/tailscale/locales/translated/ar_SA.json @@ -16,5 +16,13 @@ "tailscaleCheckOpenBrowser": "افتح المتصفح للمصادقة", "tailscaleCheckWaiting": "في انتظار مصادقة Tailscale...", "tailscaleCheckTimeout": "انتهت مهلة مصادقة Tailscale. يرجى المحاولة مرة أخرى." + }, + "newUi": { + "sidebar": { + "quickConnect": { + "connectToTerminal": "اتصل بالطرفية", + "usernameLabel": "اسم المستخدم" + } + } } } diff --git a/plugins/tailscale/locales/translated/bg_BG.json b/plugins/tailscale/locales/translated/bg_BG.json index b17437676..3b01344f8 100644 --- a/plugins/tailscale/locales/translated/bg_BG.json +++ b/plugins/tailscale/locales/translated/bg_BG.json @@ -16,5 +16,13 @@ "tailscaleCheckOpenBrowser": "Отворете браузъра за удостоверяване", "tailscaleCheckWaiting": "Чака се удостоверяване на Tailscale...", "tailscaleCheckTimeout": "Времето за изчакване на удостоверяването на Tailscale изтече. Моля, опитайте отново." + }, + "newUi": { + "sidebar": { + "quickConnect": { + "connectToTerminal": "Свързване с терминала", + "usernameLabel": "Потребителско име" + } + } } } diff --git a/plugins/tailscale/locales/translated/bn_BD.json b/plugins/tailscale/locales/translated/bn_BD.json index 9596a17bd..f9484ded2 100644 --- a/plugins/tailscale/locales/translated/bn_BD.json +++ b/plugins/tailscale/locales/translated/bn_BD.json @@ -16,5 +16,13 @@ "tailscaleCheckOpenBrowser": "প্রমাণীকরণের জন্য ব্রাউজার খুলুন", "tailscaleCheckWaiting": "টেইলস্কেল প্রমাণীকরণের জন্য অপেক্ষা করা হচ্ছে...", "tailscaleCheckTimeout": "টেইলস্কেল প্রমাণীকরণের সময়সীমা শেষ হয়ে গেছে। অনুগ্রহ করে আবার চেষ্টা করুন।" + }, + "newUi": { + "sidebar": { + "quickConnect": { + "connectToTerminal": "টার্মিনালের সাথে সংযোগ করুন", + "usernameLabel": "ব্যবহারকারীর নাম" + } + } } } diff --git a/plugins/tailscale/locales/translated/ca_ES.json b/plugins/tailscale/locales/translated/ca_ES.json index 8563a940e..b1561f23c 100644 --- a/plugins/tailscale/locales/translated/ca_ES.json +++ b/plugins/tailscale/locales/translated/ca_ES.json @@ -16,5 +16,13 @@ "tailscaleCheckOpenBrowser": "Obre el navegador per autenticar-te", "tailscaleCheckWaiting": "Esperant l'autenticació de Tailscale...", "tailscaleCheckTimeout": "S'ha esgotat el temps d'espera de l'autenticació a escala final. Torna-ho a provar." + }, + "newUi": { + "sidebar": { + "quickConnect": { + "connectToTerminal": "Connecta't al terminal", + "usernameLabel": "Nom d'usuari" + } + } } } diff --git a/plugins/tailscale/locales/translated/cs_CZ.json b/plugins/tailscale/locales/translated/cs_CZ.json index 645e7487a..f44435717 100644 --- a/plugins/tailscale/locales/translated/cs_CZ.json +++ b/plugins/tailscale/locales/translated/cs_CZ.json @@ -16,5 +16,13 @@ "tailscaleCheckOpenBrowser": "Otevřít prohlížeč pro ověření", "tailscaleCheckWaiting": "Čekání na ověření Tailscale...", "tailscaleCheckTimeout": "Časový limit pro ověřování Tailscale vypršel. Zkuste to prosím znovu." + }, + "newUi": { + "sidebar": { + "quickConnect": { + "connectToTerminal": "Připojení k terminálu", + "usernameLabel": "Uživatelské jméno" + } + } } } diff --git a/plugins/tailscale/locales/translated/da_DK.json b/plugins/tailscale/locales/translated/da_DK.json index 23000ca9b..f156ddc4d 100644 --- a/plugins/tailscale/locales/translated/da_DK.json +++ b/plugins/tailscale/locales/translated/da_DK.json @@ -16,5 +16,13 @@ "tailscaleCheckOpenBrowser": "Åbn browseren for at godkende", "tailscaleCheckWaiting": "Venter på Tailscale-godkendelse...", "tailscaleCheckTimeout": "Tailscale-godkendelsen er udløbet. Prøv igen." + }, + "newUi": { + "sidebar": { + "quickConnect": { + "connectToTerminal": "Opret forbindelse til terminalen", + "usernameLabel": "Brugernavn" + } + } } } diff --git a/plugins/tailscale/locales/translated/de_DE.json b/plugins/tailscale/locales/translated/de_DE.json index ba33133ea..47dc2b7a7 100644 --- a/plugins/tailscale/locales/translated/de_DE.json +++ b/plugins/tailscale/locales/translated/de_DE.json @@ -16,5 +16,13 @@ "tailscaleCheckOpenBrowser": "Öffnen Sie den Browser zur Authentifizierung", "tailscaleCheckWaiting": "Warten auf Tailscale-Authentifizierung...", "tailscaleCheckTimeout": "Die Tailscale-Authentifizierung ist fehlgeschlagen. Bitte versuchen Sie es erneut." + }, + "newUi": { + "sidebar": { + "quickConnect": { + "connectToTerminal": "Mit Terminal verbinden", + "usernameLabel": "Benutzername" + } + } } } diff --git a/plugins/tailscale/locales/translated/el_GR.json b/plugins/tailscale/locales/translated/el_GR.json index e313c5040..0ce781133 100644 --- a/plugins/tailscale/locales/translated/el_GR.json +++ b/plugins/tailscale/locales/translated/el_GR.json @@ -16,5 +16,13 @@ "tailscaleCheckOpenBrowser": "Άνοιγμα προγράμματος περιήγησης για έλεγχο ταυτότητας", "tailscaleCheckWaiting": "Αναμονή για έλεγχο ταυτότητας Tailscale...", "tailscaleCheckTimeout": "Το χρονικό όριο ελέγχου ταυτότητας κλίμακας έληξε. Δοκιμάστε ξανά." + }, + "newUi": { + "sidebar": { + "quickConnect": { + "connectToTerminal": "Σύνδεση με τερματικό", + "usernameLabel": "Όνομα χρήστη" + } + } } } diff --git a/plugins/tailscale/locales/translated/es_ES.json b/plugins/tailscale/locales/translated/es_ES.json index 71cb90cbb..08c5584e3 100644 --- a/plugins/tailscale/locales/translated/es_ES.json +++ b/plugins/tailscale/locales/translated/es_ES.json @@ -16,5 +16,13 @@ "tailscaleCheckOpenBrowser": "Abra el navegador para autenticarse.", "tailscaleCheckWaiting": "Esperando la autenticación de Tailscale...", "tailscaleCheckTimeout": "La autenticación de Tailscale ha caducado. Inténtalo de nuevo." + }, + "newUi": { + "sidebar": { + "quickConnect": { + "connectToTerminal": "Conectar a Terminal", + "usernameLabel": "Nombre de usuario" + } + } } } diff --git a/plugins/tailscale/locales/translated/fi_FI.json b/plugins/tailscale/locales/translated/fi_FI.json index ca8566346..148cee615 100644 --- a/plugins/tailscale/locales/translated/fi_FI.json +++ b/plugins/tailscale/locales/translated/fi_FI.json @@ -16,5 +16,13 @@ "tailscaleCheckOpenBrowser": "Avaa selain todennusta varten", "tailscaleCheckWaiting": "Odotetaan Tailscale-todennusta...", "tailscaleCheckTimeout": "Tailscale-todennus aikakatkaistiin. Yritä uudelleen." + }, + "newUi": { + "sidebar": { + "quickConnect": { + "connectToTerminal": "Yhdistä terminaaliin", + "usernameLabel": "Käyttäjätunnus" + } + } } } diff --git a/plugins/tailscale/locales/translated/fr_FR.json b/plugins/tailscale/locales/translated/fr_FR.json index f254b15ff..d10c257bf 100644 --- a/plugins/tailscale/locales/translated/fr_FR.json +++ b/plugins/tailscale/locales/translated/fr_FR.json @@ -16,5 +16,13 @@ "tailscaleCheckOpenBrowser": "Ouvrez votre navigateur pour vous authentifier.", "tailscaleCheckWaiting": "En attente de l'authentification Tailscale...", "tailscaleCheckTimeout": "L'authentification Tailscale a expiré. Veuillez réessayer." + }, + "newUi": { + "sidebar": { + "quickConnect": { + "connectToTerminal": "Se connecter au terminal", + "usernameLabel": "Nom d’utilisateur" + } + } } } diff --git a/plugins/tailscale/locales/translated/he_IL.json b/plugins/tailscale/locales/translated/he_IL.json index ec11ffd09..72fd4f584 100644 --- a/plugins/tailscale/locales/translated/he_IL.json +++ b/plugins/tailscale/locales/translated/he_IL.json @@ -16,5 +16,13 @@ "tailscaleCheckOpenBrowser": "פתח את הדפדפן כדי לאמת", "tailscaleCheckWaiting": "ממתין לאימות Tailscale...", "tailscaleCheckTimeout": "אימות Tailscale הסתיים. אנא נסה שוב." + }, + "newUi": { + "sidebar": { + "quickConnect": { + "connectToTerminal": "התחברות לטרמינל", + "usernameLabel": "שם משתמש" + } + } } } diff --git a/plugins/tailscale/locales/translated/hi_IN.json b/plugins/tailscale/locales/translated/hi_IN.json index ff7246bd1..96a777d93 100644 --- a/plugins/tailscale/locales/translated/hi_IN.json +++ b/plugins/tailscale/locales/translated/hi_IN.json @@ -16,5 +16,13 @@ "tailscaleCheckOpenBrowser": "प्रमाणीकरण के लिए ब्राउज़र खोलें", "tailscaleCheckWaiting": "टेलस्केल प्रमाणीकरण की प्रतीक्षा की जा रही है...", "tailscaleCheckTimeout": "टेलस्केल प्रमाणीकरण का समय समाप्त हो गया। कृपया पुनः प्रयास करें।" + }, + "newUi": { + "sidebar": { + "quickConnect": { + "connectToTerminal": "टर्मिनल से कनेक्ट करें", + "usernameLabel": "उपयोगकर्ता नाम" + } + } } } diff --git a/plugins/tailscale/locales/translated/hu_HU.json b/plugins/tailscale/locales/translated/hu_HU.json index d50fbdea4..2f4a816b6 100644 --- a/plugins/tailscale/locales/translated/hu_HU.json +++ b/plugins/tailscale/locales/translated/hu_HU.json @@ -16,5 +16,13 @@ "tailscaleCheckOpenBrowser": "Böngésző megnyitása a hitelesítéshez", "tailscaleCheckWaiting": "Tailscale hitelesítésre várunk...", "tailscaleCheckTimeout": "A farokskálázási hitelesítés időtúllépést okozott. Próbálja újra." + }, + "newUi": { + "sidebar": { + "quickConnect": { + "connectToTerminal": "Csatlakozás a terminálhoz", + "usernameLabel": "Felhasználónév" + } + } } } diff --git a/plugins/tailscale/locales/translated/id_ID.json b/plugins/tailscale/locales/translated/id_ID.json index b54adebd1..f79df686f 100644 --- a/plugins/tailscale/locales/translated/id_ID.json +++ b/plugins/tailscale/locales/translated/id_ID.json @@ -16,5 +16,13 @@ "tailscaleCheckOpenBrowser": "Buka Browser untuk Melakukan Otentikasi", "tailscaleCheckWaiting": "Menunggu autentikasi Tailscale...", "tailscaleCheckTimeout": "Autentikasi Tailscale habis waktu. Silakan coba lagi." + }, + "newUi": { + "sidebar": { + "quickConnect": { + "connectToTerminal": "Hubungkan ke Terminal", + "usernameLabel": "Nama belakang" + } + } } } diff --git a/plugins/tailscale/locales/translated/it_IT.json b/plugins/tailscale/locales/translated/it_IT.json index c37688dc2..82451746b 100644 --- a/plugins/tailscale/locales/translated/it_IT.json +++ b/plugins/tailscale/locales/translated/it_IT.json @@ -16,5 +16,13 @@ "tailscaleCheckOpenBrowser": "Apri il browser per autenticarti", "tailscaleCheckWaiting": "In attesa dell'autenticazione di Tailscale...", "tailscaleCheckTimeout": "Autenticazione di Tailscale scaduta. Riprova." + }, + "newUi": { + "sidebar": { + "quickConnect": { + "connectToTerminal": "Connetti al terminale", + "usernameLabel": "Nome utente" + } + } } } diff --git a/plugins/tailscale/locales/translated/ja_JP.json b/plugins/tailscale/locales/translated/ja_JP.json index be8fd5368..4c22f5532 100644 --- a/plugins/tailscale/locales/translated/ja_JP.json +++ b/plugins/tailscale/locales/translated/ja_JP.json @@ -16,5 +16,13 @@ "tailscaleCheckOpenBrowser": "認証のためにブラウザを開く", "tailscaleCheckWaiting": "Tailscaleの認証を待っています...", "tailscaleCheckTimeout": "Tailscaleの認証がタイムアウトしました。もう一度お試しください。" + }, + "newUi": { + "sidebar": { + "quickConnect": { + "connectToTerminal": "ターミナルに接続", + "usernameLabel": "ユーザー名" + } + } } } diff --git a/plugins/tailscale/locales/translated/ko_KR.json b/plugins/tailscale/locales/translated/ko_KR.json index 264cd8654..4d6e1311e 100644 --- a/plugins/tailscale/locales/translated/ko_KR.json +++ b/plugins/tailscale/locales/translated/ko_KR.json @@ -16,5 +16,13 @@ "tailscaleCheckOpenBrowser": "인증하려면 브라우저를 여세요", "tailscaleCheckWaiting": "Tailscale 인증을 기다리는 중...", "tailscaleCheckTimeout": "Tailscale 인증 시간이 초과되었습니다. 다시 시도해 주세요." + }, + "newUi": { + "sidebar": { + "quickConnect": { + "connectToTerminal": "터미널에 연결", + "usernameLabel": "사용자 이름" + } + } } } diff --git a/plugins/tailscale/locales/translated/nl_NL.json b/plugins/tailscale/locales/translated/nl_NL.json index 55dfab20f..f52762077 100644 --- a/plugins/tailscale/locales/translated/nl_NL.json +++ b/plugins/tailscale/locales/translated/nl_NL.json @@ -16,5 +16,13 @@ "tailscaleCheckOpenBrowser": "Open de browser om te authenticeren.", "tailscaleCheckWaiting": "Wachten op Tailscale-authenticatie...", "tailscaleCheckTimeout": "De authenticatie bij Tailscale is mislukt vanwege een time-out. Probeer het opnieuw." + }, + "newUi": { + "sidebar": { + "quickConnect": { + "connectToTerminal": "Verbinden met de terminal", + "usernameLabel": "Gebruikersnaam" + } + } } } diff --git a/plugins/tailscale/locales/translated/no_NO.json b/plugins/tailscale/locales/translated/no_NO.json index 80601ec09..24e874354 100644 --- a/plugins/tailscale/locales/translated/no_NO.json +++ b/plugins/tailscale/locales/translated/no_NO.json @@ -16,5 +16,13 @@ "tailscaleCheckOpenBrowser": "Åpne nettleseren for å autentisere", "tailscaleCheckWaiting": "Venter på Tailscale-autentisering...", "tailscaleCheckTimeout": "Tailscale-autentiseringen er tidsavbrutt. Prøv på nytt." + }, + "newUi": { + "sidebar": { + "quickConnect": { + "connectToTerminal": "Koble til terminalen", + "usernameLabel": "Brukernavn" + } + } } } diff --git a/plugins/tailscale/locales/translated/pl_PL.json b/plugins/tailscale/locales/translated/pl_PL.json index ecefdc425..4a2f66c3a 100644 --- a/plugins/tailscale/locales/translated/pl_PL.json +++ b/plugins/tailscale/locales/translated/pl_PL.json @@ -16,5 +16,13 @@ "tailscaleCheckOpenBrowser": "Otwórz przeglądarkę, aby uwierzytelnić", "tailscaleCheckWaiting": "Oczekiwanie na uwierzytelnienie Tailscale...", "tailscaleCheckTimeout": "Upłynął limit czasu uwierzytelniania Tailscale. Spróbuj ponownie." + }, + "newUi": { + "sidebar": { + "quickConnect": { + "connectToTerminal": "Połącz z terminalem", + "usernameLabel": "Nazwa użytkownika" + } + } } } diff --git a/plugins/tailscale/locales/translated/pt_BR.json b/plugins/tailscale/locales/translated/pt_BR.json index 9ab5b1086..f976a3088 100644 --- a/plugins/tailscale/locales/translated/pt_BR.json +++ b/plugins/tailscale/locales/translated/pt_BR.json @@ -16,5 +16,13 @@ "tailscaleCheckOpenBrowser": "Abra o navegador para autenticar.", "tailscaleCheckWaiting": "Aguardando autenticação do Tailscale...", "tailscaleCheckTimeout": "A autenticação no Tailscale expirou. Tente novamente." + }, + "newUi": { + "sidebar": { + "quickConnect": { + "connectToTerminal": "Conectar ao terminal", + "usernameLabel": "Nome de usuário" + } + } } } diff --git a/plugins/tailscale/locales/translated/pt_PT.json b/plugins/tailscale/locales/translated/pt_PT.json index fc6cc11a6..c11ae48e6 100644 --- a/plugins/tailscale/locales/translated/pt_PT.json +++ b/plugins/tailscale/locales/translated/pt_PT.json @@ -16,5 +16,13 @@ "tailscaleCheckOpenBrowser": "Abra o browser para autenticar.", "tailscaleCheckWaiting": "Aguarda-se autenticação do Tailscale...", "tailscaleCheckTimeout": "A autenticação no Tailscale expirou. Tente novamente." + }, + "newUi": { + "sidebar": { + "quickConnect": { + "connectToTerminal": "Ligar ao Terminal", + "usernameLabel": "Nome de utilizador" + } + } } } diff --git a/plugins/tailscale/locales/translated/ro_RO.json b/plugins/tailscale/locales/translated/ro_RO.json index 88d9ebca7..5fdfebbe2 100644 --- a/plugins/tailscale/locales/translated/ro_RO.json +++ b/plugins/tailscale/locales/translated/ro_RO.json @@ -16,5 +16,13 @@ "tailscaleCheckOpenBrowser": "Deschideți browserul pentru autentificare", "tailscaleCheckWaiting": "Se așteaptă autentificarea Tailscale...", "tailscaleCheckTimeout": "Autentificarea la scară mică a expirat. Vă rugăm să încercați din nou." + }, + "newUi": { + "sidebar": { + "quickConnect": { + "connectToTerminal": "Conectați-vă la terminal", + "usernameLabel": "Nume de utilizator" + } + } } } diff --git a/plugins/tailscale/locales/translated/ru_RU.json b/plugins/tailscale/locales/translated/ru_RU.json index 9a47b9dbc..37a38bec8 100644 --- a/plugins/tailscale/locales/translated/ru_RU.json +++ b/plugins/tailscale/locales/translated/ru_RU.json @@ -16,5 +16,13 @@ "tailscaleCheckOpenBrowser": "Откройте браузер для аутентификации.", "tailscaleCheckWaiting": "Ожидание аутентификации Tailscale...", "tailscaleCheckTimeout": "Время ожидания аутентификации Tailscale истекло. Пожалуйста, попробуйте еще раз." + }, + "newUi": { + "sidebar": { + "quickConnect": { + "connectToTerminal": "Подключиться к терминалу", + "usernameLabel": "Имя пользователя" + } + } } } diff --git a/plugins/tailscale/locales/translated/sr_SP.json b/plugins/tailscale/locales/translated/sr_SP.json index 2f823dcc5..137e802df 100644 --- a/plugins/tailscale/locales/translated/sr_SP.json +++ b/plugins/tailscale/locales/translated/sr_SP.json @@ -16,5 +16,13 @@ "tailscaleCheckOpenBrowser": "Отворите прегледач за аутентификацију", "tailscaleCheckWaiting": "Чекање на Tailscale аутентификацију...", "tailscaleCheckTimeout": "Временско ограничење за аутентификацију Tailscale-а је истекло. Молимо покушајте поново." + }, + "newUi": { + "sidebar": { + "quickConnect": { + "connectToTerminal": "Повежи се са терминалом", + "usernameLabel": "Корисничко име" + } + } } } diff --git a/plugins/tailscale/locales/translated/sv_SE.json b/plugins/tailscale/locales/translated/sv_SE.json index 70eaf08bc..23e1c302b 100644 --- a/plugins/tailscale/locales/translated/sv_SE.json +++ b/plugins/tailscale/locales/translated/sv_SE.json @@ -16,5 +16,13 @@ "tailscaleCheckOpenBrowser": "Öppna webbläsaren för att autentisera", "tailscaleCheckWaiting": "Väntar på Tailscale-autentisering...", "tailscaleCheckTimeout": "Tailscale-autentiseringen har gått ut. Försök igen." + }, + "newUi": { + "sidebar": { + "quickConnect": { + "connectToTerminal": "Anslut till terminalen", + "usernameLabel": "Användarnamn" + } + } } } diff --git a/plugins/tailscale/locales/translated/th_TH.json b/plugins/tailscale/locales/translated/th_TH.json index 3c29439f4..ef3d65962 100644 --- a/plugins/tailscale/locales/translated/th_TH.json +++ b/plugins/tailscale/locales/translated/th_TH.json @@ -16,5 +16,13 @@ "tailscaleCheckOpenBrowser": "เปิดเบราว์เซอร์เพื่อยืนยันตัวตน", "tailscaleCheckWaiting": "กำลังรอการยืนยันตัวตนจาก Tailscale...", "tailscaleCheckTimeout": "การตรวจสอบสิทธิ์ Tailscale หมดเวลา โปรดลองอีกครั้ง" + }, + "newUi": { + "sidebar": { + "quickConnect": { + "connectToTerminal": "เชื่อมต่อกับเทอร์มินัล", + "usernameLabel": "ชื่อผู้ใช้" + } + } } } diff --git a/plugins/tailscale/locales/translated/tr_TR.json b/plugins/tailscale/locales/translated/tr_TR.json index dea00bdf3..0d0ef1106 100644 --- a/plugins/tailscale/locales/translated/tr_TR.json +++ b/plugins/tailscale/locales/translated/tr_TR.json @@ -16,5 +16,13 @@ "tailscaleCheckOpenBrowser": "Kimlik doğrulaması için tarayıcıyı açın.", "tailscaleCheckWaiting": "Tailscale kimlik doğrulamasının tamamlanmasını bekliyoruz...", "tailscaleCheckTimeout": "Tailscale kimlik doğrulama işlemi zaman aşımına uğradı. Lütfen tekrar deneyin." + }, + "newUi": { + "sidebar": { + "quickConnect": { + "connectToTerminal": "Terminale Bağlan", + "usernameLabel": "Kullanıcı Adı" + } + } } } diff --git a/plugins/tailscale/locales/translated/uk_UA.json b/plugins/tailscale/locales/translated/uk_UA.json index bbc6ae3d0..ec228c087 100644 --- a/plugins/tailscale/locales/translated/uk_UA.json +++ b/plugins/tailscale/locales/translated/uk_UA.json @@ -16,5 +16,13 @@ "tailscaleCheckOpenBrowser": "Відкрийте браузер для автентифікації", "tailscaleCheckWaiting": "Очікування автентифікації Tailscale...", "tailscaleCheckTimeout": "Час очікування автентифікації Tailscale минув. Будь ласка, спробуйте ще раз." + }, + "newUi": { + "sidebar": { + "quickConnect": { + "connectToTerminal": "Підключення до терміналу", + "usernameLabel": "Ім'я користувача" + } + } } } diff --git a/plugins/tailscale/locales/translated/vi_VN.json b/plugins/tailscale/locales/translated/vi_VN.json index 1e019f82b..9583b7888 100644 --- a/plugins/tailscale/locales/translated/vi_VN.json +++ b/plugins/tailscale/locales/translated/vi_VN.json @@ -16,5 +16,13 @@ "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." + }, + "newUi": { + "sidebar": { + "quickConnect": { + "connectToTerminal": "Kết nối đến Terminal", + "usernameLabel": "Tên đăng nhập" + } + } } } diff --git a/plugins/tailscale/locales/translated/zh_CN.json b/plugins/tailscale/locales/translated/zh_CN.json index 7e88d4c00..73fe6188d 100644 --- a/plugins/tailscale/locales/translated/zh_CN.json +++ b/plugins/tailscale/locales/translated/zh_CN.json @@ -16,5 +16,13 @@ "tailscaleCheckOpenBrowser": "打开浏览器进行身份验证", "tailscaleCheckWaiting": "正在等待 Tailscale 身份验证……", "tailscaleCheckTimeout": "Tailscale 身份验证超时,请重试。" + }, + "newUi": { + "sidebar": { + "quickConnect": { + "connectToTerminal": "连接到终端", + "usernameLabel": "用户名" + } + } } } diff --git a/plugins/tailscale/locales/translated/zh_TW.json b/plugins/tailscale/locales/translated/zh_TW.json index 52c0fd1a1..6bd43e293 100644 --- a/plugins/tailscale/locales/translated/zh_TW.json +++ b/plugins/tailscale/locales/translated/zh_TW.json @@ -16,5 +16,13 @@ "tailscaleCheckOpenBrowser": "開啟瀏覽器進行身份驗證", "tailscaleCheckWaiting": "正在等待 Tailscale 身份驗證…", "tailscaleCheckTimeout": "Tailscale身份驗證逾時,請重試。" + }, + "newUi": { + "sidebar": { + "quickConnect": { + "connectToTerminal": "連線至終端機", + "usernameLabel": "使用者名稱" + } + } } } diff --git a/plugins/tmux-monitor/locales/en.json b/plugins/tmux-monitor/locales/en.json index 54007538e..f38d2f6d8 100644 --- a/plugins/tmux-monitor/locales/en.json +++ b/plugins/tmux-monitor/locales/en.json @@ -2,7 +2,8 @@ "hosts": { "enableTmuxMonitor": "Enable Tmux Monitor", "enableTmuxMonitorDesc": "Show this host in the Tmux Monitor and add its tmux actions to the sidebar", - "tabTmuxMonitor": "Tmux Monitor" + "tabTmuxMonitor": "Tmux Monitor", + "docsLink": "View docs" }, "nav": { "tmuxMonitor": "Tmux Monitor" diff --git a/plugins/tmux-monitor/locales/translated/af_ZA.json b/plugins/tmux-monitor/locales/translated/af_ZA.json index 2617335a3..59e71d680 100644 --- a/plugins/tmux-monitor/locales/translated/af_ZA.json +++ b/plugins/tmux-monitor/locales/translated/af_ZA.json @@ -4,7 +4,8 @@ }, "hosts": { "enableTmuxMonitor": "Aktiveer Tmux-monitor", - "enableTmuxMonitorDesc": "Wys hierdie gasheer in die Tmux Monitor en voeg sy tmux-aksies by die sybalk." + "enableTmuxMonitorDesc": "Wys hierdie gasheer in die Tmux Monitor en voeg sy tmux-aksies by die sybalk.", + "docsLink": "Bekyk dokumente" }, "tmuxMonitor": { "title": "Tmux-monitor", diff --git a/plugins/tmux-monitor/locales/translated/ar_SA.json b/plugins/tmux-monitor/locales/translated/ar_SA.json index 641f3f4aa..0e303ba4e 100644 --- a/plugins/tmux-monitor/locales/translated/ar_SA.json +++ b/plugins/tmux-monitor/locales/translated/ar_SA.json @@ -4,7 +4,8 @@ }, "hosts": { "enableTmuxMonitor": "تمكين مراقب Tmux", - "enableTmuxMonitorDesc": "إظهار هذا المضيف في مراقب Tmux وإضافة إجراءات tmux الخاصة به إلى الشريط الجانبي" + "enableTmuxMonitorDesc": "إظهار هذا المضيف في مراقب Tmux وإضافة إجراءات tmux الخاصة به إلى الشريط الجانبي", + "docsLink": "عرض المستندات" }, "tmuxMonitor": { "title": "مراقب Tmux", diff --git a/plugins/tmux-monitor/locales/translated/bg_BG.json b/plugins/tmux-monitor/locales/translated/bg_BG.json index 71ffae899..a8ac9dc60 100644 --- a/plugins/tmux-monitor/locales/translated/bg_BG.json +++ b/plugins/tmux-monitor/locales/translated/bg_BG.json @@ -4,7 +4,8 @@ }, "hosts": { "enableTmuxMonitor": "Активиране на Tmux монитор", - "enableTmuxMonitorDesc": "Показване на този хост в Tmux монитора и добавяне на неговите tmux действия към страничната лента" + "enableTmuxMonitorDesc": "Показване на този хост в Tmux монитора и добавяне на неговите tmux действия към страничната лента", + "docsLink": "Преглед на документи" }, "tmuxMonitor": { "title": "Tmux монитор", diff --git a/plugins/tmux-monitor/locales/translated/bn_BD.json b/plugins/tmux-monitor/locales/translated/bn_BD.json index 23702f24d..746934392 100644 --- a/plugins/tmux-monitor/locales/translated/bn_BD.json +++ b/plugins/tmux-monitor/locales/translated/bn_BD.json @@ -4,7 +4,8 @@ }, "hosts": { "enableTmuxMonitor": "Tmux মনিটর সক্রিয় করুন", - "enableTmuxMonitorDesc": "এই হোস্টটিকে Tmux মনিটরে দেখান এবং এর tmux অ্যাকশনগুলো সাইডবারে যোগ করুন।" + "enableTmuxMonitorDesc": "এই হোস্টটিকে Tmux মনিটরে দেখান এবং এর tmux অ্যাকশনগুলো সাইডবারে যোগ করুন।", + "docsLink": "নথি দেখুন" }, "tmuxMonitor": { "title": "Tmux মনিটর", diff --git a/plugins/tmux-monitor/locales/translated/ca_ES.json b/plugins/tmux-monitor/locales/translated/ca_ES.json index d72f8250e..342484771 100644 --- a/plugins/tmux-monitor/locales/translated/ca_ES.json +++ b/plugins/tmux-monitor/locales/translated/ca_ES.json @@ -4,7 +4,8 @@ }, "hosts": { "enableTmuxMonitor": "Activa el monitor Tmux", - "enableTmuxMonitorDesc": "Mostra aquest host al monitor Tmux i afegeix les seves accions tmux a la barra lateral" + "enableTmuxMonitorDesc": "Mostra aquest host al monitor Tmux i afegeix les seves accions tmux a la barra lateral", + "docsLink": "Veure documents" }, "tmuxMonitor": { "title": "Monitor Tmux", diff --git a/plugins/tmux-monitor/locales/translated/cs_CZ.json b/plugins/tmux-monitor/locales/translated/cs_CZ.json index e603d4cff..dba518a9a 100644 --- a/plugins/tmux-monitor/locales/translated/cs_CZ.json +++ b/plugins/tmux-monitor/locales/translated/cs_CZ.json @@ -4,7 +4,8 @@ }, "hosts": { "enableTmuxMonitor": "Povolit monitorování Tmux", - "enableTmuxMonitorDesc": "Zobrazit tohoto hostitele v Tmux Monitoru a přidat jeho tmux akce do postranního panelu" + "enableTmuxMonitorDesc": "Zobrazit tohoto hostitele v Tmux Monitoru a přidat jeho tmux akce do postranního panelu", + "docsLink": "Zobrazit dokumenty" }, "tmuxMonitor": { "title": "Monitor Tmux", diff --git a/plugins/tmux-monitor/locales/translated/da_DK.json b/plugins/tmux-monitor/locales/translated/da_DK.json index 2128ce763..e21b9b638 100644 --- a/plugins/tmux-monitor/locales/translated/da_DK.json +++ b/plugins/tmux-monitor/locales/translated/da_DK.json @@ -4,7 +4,8 @@ }, "hosts": { "enableTmuxMonitor": "Aktivér Tmux-skærm", - "enableTmuxMonitorDesc": "Vis denne vært i Tmux Monitor og tilføj dens tmux-handlinger til sidebjælken" + "enableTmuxMonitorDesc": "Vis denne vært i Tmux Monitor og tilføj dens tmux-handlinger til sidebjælken", + "docsLink": "Se dokumenter" }, "tmuxMonitor": { "title": "Tmux-skærm", diff --git a/plugins/tmux-monitor/locales/translated/de_DE.json b/plugins/tmux-monitor/locales/translated/de_DE.json index 4d02e8b4f..1bd7f3178 100644 --- a/plugins/tmux-monitor/locales/translated/de_DE.json +++ b/plugins/tmux-monitor/locales/translated/de_DE.json @@ -4,7 +4,8 @@ }, "hosts": { "enableTmuxMonitor": "Tmux-Monitor aktivieren", - "enableTmuxMonitorDesc": "Diesen Host im Tmux-Monitor anzeigen und seine tmux-Aktionen zur Seitenleiste hinzufügen" + "enableTmuxMonitorDesc": "Diesen Host im Tmux-Monitor anzeigen und seine tmux-Aktionen zur Seitenleiste hinzufügen", + "docsLink": "Dokumentation anzeigen" }, "tmuxMonitor": { "title": "Tmux-Monitor", diff --git a/plugins/tmux-monitor/locales/translated/el_GR.json b/plugins/tmux-monitor/locales/translated/el_GR.json index f95aad0dc..43c963f48 100644 --- a/plugins/tmux-monitor/locales/translated/el_GR.json +++ b/plugins/tmux-monitor/locales/translated/el_GR.json @@ -4,7 +4,8 @@ }, "hosts": { "enableTmuxMonitor": "Ενεργοποίηση παρακολούθησης Tmux", - "enableTmuxMonitorDesc": "Εμφάνιση αυτού του κεντρικού υπολογιστή στην οθόνη Tmux και προσθήκη των ενεργειών tmux του στην πλαϊνή μπάρα" + "enableTmuxMonitorDesc": "Εμφάνιση αυτού του κεντρικού υπολογιστή στην οθόνη Tmux και προσθήκη των ενεργειών tmux του στην πλαϊνή μπάρα", + "docsLink": "Προβολή εγγράφων" }, "tmuxMonitor": { "title": "Παρακολούθηση Tmux", diff --git a/plugins/tmux-monitor/locales/translated/es_ES.json b/plugins/tmux-monitor/locales/translated/es_ES.json index 820f7916c..e0a847505 100644 --- a/plugins/tmux-monitor/locales/translated/es_ES.json +++ b/plugins/tmux-monitor/locales/translated/es_ES.json @@ -4,7 +4,8 @@ }, "hosts": { "enableTmuxMonitor": "Activar Tmux Monitor", - "enableTmuxMonitorDesc": "Mostrar este host en el Tmux Monitor y añadir sus acciones de tmux a la barra lateral." + "enableTmuxMonitorDesc": "Mostrar este host en el Tmux Monitor y añadir sus acciones de tmux a la barra lateral.", + "docsLink": "Ver documentación" }, "tmuxMonitor": { "title": "Monitor Tmux", diff --git a/plugins/tmux-monitor/locales/translated/fi_FI.json b/plugins/tmux-monitor/locales/translated/fi_FI.json index 194246f03..b4ebc5deb 100644 --- a/plugins/tmux-monitor/locales/translated/fi_FI.json +++ b/plugins/tmux-monitor/locales/translated/fi_FI.json @@ -4,7 +4,8 @@ }, "hosts": { "enableTmuxMonitor": "Ota Tmux-monitori käyttöön", - "enableTmuxMonitorDesc": "Näytä tämä isäntä Tmux-monitorissa ja lisää sen tmux-toiminnot sivupalkkiin" + "enableTmuxMonitorDesc": "Näytä tämä isäntä Tmux-monitorissa ja lisää sen tmux-toiminnot sivupalkkiin", + "docsLink": "Näytä dokumentit" }, "tmuxMonitor": { "title": "Tmux-näyttö", diff --git a/plugins/tmux-monitor/locales/translated/fr_FR.json b/plugins/tmux-monitor/locales/translated/fr_FR.json index a04beb3e8..b969cf1fc 100644 --- a/plugins/tmux-monitor/locales/translated/fr_FR.json +++ b/plugins/tmux-monitor/locales/translated/fr_FR.json @@ -4,7 +4,8 @@ }, "hosts": { "enableTmuxMonitor": "Activer le Moniteur Tmux", - "enableTmuxMonitorDesc": "Afficher cet hôte dans le Moniteur Tmux et ajouter ses actions tmux à la barre latérale" + "enableTmuxMonitorDesc": "Afficher cet hôte dans le Moniteur Tmux et ajouter ses actions tmux à la barre latérale", + "docsLink": "Voir la documentation" }, "tmuxMonitor": { "title": "Moniteur tmux", diff --git a/plugins/tmux-monitor/locales/translated/he_IL.json b/plugins/tmux-monitor/locales/translated/he_IL.json index 9ff77a614..a77507adb 100644 --- a/plugins/tmux-monitor/locales/translated/he_IL.json +++ b/plugins/tmux-monitor/locales/translated/he_IL.json @@ -4,7 +4,8 @@ }, "hosts": { "enableTmuxMonitor": "הפעל את צג Tmux", - "enableTmuxMonitorDesc": "הצג מארח זה בצג Tmux והוסף את פעולות ה-tmux שלו לסרגל הצד" + "enableTmuxMonitorDesc": "הצג מארח זה בצג Tmux והוסף את פעולות ה-tmux שלו לסרגל הצד", + "docsLink": "הצג מסמכים" }, "tmuxMonitor": { "title": "צג Tmux", diff --git a/plugins/tmux-monitor/locales/translated/hi_IN.json b/plugins/tmux-monitor/locales/translated/hi_IN.json index ed8291846..3f9a003a5 100644 --- a/plugins/tmux-monitor/locales/translated/hi_IN.json +++ b/plugins/tmux-monitor/locales/translated/hi_IN.json @@ -4,7 +4,8 @@ }, "hosts": { "enableTmuxMonitor": "Tmux मॉनिटर सक्षम करें", - "enableTmuxMonitorDesc": "इस होस्ट को Tmux मॉनिटर में दिखाएँ और इसकी tmux क्रियाओं को साइडबार में जोड़ें" + "enableTmuxMonitorDesc": "इस होस्ट को Tmux मॉनिटर में दिखाएँ और इसकी tmux क्रियाओं को साइडबार में जोड़ें", + "docsLink": "दस्तावेज़ देखें" }, "tmuxMonitor": { "title": "Tmux मॉनिटर", diff --git a/plugins/tmux-monitor/locales/translated/hu_HU.json b/plugins/tmux-monitor/locales/translated/hu_HU.json index 07f09199e..5585574eb 100644 --- a/plugins/tmux-monitor/locales/translated/hu_HU.json +++ b/plugins/tmux-monitor/locales/translated/hu_HU.json @@ -4,7 +4,8 @@ }, "hosts": { "enableTmuxMonitor": "Tmux monitor engedélyezése", - "enableTmuxMonitorDesc": "Mutassa meg ezt a gépet a Tmux Monitorban, és adja hozzá a tmux műveleteit az oldalsávhoz" + "enableTmuxMonitorDesc": "Mutassa meg ezt a gépet a Tmux Monitorban, és adja hozzá a tmux műveleteit az oldalsávhoz", + "docsLink": "Dokumentumok megtekintése" }, "tmuxMonitor": { "title": "Tmux monitor", diff --git a/plugins/tmux-monitor/locales/translated/id_ID.json b/plugins/tmux-monitor/locales/translated/id_ID.json index 03d54d7f3..98bbcbf03 100644 --- a/plugins/tmux-monitor/locales/translated/id_ID.json +++ b/plugins/tmux-monitor/locales/translated/id_ID.json @@ -4,7 +4,8 @@ }, "hosts": { "enableTmuxMonitor": "Aktifkan Monitor Tmux", - "enableTmuxMonitorDesc": "Tampilkan host ini di Tmux Monitor dan tambahkan aksi tmux-nya ke sidebar." + "enableTmuxMonitorDesc": "Tampilkan host ini di Tmux Monitor dan tambahkan aksi tmux-nya ke sidebar.", + "docsLink": "Lihat dokumen" }, "tmuxMonitor": { "title": "Monitor Tmux", diff --git a/plugins/tmux-monitor/locales/translated/it_IT.json b/plugins/tmux-monitor/locales/translated/it_IT.json index f33763ff6..94a82d9be 100644 --- a/plugins/tmux-monitor/locales/translated/it_IT.json +++ b/plugins/tmux-monitor/locales/translated/it_IT.json @@ -4,7 +4,8 @@ }, "hosts": { "enableTmuxMonitor": "Abilita Monitor Tmux", - "enableTmuxMonitorDesc": "Mostra questo host nel Monitor Tmux e aggiungi le sue azioni tmux alla barra laterale" + "enableTmuxMonitorDesc": "Mostra questo host nel Monitor Tmux e aggiungi le sue azioni tmux alla barra laterale", + "docsLink": "Visualizza documentazione" }, "tmuxMonitor": { "title": "Monitor Tmux", diff --git a/plugins/tmux-monitor/locales/translated/ja_JP.json b/plugins/tmux-monitor/locales/translated/ja_JP.json index 71662bf0e..15f6b81c0 100644 --- a/plugins/tmux-monitor/locales/translated/ja_JP.json +++ b/plugins/tmux-monitor/locales/translated/ja_JP.json @@ -4,7 +4,8 @@ }, "hosts": { "enableTmuxMonitor": "Tmuxモニターを有効にする", - "enableTmuxMonitorDesc": "Tmuxモニターにこのホストを表示し、tmuxアクションをサイドバーに追加します。" + "enableTmuxMonitorDesc": "Tmuxモニターにこのホストを表示し、tmuxアクションをサイドバーに追加します。", + "docsLink": "ドキュメントを表示" }, "tmuxMonitor": { "title": "Tmux モニター", diff --git a/plugins/tmux-monitor/locales/translated/ko_KR.json b/plugins/tmux-monitor/locales/translated/ko_KR.json index 75094f07e..335f9b718 100644 --- a/plugins/tmux-monitor/locales/translated/ko_KR.json +++ b/plugins/tmux-monitor/locales/translated/ko_KR.json @@ -4,7 +4,8 @@ }, "hosts": { "enableTmuxMonitor": "Tmux 모니터 활성화", - "enableTmuxMonitorDesc": "Tmux 모니터에 이 호스트를 표시하고 tmux 작업을 사이드바에 추가합니다." + "enableTmuxMonitorDesc": "Tmux 모니터에 이 호스트를 표시하고 tmux 작업을 사이드바에 추가합니다.", + "docsLink": "문서 보기" }, "tmuxMonitor": { "title": "Tmux 모니터", diff --git a/plugins/tmux-monitor/locales/translated/nl_NL.json b/plugins/tmux-monitor/locales/translated/nl_NL.json index 001baca29..3ff626a40 100644 --- a/plugins/tmux-monitor/locales/translated/nl_NL.json +++ b/plugins/tmux-monitor/locales/translated/nl_NL.json @@ -4,7 +4,8 @@ }, "hosts": { "enableTmuxMonitor": "Tmux Monitor inschakelen", - "enableTmuxMonitorDesc": "Toon deze host in de Tmux Monitor en voeg de bijbehorende Tmux-acties toe aan de zijbalk." + "enableTmuxMonitorDesc": "Toon deze host in de Tmux Monitor en voeg de bijbehorende Tmux-acties toe aan de zijbalk.", + "docsLink": "Documenten bekijken" }, "tmuxMonitor": { "title": "Tmux Monitor", diff --git a/plugins/tmux-monitor/locales/translated/no_NO.json b/plugins/tmux-monitor/locales/translated/no_NO.json index b205a77ed..11876f4cc 100644 --- a/plugins/tmux-monitor/locales/translated/no_NO.json +++ b/plugins/tmux-monitor/locales/translated/no_NO.json @@ -4,7 +4,8 @@ }, "hosts": { "enableTmuxMonitor": "Aktiver Tmux-monitor", - "enableTmuxMonitorDesc": "Vis denne verten i Tmux-monitoren og legg til tmux-handlingene i sidefeltet" + "enableTmuxMonitorDesc": "Vis denne verten i Tmux-monitoren og legg til tmux-handlingene i sidefeltet", + "docsLink": "Vis dokumenter" }, "tmuxMonitor": { "title": "Tmux-skjerm", diff --git a/plugins/tmux-monitor/locales/translated/pl_PL.json b/plugins/tmux-monitor/locales/translated/pl_PL.json index 255021b53..75b42f4d9 100644 --- a/plugins/tmux-monitor/locales/translated/pl_PL.json +++ b/plugins/tmux-monitor/locales/translated/pl_PL.json @@ -4,7 +4,8 @@ }, "hosts": { "enableTmuxMonitor": "Włącz monitor Tmux", - "enableTmuxMonitorDesc": "Pokaż tego hosta w monitorze Tmux i dodaj jego akcje tmux do paska bocznego" + "enableTmuxMonitorDesc": "Pokaż tego hosta w monitorze Tmux i dodaj jego akcje tmux do paska bocznego", + "docsLink": "Zobacz dokumentację" }, "tmuxMonitor": { "title": "Monitor Tmux", diff --git a/plugins/tmux-monitor/locales/translated/pt_BR.json b/plugins/tmux-monitor/locales/translated/pt_BR.json index 6668a95f4..2779745d2 100644 --- a/plugins/tmux-monitor/locales/translated/pt_BR.json +++ b/plugins/tmux-monitor/locales/translated/pt_BR.json @@ -4,7 +4,8 @@ }, "hosts": { "enableTmuxMonitor": "Ativar monitor Tmux", - "enableTmuxMonitorDesc": "Exiba este host no Monitor Tmux e adicione suas ações tmux à barra lateral." + "enableTmuxMonitorDesc": "Exiba este host no Monitor Tmux e adicione suas ações tmux à barra lateral.", + "docsLink": "Ver documentos" }, "tmuxMonitor": { "title": "Monitor Tmux", diff --git a/plugins/tmux-monitor/locales/translated/pt_PT.json b/plugins/tmux-monitor/locales/translated/pt_PT.json index 88fdca512..31623bb9f 100644 --- a/plugins/tmux-monitor/locales/translated/pt_PT.json +++ b/plugins/tmux-monitor/locales/translated/pt_PT.json @@ -4,7 +4,8 @@ }, "hosts": { "enableTmuxMonitor": "Ativar Monitor Tmux", - "enableTmuxMonitorDesc": "Mostrar este host no Monitor Tmux e adicionar as suas ações tmux à barra lateral" + "enableTmuxMonitorDesc": "Mostrar este host no Monitor Tmux e adicionar as suas ações tmux à barra lateral", + "docsLink": "Ver documentação" }, "tmuxMonitor": { "title": "Monitor Tmux", diff --git a/plugins/tmux-monitor/locales/translated/ro_RO.json b/plugins/tmux-monitor/locales/translated/ro_RO.json index bf0af6552..ff15973ce 100644 --- a/plugins/tmux-monitor/locales/translated/ro_RO.json +++ b/plugins/tmux-monitor/locales/translated/ro_RO.json @@ -4,7 +4,8 @@ }, "hosts": { "enableTmuxMonitor": "Activează monitorul Tmux", - "enableTmuxMonitorDesc": "Afișează această gazdă în Monitorul Tmux și adaugă acțiunile sale tmux în bara laterală" + "enableTmuxMonitorDesc": "Afișează această gazdă în Monitorul Tmux și adaugă acțiunile sale tmux în bara laterală", + "docsLink": "Vizualizați documentele" }, "tmuxMonitor": { "title": "Monitorul Tmux", diff --git a/plugins/tmux-monitor/locales/translated/ru_RU.json b/plugins/tmux-monitor/locales/translated/ru_RU.json index e518fc8ad..c1180a1e1 100644 --- a/plugins/tmux-monitor/locales/translated/ru_RU.json +++ b/plugins/tmux-monitor/locales/translated/ru_RU.json @@ -4,7 +4,8 @@ }, "hosts": { "enableTmuxMonitor": "Включить монитор Tmux", - "enableTmuxMonitorDesc": "Показывать этот хост в Мониторе Tmux и добавлять действия tmux в боковую панель" + "enableTmuxMonitorDesc": "Показывать этот хост в Мониторе Tmux и добавлять действия tmux в боковую панель", + "docsLink": "Документация" }, "tmuxMonitor": { "title": "Монитор Tmux", diff --git a/plugins/tmux-monitor/locales/translated/sr_SP.json b/plugins/tmux-monitor/locales/translated/sr_SP.json index 17a85f882..fe661d404 100644 --- a/plugins/tmux-monitor/locales/translated/sr_SP.json +++ b/plugins/tmux-monitor/locales/translated/sr_SP.json @@ -4,7 +4,8 @@ }, "hosts": { "enableTmuxMonitor": "Омогући Tmux монитор", - "enableTmuxMonitorDesc": "Прикажи овај хост у Tmux монитору и додај његове tmux акције у бочну траку" + "enableTmuxMonitorDesc": "Прикажи овај хост у Tmux монитору и додај његове tmux акције у бочну траку", + "docsLink": "Прикажи документе" }, "tmuxMonitor": { "title": "Tmux монитор", diff --git a/plugins/tmux-monitor/locales/translated/sv_SE.json b/plugins/tmux-monitor/locales/translated/sv_SE.json index 273969165..73542ff5f 100644 --- a/plugins/tmux-monitor/locales/translated/sv_SE.json +++ b/plugins/tmux-monitor/locales/translated/sv_SE.json @@ -4,7 +4,8 @@ }, "hosts": { "enableTmuxMonitor": "Aktivera Tmux-monitorn", - "enableTmuxMonitorDesc": "Visa denna värd i Tmux Monitor och lägg till dess tmux-åtgärder i sidofältet" + "enableTmuxMonitorDesc": "Visa denna värd i Tmux Monitor och lägg till dess tmux-åtgärder i sidofältet", + "docsLink": "Visa dokument" }, "tmuxMonitor": { "title": "Tmux-monitor", diff --git a/plugins/tmux-monitor/locales/translated/th_TH.json b/plugins/tmux-monitor/locales/translated/th_TH.json index cf7027899..f77b8287d 100644 --- a/plugins/tmux-monitor/locales/translated/th_TH.json +++ b/plugins/tmux-monitor/locales/translated/th_TH.json @@ -4,7 +4,8 @@ }, "hosts": { "enableTmuxMonitor": "เปิดใช้งาน Tmux Monitor", - "enableTmuxMonitorDesc": "แสดงโฮสต์นี้ใน Tmux Monitor และเพิ่มการดำเนินการ tmux ของโฮสต์นี้ลงในแถบด้านข้าง" + "enableTmuxMonitorDesc": "แสดงโฮสต์นี้ใน Tmux Monitor และเพิ่มการดำเนินการ tmux ของโฮสต์นี้ลงในแถบด้านข้าง", + "docsLink": "ดูเอกสาร" }, "tmuxMonitor": { "title": "มอนิเตอร์ Tmux", diff --git a/plugins/tmux-monitor/locales/translated/tr_TR.json b/plugins/tmux-monitor/locales/translated/tr_TR.json index 0f22bfd8a..ee2312f01 100644 --- a/plugins/tmux-monitor/locales/translated/tr_TR.json +++ b/plugins/tmux-monitor/locales/translated/tr_TR.json @@ -4,7 +4,8 @@ }, "hosts": { "enableTmuxMonitor": "Tmux İzleyiciyi Etkinleştir", - "enableTmuxMonitorDesc": "Bu ana bilgisayarı Tmux İzleyicide göster ve tmux eylemlerini kenar çubuğuna ekle" + "enableTmuxMonitorDesc": "Bu ana bilgisayarı Tmux İzleyicide göster ve tmux eylemlerini kenar çubuğuna ekle", + "docsLink": "Dokümanları görüntüle" }, "tmuxMonitor": { "title": "Tmux İzleyici", diff --git a/plugins/tmux-monitor/locales/translated/uk_UA.json b/plugins/tmux-monitor/locales/translated/uk_UA.json index 679c4370e..5cbcbee01 100644 --- a/plugins/tmux-monitor/locales/translated/uk_UA.json +++ b/plugins/tmux-monitor/locales/translated/uk_UA.json @@ -4,7 +4,8 @@ }, "hosts": { "enableTmuxMonitor": "Увімкнути монітор Tmux", - "enableTmuxMonitorDesc": "Показати цей хост у моніторі Tmux та додати його дії tmux до бічної панелі" + "enableTmuxMonitorDesc": "Показати цей хост у моніторі Tmux та додати його дії tmux до бічної панелі", + "docsLink": "Переглянути документи" }, "tmuxMonitor": { "title": "Монітор Tmux", diff --git a/plugins/tmux-monitor/locales/translated/vi_VN.json b/plugins/tmux-monitor/locales/translated/vi_VN.json index 8f1df86f6..327662681 100644 --- a/plugins/tmux-monitor/locales/translated/vi_VN.json +++ b/plugins/tmux-monitor/locales/translated/vi_VN.json @@ -4,7 +4,8 @@ }, "hosts": { "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" + "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", + "docsLink": "Xem tài liệu" }, "tmuxMonitor": { "title": "Giám sát Tmux", diff --git a/plugins/tmux-monitor/locales/translated/zh_CN.json b/plugins/tmux-monitor/locales/translated/zh_CN.json index 15487fa52..56ce32583 100644 --- a/plugins/tmux-monitor/locales/translated/zh_CN.json +++ b/plugins/tmux-monitor/locales/translated/zh_CN.json @@ -4,7 +4,8 @@ }, "hosts": { "enableTmuxMonitor": "启用 Tmux 监控", - "enableTmuxMonitorDesc": "在 Tmux 监控中显示此主机,并将其 tmux 操作添加到侧边栏" + "enableTmuxMonitorDesc": "在 Tmux 监控中显示此主机,并将其 tmux 操作添加到侧边栏", + "docsLink": "查看文档" }, "tmuxMonitor": { "title": "Tmux 监视器", diff --git a/plugins/tmux-monitor/locales/translated/zh_TW.json b/plugins/tmux-monitor/locales/translated/zh_TW.json index 4ff1f5fb5..9ad43c691 100644 --- a/plugins/tmux-monitor/locales/translated/zh_TW.json +++ b/plugins/tmux-monitor/locales/translated/zh_TW.json @@ -4,7 +4,8 @@ }, "hosts": { "enableTmuxMonitor": "啟用 Tmux 監控器", - "enableTmuxMonitorDesc": "在 Tmux 監控器中顯示此主機,並將其 tmux 操作新增至側邊欄" + "enableTmuxMonitorDesc": "在 Tmux 監控器中顯示此主機,並將其 tmux 操作新增至側邊欄", + "docsLink": "檢視文件" }, "tmuxMonitor": { "title": "Tmux 監視器", diff --git a/plugins/tmux-monitor/src/frontend/PanePreview.tsx b/plugins/tmux-monitor/src/frontend/PanePreview.tsx index 629e2a3cc..189b02adc 100644 --- a/plugins/tmux-monitor/src/frontend/PanePreview.tsx +++ b/plugins/tmux-monitor/src/frontend/PanePreview.tsx @@ -68,10 +68,9 @@ export function PanePreview({ // The host's own authType travels in the spread, so a Tailscale host still // gets the Tailscale-aware PTY path. The SSH port may be non-standard. - const hostRecord = host as unknown as Record; - const resolvedPort = hostRecord.sshPort ?? hostRecord.port; + const resolvedPort = host.sshPort ?? host.port; const terminalHostConfig = { - ...hostRecord, + ...host, port: resolvedPort, sshPort: resolvedPort, instanceId: instanceIdRef.current, diff --git a/plugins/tunnels/locales/en.json b/plugins/tunnels/locales/en.json index f094a9999..9b1e272dc 100644 --- a/plugins/tunnels/locales/en.json +++ b/plugins/tunnels/locales/en.json @@ -26,7 +26,11 @@ "tunnelModeRemoteDesc": "Forward a port on the remote server back to a local port on your machine.", "tunnelRequirementsText": "The SSH server must have GatewayPorts yes, AllowTcpForwarding yes, and PermitRootLogin yes set in /etc/ssh/sshd_config.", "tunnelSettings": "Tunnel Settings", - "tunnelType": "Tunnel Type" + "tunnelType": "Tunnel Type", + "bindHost": "Bind Host", + "docsLink": "View docs", + "hostNotFound": "Host not found", + "loadingHost": "Loading host..." }, "nav": { "portForwarding": "Forwarding", @@ -142,7 +146,9 @@ "socksProxy": "SOCKS5 proxy", "waiting": "Waiting", "remoteSessionExpired": "Remote Sync session expired. Reconnect Remote Sync and try again.", - "activeTunnels": "Active Tunnels" + "activeTunnels": "Active Tunnels", + "start": "Start", + "stop": "Stop" }, "permissions": { "use": { @@ -157,5 +163,9 @@ "description": "Set up SSH tunnels through this host." } } + }, + "onboarding": { + "feature_tunnels": "Tunnels", + "feature_tunnels_desc": "Forward ports through a server to reach services that are not exposed." } } diff --git a/plugins/tunnels/locales/translated/af_ZA.json b/plugins/tunnels/locales/translated/af_ZA.json index 95d9bd530..60815de8d 100644 --- a/plugins/tunnels/locales/translated/af_ZA.json +++ b/plugins/tunnels/locales/translated/af_ZA.json @@ -26,7 +26,11 @@ "tunnelModeRemoteDesc": "Stuur 'n poort op die afgeleë bediener terug na 'n plaaslike poort op jou masjien.", "tunnelRequirementsText": "Die SSH-bediener moet GatewayPorts ja, AllowTcpForwarding ja, en PermitRootLogin ja gestel hê in /etc/ssh/sshd_config.", "tunnelSettings": "Tonnelinstellings", - "tunnelType": "Tonnel Tipe" + "tunnelType": "Tonnel Tipe", + "bindHost": "Bind gasheer", + "docsLink": "Bekyk dokumente", + "hostNotFound": "Gasheer nie gevind nie", + "loadingHost": "Laai gasheer..." }, "nav": { "portForwarding": "Aanstuur", @@ -134,6 +138,12 @@ "typeDynamic": "Dinamiese (-D)", "typeLocal": "Plaaslik (-L)", "typeRemote": "Afstandbeheer (-R)", - "working": "Werk..." + "working": "Werk...", + "start": "Begin", + "stop": "Stop" + }, + "onboarding": { + "feature_tunnels": "Tonnels", + "feature_tunnels_desc": "Stuur poorte deur 'n bediener aan om dienste te bereik wat nie blootgestel is nie." } } diff --git a/plugins/tunnels/locales/translated/ar_SA.json b/plugins/tunnels/locales/translated/ar_SA.json index 4a97b20b3..8c9b97fce 100644 --- a/plugins/tunnels/locales/translated/ar_SA.json +++ b/plugins/tunnels/locales/translated/ar_SA.json @@ -26,7 +26,11 @@ "tunnelModeRemoteDesc": "إعادة توجيه منفذ على الخادم البعيد إلى منفذ محلي على جهازك.", "tunnelRequirementsText": "يجب أن يحتوي خادم SSH على الإعدادات GatewayPorts yes و AllowTcpForwarding yes و PermitRootLogin yes في الملف /etc/ssh/sshd_config.", "tunnelSettings": "إعدادات النفق", - "tunnelType": "نوع النفق" + "tunnelType": "نوع النفق", + "bindHost": "مضيف الربط", + "docsLink": "عرض المستندات", + "hostNotFound": "المضيف غير موجود", + "loadingHost": "جارٍ تحميل المضيف..." }, "nav": { "portForwarding": "إعادة التوجيه", @@ -134,6 +138,12 @@ "typeDynamic": "ديناميكي (-D)", "typeLocal": "محلي (-L)", "typeRemote": "بعيد (-R)", - "working": "جارٍ العمل..." + "working": "جارٍ العمل...", + "start": "تشغيل", + "stop": "إيقاف" + }, + "onboarding": { + "feature_tunnels": "الأنفاق", + "feature_tunnels_desc": "إعادة توجيه المنافذ عبر خادم للوصول إلى الخدمات غير المكشوفة." } } diff --git a/plugins/tunnels/locales/translated/bg_BG.json b/plugins/tunnels/locales/translated/bg_BG.json index 5a6cf1056..1b79d0ba5 100644 --- a/plugins/tunnels/locales/translated/bg_BG.json +++ b/plugins/tunnels/locales/translated/bg_BG.json @@ -26,7 +26,11 @@ "tunnelModeRemoteDesc": "Пренасочете порт на отдалечения сървър обратно към локален порт на вашата машина.", "tunnelRequirementsText": "SSH сървърът трябва да има зададени стойности за GatewayPorts (да), AllowTcpForwarding (да) и PermitRootLogin (да) в /etc/ssh/sshd_config.", "tunnelSettings": "Настройки на тунела", - "tunnelType": "Тип тунел" + "tunnelType": "Тип тунел", + "bindHost": "Свързване на хост", + "docsLink": "Преглед на документи", + "hostNotFound": "Хостът не е намерен", + "loadingHost": "Зареждане на хоста..." }, "nav": { "portForwarding": "Препращане", @@ -134,6 +138,12 @@ "typeDynamic": "Динамичен (-D)", "typeLocal": "Местен (-L)", "typeRemote": "Дистанционно (-R)", - "working": "Работа..." + "working": "Работа...", + "start": "Старт", + "stop": "Спри" + }, + "onboarding": { + "feature_tunnels": "Тунели", + "feature_tunnels_desc": "Пренасочване на портове през сървър, за да се достигне до услуги, които не са изложени на риск." } } diff --git a/plugins/tunnels/locales/translated/bn_BD.json b/plugins/tunnels/locales/translated/bn_BD.json index 095da443e..1fcf1aa31 100644 --- a/plugins/tunnels/locales/translated/bn_BD.json +++ b/plugins/tunnels/locales/translated/bn_BD.json @@ -26,7 +26,11 @@ "tunnelModeRemoteDesc": "রিমোট সার্ভারের একটি পোর্ট আপনার মেশিনের লোকাল পোর্টে ফরওয়ার্ড করুন।", "tunnelRequirementsText": "SSH সার্ভারের /etc/ssh/sshd_config ফাইলে GatewayPorts yes, AllowTcpForwarding yes, এবং PermitRootLogin yes সেট করা থাকতে হবে।", "tunnelSettings": "টানেল সেটিংস", - "tunnelType": "টানেল টাইপ" + "tunnelType": "টানেল টাইপ", + "bindHost": "হোস্টকে বাঁধুন", + "docsLink": "নথি দেখুন", + "hostNotFound": "হোস্ট খুঁজে পাওয়া যায়নি", + "loadingHost": "হোস্ট লোড হচ্ছে..." }, "nav": { "portForwarding": "ফরোয়ার্ডিং", @@ -134,6 +138,12 @@ "typeDynamic": "গতিশীল (-D)", "typeLocal": "স্থানীয় (-L)", "typeRemote": "রিমোট (-R)", - "working": "কাজ চলছে..." + "working": "কাজ চলছে...", + "start": "শুরু করুন", + "stop": "থামুন" + }, + "onboarding": { + "feature_tunnels": "টানেল", + "feature_tunnels_desc": "যেসব পরিষেবা উন্মুক্ত নয়, সেগুলোতে পৌঁছানোর জন্য পোর্টগুলো একটি সার্ভারের মাধ্যমে ফরওয়ার্ড করুন।" } } diff --git a/plugins/tunnels/locales/translated/ca_ES.json b/plugins/tunnels/locales/translated/ca_ES.json index ef26da59d..c154eb8f3 100644 --- a/plugins/tunnels/locales/translated/ca_ES.json +++ b/plugins/tunnels/locales/translated/ca_ES.json @@ -26,7 +26,11 @@ "tunnelModeRemoteDesc": "Reenvia un port del servidor remot a un port local de la teva màquina.", "tunnelRequirementsText": "El servidor SSH ha de tenir definits GatewayPorts sí, AllowTcpForwarding sí i PermitRootLogin sí a /etc/ssh/sshd_config.", "tunnelSettings": "Configuració del túnel", - "tunnelType": "Tipus de túnel" + "tunnelType": "Tipus de túnel", + "bindHost": "Vincula l'amfitrió", + "docsLink": "Veure documents", + "hostNotFound": "No s'ha trobat l'amfitrió", + "loadingHost": "S'està carregant l'amfitrió..." }, "nav": { "portForwarding": "Reenviament", @@ -134,6 +138,12 @@ "typeDynamic": "Dinàmic (-D)", "typeLocal": "Local (-L)", "typeRemote": "Comandament a distància (-R)", - "working": "Treballant..." + "working": "Treballant...", + "start": "Inici", + "stop": "Atura" + }, + "onboarding": { + "feature_tunnels": "Túnels", + "feature_tunnels_desc": "Reenvia ports a través d'un servidor per arribar a serveis que no estan exposats." } } diff --git a/plugins/tunnels/locales/translated/cs_CZ.json b/plugins/tunnels/locales/translated/cs_CZ.json index b1e5021d6..bb626b043 100644 --- a/plugins/tunnels/locales/translated/cs_CZ.json +++ b/plugins/tunnels/locales/translated/cs_CZ.json @@ -26,7 +26,11 @@ "tunnelModeRemoteDesc": "Přesměrujte port na vzdáleném serveru zpět na lokální port na vašem počítači.", "tunnelRequirementsText": "SSH server musí mít v souboru /etc/ssh/sshd_config nastaveny hodnoty GatewayPorts – yes, AllowTcpForwarding – yes a PermitRootLogin – yes.", "tunnelSettings": "Nastavení tunelu", - "tunnelType": "Typ tunelu" + "tunnelType": "Typ tunelu", + "bindHost": "Vázat hostitele", + "docsLink": "Zobrazit dokumenty", + "hostNotFound": "Hostitel nenalezen", + "loadingHost": "Načítání hostitele..." }, "nav": { "portForwarding": "Přeposílání", @@ -134,6 +138,12 @@ "typeDynamic": "Dynamický (-D)", "typeLocal": "Místní (-L)", "typeRemote": "Vzdálené (-R)", - "working": "Pracovní..." + "working": "Pracovní...", + "start": "Start", + "stop": "Zastávka" + }, + "onboarding": { + "feature_tunnels": "Tunely", + "feature_tunnels_desc": "Přesměrování portů přes server pro přístup ke službám, které nejsou vystaveny." } } diff --git a/plugins/tunnels/locales/translated/da_DK.json b/plugins/tunnels/locales/translated/da_DK.json index 36d79ef82..f4cc42db7 100644 --- a/plugins/tunnels/locales/translated/da_DK.json +++ b/plugins/tunnels/locales/translated/da_DK.json @@ -26,7 +26,11 @@ "tunnelModeRemoteDesc": "Videresend en port på den eksterne server tilbage til en lokal port på din maskine.", "tunnelRequirementsText": "SSH-serveren skal have GatewayPorts angivet ja, AllowTcpForwarding ja og PermitRootLogin ja i /etc/ssh/sshd_config.", "tunnelSettings": "Tunnelindstillinger", - "tunnelType": "Tunneltype" + "tunnelType": "Tunneltype", + "bindHost": "Bind vært", + "docsLink": "Se dokumenter", + "hostNotFound": "Værten blev ikke fundet", + "loadingHost": "Indlæser vært..." }, "nav": { "portForwarding": "Videresendelse", @@ -134,6 +138,12 @@ "typeDynamic": "Dynamisk (-D)", "typeLocal": "Lokal (-L)", "typeRemote": "Fjernbetjening (-R)", - "working": "Arbejder..." + "working": "Arbejder...", + "start": "Starte", + "stop": "Stop" + }, + "onboarding": { + "feature_tunnels": "Tunneler", + "feature_tunnels_desc": "Videresend porte via en server for at nå tjenester, der ikke er eksponerede." } } diff --git a/plugins/tunnels/locales/translated/de_DE.json b/plugins/tunnels/locales/translated/de_DE.json index d3657cf33..b8b63ee08 100644 --- a/plugins/tunnels/locales/translated/de_DE.json +++ b/plugins/tunnels/locales/translated/de_DE.json @@ -26,7 +26,11 @@ "tunnelModeRemoteDesc": "Leitet einen Port auf dem Remote-Server zurück zu einem lokalen Port auf Ihrem Rechner weiter.", "tunnelRequirementsText": "Der SSH-Server muss in /etc/ssh/sshd_config die Optionen GatewayPorts yes, AllowTcpForwarding yes und PermitRootLogin yes gesetzt haben.", "tunnelSettings": "Tunnel-Einstellungen", - "tunnelType": "Tunneltyp" + "tunnelType": "Tunneltyp", + "bindHost": "Bind-Host", + "docsLink": "Dokumentation anzeigen", + "hostNotFound": "Host nicht gefunden", + "loadingHost": "Host wird geladen..." }, "nav": { "portForwarding": "Weiterleitung", @@ -134,6 +138,12 @@ "typeDynamic": "Dynamisch (-D)", "typeLocal": "Lokal (-L)", "typeRemote": "Remote (-R)", - "working": "In Bearbeitung..." + "working": "In Bearbeitung...", + "start": "Start", + "stop": "Stop" + }, + "onboarding": { + "feature_tunnels": "Tunnel", + "feature_tunnels_desc": "Leiten Sie Ports über einen Server weiter, um Dienste zu erreichen, die nicht öffentlich zugänglich sind." } } diff --git a/plugins/tunnels/locales/translated/el_GR.json b/plugins/tunnels/locales/translated/el_GR.json index 341d80fd9..aab35448b 100644 --- a/plugins/tunnels/locales/translated/el_GR.json +++ b/plugins/tunnels/locales/translated/el_GR.json @@ -26,7 +26,11 @@ "tunnelModeRemoteDesc": "Προωθήστε μια θύρα στον απομακρυσμένο διακομιστή πίσω σε μια τοπική θύρα στο μηχάνημά σας.", "tunnelRequirementsText": "Ο διακομιστής SSH πρέπει να έχει ορίσει τις τιμές GatewayPorts yes, AllowTcpForwarding yes και PermitRootLogin yes στο /etc/ssh/sshd_config.", "tunnelSettings": "Ρυθμίσεις σήραγγας", - "tunnelType": "Τύπος σήραγγας" + "tunnelType": "Τύπος σήραγγας", + "bindHost": "Bind Host", + "docsLink": "Προβολή εγγράφων", + "hostNotFound": "Δεν βρέθηκε κεντρικός υπολογιστής", + "loadingHost": "Φόρτωση κεντρικού υπολογιστή..." }, "nav": { "portForwarding": "Προώθηση", @@ -134,6 +138,12 @@ "typeDynamic": "Δυναμικό (-D)", "typeLocal": "Τοπικό (-L)", "typeRemote": "Τηλεχειριστήριο (-R)", - "working": "Εργαζόμενος..." + "working": "Εργαζόμενος...", + "start": "Αρχή", + "stop": "Στάση" + }, + "onboarding": { + "feature_tunnels": "Σήραγγες", + "feature_tunnels_desc": "Προώθηση θυρών μέσω ενός διακομιστή για πρόσβαση σε υπηρεσίες που δεν είναι εκτεθειμένες." } } diff --git a/plugins/tunnels/locales/translated/es_ES.json b/plugins/tunnels/locales/translated/es_ES.json index a89455510..860843f49 100644 --- a/plugins/tunnels/locales/translated/es_ES.json +++ b/plugins/tunnels/locales/translated/es_ES.json @@ -26,7 +26,11 @@ "tunnelModeRemoteDesc": "Reenviar un puerto del servidor remoto a un puerto local en tu equipo.", "tunnelRequirementsText": "El servidor SSH debe tener GatewayPorts yes, AllowTcpForwarding yes y PermitRootLogin yes configurados en /etc/ssh/sshd_config.", "tunnelSettings": "Configuración de túnel", - "tunnelType": "Tipo de túnel" + "tunnelType": "Tipo de túnel", + "bindHost": "Host de enlace", + "docsLink": "Ver documentación", + "hostNotFound": "Host no encontrado", + "loadingHost": "Cargando host..." }, "nav": { "portForwarding": "Reenvío", @@ -134,6 +138,12 @@ "typeDynamic": "Dinámico (-D)", "typeLocal": "Local (-L)", "typeRemote": "Remoto (-R)", - "working": "Trabajando..." + "working": "Trabajando...", + "start": "Iniciar", + "stop": "Detener" + }, + "onboarding": { + "feature_tunnels": "Túneles", + "feature_tunnels_desc": "Reenvía puertos a través de un servidor para acceder a servicios que no están expuestos." } } diff --git a/plugins/tunnels/locales/translated/fi_FI.json b/plugins/tunnels/locales/translated/fi_FI.json index 9092450b5..d6a1f581c 100644 --- a/plugins/tunnels/locales/translated/fi_FI.json +++ b/plugins/tunnels/locales/translated/fi_FI.json @@ -26,7 +26,11 @@ "tunnelModeRemoteDesc": "Lähetä etäpalvelimen portti takaisin oman koneesi paikalliseen porttiin.", "tunnelRequirementsText": "SSH-palvelimella on oltava GatewayPorts-, AllowTcpForwarding- ja PermitRootLogin-arvot asetettuina tiedostossa /etc/ssh/sshd_config.", "tunnelSettings": "Tunnelin asetukset", - "tunnelType": "Tunnelin tyyppi" + "tunnelType": "Tunnelin tyyppi", + "bindHost": "Sido isäntä", + "docsLink": "Näytä dokumentit", + "hostNotFound": "Isäntää ei löydy", + "loadingHost": "Ladataan isäntää..." }, "nav": { "portForwarding": "Edelleenlähetys", @@ -134,6 +138,12 @@ "typeDynamic": "Dynaaminen (-D)", "typeLocal": "Paikallinen (-L)", "typeRemote": "Kauko-ohjain (-R)", - "working": "Työskentely..." + "working": "Työskentely...", + "start": "Aloita", + "stop": "Stop" + }, + "onboarding": { + "feature_tunnels": "Tunnelit", + "feature_tunnels_desc": "Lähetä portteja palvelimen kautta tavoittaaksesi palvelut, jotka eivät ole alttiina." } } diff --git a/plugins/tunnels/locales/translated/fr_FR.json b/plugins/tunnels/locales/translated/fr_FR.json index dff98f7bc..aa716b43e 100644 --- a/plugins/tunnels/locales/translated/fr_FR.json +++ b/plugins/tunnels/locales/translated/fr_FR.json @@ -26,7 +26,11 @@ "tunnelModeRemoteDesc": "Redirige un port sur le serveur distant vers un port local sur votre machine.", "tunnelRequirementsText": "Le serveur SSH doit avoir GatewayPorts yes, AllowTcpForwarding yes et PermitRootLogin yes définis dans /etc/ssh/sshd_config.", "tunnelSettings": "Paramètres du tunnel", - "tunnelType": "Type de tunnel" + "tunnelType": "Type de tunnel", + "bindHost": "Hôte de liaison", + "docsLink": "Voir la documentation", + "hostNotFound": "Hôte introuvable", + "loadingHost": "Chargement de l'hôte..." }, "nav": { "portForwarding": "Expéditeur", @@ -134,6 +138,12 @@ "typeDynamic": "Dynamique (-D)", "typeLocal": "Local (-L)", "typeRemote": "Distant (-R)", - "working": "En cours…" + "working": "En cours…", + "start": "Démarrer", + "stop": "Arrêter" + }, + "onboarding": { + "feature_tunnels": "Tunnels", + "feature_tunnels_desc": "Redirigez les ports via un serveur pour accéder aux services non exposés." } } diff --git a/plugins/tunnels/locales/translated/he_IL.json b/plugins/tunnels/locales/translated/he_IL.json index 2890d2b45..bdd9f1736 100644 --- a/plugins/tunnels/locales/translated/he_IL.json +++ b/plugins/tunnels/locales/translated/he_IL.json @@ -26,7 +26,11 @@ "tunnelModeRemoteDesc": "העבר פורט בשרת המרוחק חזרה לפורט מקומי במחשב שלך.", "tunnelRequirementsText": "שרת ה-SSH חייב להגדיר את האפשרויות GatewayPorts כן, AllowTcpForwarding כן, ו-PermitRootLogin כן ב-/etc/ssh/sshd_config.", "tunnelSettings": "הגדרות מנהרה", - "tunnelType": "סוג המנהרה" + "tunnelType": "סוג המנהרה", + "bindHost": "מארח קשירה", + "docsLink": "הצג מסמכים", + "hostNotFound": "המארח לא נמצא", + "loadingHost": "טוען מארח..." }, "nav": { "portForwarding": "העברה", @@ -134,6 +138,12 @@ "typeDynamic": "דינמי (-D)", "typeLocal": "מקומי (-L)", "typeRemote": "מרחוק (-R)", - "working": "עובד..." + "working": "עובד...", + "start": "הַתחָלָה", + "stop": "לְהַפְסִיק" + }, + "onboarding": { + "feature_tunnels": "מנהרות", + "feature_tunnels_desc": "העברת פורטים דרך שרת כדי להגיע לשירותים שאינם חשופים." } } diff --git a/plugins/tunnels/locales/translated/hi_IN.json b/plugins/tunnels/locales/translated/hi_IN.json index 6494bcce7..e941b5ccc 100644 --- a/plugins/tunnels/locales/translated/hi_IN.json +++ b/plugins/tunnels/locales/translated/hi_IN.json @@ -26,7 +26,11 @@ "tunnelModeRemoteDesc": "दूरस्थ सर्वर पर एक पोर्ट को अपनी मशीन पर स्थानीय पोर्ट पर वापस अग्रेषित करें।", "tunnelRequirementsText": "SSH सर्वर में /etc/ssh/sshd_config में GatewayPorts yes, AllowTcpForwarding yes, और PermitRootLogin yes सेट होना चाहिए।", "tunnelSettings": "टनल सेटिंग्स", - "tunnelType": "टनल प्रकार" + "tunnelType": "टनल प्रकार", + "bindHost": "बाइंड होस्ट", + "docsLink": "दस्तावेज़ देखें", + "hostNotFound": "होस्ट नहीं मिला", + "loadingHost": "होस्ट लोड हो रहा है..." }, "nav": { "portForwarding": "अग्रेषित करना", @@ -134,6 +138,12 @@ "typeDynamic": "डायनामिक (-D)", "typeLocal": "स्थानीय (-L)", "typeRemote": "दूरस्थ (-R)", - "working": "कार्यरत..." + "working": "कार्यरत...", + "start": "शुरू करें", + "stop": "बंद करें" + }, + "onboarding": { + "feature_tunnels": "सुरंगों", + "feature_tunnels_desc": "सर्वर के माध्यम से पोर्ट को फॉरवर्ड करके उन सेवाओं तक पहुंचें जो उपलब्ध नहीं हैं।" } } diff --git a/plugins/tunnels/locales/translated/hu_HU.json b/plugins/tunnels/locales/translated/hu_HU.json index e9c012e5e..0f40db650 100644 --- a/plugins/tunnels/locales/translated/hu_HU.json +++ b/plugins/tunnels/locales/translated/hu_HU.json @@ -26,7 +26,11 @@ "tunnelModeRemoteDesc": "Továbbítsd a távoli szerver egyik portját a saját gépeden lévő helyi portra.", "tunnelRequirementsText": "Az SSH szervernek a /etc/ssh/sshd_config fájlban be kell állítania a GatewayPorts yes, az AllowTcpForwarding yes és a PermitRootLogin yes értékeket.", "tunnelSettings": "Alagútbeállítások", - "tunnelType": "Alagút típusa" + "tunnelType": "Alagút típusa", + "bindHost": "Kötőállomás", + "docsLink": "Dokumentumok megtekintése", + "hostNotFound": "Nem található gazdagép", + "loadingHost": "Gazdagép betöltése..." }, "nav": { "portForwarding": "Szállítmányozás", @@ -134,6 +138,12 @@ "typeDynamic": "Dinamikus (-D)", "typeLocal": "Helyi (-L)", "typeRemote": "Távoli (-R)", - "working": "Dolgozó..." + "working": "Dolgozó...", + "start": "Indul", + "stop": "Stop" + }, + "onboarding": { + "feature_tunnels": "Alagutak", + "feature_tunnels_desc": "Portok továbbítása egy szerveren keresztül a nem elérhető szolgáltatások eléréséhez." } } diff --git a/plugins/tunnels/locales/translated/id_ID.json b/plugins/tunnels/locales/translated/id_ID.json index 48c220fbf..1ad64517e 100644 --- a/plugins/tunnels/locales/translated/id_ID.json +++ b/plugins/tunnels/locales/translated/id_ID.json @@ -26,7 +26,11 @@ "tunnelModeRemoteDesc": "Teruskan port pada server jarak jauh kembali ke port lokal pada mesin Anda.", "tunnelRequirementsText": "Server SSH harus memiliki pengaturan GatewayPorts yes, AllowTcpForwarding yes, dan PermitRootLogin yes di /etc/ssh/sshd_config.", "tunnelSettings": "Pengaturan Terowongan", - "tunnelType": "Jenis Terowongan" + "tunnelType": "Jenis Terowongan", + "bindHost": "Host Terikat", + "docsLink": "Lihat dokumen", + "hostNotFound": "Host tidak ditemukan", + "loadingHost": "Memuat host..." }, "nav": { "portForwarding": "Meneruskan", @@ -134,6 +138,12 @@ "typeDynamic": "Dinamis (-D)", "typeLocal": "Lokal (-L)", "typeRemote": "Jarak Jauh (-R)", - "working": "Bekerja..." + "working": "Bekerja...", + "start": "Awal", + "stop": "Berhenti" + }, + "onboarding": { + "feature_tunnels": "Terowongan", + "feature_tunnels_desc": "Meneruskan port melalui server untuk mengakses layanan yang tidak terekspos." } } diff --git a/plugins/tunnels/locales/translated/it_IT.json b/plugins/tunnels/locales/translated/it_IT.json index 68831e8ec..d64c89dc6 100644 --- a/plugins/tunnels/locales/translated/it_IT.json +++ b/plugins/tunnels/locales/translated/it_IT.json @@ -26,7 +26,11 @@ "tunnelModeRemoteDesc": "Inoltra una porta sul server remoto verso una porta locale sulla tua macchina.", "tunnelRequirementsText": "Il server SSH deve avere GatewayPorts yes, AllowTcpForwarding yes e PermitRootLogin yes impostati in /etc/ssh/sshd_config.", "tunnelSettings": "Impostazioni tunnel", - "tunnelType": "Tipo di tunnel" + "tunnelType": "Tipo di tunnel", + "bindHost": "Host di bind", + "docsLink": "Visualizza documentazione", + "hostNotFound": "Host non trovato", + "loadingHost": "Caricamento host..." }, "nav": { "portForwarding": "Inoltro", @@ -134,6 +138,12 @@ "typeDynamic": "Dinamico (-D)", "typeLocal": "Locale (-L)", "typeRemote": "Remoto (-R)", - "working": "In corso..." + "working": "In corso...", + "start": "Avvia", + "stop": "Ferma" + }, + "onboarding": { + "feature_tunnels": "Gallerie", + "feature_tunnels_desc": "Inoltrare le porte attraverso un server per raggiungere servizi non esposti." } } diff --git a/plugins/tunnels/locales/translated/ja_JP.json b/plugins/tunnels/locales/translated/ja_JP.json index 0aa6f0cf7..3581f1b07 100644 --- a/plugins/tunnels/locales/translated/ja_JP.json +++ b/plugins/tunnels/locales/translated/ja_JP.json @@ -26,7 +26,11 @@ "tunnelModeRemoteDesc": "リモートサーバーのポートをローカルマシンのポートに転送します。", "tunnelRequirementsText": "SSHサーバーの/etc/ssh/sshd_configに、GatewayPorts yes、AllowTcpForwarding yes、PermitRootLogin yesが設定されている必要があります。", "tunnelSettings": "トンネル設定", - "tunnelType": "トンネルの種類" + "tunnelType": "トンネルの種類", + "bindHost": "バインドホスト", + "docsLink": "ドキュメントを表示", + "hostNotFound": "ホストが見つかりません", + "loadingHost": "ホストを読み込み中..." }, "nav": { "portForwarding": "転送", @@ -134,6 +138,12 @@ "typeDynamic": "ダイナミック (-D)", "typeLocal": "ローカル (-L)", "typeRemote": "リモート (-R)", - "working": "処理中..." + "working": "処理中...", + "start": "開始", + "stop": "停止" + }, + "onboarding": { + "feature_tunnels": "トンネル", + "feature_tunnels_desc": "公開されていないサービスにアクセスできるように、サーバー経由でポートを転送します。" } } diff --git a/plugins/tunnels/locales/translated/ko_KR.json b/plugins/tunnels/locales/translated/ko_KR.json index 83e167d60..c82a94082 100644 --- a/plugins/tunnels/locales/translated/ko_KR.json +++ b/plugins/tunnels/locales/translated/ko_KR.json @@ -26,7 +26,11 @@ "tunnelModeRemoteDesc": "원격 서버의 포트를 내 컴퓨터의 로컬 포트로 역방향 포워딩합니다.", "tunnelRequirementsText": "SSH 서버의 /etc/ssh/sshd_config에 GatewayPorts yes, AllowTcpForwarding yes, PermitRootLogin yes가 설정되어 있어야 합니다.", "tunnelSettings": "터널 설정", - "tunnelType": "터널 유형" + "tunnelType": "터널 유형", + "bindHost": "바인드 호스트", + "docsLink": "문서 보기", + "hostNotFound": "호스트를 찾을 수 없습니다", + "loadingHost": "호스트 로드 중..." }, "nav": { "portForwarding": "전송", @@ -134,6 +138,12 @@ "typeDynamic": "동적 (-D)", "typeLocal": "로컬 (-L)", "typeRemote": "원격 (-R)", - "working": "작업 중..." + "working": "작업 중...", + "start": "시작", + "stop": "중지" + }, + "onboarding": { + "feature_tunnels": "터널", + "feature_tunnels_desc": "서버를 통해 포트를 포워딩하여 외부에 노출되지 않은 서비스에 접근할 수 있습니다." } } diff --git a/plugins/tunnels/locales/translated/nl_NL.json b/plugins/tunnels/locales/translated/nl_NL.json index a8f18b73b..6356d1a31 100644 --- a/plugins/tunnels/locales/translated/nl_NL.json +++ b/plugins/tunnels/locales/translated/nl_NL.json @@ -26,7 +26,11 @@ "tunnelModeRemoteDesc": "Een poort op de externe server doorsturen naar een lokale poort op uw computer.", "tunnelRequirementsText": "De SSH-server moet de volgende instellingen hebben: GatewayPorts yes, AllowTcpForwarding yes en PermitRootLogin yes in /etc/ssh/sshd_config.", "tunnelSettings": "Tunnelinstellingen", - "tunnelType": "Tunneltype" + "tunnelType": "Tunneltype", + "bindHost": "Bind Host", + "docsLink": "Documenten bekijken", + "hostNotFound": "Host niet gevonden", + "loadingHost": "Host wordt geladen..." }, "nav": { "portForwarding": "Doorsturen", @@ -134,6 +138,12 @@ "typeDynamic": "Dynamisch (-D)", "typeLocal": "Lokaal (-L)", "typeRemote": "Afstandsbediening (-R)", - "working": "Bezig met verwerken..." + "working": "Bezig met verwerken...", + "start": "Begin", + "stop": "Stop" + }, + "onboarding": { + "feature_tunnels": "Tunnels", + "feature_tunnels_desc": "Poorten doorsturen via een server om toegang te krijgen tot services die niet openbaar toegankelijk zijn." } } diff --git a/plugins/tunnels/locales/translated/no_NO.json b/plugins/tunnels/locales/translated/no_NO.json index ff172fc3a..a528fc4c0 100644 --- a/plugins/tunnels/locales/translated/no_NO.json +++ b/plugins/tunnels/locales/translated/no_NO.json @@ -26,7 +26,11 @@ "tunnelModeRemoteDesc": "Videresend en port på den eksterne serveren tilbake til en lokal port på maskinen din.", "tunnelRequirementsText": "SSH-serveren må ha GatewayPorts ja, AllowTcpForwarding ja og PermitRootLogin ja angitt i /etc/ssh/sshd_config.", "tunnelSettings": "Tunnelinnstillinger", - "tunnelType": "Tunneltype" + "tunnelType": "Tunneltype", + "bindHost": "Bind vert", + "docsLink": "Vis dokumenter", + "hostNotFound": "Verten ble ikke funnet", + "loadingHost": "Laster inn vert ..." }, "nav": { "portForwarding": "Videresending", @@ -134,6 +138,12 @@ "typeDynamic": "Dynamisk (-D)", "typeLocal": "Lokal (-L)", "typeRemote": "Fjernkontroll (-R)", - "working": "Arbeider..." + "working": "Arbeider...", + "start": "Start", + "stop": "Stoppe" + }, + "onboarding": { + "feature_tunnels": "Tunneler", + "feature_tunnels_desc": "Videresend porter gjennom en server for å nå tjenester som ikke er eksponert." } } diff --git a/plugins/tunnels/locales/translated/pl_PL.json b/plugins/tunnels/locales/translated/pl_PL.json index 0cea9f5e1..229909064 100644 --- a/plugins/tunnels/locales/translated/pl_PL.json +++ b/plugins/tunnels/locales/translated/pl_PL.json @@ -26,7 +26,11 @@ "tunnelModeRemoteDesc": "Przekieruj port na serwerze zdalnym z powrotem do portu lokalnego na swoim komputerze.", "tunnelRequirementsText": "Serwer SSH musi mieć w /etc/ssh/sshd_config ustawione GatewayPorts yes, AllowTcpForwarding yes i PermitRootLogin yes.", "tunnelSettings": "Ustawienia tunelu", - "tunnelType": "Typ tunelu" + "tunnelType": "Typ tunelu", + "bindHost": "Host nasłuchu", + "docsLink": "Zobacz dokumentację", + "hostNotFound": "Nie znaleziono hosta", + "loadingHost": "Ładowanie hosta..." }, "nav": { "portForwarding": "Przekierowanie", @@ -134,6 +138,12 @@ "typeDynamic": "Dynamiczny (-D)", "typeLocal": "Lokalny (-L)", "typeRemote": "Zdalny (-R)", - "working": "Przetwarzanie..." + "working": "Przetwarzanie...", + "start": "Start", + "stop": "Zatrzymaj" + }, + "onboarding": { + "feature_tunnels": "Tunele", + "feature_tunnels_desc": "Przekierowuj porty przez serwer, aby dotrzeć do usług niewystawionych na zewnątrz." } } diff --git a/plugins/tunnels/locales/translated/pt_BR.json b/plugins/tunnels/locales/translated/pt_BR.json index f65d220bf..d75d2f97d 100644 --- a/plugins/tunnels/locales/translated/pt_BR.json +++ b/plugins/tunnels/locales/translated/pt_BR.json @@ -26,7 +26,11 @@ "tunnelModeRemoteDesc": "Encaminhe uma porta no servidor remoto de volta para uma porta local em sua máquina.", "tunnelRequirementsText": "O servidor SSH deve ter as seguintes configurações definidas em /etc/ssh/sshd_config: GatewayPorts yes, AllowTcpForwarding yes e PermitRootLogin yes.", "tunnelSettings": "Configurações do túnel", - "tunnelType": "Tipo de túnel" + "tunnelType": "Tipo de túnel", + "bindHost": "Vincular host", + "docsLink": "Ver documentos", + "hostNotFound": "Host não encontrado", + "loadingHost": "Carregando host..." }, "nav": { "portForwarding": "Encaminhamento", @@ -134,6 +138,12 @@ "typeDynamic": "Dinâmico (-D)", "typeLocal": "Local (-L)", "typeRemote": "Remoto (-R)", - "working": "Trabalhando..." + "working": "Trabalhando...", + "start": "Começar", + "stop": "Parar" + }, + "onboarding": { + "feature_tunnels": "Túneis", + "feature_tunnels_desc": "Encaminhar portas através de um servidor para alcançar serviços que não estão expostos." } } diff --git a/plugins/tunnels/locales/translated/pt_PT.json b/plugins/tunnels/locales/translated/pt_PT.json index b10f23f4d..b34fdda71 100644 --- a/plugins/tunnels/locales/translated/pt_PT.json +++ b/plugins/tunnels/locales/translated/pt_PT.json @@ -26,7 +26,11 @@ "tunnelModeRemoteDesc": "Reencaminhar uma porta no servidor remoto de volta para uma porta local na sua máquina.", "tunnelRequirementsText": "O servidor SSH deve ter GatewayPorts yes, AllowTcpForwarding yes e PermitRootLogin yes definidos em /etc/ssh/sshd_config.", "tunnelSettings": "Definições de túnel", - "tunnelType": "Tipo de túnel" + "tunnelType": "Tipo de túnel", + "bindHost": "Host de Ligação", + "docsLink": "Ver documentação", + "hostNotFound": "Host não encontrado", + "loadingHost": "A carregar o host..." }, "nav": { "portForwarding": "Encaminhamento", @@ -134,6 +138,12 @@ "typeDynamic": "Dinâmico (-D)", "typeLocal": "Local (-L)", "typeRemote": "Remoto (-R)", - "working": "A trabalhar..." + "working": "A trabalhar...", + "start": "Iniciar", + "stop": "Parar" + }, + "onboarding": { + "feature_tunnels": "Túneis", + "feature_tunnels_desc": "Encaminhar portas através de um servidor para chegar a serviços que não estão expostos." } } diff --git a/plugins/tunnels/locales/translated/ro_RO.json b/plugins/tunnels/locales/translated/ro_RO.json index 95e786ce4..becd4b122 100644 --- a/plugins/tunnels/locales/translated/ro_RO.json +++ b/plugins/tunnels/locales/translated/ro_RO.json @@ -26,7 +26,11 @@ "tunnelModeRemoteDesc": "Redirecționează un port de pe serverul la distanță înapoi către un port local de pe mașina ta.", "tunnelRequirementsText": "Serverul SSH trebuie să aibă setate GatewayPorts da, AllowTcpForwarding da și PermitRootLogin da în /etc/ssh/sshd_config.", "tunnelSettings": "Setări tunel", - "tunnelType": "Tipul de tunel" + "tunnelType": "Tipul de tunel", + "bindHost": "Legați gazda", + "docsLink": "Vizualizați documentele", + "hostNotFound": "Gazdă negăsită", + "loadingHost": "Se încarcă gazda..." }, "nav": { "portForwarding": "Redirecționare", @@ -134,6 +138,12 @@ "typeDynamic": "Dinamic (-D)", "typeLocal": "Local (-L)", "typeRemote": "Telecomandă (-R)", - "working": "Lucru..." + "working": "Lucru...", + "start": "Început", + "stop": "Stop" + }, + "onboarding": { + "feature_tunnels": "Tuneluri", + "feature_tunnels_desc": "Redirecționează porturile printr-un server pentru a accesa servicii care nu sunt expuse." } } diff --git a/plugins/tunnels/locales/translated/ru_RU.json b/plugins/tunnels/locales/translated/ru_RU.json index 0f2b0e30a..c6788aa5c 100644 --- a/plugins/tunnels/locales/translated/ru_RU.json +++ b/plugins/tunnels/locales/translated/ru_RU.json @@ -26,7 +26,11 @@ "tunnelModeRemoteDesc": "Пробросить порт на удалённом сервере на локальный порт вашей машины.", "tunnelRequirementsText": "На SSH-сервере должны быть установлены параметры GatewayPorts yes, AllowTcpForwarding yes и PermitRootLogin yes в /etc/ssh/sshd_config.", "tunnelSettings": "Настройки туннеля", - "tunnelType": "Тип туннеля" + "tunnelType": "Тип туннеля", + "bindHost": "Хост для привязки", + "docsLink": "Документация", + "hostNotFound": "Хост не найден", + "loadingHost": "Загрузка хоста..." }, "nav": { "portForwarding": "Пересылка", @@ -134,6 +138,12 @@ "typeDynamic": "Динамический (-D)", "typeLocal": "Локальный (-L)", "typeRemote": "Удалённый (-R)", - "working": "Выполняется..." + "working": "Выполняется...", + "start": "Запустить", + "stop": "Остановить" + }, + "onboarding": { + "feature_tunnels": "Туннели", + "feature_tunnels_desc": "Перенаправляйте порты через сервер для доступа к службам, которые не доступны извне." } } diff --git a/plugins/tunnels/locales/translated/sr_SP.json b/plugins/tunnels/locales/translated/sr_SP.json index d64e08b69..0de43196c 100644 --- a/plugins/tunnels/locales/translated/sr_SP.json +++ b/plugins/tunnels/locales/translated/sr_SP.json @@ -26,7 +26,11 @@ "tunnelModeRemoteDesc": "Проследите порт на удаљеном серверу назад на локални порт на вашој машини.", "tunnelRequirementsText": "SSH сервер мора имати подешена подешавања за GatewayPorts, AllowTcpForwarding и PermitRootLogin у /etc/ssh/sshd_config.", "tunnelSettings": "Подешавања тунела", - "tunnelType": "Тип тунела" + "tunnelType": "Тип тунела", + "bindHost": "Повежи хост", + "docsLink": "Прикажи документе", + "hostNotFound": "Хост није пронађен", + "loadingHost": "Учитавање хоста..." }, "nav": { "portForwarding": "Преусмеравање", @@ -134,6 +138,12 @@ "typeDynamic": "Динамички (-Д)", "typeLocal": "Локално (-Л)", "typeRemote": "Даљински (-R)", - "working": "Ради се..." + "working": "Ради се...", + "start": "Почетак", + "stop": "Заустави" + }, + "onboarding": { + "feature_tunnels": "Тунели", + "feature_tunnels_desc": "Прослеђујте портове кроз сервер да бисте дошли до сервиса који нису изложени." } } diff --git a/plugins/tunnels/locales/translated/sv_SE.json b/plugins/tunnels/locales/translated/sv_SE.json index b315cf508..5bfb1d19e 100644 --- a/plugins/tunnels/locales/translated/sv_SE.json +++ b/plugins/tunnels/locales/translated/sv_SE.json @@ -26,7 +26,11 @@ "tunnelModeRemoteDesc": "Vidarebefordra en port på fjärrservern tillbaka till en lokal port på din maskin.", "tunnelRequirementsText": "SSH-servern måste ha GatewayPorts ja, AllowTcpForwarding ja och PermitRootLogin ja angivna i /etc/ssh/sshd_config.", "tunnelSettings": "Tunnelinställningar", - "tunnelType": "Tunneltyp" + "tunnelType": "Tunneltyp", + "bindHost": "Bind värd", + "docsLink": "Visa dokument", + "hostNotFound": "Värden hittades inte", + "loadingHost": "Laddar värd..." }, "nav": { "portForwarding": "Spedition", @@ -134,6 +138,12 @@ "typeDynamic": "Dynamisk (-D)", "typeLocal": "Lokal (-L)", "typeRemote": "Fjärrkontroll (-R)", - "working": "Arbetssätt..." + "working": "Arbetssätt...", + "start": "Start", + "stop": "Stopp" + }, + "onboarding": { + "feature_tunnels": "Tunnlar", + "feature_tunnels_desc": "Vidarebefordra portar via en server för att nå tjänster som inte är exponerade." } } diff --git a/plugins/tunnels/locales/translated/th_TH.json b/plugins/tunnels/locales/translated/th_TH.json index 4e916ce40..c6849c6ce 100644 --- a/plugins/tunnels/locales/translated/th_TH.json +++ b/plugins/tunnels/locales/translated/th_TH.json @@ -26,7 +26,11 @@ "tunnelModeRemoteDesc": "ส่งต่อพอร์ตบนเซิร์ฟเวอร์ระยะไกลกลับมายังพอร์ตภายในเครื่องของคุณ", "tunnelRequirementsText": "เซิร์ฟเวอร์ SSH ต้องตั้งค่า GatewayPorts yes, AllowTcpForwarding yes และ PermitRootLogin yes ในไฟล์ /etc/ssh/sshd_config", "tunnelSettings": "การตั้งค่าอุโมงค์", - "tunnelType": "ประเภทอุโมงค์" + "tunnelType": "ประเภทอุโมงค์", + "bindHost": "โฮสต์ผูก", + "docsLink": "ดูเอกสาร", + "hostNotFound": "ไม่พบโฮสต์", + "loadingHost": "กำลังโหลดโฮสต์..." }, "nav": { "portForwarding": "การส่งต่อ", @@ -134,6 +138,12 @@ "typeDynamic": "ไดนามิก (-D)", "typeLocal": "ท้องถิ่น (-L)", "typeRemote": "รีโมท (-R)", - "working": "การทำงาน..." + "working": "การทำงาน...", + "start": "เริ่ม", + "stop": "หยุด" + }, + "onboarding": { + "feature_tunnels": "อุโมงค์", + "feature_tunnels_desc": "ส่งต่อพอร์ตผ่านเซิร์ฟเวอร์เพื่อเข้าถึงบริการที่ไม่เปิดเผยต่อสาธารณะ" } } diff --git a/plugins/tunnels/locales/translated/tr_TR.json b/plugins/tunnels/locales/translated/tr_TR.json index 853496539..48ad38849 100644 --- a/plugins/tunnels/locales/translated/tr_TR.json +++ b/plugins/tunnels/locales/translated/tr_TR.json @@ -26,7 +26,11 @@ "tunnelModeRemoteDesc": "Uzak sunucudaki bir portu, makinenizdeki yerel bir porta geri yönlendirin.", "tunnelRequirementsText": "SSH sunucusunda /etc/ssh/sshd_config dosyasında GatewayPorts yes, AllowTcpForwarding yes ve PermitRootLogin yes ayarlanmış olmalıdır.", "tunnelSettings": "Tünel Ayarları", - "tunnelType": "Tünel Türü" + "tunnelType": "Tünel Türü", + "bindHost": "Bağlanma Ana Bilgisayarı", + "docsLink": "Dokümanları görüntüle", + "hostNotFound": "Host bulunamadı", + "loadingHost": "Host yükleniyor..." }, "nav": { "portForwarding": "İletme", @@ -134,6 +138,12 @@ "typeDynamic": "Dinamik (-D)", "typeLocal": "Yerel (-L)", "typeRemote": "Uzak (-R)", - "working": "Çalışıyor..." + "working": "Çalışıyor...", + "start": "Başlat", + "stop": "Durdur" + }, + "onboarding": { + "feature_tunnels": "Tüneller", + "feature_tunnels_desc": "Sunucu üzerinden port yönlendirmesi yaparak, erişime açık olmayan hizmetlere ulaşabilirsiniz." } } diff --git a/plugins/tunnels/locales/translated/uk_UA.json b/plugins/tunnels/locales/translated/uk_UA.json index 122b3c81d..53d35028b 100644 --- a/plugins/tunnels/locales/translated/uk_UA.json +++ b/plugins/tunnels/locales/translated/uk_UA.json @@ -26,7 +26,11 @@ "tunnelModeRemoteDesc": "Перенаправте порт на віддаленому сервері назад на локальний порт на вашому комп'ютері.", "tunnelRequirementsText": "Для SSH-сервера у файлі /etc/ssh/sshd_config мають бути встановлені значення GatewayPorts: «так», AllowTcpForwarding: «так» та PermitRootLogin: «так».", "tunnelSettings": "Налаштування тунелю", - "tunnelType": "Тип тунелю" + "tunnelType": "Тип тунелю", + "bindHost": "Прив’язати хост", + "docsLink": "Переглянути документи", + "hostNotFound": "Хост не знайдено", + "loadingHost": "Завантаження хоста..." }, "nav": { "portForwarding": "Переадресація", @@ -134,6 +138,12 @@ "typeDynamic": "Динамічний (-D)", "typeLocal": "Місцевий (-L)", "typeRemote": "Віддалений (-R)", - "working": "Працюємо..." + "working": "Працюємо...", + "start": "Початок", + "stop": "СТІЙ" + }, + "onboarding": { + "feature_tunnels": "Тунелі", + "feature_tunnels_desc": "Переадресовувати порти через сервер для доступу до служб, які не піддаються впливу." } } diff --git a/plugins/tunnels/locales/translated/vi_VN.json b/plugins/tunnels/locales/translated/vi_VN.json index 297b50d85..72259638f 100644 --- a/plugins/tunnels/locales/translated/vi_VN.json +++ b/plugins/tunnels/locales/translated/vi_VN.json @@ -26,7 +26,11 @@ "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.", "tunnelRequirementsText": "Máy chủ SSH phải có GatewayPorts yes, AllowTcpForwarding yes, và PermitRootLogin yes được đặt trong /etc/ssh/sshd_config.", "tunnelSettings": "Cài đặt đường hầm", - "tunnelType": "Loại đường hầm" + "tunnelType": "Loại đường hầm", + "bindHost": "Máy chủ bind", + "docsLink": "Xem tài liệu", + "hostNotFound": "Không tìm thấy máy chủ", + "loadingHost": "Đang tải máy chủ..." }, "nav": { "portForwarding": "Chuyển tiếp", @@ -134,6 +138,12 @@ "typeDynamic": "Động (-D)", "typeLocal": "Cục bộ (-L)", "typeRemote": "Từ xa (-R)", - "working": "Đang làm việc..." + "working": "Đang làm việc...", + "start": "Bắt đầu", + "stop": "Dừng" + }, + "onboarding": { + "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." } } diff --git a/plugins/tunnels/locales/translated/zh_CN.json b/plugins/tunnels/locales/translated/zh_CN.json index 2d2baf4a2..3fa686429 100644 --- a/plugins/tunnels/locales/translated/zh_CN.json +++ b/plugins/tunnels/locales/translated/zh_CN.json @@ -26,7 +26,11 @@ "tunnelModeRemoteDesc": "将远程服务器上的端口转发回您机器上的本地端口。", "tunnelRequirementsText": "SSH 服务器必须在 /etc/ssh/sshd_config 中设置 GatewayPorts yes、AllowTcpForwarding yes 和 PermitRootLogin yes。", "tunnelSettings": "隧道设置", - "tunnelType": "隧道类型" + "tunnelType": "隧道类型", + "bindHost": "绑定主机", + "docsLink": "查看文档", + "hostNotFound": "未找到主机", + "loadingHost": "正在加载主机..." }, "nav": { "portForwarding": "转发", @@ -134,6 +138,12 @@ "typeDynamic": "动态 (-D)", "typeLocal": "本地 (-L)", "typeRemote": "远程 (-R)", - "working": "处理中..." + "working": "处理中...", + "start": "启动", + "stop": "停止" + }, + "onboarding": { + "feature_tunnels": "隧道", + "feature_tunnels_desc": "通过服务器转发端口以访问未暴露的服务。" } } diff --git a/plugins/tunnels/locales/translated/zh_TW.json b/plugins/tunnels/locales/translated/zh_TW.json index 96e0a5f93..7f3b603e7 100644 --- a/plugins/tunnels/locales/translated/zh_TW.json +++ b/plugins/tunnels/locales/translated/zh_TW.json @@ -26,7 +26,11 @@ "tunnelModeRemoteDesc": "將遠端伺服器的連接埠轉送回本機的連接埠。", "tunnelRequirementsText": "SSH 伺服器必須在 /etc/ssh/sshd_config 中設定 GatewayPorts yes、AllowTcpForwarding yes 以及 PermitRootLogin yes。", "tunnelSettings": "通道設定", - "tunnelType": "通道類型" + "tunnelType": "通道類型", + "bindHost": "綁定主機", + "docsLink": "檢視文件", + "hostNotFound": "找不到主機", + "loadingHost": "正在載入主機..." }, "nav": { "portForwarding": "轉發", @@ -134,6 +138,12 @@ "typeDynamic": "動態 (-D)", "typeLocal": "本機 (-L)", "typeRemote": "遠端 (-R)", - "working": "處理中..." + "working": "處理中...", + "start": "啟動", + "stop": "停止" + }, + "onboarding": { + "feature_tunnels": "隧道", + "feature_tunnels_desc": "透過伺服器轉送連接埠以存取未公開的服務。" } } diff --git a/plugins/wake-on-lan/src/frontend/host-action.ts b/plugins/wake-on-lan/src/frontend/host-action.ts index d0dcacc5b..bcc121121 100644 --- a/plugins/wake-on-lan/src/frontend/host-action.ts +++ b/plugins/wake-on-lan/src/frontend/host-action.ts @@ -1,10 +1,14 @@ import { toast } from "sonner"; -import type { PluginApiClient, TermixApp } from "@termix/plugin-sdk/frontend"; +import type { + PluginApiClient, + PluginHostRecord, + TermixApp, +} from "@termix/plugin-sdk/frontend"; -export function hasMacAddress(host: Record): boolean { - const settings = host.pluginSettings as - Record> | undefined; - const macAddress = settings?.["wake-on-lan"]?.macAddress; +export function hasMacAddress( + host: Pick, +): boolean { + const macAddress = host.pluginSettings?.["wake-on-lan"]?.macAddress; return typeof macAddress === "string" && macAddress.trim().length > 0; } diff --git a/plugins/wake-on-lan/src/frontend/index.tsx b/plugins/wake-on-lan/src/frontend/index.tsx index 1bb2b490a..084a16e5a 100644 --- a/plugins/wake-on-lan/src/frontend/index.tsx +++ b/plugins/wake-on-lan/src/frontend/index.tsx @@ -9,7 +9,7 @@ export function activate(app: TermixApp): void { icon: Zap, kind: "open", order: 50, - when: (host) => hasMacAddress(host as Record), + when: (host) => hasMacAddress(host), run: (host) => wakeHost(app.api, app.t, String(host.id)), }); } diff --git a/plugins/web-endpoint/locales/en.json b/plugins/web-endpoint/locales/en.json index 300f5a0bf..6e633f96d 100644 --- a/plugins/web-endpoint/locales/en.json +++ b/plugins/web-endpoint/locales/en.json @@ -47,6 +47,7 @@ "webUiIgnoreCert": "Allow invalid certificate", "webUiIgnoreCertDesc": "Direct endpoints only. Loopback is already exempt, so this has no effect on tunnel endpoints.", "webUiRemoveEndpoint": "Remove endpoint", - "webUiOpenFailed": "Failed to open the web endpoint" + "webUiOpenFailed": "Failed to open the web endpoint", + "bindHost": "Bind Host" } } diff --git a/plugins/web-endpoint/locales/translated/af_ZA.json b/plugins/web-endpoint/locales/translated/af_ZA.json index cc714d7e4..8c141c578 100644 --- a/plugins/web-endpoint/locales/translated/af_ZA.json +++ b/plugins/web-endpoint/locales/translated/af_ZA.json @@ -47,6 +47,7 @@ "webUiIgnoreCert": "Laat ongeldige sertifikaat toe", "webUiIgnoreCertDesc": "Slegs direkte eindpunte. Teruglus is reeds vrygestel, dus het dit geen effek op tonneleindpunte nie.", "webUiRemoveEndpoint": "Verwyder eindpunt", - "webUiOpenFailed": "Kon nie die web-eindpunt oopmaak nie" + "webUiOpenFailed": "Kon nie die web-eindpunt oopmaak nie", + "bindHost": "Bind gasheer" } } diff --git a/plugins/web-endpoint/locales/translated/ar_SA.json b/plugins/web-endpoint/locales/translated/ar_SA.json index e23cc1a7b..6cdcc930e 100644 --- a/plugins/web-endpoint/locales/translated/ar_SA.json +++ b/plugins/web-endpoint/locales/translated/ar_SA.json @@ -47,6 +47,7 @@ "webUiIgnoreCert": "السماح بشهادة غير صالحة", "webUiIgnoreCertDesc": "نقاط النهاية المباشرة فقط. تم إعفاء نقاط نهاية Loopback بالفعل، لذا لن يكون لهذا أي تأثير على نقاط نهاية النفق.", "webUiRemoveEndpoint": "إزالة نقطة النهاية", - "webUiOpenFailed": "فشل فتح نقطة نهاية الويب" + "webUiOpenFailed": "فشل فتح نقطة نهاية الويب", + "bindHost": "مضيف الربط" } } diff --git a/plugins/web-endpoint/locales/translated/bg_BG.json b/plugins/web-endpoint/locales/translated/bg_BG.json index 85bc7d6b7..703d95863 100644 --- a/plugins/web-endpoint/locales/translated/bg_BG.json +++ b/plugins/web-endpoint/locales/translated/bg_BG.json @@ -47,6 +47,7 @@ "webUiIgnoreCert": "Разрешаване на невалиден сертификат", "webUiIgnoreCertDesc": "Само директни крайни точки. Loopback вече е изключен, така че това няма ефект върху крайните точки на тунела.", "webUiRemoveEndpoint": "Премахване на крайната точка", - "webUiOpenFailed": "Неуспешно отваряне на уеб крайната точка" + "webUiOpenFailed": "Неуспешно отваряне на уеб крайната точка", + "bindHost": "Свързване на хост" } } diff --git a/plugins/web-endpoint/locales/translated/bn_BD.json b/plugins/web-endpoint/locales/translated/bn_BD.json index e98cc8aa6..646c11816 100644 --- a/plugins/web-endpoint/locales/translated/bn_BD.json +++ b/plugins/web-endpoint/locales/translated/bn_BD.json @@ -47,6 +47,7 @@ "webUiIgnoreCert": "অবৈধ সার্টিফিকেট অনুমোদন করুন", "webUiIgnoreCertDesc": "শুধুমাত্র ডাইরেক্ট এন্ডপয়েন্টগুলোর জন্য প্রযোজ্য। লুপব্যাক ইতিমধ্যে অব্যাহতিপ্রাপ্ত, তাই টানেল এন্ডপয়েন্টগুলোর উপর এর কোনো প্রভাব নেই।", "webUiRemoveEndpoint": "এন্ডপয়েন্ট সরান", - "webUiOpenFailed": "ওয়েব এন্ডপয়েন্ট খুলতে ব্যর্থ হয়েছে" + "webUiOpenFailed": "ওয়েব এন্ডপয়েন্ট খুলতে ব্যর্থ হয়েছে", + "bindHost": "হোস্টকে বাঁধুন" } } diff --git a/plugins/web-endpoint/locales/translated/ca_ES.json b/plugins/web-endpoint/locales/translated/ca_ES.json index 895ace6a6..c00d7c8cf 100644 --- a/plugins/web-endpoint/locales/translated/ca_ES.json +++ b/plugins/web-endpoint/locales/translated/ca_ES.json @@ -47,6 +47,7 @@ "webUiIgnoreCert": "Permetre certificat no vàlid", "webUiIgnoreCertDesc": "Només punts finals directes. El bucle ja està exempt, per tant, això no té cap efecte sobre els punts finals del túnel.", "webUiRemoveEndpoint": "Elimina el punt final", - "webUiOpenFailed": "No s'ha pogut obrir el punt final web." + "webUiOpenFailed": "No s'ha pogut obrir el punt final web.", + "bindHost": "Vincula l'amfitrió" } } diff --git a/plugins/web-endpoint/locales/translated/cs_CZ.json b/plugins/web-endpoint/locales/translated/cs_CZ.json index e5544d4e7..7dededca2 100644 --- a/plugins/web-endpoint/locales/translated/cs_CZ.json +++ b/plugins/web-endpoint/locales/translated/cs_CZ.json @@ -47,6 +47,7 @@ "webUiIgnoreCert": "Povolit neplatný certifikát", "webUiIgnoreCertDesc": "Pouze přímé koncové body. Zpětná smyčka je již vyňata, takže to nemá žádný vliv na koncové body tunelu.", "webUiRemoveEndpoint": "Odebrat koncový bod", - "webUiOpenFailed": "Nepodařilo se otevřít webový koncový bod" + "webUiOpenFailed": "Nepodařilo se otevřít webový koncový bod", + "bindHost": "Vázat hostitele" } } diff --git a/plugins/web-endpoint/locales/translated/da_DK.json b/plugins/web-endpoint/locales/translated/da_DK.json index 4a7db0a2e..4c830376c 100644 --- a/plugins/web-endpoint/locales/translated/da_DK.json +++ b/plugins/web-endpoint/locales/translated/da_DK.json @@ -47,6 +47,7 @@ "webUiIgnoreCert": "Tillad ugyldigt certifikat", "webUiIgnoreCertDesc": "Kun direkte slutpunkter. Loopback er allerede undtaget, så dette har ingen effekt på tunnelslutpunkter.", "webUiRemoveEndpoint": "Fjern slutpunkt", - "webUiOpenFailed": "Kunne ikke åbne web-slutpunktet" + "webUiOpenFailed": "Kunne ikke åbne web-slutpunktet", + "bindHost": "Bind vært" } } diff --git a/plugins/web-endpoint/locales/translated/de_DE.json b/plugins/web-endpoint/locales/translated/de_DE.json index 4daaea2f4..737e79b9f 100644 --- a/plugins/web-endpoint/locales/translated/de_DE.json +++ b/plugins/web-endpoint/locales/translated/de_DE.json @@ -47,6 +47,7 @@ "webUiIgnoreCert": "Ungültiges Zertifikat zulassen", "webUiIgnoreCertDesc": "Nur direkte Endpunkte. Loopback ist bereits ausgenommen, daher hat dies keine Auswirkungen auf Tunnelendpunkte.", "webUiRemoveEndpoint": "Endpunkt entfernen", - "webUiOpenFailed": "Der Web-Endpunkt konnte nicht geöffnet werden." + "webUiOpenFailed": "Der Web-Endpunkt konnte nicht geöffnet werden.", + "bindHost": "Bind-Host" } } diff --git a/plugins/web-endpoint/locales/translated/el_GR.json b/plugins/web-endpoint/locales/translated/el_GR.json index 5c6225607..c51518622 100644 --- a/plugins/web-endpoint/locales/translated/el_GR.json +++ b/plugins/web-endpoint/locales/translated/el_GR.json @@ -47,6 +47,7 @@ "webUiIgnoreCert": "Να επιτρέπεται το μη έγκυρο πιστοποιητικό", "webUiIgnoreCertDesc": "Μόνο άμεσα τελικά σημεία. Η επαναφορά μέσω βρόχου εξαιρείται ήδη, επομένως αυτό δεν έχει καμία επίδραση στα τελικά σημεία σήραγγας.", "webUiRemoveEndpoint": "Αφαίρεση τελικού σημείου", - "webUiOpenFailed": "Αποτυχία ανοίγματος του τελικού σημείου ιστού" + "webUiOpenFailed": "Αποτυχία ανοίγματος του τελικού σημείου ιστού", + "bindHost": "Bind Host" } } diff --git a/plugins/web-endpoint/locales/translated/es_ES.json b/plugins/web-endpoint/locales/translated/es_ES.json index e8aa5b455..4a6f4fd37 100644 --- a/plugins/web-endpoint/locales/translated/es_ES.json +++ b/plugins/web-endpoint/locales/translated/es_ES.json @@ -47,6 +47,7 @@ "webUiIgnoreCert": "Permitir certificado no válido", "webUiIgnoreCertDesc": "Solo se aplican puntos finales directos. Loopback ya está exento, por lo que esto no afecta a los puntos finales de túnel.", "webUiRemoveEndpoint": "Eliminar punto final", - "webUiOpenFailed": "No se pudo abrir el punto final web." + "webUiOpenFailed": "No se pudo abrir el punto final web.", + "bindHost": "Host de enlace" } } diff --git a/plugins/web-endpoint/locales/translated/fi_FI.json b/plugins/web-endpoint/locales/translated/fi_FI.json index 2dbaa468f..776a6990b 100644 --- a/plugins/web-endpoint/locales/translated/fi_FI.json +++ b/plugins/web-endpoint/locales/translated/fi_FI.json @@ -47,6 +47,7 @@ "webUiIgnoreCert": "Salli virheellinen varmenne", "webUiIgnoreCertDesc": "Vain suorat päätepisteet. Loopback on jo vapautettu, joten tällä ei ole vaikutusta tunnelin päätepisteisiin.", "webUiRemoveEndpoint": "Poista päätepiste", - "webUiOpenFailed": "Verkkopäätepisteen avaaminen epäonnistui" + "webUiOpenFailed": "Verkkopäätepisteen avaaminen epäonnistui", + "bindHost": "Sido isäntä" } } diff --git a/plugins/web-endpoint/locales/translated/fr_FR.json b/plugins/web-endpoint/locales/translated/fr_FR.json index c1deb487a..b3f8cbe89 100644 --- a/plugins/web-endpoint/locales/translated/fr_FR.json +++ b/plugins/web-endpoint/locales/translated/fr_FR.json @@ -47,6 +47,7 @@ "webUiIgnoreCert": "Autoriser un certificat invalide", "webUiIgnoreCertDesc": "Seuls les points de terminaison directs sont concernés. Les points de terminaison de bouclage sont déjà exemptés ; cette mesure n’a donc aucun impact sur les points de terminaison de tunnel.", "webUiRemoveEndpoint": "Supprimer le point de terminaison", - "webUiOpenFailed": "Impossible d'ouvrir le point de terminaison Web" + "webUiOpenFailed": "Impossible d'ouvrir le point de terminaison Web", + "bindHost": "Hôte de liaison" } } diff --git a/plugins/web-endpoint/locales/translated/he_IL.json b/plugins/web-endpoint/locales/translated/he_IL.json index 44de7367a..b175fc8e7 100644 --- a/plugins/web-endpoint/locales/translated/he_IL.json +++ b/plugins/web-endpoint/locales/translated/he_IL.json @@ -47,6 +47,7 @@ "webUiIgnoreCert": "אפשר אישור לא חוקי", "webUiIgnoreCertDesc": "נקודות קצה ישירות בלבד. לולאה חוזרת כבר פטורה, כך שאין לכך השפעה על נקודות קצה של המנהרה.", "webUiRemoveEndpoint": "הסר את נקודת הקצה", - "webUiOpenFailed": "נכשלה פתיחת נקודת הקצה של האינטרנט" + "webUiOpenFailed": "נכשלה פתיחת נקודת הקצה של האינטרנט", + "bindHost": "מארח קשירה" } } diff --git a/plugins/web-endpoint/locales/translated/hi_IN.json b/plugins/web-endpoint/locales/translated/hi_IN.json index 8de98f681..93f1d7825 100644 --- a/plugins/web-endpoint/locales/translated/hi_IN.json +++ b/plugins/web-endpoint/locales/translated/hi_IN.json @@ -47,6 +47,7 @@ "webUiIgnoreCert": "अमान्य प्रमाणपत्र की अनुमति दें", "webUiIgnoreCertDesc": "केवल डायरेक्ट एंडपॉइंट्स के लिए। लूपबैक पहले से ही छूट प्राप्त है, इसलिए इसका टनल एंडपॉइंट्स पर कोई प्रभाव नहीं पड़ता।", "webUiRemoveEndpoint": "एंडपॉइंट हटाएँ", - "webUiOpenFailed": "वेब एंडपॉइंट खोलने में विफल।" + "webUiOpenFailed": "वेब एंडपॉइंट खोलने में विफल।", + "bindHost": "बाइंड होस्ट" } } diff --git a/plugins/web-endpoint/locales/translated/hu_HU.json b/plugins/web-endpoint/locales/translated/hu_HU.json index bf9c19153..455f8d9fa 100644 --- a/plugins/web-endpoint/locales/translated/hu_HU.json +++ b/plugins/web-endpoint/locales/translated/hu_HU.json @@ -47,6 +47,7 @@ "webUiIgnoreCert": "Érvénytelen tanúsítvány engedélyezése", "webUiIgnoreCertDesc": "Csak közvetlen végpontok. A visszacsatolás már mentesül ez alól, így ennek nincs hatása az alagút végpontjaira.", "webUiRemoveEndpoint": "Végpont eltávolítása", - "webUiOpenFailed": "Nem sikerült megnyitni a webes végpontot" + "webUiOpenFailed": "Nem sikerült megnyitni a webes végpontot", + "bindHost": "Kötőállomás" } } diff --git a/plugins/web-endpoint/locales/translated/id_ID.json b/plugins/web-endpoint/locales/translated/id_ID.json index a6a87648d..36c24c21f 100644 --- a/plugins/web-endpoint/locales/translated/id_ID.json +++ b/plugins/web-endpoint/locales/translated/id_ID.json @@ -47,6 +47,7 @@ "webUiIgnoreCert": "Izinkan sertifikat tidak valid", "webUiIgnoreCertDesc": "Hanya untuk endpoint langsung. Loopback sudah dikecualikan, jadi ini tidak berpengaruh pada endpoint tunnel.", "webUiRemoveEndpoint": "Hapus titik akhir", - "webUiOpenFailed": "Gagal membuka titik akhir web." + "webUiOpenFailed": "Gagal membuka titik akhir web.", + "bindHost": "Host Terikat" } } diff --git a/plugins/web-endpoint/locales/translated/it_IT.json b/plugins/web-endpoint/locales/translated/it_IT.json index 6e612fbdf..7514dd6f7 100644 --- a/plugins/web-endpoint/locales/translated/it_IT.json +++ b/plugins/web-endpoint/locales/translated/it_IT.json @@ -47,6 +47,7 @@ "webUiIgnoreCert": "Consenti certificato non valido", "webUiIgnoreCertDesc": "Solo endpoint diretti. Il loopback è già escluso, quindi ciò non ha alcun effetto sugli endpoint del tunnel.", "webUiRemoveEndpoint": "Rimuovi endpoint", - "webUiOpenFailed": "Impossibile aprire l'endpoint web" + "webUiOpenFailed": "Impossibile aprire l'endpoint web", + "bindHost": "Host di bind" } } diff --git a/plugins/web-endpoint/locales/translated/ja_JP.json b/plugins/web-endpoint/locales/translated/ja_JP.json index 89f4c06ce..bc9c2dea8 100644 --- a/plugins/web-endpoint/locales/translated/ja_JP.json +++ b/plugins/web-endpoint/locales/translated/ja_JP.json @@ -47,6 +47,7 @@ "webUiIgnoreCert": "無効な証明書を許可する", "webUiIgnoreCertDesc": "直接エンドポイントのみが対象です。ループバックは既に対象外となっているため、トンネルエンドポイントには影響しません。", "webUiRemoveEndpoint": "エンドポイントを削除", - "webUiOpenFailed": "ウェブエンドポイントを開くのに失敗しました" + "webUiOpenFailed": "ウェブエンドポイントを開くのに失敗しました", + "bindHost": "バインドホスト" } } diff --git a/plugins/web-endpoint/locales/translated/ko_KR.json b/plugins/web-endpoint/locales/translated/ko_KR.json index 8c296dd24..692e82141 100644 --- a/plugins/web-endpoint/locales/translated/ko_KR.json +++ b/plugins/web-endpoint/locales/translated/ko_KR.json @@ -47,6 +47,7 @@ "webUiIgnoreCert": "유효하지 않은 인증서를 허용합니다", "webUiIgnoreCertDesc": "직접 연결 엔드포인트에만 적용됩니다. 루프백은 이미 제외되어 있으므로 터널 엔드포인트에는 영향을 미치지 않습니다.", "webUiRemoveEndpoint": "엔드포인트를 제거합니다.", - "webUiOpenFailed": "웹 엔드포인트를 열 수 없습니다." + "webUiOpenFailed": "웹 엔드포인트를 열 수 없습니다.", + "bindHost": "바인드 호스트" } } diff --git a/plugins/web-endpoint/locales/translated/nl_NL.json b/plugins/web-endpoint/locales/translated/nl_NL.json index 74a54a876..23c1afcab 100644 --- a/plugins/web-endpoint/locales/translated/nl_NL.json +++ b/plugins/web-endpoint/locales/translated/nl_NL.json @@ -47,6 +47,7 @@ "webUiIgnoreCert": "Ongeldig certificaat toestaan", "webUiIgnoreCertDesc": "Alleen directe eindpunten. Loopback is al uitgezonderd, dus dit heeft geen effect op tunnel-eindpunten.", "webUiRemoveEndpoint": "Eindpunt verwijderen", - "webUiOpenFailed": "Het openen van het web-eindpunt is mislukt." + "webUiOpenFailed": "Het openen van het web-eindpunt is mislukt.", + "bindHost": "Bind Host" } } diff --git a/plugins/web-endpoint/locales/translated/no_NO.json b/plugins/web-endpoint/locales/translated/no_NO.json index 7610bb9a5..da57f61d7 100644 --- a/plugins/web-endpoint/locales/translated/no_NO.json +++ b/plugins/web-endpoint/locales/translated/no_NO.json @@ -47,6 +47,7 @@ "webUiIgnoreCert": "Tillat ugyldig sertifikat", "webUiIgnoreCertDesc": "Kun direkte endepunkter. Loopback er allerede unntatt, så dette har ingen effekt på tunnelendepunkter.", "webUiRemoveEndpoint": "Fjern endepunkt", - "webUiOpenFailed": "Kunne ikke åpne nettendepunktet" + "webUiOpenFailed": "Kunne ikke åpne nettendepunktet", + "bindHost": "Bind vert" } } diff --git a/plugins/web-endpoint/locales/translated/pl_PL.json b/plugins/web-endpoint/locales/translated/pl_PL.json index 1ee76631f..12fab860b 100644 --- a/plugins/web-endpoint/locales/translated/pl_PL.json +++ b/plugins/web-endpoint/locales/translated/pl_PL.json @@ -47,6 +47,7 @@ "webUiIgnoreCert": "Zezwól na nieprawidłowy certyfikat", "webUiIgnoreCertDesc": "Tylko bezpośrednie punkty końcowe. Pętla zwrotna jest już wyłączona, więc nie ma to wpływu na punkty końcowe tunelu.", "webUiRemoveEndpoint": "Usuń punkt końcowy", - "webUiOpenFailed": "Nie udało się otworzyć punktu końcowego sieci Web" + "webUiOpenFailed": "Nie udało się otworzyć punktu końcowego sieci Web", + "bindHost": "Host nasłuchu" } } diff --git a/plugins/web-endpoint/locales/translated/pt_BR.json b/plugins/web-endpoint/locales/translated/pt_BR.json index 77bc99d7e..1172da7d3 100644 --- a/plugins/web-endpoint/locales/translated/pt_BR.json +++ b/plugins/web-endpoint/locales/translated/pt_BR.json @@ -47,6 +47,7 @@ "webUiIgnoreCert": "Permitir certificado inválido", "webUiIgnoreCertDesc": "Apenas endpoints diretos. O loopback já está isento, portanto, isso não afeta os endpoints do túnel.", "webUiRemoveEndpoint": "Remover ponto final", - "webUiOpenFailed": "Falha ao abrir o endpoint da web" + "webUiOpenFailed": "Falha ao abrir o endpoint da web", + "bindHost": "Vincular host" } } diff --git a/plugins/web-endpoint/locales/translated/pt_PT.json b/plugins/web-endpoint/locales/translated/pt_PT.json index 23860ec89..cf89105fe 100644 --- a/plugins/web-endpoint/locales/translated/pt_PT.json +++ b/plugins/web-endpoint/locales/translated/pt_PT.json @@ -47,6 +47,7 @@ "webUiIgnoreCert": "Permitir certificado inválido", "webUiIgnoreCertDesc": "Apenas endpoints diretos. O loopback já está isento, pelo que isto não afeta os endpoints do túnel.", "webUiRemoveEndpoint": "Remover ponto final", - "webUiOpenFailed": "Falha ao abrir o endpoint web" + "webUiOpenFailed": "Falha ao abrir o endpoint web", + "bindHost": "Host de Ligação" } } diff --git a/plugins/web-endpoint/locales/translated/ro_RO.json b/plugins/web-endpoint/locales/translated/ro_RO.json index 7aa3bd105..035ef36ea 100644 --- a/plugins/web-endpoint/locales/translated/ro_RO.json +++ b/plugins/web-endpoint/locales/translated/ro_RO.json @@ -47,6 +47,7 @@ "webUiIgnoreCert": "Permiteți certificatul nevalid", "webUiIgnoreCertDesc": "Numai puncte finale directe. Loopback-ul este deja exceptat, deci acest lucru nu are efect asupra punctelor finale ale tunelului.", "webUiRemoveEndpoint": "Eliminați punctul final", - "webUiOpenFailed": "Nu s-a putut deschide endpoint-ul web" + "webUiOpenFailed": "Nu s-a putut deschide endpoint-ul web", + "bindHost": "Legați gazda" } } diff --git a/plugins/web-endpoint/locales/translated/ru_RU.json b/plugins/web-endpoint/locales/translated/ru_RU.json index 71a5f40ae..bd82aaf06 100644 --- a/plugins/web-endpoint/locales/translated/ru_RU.json +++ b/plugins/web-endpoint/locales/translated/ru_RU.json @@ -47,6 +47,7 @@ "webUiIgnoreCert": "Разрешить использование недействительного сертификата", "webUiIgnoreCertDesc": "Только прямые конечные точки. Замыкания (loopback) уже исключены, поэтому это не влияет на туннельные конечные точки.", "webUiRemoveEndpoint": "Удалить конечную точку", - "webUiOpenFailed": "Не удалось открыть веб-интерфейс." + "webUiOpenFailed": "Не удалось открыть веб-интерфейс.", + "bindHost": "Хост для привязки" } } diff --git a/plugins/web-endpoint/locales/translated/sr_SP.json b/plugins/web-endpoint/locales/translated/sr_SP.json index 06ea6134d..379787ae7 100644 --- a/plugins/web-endpoint/locales/translated/sr_SP.json +++ b/plugins/web-endpoint/locales/translated/sr_SP.json @@ -47,6 +47,7 @@ "webUiIgnoreCert": "Дозволи неважећи сертификат", "webUiIgnoreCertDesc": "Само директне крајње тачке. Повратна петља је већ изузета, тако да ово нема утицаја на крајње тачке тунела.", "webUiRemoveEndpoint": "Уклони крајњу тачку", - "webUiOpenFailed": "Отварање веб крајње тачке није успело" + "webUiOpenFailed": "Отварање веб крајње тачке није успело", + "bindHost": "Повежи хост" } } diff --git a/plugins/web-endpoint/locales/translated/sv_SE.json b/plugins/web-endpoint/locales/translated/sv_SE.json index 1b7a6aa74..06c0c9906 100644 --- a/plugins/web-endpoint/locales/translated/sv_SE.json +++ b/plugins/web-endpoint/locales/translated/sv_SE.json @@ -47,6 +47,7 @@ "webUiIgnoreCert": "Tillåt ogiltigt certifikat", "webUiIgnoreCertDesc": "Endast direkta slutpunkter. Loopback är redan undantaget, så detta har ingen effekt på tunnelslutpunkter.", "webUiRemoveEndpoint": "Ta bort slutpunkten", - "webUiOpenFailed": "Misslyckades med att öppna webbslutpunkten" + "webUiOpenFailed": "Misslyckades med att öppna webbslutpunkten", + "bindHost": "Bind värd" } } diff --git a/plugins/web-endpoint/locales/translated/th_TH.json b/plugins/web-endpoint/locales/translated/th_TH.json index 8dd61bf31..0dedfb22d 100644 --- a/plugins/web-endpoint/locales/translated/th_TH.json +++ b/plugins/web-endpoint/locales/translated/th_TH.json @@ -47,6 +47,7 @@ "webUiIgnoreCert": "อนุญาตให้ใช้ใบรับรองที่ไม่ถูกต้อง", "webUiIgnoreCertDesc": "เฉพาะปลายทางที่เชื่อมต่อโดยตรงเท่านั้น การเชื่อมต่อแบบ Loopback ได้รับการยกเว้นอยู่แล้ว ดังนั้นจึงไม่มีผลกระทบต่อปลายทางแบบ Tunnel", "webUiRemoveEndpoint": "ลบจุดสิ้นสุด", - "webUiOpenFailed": "ไม่สามารถเปิดเว็บเอนด์พอยต์ได้" + "webUiOpenFailed": "ไม่สามารถเปิดเว็บเอนด์พอยต์ได้", + "bindHost": "โฮสต์ผูก" } } diff --git a/plugins/web-endpoint/locales/translated/tr_TR.json b/plugins/web-endpoint/locales/translated/tr_TR.json index 721c55628..de52315ab 100644 --- a/plugins/web-endpoint/locales/translated/tr_TR.json +++ b/plugins/web-endpoint/locales/translated/tr_TR.json @@ -47,6 +47,7 @@ "webUiIgnoreCert": "Geçersiz sertifikaya izin ver", "webUiIgnoreCertDesc": "Yalnızca doğrudan uç noktalar için geçerlidir. Loopback zaten muaf tutulmuştur, bu nedenle tünel uç noktalarını etkilemez.", "webUiRemoveEndpoint": "Uç noktayı kaldır", - "webUiOpenFailed": "Web uç noktası açılamadı." + "webUiOpenFailed": "Web uç noktası açılamadı.", + "bindHost": "Bağlanma Ana Bilgisayarı" } } diff --git a/plugins/web-endpoint/locales/translated/uk_UA.json b/plugins/web-endpoint/locales/translated/uk_UA.json index 45070ea09..ae016db25 100644 --- a/plugins/web-endpoint/locales/translated/uk_UA.json +++ b/plugins/web-endpoint/locales/translated/uk_UA.json @@ -47,6 +47,7 @@ "webUiIgnoreCert": "Дозволити недійсний сертифікат", "webUiIgnoreCertDesc": "Тільки прямі кінцеві точки. Зациклення вже виключено, тому це не впливає на кінцеві точки тунелю.", "webUiRemoveEndpoint": "Видалити кінцеву точку", - "webUiOpenFailed": "Не вдалося відкрити кінцеву точку веб-сайту" + "webUiOpenFailed": "Не вдалося відкрити кінцеву точку веб-сайту", + "bindHost": "Прив’язати хост" } } diff --git a/plugins/web-endpoint/locales/translated/vi_VN.json b/plugins/web-endpoint/locales/translated/vi_VN.json index 71d0af477..6e9b753ad 100644 --- a/plugins/web-endpoint/locales/translated/vi_VN.json +++ b/plugins/web-endpoint/locales/translated/vi_VN.json @@ -47,6 +47,7 @@ "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" + "webUiOpenFailed": "Không thể mở điểm cuối web", + "bindHost": "Máy chủ bind" } } diff --git a/plugins/web-endpoint/locales/translated/zh_CN.json b/plugins/web-endpoint/locales/translated/zh_CN.json index 45ad8102d..310591ad6 100644 --- a/plugins/web-endpoint/locales/translated/zh_CN.json +++ b/plugins/web-endpoint/locales/translated/zh_CN.json @@ -47,6 +47,7 @@ "webUiIgnoreCert": "允许无效证书", "webUiIgnoreCertDesc": "仅限直接端点。环回接口已获豁免,因此对隧道端点没有影响。", "webUiRemoveEndpoint": "移除端点", - "webUiOpenFailed": "打开 Web 端点失败" + "webUiOpenFailed": "打开 Web 端点失败", + "bindHost": "绑定主机" } } diff --git a/plugins/web-endpoint/locales/translated/zh_TW.json b/plugins/web-endpoint/locales/translated/zh_TW.json index 93a434a5d..3f44f3df9 100644 --- a/plugins/web-endpoint/locales/translated/zh_TW.json +++ b/plugins/web-endpoint/locales/translated/zh_TW.json @@ -47,6 +47,7 @@ "webUiIgnoreCert": "允許無效證書", "webUiIgnoreCertDesc": "僅限直接端點。環回介面已獲豁免,因此對隧道端點沒有影響。", "webUiRemoveEndpoint": "移除端點", - "webUiOpenFailed": "開啟 Web 端點失敗" + "webUiOpenFailed": "開啟 Web 端點失敗", + "bindHost": "綁定主機" } } diff --git a/plugins/workspaces/locales/en.json b/plugins/workspaces/locales/en.json index c2dbe7496..b74108f09 100644 --- a/plugins/workspaces/locales/en.json +++ b/plugins/workspaces/locales/en.json @@ -63,5 +63,8 @@ "title": "Use workspaces", "description": "Save, apply and manage saved tab layouts." } + }, + "hosts": { + "docsLink": "View docs" } } diff --git a/plugins/workspaces/locales/translated/af_ZA.json b/plugins/workspaces/locales/translated/af_ZA.json index 7f1d8af66..bb0e1a44f 100644 --- a/plugins/workspaces/locales/translated/af_ZA.json +++ b/plugins/workspaces/locales/translated/af_ZA.json @@ -51,5 +51,8 @@ "onboarding": { "workflow_workspaces": "Werkruimtes", "workflow_workspaces_desc": "Stoor 'n stel oop oortjies en heropen die hele uitleg later." + }, + "hosts": { + "docsLink": "Bekyk dokumente" } } diff --git a/plugins/workspaces/locales/translated/ar_SA.json b/plugins/workspaces/locales/translated/ar_SA.json index c6a8a5117..4bde35404 100644 --- a/plugins/workspaces/locales/translated/ar_SA.json +++ b/plugins/workspaces/locales/translated/ar_SA.json @@ -51,5 +51,8 @@ "onboarding": { "workflow_workspaces": "مساحات العمل", "workflow_workspaces_desc": "احفظ مجموعة من علامات التبويب المفتوحة وأعد فتح التخطيط بأكمله لاحقًا." + }, + "hosts": { + "docsLink": "عرض المستندات" } } diff --git a/plugins/workspaces/locales/translated/bg_BG.json b/plugins/workspaces/locales/translated/bg_BG.json index e63caaebc..9f2d25677 100644 --- a/plugins/workspaces/locales/translated/bg_BG.json +++ b/plugins/workspaces/locales/translated/bg_BG.json @@ -51,5 +51,8 @@ "onboarding": { "workflow_workspaces": "Работни пространства", "workflow_workspaces_desc": "Запазете набор от отворени раздели и отворете отново цялото оформление по-късно." + }, + "hosts": { + "docsLink": "Преглед на документи" } } diff --git a/plugins/workspaces/locales/translated/bn_BD.json b/plugins/workspaces/locales/translated/bn_BD.json index b9098554d..26314e380 100644 --- a/plugins/workspaces/locales/translated/bn_BD.json +++ b/plugins/workspaces/locales/translated/bn_BD.json @@ -51,5 +51,8 @@ "onboarding": { "workflow_workspaces": "কর্মক্ষেত্র", "workflow_workspaces_desc": "খোলা ট্যাবগুলো সংরক্ষণ করুন এবং পরে সম্পূর্ণ লেআউটটি আবার খুলুন।" + }, + "hosts": { + "docsLink": "নথি দেখুন" } } diff --git a/plugins/workspaces/locales/translated/ca_ES.json b/plugins/workspaces/locales/translated/ca_ES.json index e9be76f0c..57c786850 100644 --- a/plugins/workspaces/locales/translated/ca_ES.json +++ b/plugins/workspaces/locales/translated/ca_ES.json @@ -51,5 +51,8 @@ "onboarding": { "workflow_workspaces": "Espais de treball", "workflow_workspaces_desc": "Desa un conjunt de pestanyes obertes i torna a obrir tot el disseny més tard." + }, + "hosts": { + "docsLink": "Veure documents" } } diff --git a/plugins/workspaces/locales/translated/cs_CZ.json b/plugins/workspaces/locales/translated/cs_CZ.json index bf8e6f90b..330aa8bff 100644 --- a/plugins/workspaces/locales/translated/cs_CZ.json +++ b/plugins/workspaces/locales/translated/cs_CZ.json @@ -51,5 +51,8 @@ "onboarding": { "workflow_workspaces": "Pracovní prostory", "workflow_workspaces_desc": "Uložte si sadu otevřených karet a celé rozvržení si znovu otevřete později." + }, + "hosts": { + "docsLink": "Zobrazit dokumenty" } } diff --git a/plugins/workspaces/locales/translated/da_DK.json b/plugins/workspaces/locales/translated/da_DK.json index 71548bca0..090add11b 100644 --- a/plugins/workspaces/locales/translated/da_DK.json +++ b/plugins/workspaces/locales/translated/da_DK.json @@ -51,5 +51,8 @@ "onboarding": { "workflow_workspaces": "Arbejdsområder", "workflow_workspaces_desc": "Gem et sæt åbne faner, og åbn hele layoutet igen senere." + }, + "hosts": { + "docsLink": "Se dokumenter" } } diff --git a/plugins/workspaces/locales/translated/de_DE.json b/plugins/workspaces/locales/translated/de_DE.json index 3ac95b444..d7ea5b4a1 100644 --- a/plugins/workspaces/locales/translated/de_DE.json +++ b/plugins/workspaces/locales/translated/de_DE.json @@ -51,5 +51,8 @@ "onboarding": { "workflow_workspaces": "Arbeitsbereiche", "workflow_workspaces_desc": "Speichern Sie einen Satz geöffneter Tabs und öffnen Sie das gesamte Layout später wieder." + }, + "hosts": { + "docsLink": "Dokumentation anzeigen" } } diff --git a/plugins/workspaces/locales/translated/el_GR.json b/plugins/workspaces/locales/translated/el_GR.json index daa108b14..68416ad54 100644 --- a/plugins/workspaces/locales/translated/el_GR.json +++ b/plugins/workspaces/locales/translated/el_GR.json @@ -51,5 +51,8 @@ "onboarding": { "workflow_workspaces": "Χώροι εργασίας", "workflow_workspaces_desc": "Αποθηκεύστε ένα σύνολο ανοιχτών καρτελών και ανοίξτε ξανά ολόκληρη τη διάταξη αργότερα." + }, + "hosts": { + "docsLink": "Προβολή εγγράφων" } } diff --git a/plugins/workspaces/locales/translated/es_ES.json b/plugins/workspaces/locales/translated/es_ES.json index 8952a6444..f599d8983 100644 --- a/plugins/workspaces/locales/translated/es_ES.json +++ b/plugins/workspaces/locales/translated/es_ES.json @@ -51,5 +51,8 @@ "onboarding": { "workflow_workspaces": "Espacios de trabajo", "workflow_workspaces_desc": "Guarda un conjunto de pestañas abiertas y vuelve a abrir toda la interfaz más tarde." + }, + "hosts": { + "docsLink": "Ver documentación" } } diff --git a/plugins/workspaces/locales/translated/fi_FI.json b/plugins/workspaces/locales/translated/fi_FI.json index 018c49297..31f07919e 100644 --- a/plugins/workspaces/locales/translated/fi_FI.json +++ b/plugins/workspaces/locales/translated/fi_FI.json @@ -51,5 +51,8 @@ "onboarding": { "workflow_workspaces": "Työtilat", "workflow_workspaces_desc": "Tallenna joukko avoimia välilehtiä ja avaa koko asettelu uudelleen myöhemmin." + }, + "hosts": { + "docsLink": "Näytä dokumentit" } } diff --git a/plugins/workspaces/locales/translated/fr_FR.json b/plugins/workspaces/locales/translated/fr_FR.json index 6eab9558a..9692ab91d 100644 --- a/plugins/workspaces/locales/translated/fr_FR.json +++ b/plugins/workspaces/locales/translated/fr_FR.json @@ -51,5 +51,8 @@ "onboarding": { "workflow_workspaces": "Espaces de travail", "workflow_workspaces_desc": "Enregistrez une série d'onglets ouverts et rouvrez l'ensemble de la mise en page plus tard." + }, + "hosts": { + "docsLink": "Voir la documentation" } } diff --git a/plugins/workspaces/locales/translated/he_IL.json b/plugins/workspaces/locales/translated/he_IL.json index 350fcc1c6..55474f1da 100644 --- a/plugins/workspaces/locales/translated/he_IL.json +++ b/plugins/workspaces/locales/translated/he_IL.json @@ -51,5 +51,8 @@ "onboarding": { "workflow_workspaces": "סביבות עבודה", "workflow_workspaces_desc": "שמור קבוצת כרטיסיות פתוחות ופתח מחדש את כל הפריסה מאוחר יותר." + }, + "hosts": { + "docsLink": "הצג מסמכים" } } diff --git a/plugins/workspaces/locales/translated/hi_IN.json b/plugins/workspaces/locales/translated/hi_IN.json index 72d1f3b46..a7b54d7d2 100644 --- a/plugins/workspaces/locales/translated/hi_IN.json +++ b/plugins/workspaces/locales/translated/hi_IN.json @@ -51,5 +51,8 @@ "onboarding": { "workflow_workspaces": "कार्यस्थानों", "workflow_workspaces_desc": "खुले हुए टैबों के एक सेट को सेव करें और बाद में पूरे लेआउट को दोबारा खोलें।" + }, + "hosts": { + "docsLink": "दस्तावेज़ देखें" } } diff --git a/plugins/workspaces/locales/translated/hu_HU.json b/plugins/workspaces/locales/translated/hu_HU.json index bd1ea068c..320d6a334 100644 --- a/plugins/workspaces/locales/translated/hu_HU.json +++ b/plugins/workspaces/locales/translated/hu_HU.json @@ -51,5 +51,8 @@ "onboarding": { "workflow_workspaces": "Munkaterületek", "workflow_workspaces_desc": "Mentse el a megnyitott lapok egy készletét, és később nyissa meg újra a teljes elrendezést." + }, + "hosts": { + "docsLink": "Dokumentumok megtekintése" } } diff --git a/plugins/workspaces/locales/translated/id_ID.json b/plugins/workspaces/locales/translated/id_ID.json index ab5bfa8e2..3ac13bc0f 100644 --- a/plugins/workspaces/locales/translated/id_ID.json +++ b/plugins/workspaces/locales/translated/id_ID.json @@ -51,5 +51,8 @@ "onboarding": { "workflow_workspaces": "Ruang kerja", "workflow_workspaces_desc": "Simpan sekumpulan tab yang terbuka dan buka kembali seluruh tata letak nanti." + }, + "hosts": { + "docsLink": "Lihat dokumen" } } diff --git a/plugins/workspaces/locales/translated/it_IT.json b/plugins/workspaces/locales/translated/it_IT.json index 0afd00db0..4c0eb7f12 100644 --- a/plugins/workspaces/locales/translated/it_IT.json +++ b/plugins/workspaces/locales/translated/it_IT.json @@ -51,5 +51,8 @@ "onboarding": { "workflow_workspaces": "Spazi di lavoro", "workflow_workspaces_desc": "Salva le schede aperte e riapri l'intero layout in seguito." + }, + "hosts": { + "docsLink": "Visualizza documentazione" } } diff --git a/plugins/workspaces/locales/translated/ja_JP.json b/plugins/workspaces/locales/translated/ja_JP.json index 07b5c310e..5eff08ed9 100644 --- a/plugins/workspaces/locales/translated/ja_JP.json +++ b/plugins/workspaces/locales/translated/ja_JP.json @@ -51,5 +51,8 @@ "onboarding": { "workflow_workspaces": "ワークスペース", "workflow_workspaces_desc": "開いているタブのセットを保存し、後でレイアウト全体を再度開くことができます。" + }, + "hosts": { + "docsLink": "ドキュメントを表示" } } diff --git a/plugins/workspaces/locales/translated/ko_KR.json b/plugins/workspaces/locales/translated/ko_KR.json index e065dc564..465064b98 100644 --- a/plugins/workspaces/locales/translated/ko_KR.json +++ b/plugins/workspaces/locales/translated/ko_KR.json @@ -51,5 +51,8 @@ "onboarding": { "workflow_workspaces": "작업 공간", "workflow_workspaces_desc": "열려 있는 탭들을 저장해두었다가 나중에 전체 레이아웃을 다시 열어보세요." + }, + "hosts": { + "docsLink": "문서 보기" } } diff --git a/plugins/workspaces/locales/translated/nl_NL.json b/plugins/workspaces/locales/translated/nl_NL.json index 1e2791b79..5563f9971 100644 --- a/plugins/workspaces/locales/translated/nl_NL.json +++ b/plugins/workspaces/locales/translated/nl_NL.json @@ -51,5 +51,8 @@ "onboarding": { "workflow_workspaces": "Werkruimtes", "workflow_workspaces_desc": "Sla een set geopende tabbladen op en open de volledige lay-out later opnieuw." + }, + "hosts": { + "docsLink": "Documenten bekijken" } } diff --git a/plugins/workspaces/locales/translated/no_NO.json b/plugins/workspaces/locales/translated/no_NO.json index a5e708455..93c6eb992 100644 --- a/plugins/workspaces/locales/translated/no_NO.json +++ b/plugins/workspaces/locales/translated/no_NO.json @@ -51,5 +51,8 @@ "onboarding": { "workflow_workspaces": "Arbeidsområder", "workflow_workspaces_desc": "Lagre et sett med åpne faner og åpne hele layouten på nytt senere." + }, + "hosts": { + "docsLink": "Vis dokumenter" } } diff --git a/plugins/workspaces/locales/translated/pl_PL.json b/plugins/workspaces/locales/translated/pl_PL.json index a6a63bb2c..a6ed929ad 100644 --- a/plugins/workspaces/locales/translated/pl_PL.json +++ b/plugins/workspaces/locales/translated/pl_PL.json @@ -51,5 +51,8 @@ "onboarding": { "workflow_workspaces": "Obszary robocze", "workflow_workspaces_desc": "Zapisz zestaw otwartych kart i otwórz cały układ później." + }, + "hosts": { + "docsLink": "Zobacz dokumentację" } } diff --git a/plugins/workspaces/locales/translated/pt_BR.json b/plugins/workspaces/locales/translated/pt_BR.json index fef7aaa8b..97596774c 100644 --- a/plugins/workspaces/locales/translated/pt_BR.json +++ b/plugins/workspaces/locales/translated/pt_BR.json @@ -51,5 +51,8 @@ "onboarding": { "workflow_workspaces": "Espaços de trabalho", "workflow_workspaces_desc": "Salve um conjunto de abas abertas e reabra todo o layout mais tarde." + }, + "hosts": { + "docsLink": "Ver documentos" } } diff --git a/plugins/workspaces/locales/translated/pt_PT.json b/plugins/workspaces/locales/translated/pt_PT.json index 611f791ba..9d1dc0657 100644 --- a/plugins/workspaces/locales/translated/pt_PT.json +++ b/plugins/workspaces/locales/translated/pt_PT.json @@ -51,5 +51,8 @@ "onboarding": { "workflow_workspaces": "Espaços de trabalho", "workflow_workspaces_desc": "Guarde um conjunto de separadores abertos e reabra todo o layout mais tarde." + }, + "hosts": { + "docsLink": "Ver documentação" } } diff --git a/plugins/workspaces/locales/translated/ro_RO.json b/plugins/workspaces/locales/translated/ro_RO.json index d6e5207ea..19de91976 100644 --- a/plugins/workspaces/locales/translated/ro_RO.json +++ b/plugins/workspaces/locales/translated/ro_RO.json @@ -51,5 +51,8 @@ "onboarding": { "workflow_workspaces": "Spații de lucru", "workflow_workspaces_desc": "Salvați un set de file deschise și redeschideți întregul aspect mai târziu." + }, + "hosts": { + "docsLink": "Vizualizați documentele" } } diff --git a/plugins/workspaces/locales/translated/ru_RU.json b/plugins/workspaces/locales/translated/ru_RU.json index fad81d601..c259d23bf 100644 --- a/plugins/workspaces/locales/translated/ru_RU.json +++ b/plugins/workspaces/locales/translated/ru_RU.json @@ -51,5 +51,8 @@ "onboarding": { "workflow_workspaces": "Рабочие места", "workflow_workspaces_desc": "Сохраните набор открытых вкладок и откройте весь интерфейс позже." + }, + "hosts": { + "docsLink": "Документация" } } diff --git a/plugins/workspaces/locales/translated/sr_SP.json b/plugins/workspaces/locales/translated/sr_SP.json index 0ade9cb61..1d205667e 100644 --- a/plugins/workspaces/locales/translated/sr_SP.json +++ b/plugins/workspaces/locales/translated/sr_SP.json @@ -51,5 +51,8 @@ "onboarding": { "workflow_workspaces": "Радни простори", "workflow_workspaces_desc": "Сачувајте скуп отворених картица и поново отворите цео распоред касније." + }, + "hosts": { + "docsLink": "Прикажи документе" } } diff --git a/plugins/workspaces/locales/translated/sv_SE.json b/plugins/workspaces/locales/translated/sv_SE.json index 4a3ef9b57..2d3253447 100644 --- a/plugins/workspaces/locales/translated/sv_SE.json +++ b/plugins/workspaces/locales/translated/sv_SE.json @@ -51,5 +51,8 @@ "onboarding": { "workflow_workspaces": "Arbetsytor", "workflow_workspaces_desc": "Spara en uppsättning öppna flikar och öppna hela layouten igen senare." + }, + "hosts": { + "docsLink": "Visa dokument" } } diff --git a/plugins/workspaces/locales/translated/th_TH.json b/plugins/workspaces/locales/translated/th_TH.json index 6721d34fa..9a528becd 100644 --- a/plugins/workspaces/locales/translated/th_TH.json +++ b/plugins/workspaces/locales/translated/th_TH.json @@ -51,5 +51,8 @@ "onboarding": { "workflow_workspaces": "พื้นที่ทำงาน", "workflow_workspaces_desc": "บันทึกชุดแท็บที่เปิดอยู่ แล้วเปิดเค้าโครงทั้งหมดอีกครั้งในภายหลัง" + }, + "hosts": { + "docsLink": "ดูเอกสาร" } } diff --git a/plugins/workspaces/locales/translated/tr_TR.json b/plugins/workspaces/locales/translated/tr_TR.json index 252c1d2dc..b217e9208 100644 --- a/plugins/workspaces/locales/translated/tr_TR.json +++ b/plugins/workspaces/locales/translated/tr_TR.json @@ -51,5 +51,8 @@ "onboarding": { "workflow_workspaces": "Çalışma Alanları", "workflow_workspaces_desc": "Açık sekmeleri kaydedin ve daha sonra tüm düzeni yeniden açın." + }, + "hosts": { + "docsLink": "Dokümanları görüntüle" } } diff --git a/plugins/workspaces/locales/translated/uk_UA.json b/plugins/workspaces/locales/translated/uk_UA.json index c4cb5d017..4a8bc0566 100644 --- a/plugins/workspaces/locales/translated/uk_UA.json +++ b/plugins/workspaces/locales/translated/uk_UA.json @@ -51,5 +51,8 @@ "onboarding": { "workflow_workspaces": "Робочі простори", "workflow_workspaces_desc": "Збережіть набір відкритих вкладок і знову відкрийте весь макет пізніше." + }, + "hosts": { + "docsLink": "Переглянути документи" } } diff --git a/plugins/workspaces/locales/translated/vi_VN.json b/plugins/workspaces/locales/translated/vi_VN.json index 2de78abb4..3dc885516 100644 --- a/plugins/workspaces/locales/translated/vi_VN.json +++ b/plugins/workspaces/locales/translated/vi_VN.json @@ -51,5 +51,8 @@ "onboarding": { "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." + }, + "hosts": { + "docsLink": "Xem tài liệu" } } diff --git a/plugins/workspaces/locales/translated/zh_CN.json b/plugins/workspaces/locales/translated/zh_CN.json index 47c6d90c8..001a82ed4 100644 --- a/plugins/workspaces/locales/translated/zh_CN.json +++ b/plugins/workspaces/locales/translated/zh_CN.json @@ -51,5 +51,8 @@ "onboarding": { "workflow_workspaces": "工作区", "workflow_workspaces_desc": "保存当前打开的标签页组合,方便之后一键恢复整个布局。" + }, + "hosts": { + "docsLink": "查看文档" } } diff --git a/plugins/workspaces/locales/translated/zh_TW.json b/plugins/workspaces/locales/translated/zh_TW.json index 7eaa71f46..3b42affcf 100644 --- a/plugins/workspaces/locales/translated/zh_TW.json +++ b/plugins/workspaces/locales/translated/zh_TW.json @@ -51,5 +51,8 @@ "onboarding": { "workflow_workspaces": "工作區", "workflow_workspaces_desc": "儲存一組開啟的標籤頁,稍後重新開啟整個佈局。" + }, + "hosts": { + "docsLink": "檢視文件" } } diff --git a/scripts/check-core-plugin-ids.cjs b/scripts/check-core-plugin-ids.cjs index 3f5465559..43ddf45f4 100644 --- a/scripts/check-core-plugin-ids.cjs +++ b/scripts/check-core-plugin-ids.cjs @@ -7,7 +7,8 @@ * action, slot or permission id that starts with one ("docker.open"). The * shell (src/ui) also may not spell a view a plugin owns (a tab, panel or * dashboard card id from a manifest). What core needs from a plugin comes - * through the registries instead. + * through the registries instead. Regex literals are read too, so + * /^\/plugin-api\/docker/ counts the same as "/plugin-api/docker". * * Tests and locales are exempt, and so is src/backend/upgrade/: the one-time * 2.8 to 2.9 data moves have to name the plugin each piece of data moves to, @@ -22,17 +23,22 @@ const fs = require("node:fs"); const path = require("node:path"); -const ROOT = path.resolve(__dirname, ".."); -const SRC = path.join(ROOT, "src"); -const UI = path.join(SRC, "ui"); -const PLUGINS = path.join(ROOT, "plugins"); const EXEMPT_DIRS = new Set(["tests", "locales"]); -const EXEMPT_PATHS = [path.join(SRC, "backend", "upgrade")]; -const SSH_CONNECT = path.join(SRC, "backend", "hosts", "connect"); const SSH_TERMS = new Set(["totp"]); -function manifests() { - const dir = path.join(ROOT, "plugins"); +function paths(root) { + const src = path.join(root, "src"); + return { + root, + src, + ui: path.join(src, "ui"), + plugins: path.join(root, "plugins"), + exempt: [path.join(src, "backend", "upgrade")], + sshConnect: path.join(src, "backend", "hosts", "connect"), + }; +} + +function manifests(dir) { return fs .readdirSync(dir, { withFileTypes: true }) .filter((entry) => entry.isDirectory()) @@ -41,10 +47,10 @@ function manifests() { .map((file) => JSON.parse(fs.readFileSync(file, "utf8"))); } -function names() { +function names(pluginsDir) { const ids = new Set(); const views = new Set(); - for (const manifest of manifests()) { + for (const manifest of manifests(pluginsDir)) { ids.add(manifest.id); const contributes = manifest.contributes ?? {}; for (const list of [ @@ -58,13 +64,13 @@ function names() { return { ids, views }; } -function walk(dir, out) { - if (EXEMPT_PATHS.includes(dir)) return out; +function walk(dir, exempt, out) { + if (exempt.includes(dir)) return out; for (const entry of fs.readdirSync(dir, { withFileTypes: true })) { const full = path.join(dir, entry.name); if (entry.isDirectory()) { if (EXEMPT_DIRS.has(entry.name)) continue; - walk(full, out); + walk(full, exempt, out); } else if (/\.(tsx?|mjs|cjs|jsx?)$/.test(entry.name)) { out.push(full); } @@ -83,25 +89,43 @@ function literals(source) { return out; } -function scan() { - const { ids, views } = names(); +/** + * Every regex literal in a file, with escaped slashes undone, so a pattern + * reads the way the path it matches does. + */ +function regexLiterals(source) { + const out = []; + const pattern = + /(^|[=(,:[!&|?{};]|\breturn)\s*\/((?:[^/\\\n[]|\\.|\[(?:[^\]\\\n]|\\.)*\])+)\/[dgimsuyv]*/gm; + for (const match of source.matchAll(pattern)) { + const body = match[2]; + // A comment, not a pattern. + if (body.startsWith("/") || body.startsWith("*")) continue; + out.push(body.replace(/\\(.)/g, "$1")); + } + return out; +} + +function scan(root = path.resolve(__dirname, "..")) { + const { src, ui, plugins, exempt, sshConnect } = paths(root); + const { ids, views } = names(plugins); const found = {}; const add = (file, what) => { - const key = path.relative(ROOT, file).replaceAll("\\", "/"); + const key = path.relative(root, file).replaceAll("\\", "/"); (found[key] ??= new Set()).add(what); }; - for (const file of walk(SRC, [])) { + for (const file of walk(src, exempt, [])) { const source = fs.readFileSync(file, "utf8"); - const inShell = file.startsWith(UI + path.sep); - const inConnect = file.startsWith(SSH_CONNECT + path.sep); + const inShell = file.startsWith(ui + path.sep); + const inConnect = file.startsWith(sshConnect + path.sep); for (const match of source.matchAll( /(?:from|import)\s*\(?\s*["']([^"']+)["']/g, )) { const target = match[1].startsWith(".") ? path.resolve(path.dirname(file), match[1]) : ""; - if (target.startsWith(PLUGINS + path.sep)) { + if (target.startsWith(plugins + path.sep)) { add(file, `import ${match[1]}`); } } @@ -118,6 +142,17 @@ function scan() { const prefix = /^([a-z][a-z0-9-]*)\.[a-zA-Z]/.exec(text); if (prefix && ids.has(prefix[1])) add(file, text); } + for (const pattern of regexLiterals(source)) { + for (const route of pattern.matchAll( + /\/plugin-(?:api|ws|assets)\/([a-z0-9-]+)/g, + )) { + if (ids.has(route[1])) add(file, `/${pattern}/`); + } + const sshTerm = inConnect && SSH_TERMS.has(pattern); + if (ids.has(pattern.replace(/^\^|\$$/g, "")) && !sshTerm) { + add(file, `/${pattern}/`); + } + } } return Object.fromEntries( Object.entries(found).map(([file, set]) => [file, [...set].sort()]), @@ -140,4 +175,6 @@ function main() { } } -main(); +if (require.main === module) main(); + +module.exports = { scan, regexLiterals }; diff --git a/scripts/check-core-plugin-ids.test.ts b/scripts/check-core-plugin-ids.test.ts new file mode 100644 index 000000000..c642c2a93 --- /dev/null +++ b/scripts/check-core-plugin-ids.test.ts @@ -0,0 +1,83 @@ +import { afterEach, describe, expect, it } from "vitest"; +import { createRequire } from "node:module"; +import fs from "node:fs"; +import os from "node:os"; +import path from "node:path"; + +const require = createRequire(import.meta.url); +const { scan, regexLiterals } = require("./check-core-plugin-ids.cjs") as { + scan: (root: string) => Record; + regexLiterals: (source: string) => string[]; +}; + +let root: string | null = null; + +afterEach(() => { + if (root) fs.rmSync(root, { recursive: true, force: true }); + root = null; +}); + +function fixture(files: Record): string { + root = fs.mkdtempSync(path.join(os.tmpdir(), "core-plugin-ids-")); + const all = { + "plugins/docker/manifest.json": JSON.stringify({ + id: "docker", + contributes: { tabs: [{ id: "docker-tab" }] }, + }), + ...files, + }; + for (const [file, content] of Object.entries(all)) { + const full = path.join(root, file); + fs.mkdirSync(path.dirname(full), { recursive: true }); + fs.writeFileSync(full, content); + } + return root; +} + +describe("regexLiterals", () => { + it("reads patterns with their slashes unescaped, not divisions or comments", () => { + const source = [ + "if (/^\\/plugin-api\\/snippets/.test(p)) return x / 2;", + "const r = a.match(/[a/b]c/g); // not /here/", + "return /docker/;", + ].join("\n"); + expect(regexLiterals(source)).toEqual([ + "^/plugin-api/snippets", + "[a/b]c", + "docker", + ]); + }); +}); + +describe("scan", () => { + it("passes core code that names no plugin", () => { + const dir = fixture({ + "src/backend/ok.ts": 'const route = "/plugin-api/" + id;\n', + }); + expect(scan(dir)).toEqual({}); + }); + + it("fails a plugin route in a string or a regex literal", () => { + const dir = fixture({ + "src/backend/string.ts": 'const a = "/plugin-api/docker/list";\n', + "src/backend/regex.ts": + "const b = /^\\/plugin-api\\/docker(\\/|$)/.test(url);\n", + }); + expect(scan(dir)).toEqual({ + "src/backend/regex.ts": ["/^/plugin-api/docker(/|$)/"], + "src/backend/string.ts": ["/plugin-api/docker"], + }); + }); + + it("fails a bare id, and a view id in the shell", () => { + const dir = fixture({ + "src/backend/id.ts": 'if (pluginId === "docker") {}\n', + "src/ui/view.ts": 'open("docker-tab");\n', + "src/ui/tests/skip.ts": 'open("docker");\n', + }); + expect(scan(dir)).toEqual({ + "src/backend/id.ts": ["docker"], + "src/ui/view.ts": ["docker-tab"], + }); + }); +}); diff --git a/scripts/check-plugin-locales.cjs b/scripts/check-plugin-locales.cjs new file mode 100644 index 000000000..6d845dadc --- /dev/null +++ b/scripts/check-plugin-locales.cjs @@ -0,0 +1,228 @@ +#!/usr/bin/env node +/** + * A plugin's strings live in its own locales/en.json. + * + * A plugin's i18next namespace falls back to core's, so a plugin can use + * `common.*` without copying it. Any other key a plugin uses has to be in the + * plugin's own en.json: one that only resolves through the fallback breaks + * the moment core renames or drops it, and core cannot tell it is in use. + * + * Reads t("...") calls and i18n key props (titleKey, labelKey and the rest) + * in plugins//src, and the *Key values in plugins//manifest.json. + * A key with a namespace ("docker:hosts.x") is checked against that plugin. + * + * --list prints what is missing per plugin, with whether core has the key. + */ + +const fs = require("node:fs"); +const path = require("node:path"); + +const ROOT = path.resolve(__dirname, ".."); +const PLUGINS = path.join(ROOT, "plugins"); +const CORE_LOCALE = path.join(ROOT, "src", "ui", "locales", "en.json"); + +const SHARED_PREFIXES = ["common."]; +const KEY = /^[A-Za-z0-9_-]+(\.[A-Za-z0-9_-]+)*$/; +const KEY_PROPS = new Set([ + "titleKey", + "labelKey", + "descriptionKey", + "noHostMessageKey", + "paletteKey", + "hintKey", + "messageKey", + "placeholderKey", + "tooltipKey", + "i18nKey", + "enableLabelKey", + "enableDescriptionKey", + "consequenceKey", + "groupKey", + "emptyKey", + "nameKey", +]); +const PLURAL_SUFFIXES = [ + "_zero", + "_one", + "_two", + "_few", + "_many", + "_other", + "_plural", +]; + +function readJson(file) { + return JSON.parse(fs.readFileSync(file, "utf8")); +} + +/** + * Whether a dotted key resolves in a locale tree, the way i18next finds it: + * a segment may itself hold dots ("services.use"), and a last segment may be + * a plural form. + */ +function hasKey(tree, key) { + const find = (node, parts) => { + if (parts.length === 0) return node !== undefined; + if (!node || typeof node !== "object") return false; + for (let end = parts.length; end >= 1; end--) { + const name = parts.slice(0, end).join("."); + if (name in node && find(node[name], parts.slice(end))) return true; + if ( + end === parts.length && + PLURAL_SUFFIXES.some((suffix) => `${name}${suffix}` in node) + ) { + return true; + } + } + return false; + }; + return find(tree, key.split(".")); +} + +function isShared(key) { + return SHARED_PREFIXES.some((prefix) => key.startsWith(prefix)); +} + +function walk(dir, out = []) { + if (!fs.existsSync(dir)) return out; + for (const entry of fs.readdirSync(dir, { withFileTypes: true })) { + const full = path.join(dir, entry.name); + if (entry.isDirectory()) walk(full, out); + else if (/\.(tsx?|jsx?)$/.test(entry.name)) out.push(full); + } + return out; +} + +/** Drops comments, so an example in one is not read as a call. */ +function stripComments(source) { + return source.replace(/\/\*[\s\S]*?\*\//g, "").replace(/^\s*\/\/.*$/gm, ""); +} + +/** + * Every literal i18n key a source file uses. A prefix a key is built from at + * run time ends in ".*". + */ +function keysInSource(text) { + const source = stripComments(text); + const keys = new Set(); + for (const match of source.matchAll( + /\bt\(\s*(["'])((?:(?!\1)[^\\\n$`])+)\1/g, + )) { + keys.add(match[2]); + } + for (const match of source.matchAll( + /\b([A-Za-z]+Key)\s*[:=]\s*\{?\s*(["'])((?:(?!\2)[^\\\n])+)\2/g, + )) { + if (KEY_PROPS.has(match[1])) keys.add(match[3]); + } + // A key built at run time: `hosts.sharing.levels.${level}.label` needs the + // whole hosts.sharing.levels subtree. A one-segment prefix says too little + // to check. + for (const match of source.matchAll( + /\bt\(\s*`((?:[A-Za-z0-9_-]+\.){2,})\$\{/g, + )) { + keys.add(`${match[1]}*`); + } + return [...keys].filter((key) => + KEY.test(key.replace(/^[a-z0-9-]+:/, "").replace(/\.\*$/, "")), + ); +} + +function keysInManifest(value, out = new Set()) { + if (Array.isArray(value)) { + for (const item of value) keysInManifest(item, out); + } else if (value && typeof value === "object") { + for (const [name, child] of Object.entries(value)) { + if (KEY_PROPS.has(name) && typeof child === "string") out.add(child); + else keysInManifest(child, out); + } + } + return out; +} + +function pluginIds(pluginsDir) { + return fs + .readdirSync(pluginsDir, { withFileTypes: true }) + .filter((entry) => entry.isDirectory()) + .map((entry) => entry.name) + .filter((id) => fs.existsSync(path.join(pluginsDir, id, "manifest.json"))) + .sort(); +} + +/** + * Keys each plugin uses but does not define, other than the shared ones. + * Returns { [pluginId]: [{ key, file, inCore }] }. + */ +function scan({ pluginsDir = PLUGINS, coreLocale = CORE_LOCALE } = {}) { + const core = fs.existsSync(coreLocale) ? readJson(coreLocale) : {}; + const ids = pluginIds(pluginsDir); + const locales = new Map( + ids.map((id) => { + const file = path.join(pluginsDir, id, "locales", "en.json"); + return [id, fs.existsSync(file) ? readJson(file) : {}]; + }), + ); + + const missing = {}; + const check = (owner, rawKey, file) => { + const colon = rawKey.indexOf(":"); + const namespace = colon > 0 ? rawKey.slice(0, colon) : owner; + const key = colon > 0 ? rawKey.slice(colon + 1) : rawKey; + if (isShared(key)) return; + const tree = locales.get(namespace); + const lookup = key.endsWith(".*") ? key.slice(0, -2) : key; + if (tree && hasKey(tree, lookup)) return; + const inCore = hasKey(core, lookup); + // A bare word that is nowhere is a local helper named t, not a string. + if (!key.includes(".") && !inCore) return; + const list = (missing[owner] ??= []); + if (!list.some((entry) => entry.key === rawKey)) { + list.push({ + key: rawKey, + file: path.relative(ROOT, file).replaceAll("\\", "/"), + inCore, + }); + } + }; + + for (const id of ids) { + const manifestFile = path.join(pluginsDir, id, "manifest.json"); + for (const key of keysInManifest(readJson(manifestFile))) { + if (KEY.test(key.replace(/^[a-z0-9-]+:/, ""))) { + check(id, key, manifestFile); + } + } + for (const file of walk(path.join(pluginsDir, id, "src"))) { + for (const key of keysInSource(fs.readFileSync(file, "utf8"))) { + check(id, key, file); + } + } + } + for (const list of Object.values(missing)) { + list.sort((a, b) => a.key.localeCompare(b.key)); + } + return missing; +} + +function main() { + const missing = scan(); + if (process.argv.includes("--list")) { + console.log(JSON.stringify(missing, null, 2)); + return; + } + const entries = Object.entries(missing); + if (entries.length === 0) return; + console.error( + "Plugins use i18n keys their own locales/en.json does not define:", + ); + for (const [id, list] of entries) { + for (const { key, file } of list) { + console.error(` ${id}: ${key} (${file})`); + } + } + process.exit(1); +} + +if (require.main === module) main(); + +module.exports = { scan, keysInSource, hasKey }; diff --git a/scripts/check-plugin-locales.test.ts b/scripts/check-plugin-locales.test.ts new file mode 100644 index 000000000..a0cdf975f --- /dev/null +++ b/scripts/check-plugin-locales.test.ts @@ -0,0 +1,127 @@ +import { afterEach, describe, expect, it } from "vitest"; +import { createRequire } from "node:module"; +import fs from "node:fs"; +import os from "node:os"; +import path from "node:path"; + +const require = createRequire(import.meta.url); +const { scan, keysInSource, hasKey } = + require("./check-plugin-locales.cjs") as { + scan: (options: { + pluginsDir: string; + coreLocale: string; + }) => Record>; + keysInSource: (source: string) => string[]; + hasKey: (tree: unknown, key: string) => boolean; + }; + +let dir: string | null = null; + +afterEach(() => { + if (dir) fs.rmSync(dir, { recursive: true, force: true }); + dir = null; +}); + +function fixture(files: Record) { + dir = fs.mkdtempSync(path.join(os.tmpdir(), "plugin-locales-")); + for (const [file, content] of Object.entries(files)) { + const full = path.join(dir, file); + fs.mkdirSync(path.dirname(full), { recursive: true }); + fs.writeFileSync( + full, + typeof content === "string" ? content : JSON.stringify(content), + ); + } + return { + pluginsDir: path.join(dir, "plugins"), + coreLocale: path.join(dir, "core.json"), + }; +} + +describe("keysInSource", () => { + it("reads t() calls, key props and run time prefixes, not comments", () => { + const keys = keysInSource( + [ + 'const a = t("hosts.one");', + "const b = i18next.t('docker:hosts.two', { x: 1 });", + 'app.registerTab("x", X, { titleKey: "nav.three" });', + '', + "t(`hosts.sharing.levels.${level}.label`);", + "t(`hosts.${label}`);", + '// t("hosts.commented")', + 'storageKey: "not.a.string.key"', + ].join("\n"), + ); + expect(keys.sort()).toEqual( + [ + "docker:hosts.two", + "hosts.four", + "hosts.one", + "hosts.sharing.levels.*", + "nav.three", + ].sort(), + ); + }); +}); + +describe("hasKey", () => { + it("finds nested keys, dotted names and plural forms", () => { + const tree = { + a: { b: "x" }, + permissions: { "services.use": { title: "t" } }, + items: { count_one: "1", count_other: "n" }, + }; + expect(hasKey(tree, "a.b")).toBe(true); + expect(hasKey(tree, "a")).toBe(true); + expect(hasKey(tree, "permissions.services.use.title")).toBe(true); + expect(hasKey(tree, "items.count")).toBe(true); + expect(hasKey(tree, "a.c")).toBe(false); + }); +}); + +describe("scan", () => { + it("passes keys a plugin defines and the shared common ones", () => { + const options = fixture({ + "core.json": { common: { save: "Save" }, hosts: { name: "Name" } }, + "plugins/demo/manifest.json": { id: "demo", titleKey: "title" }, + "plugins/demo/locales/en.json": { title: "Demo", hosts: { name: "N" } }, + "plugins/demo/src/frontend/index.tsx": + 't("common.save"); t("hosts.name"); t("title");', + }); + expect(scan(options)).toEqual({}); + }); + + it("fails a key that only resolves through core's fallback", () => { + const options = fixture({ + "core.json": { hosts: { name: "Name" } }, + "plugins/demo/manifest.json": { id: "demo" }, + "plugins/demo/locales/en.json": {}, + "plugins/demo/src/frontend/index.tsx": 't("hosts.name");', + }); + expect(scan(options)).toEqual({ + demo: [ + { + key: "hosts.name", + file: expect.stringContaining("index.tsx"), + inCore: true, + }, + ], + }); + }); + + it("checks a namespaced key against that plugin and a prefix as a subtree", () => { + const options = fixture({ + "core.json": { hosts: { levels: { view: "View" } } }, + "plugins/demo/manifest.json": { id: "demo" }, + "plugins/demo/locales/en.json": {}, + "plugins/demo/src/frontend/index.tsx": + 't("other:known.key"); t("other:gone.key"); t(`hosts.levels.${l}`);', + "plugins/other/manifest.json": { id: "other" }, + "plugins/other/locales/en.json": { known: { key: "k" } }, + }); + expect(scan(options).demo.map((entry) => entry.key)).toEqual([ + "hosts.levels.*", + "other:gone.key", + ]); + }); +}); diff --git a/scripts/check-sdk-ui-exports.cjs b/scripts/check-sdk-ui-exports.cjs new file mode 100644 index 000000000..abd55f247 --- /dev/null +++ b/scripts/check-sdk-ui-exports.cjs @@ -0,0 +1,281 @@ +#!/usr/bin/env node +/** + * @termix/plugin-sdk/ui is public API, implemented by + * src/ui/plugin-host/sdk-ui.ts. Adding to it is a contract change and + * removing from it is a breaking one, so neither should happen by accident. + * + * Resolves every name the module exports (through its `export *` lines too) + * and fails when that differs from ALLOWED. A new export goes on the list in + * the same change, which is what makes it a deliberate one. Only generic + * shell pieces belong here: anything one feature needs lives in its plugin. + * + * --list prints what the module exports now. + */ + +const path = require("node:path"); + +const ROOT = path.resolve(__dirname, ".."); +const SDK_UI = path.join(ROOT, "src", "ui", "plugin-host", "sdk-ui.ts"); +const TSCONFIG = path.join(ROOT, "tsconfig.app.json"); + +const ALLOWED = [ + "ActionSlot", + "Alert", + "AlertDescription", + "AlertDialog", + "AlertDialogAction", + "AlertDialogCancel", + "AlertDialogContent", + "AlertDialogDescription", + "AlertDialogFooter", + "AlertDialogHeader", + "AlertDialogOverlay", + "AlertDialogPortal", + "AlertDialogTitle", + "AlertDialogTrigger", + "AlertTitle", + "Badge", + "BarSeries", + "BarSeriesItem", + "BarSeriesProps", + "BrowserSignInDialog", + "Button", + "ButtonProps", + "Card", + "CardAction", + "CardContent", + "CardDescription", + "CardFooter", + "CardGridCanvas", + "CardHeader", + "CardTitle", + "Checkbox", + "ColumnCountStepper", + "ComponentSlot", + "ConnectionLogPanel", + "ConnectionLogProvider", + "ConnectionOrigin", + "ConnectionScreen", + "ConnectionStage", + "ConnectionStatus", + "CustomKeybinding", + "Dialog", + "DialogClose", + "DialogContent", + "DialogDescription", + "DialogFooter", + "DialogHeader", + "DialogOverlay", + "DialogPortal", + "DialogTitle", + "DialogTrigger", + "DropdownMenu", + "DropdownMenuCheckboxItem", + "DropdownMenuContent", + "DropdownMenuGroup", + "DropdownMenuItem", + "DropdownMenuLabel", + "DropdownMenuPortal", + "DropdownMenuRadioGroup", + "DropdownMenuRadioItem", + "DropdownMenuSeparator", + "DropdownMenuShortcut", + "DropdownMenuSub", + "DropdownMenuSubContent", + "DropdownMenuSubTrigger", + "DropdownMenuTrigger", + "EmptyState", + "FOLDER_COLORS", + "FakeSwitch", + "FullScreenAppPhase", + "FullScreenAppWrapper", + "GridCardCatalogEntry", + "GridColSpan", + "GridLayout", + "GridSlot", + "HostFeatureFields", + "HostFeatureFieldsProps", + "HostKeyVerificationDialog", + "Input", + "Kbd", + "KbdKey", + "KbdSeparator", + "KeyCombo", + "KeybindingAction", + "KeybindingActionType", + "Label", + "LineChart", + "LineChartSeries", + "LocalCollectedFile", + "LocalDirectoryListing", + "LocalFileEntry", + "LocalFsHomeInfo", + "LocalFsResult", + "LocalTransferOrigin", + "LocalTransferProgress", + "LocalTrashResult", + "LocalWalkFile", + "LocalWalkResult", + "LogContext", + "LogEntry", + "MFAPromptMode", + "ManagerCardError", + "ManagerCardShell", + "ManagerSearch", + "MetricCard", + "MiniStat", + "PassphraseDialog", + "PasswordInput", + "PluginComponent", + "PluginViewPlaceholder", + "Popover", + "PopoverAnchor", + "PopoverContent", + "PopoverTrigger", + "RadialGauge", + "RadialGaugeProps", + "RecentActivityItem", + "RobustClipboardProvider", + "SSHAuthDialog", + "ScrollArea", + "ScrollBar", + "SectionCard", + "Select", + "Select2", + "SelectContent", + "SelectGroup", + "SelectItem", + "SelectLabel", + "SelectScrollDownButton", + "SelectScrollUpButton", + "SelectSeparator", + "SelectTrigger", + "SelectValue", + "Separator", + "SettingRow", + "Sheet", + "SheetClose", + "SheetContent", + "SheetDescription", + "SheetFooter", + "SheetHeader", + "SheetTitle", + "SheetTrigger", + "Skeleton", + "Slider", + "Sparkline", + "SparklineProps", + "StatRow", + "Switch", + "TOTPDialog", + "Textarea", + "TextareaProps", + "Tooltip", + "TooltipContent", + "TooltipProvider", + "TooltipTrigger", + "UptimeInfo", + "VersionInfo", + "WebSocketConnectionTarget", + "WidgetTitle", + "badgeVariants", + "buildOriginWsUrl", + "buttonVariants", + "cn", + "copyToClipboard", + "createFrontendLogger", + "createQuickConnectHost", + "findMatchingKeybinding", + "getAdaptiveResourceBudget", + "getBasePath", + "getDatabaseHealth", + "getDeviceId", + "getPollingEnvironmentMultiplier", + "getRecentActivity", + "getUptime", + "getVersionInfo", + "globalShortcutHandler", + "guacStateToStage", + "guacStateToStatus", + "hydrateLocalSharedHostAuth", + "isElectron", + "isMacPlatform", + "isQuickConnectHost", + "isTabJumpHotkey", + "linkedServerUrl", + "markAdaptiveResourceUsed", + "pluginWsUrl", + "readFromClipboard", + "resolveConnectionOrigin", + "resolveRemoteHostId", + "runAdaptiveBackgroundTask", + "runAdaptivePolling", + "runVisibleInterval", + "useAdaptivePolling", + "useAppTheme", + "useConfirmation", + "useConnectionLog", + "useIsMobile", + "useOptionalConnectionLog", + "useTabs", + "useTabsSafe", +]; + +/** Every name a module exports, resolved the way the compiler sees it. */ +function exportedNames(file = SDK_UI, tsconfig = TSCONFIG) { + const ts = require("typescript"); + const parsed = ts.getParsedCommandLineOfConfigFile( + tsconfig, + {}, + { ...ts.sys, onUnRecoverableConfigFileDiagnostic: () => {} }, + ); + const program = ts.createProgram([file], { + ...(parsed?.options ?? {}), + noEmit: true, + }); + const checker = program.getTypeChecker(); + const source = program.getSourceFile(file); + const symbol = source && checker.getSymbolAtLocation(source); + if (!symbol) throw new Error(`Cannot read the exports of ${file}`); + return checker + .getExportsOfModule(symbol) + .map((entry) => entry.getName()) + .sort(); +} + +/** What the module adds to, and drops from, the allowlist. */ +function compare(names, allowed = ALLOWED) { + const allowedSet = new Set(allowed); + const nameSet = new Set(names); + return { + added: names.filter((name) => !allowedSet.has(name)), + removed: allowed.filter((name) => !nameSet.has(name)), + }; +} + +function main() { + const names = exportedNames(); + if (process.argv.includes("--list")) { + console.log(names.join("\n")); + return; + } + const { added, removed } = compare(names); + if (added.length === 0 && removed.length === 0) return; + if (added.length > 0) { + console.error( + "@termix/plugin-sdk/ui exports names that are not on the allowlist in scripts/check-sdk-ui-exports.cjs:", + ); + for (const name of added) console.error(` + ${name}`); + } + if (removed.length > 0) { + console.error( + "@termix/plugin-sdk/ui no longer exports these allowlisted names (a breaking change for plugins):", + ); + for (const name of removed) console.error(` - ${name}`); + } + process.exit(1); +} + +if (require.main === module) main(); + +module.exports = { ALLOWED, compare, exportedNames }; diff --git a/scripts/check-sdk-ui-exports.test.ts b/scripts/check-sdk-ui-exports.test.ts new file mode 100644 index 000000000..fd0d1898b --- /dev/null +++ b/scripts/check-sdk-ui-exports.test.ts @@ -0,0 +1,61 @@ +import { afterEach, describe, expect, it } from "vitest"; +import { createRequire } from "node:module"; +import fs from "node:fs"; +import os from "node:os"; +import path from "node:path"; + +const require = createRequire(import.meta.url); +const { ALLOWED, compare, exportedNames } = + require("./check-sdk-ui-exports.cjs") as { + ALLOWED: string[]; + compare: ( + names: string[], + allowed?: string[], + ) => { added: string[]; removed: string[] }; + exportedNames: (file?: string, tsconfig?: string) => string[]; + }; + +let dir: string | null = null; + +afterEach(() => { + if (dir) fs.rmSync(dir, { recursive: true, force: true }); + dir = null; +}); + +describe("compare", () => { + it("names what was added and what was dropped", () => { + expect(compare(["a", "b", "c"], ["a", "b", "d"])).toEqual({ + added: ["c"], + removed: ["d"], + }); + expect(compare(["a"], ["a"])).toEqual({ added: [], removed: [] }); + }); + + it("keeps the allowlist free of duplicates", () => { + expect(new Set(ALLOWED).size).toBe(ALLOWED.length); + }); +}); + +describe("exportedNames", () => { + it("follows export * and renamed exports", () => { + dir = fs.mkdtempSync(path.join(os.tmpdir(), "sdk-ui-exports-")); + fs.writeFileSync( + path.join(dir, "tsconfig.json"), + JSON.stringify({ compilerOptions: { module: "esnext", strict: true } }), + ); + fs.writeFileSync( + path.join(dir, "parts.ts"), + "export const Button = 1;\nexport type ButtonProps = { a: 1 };\n", + ); + fs.writeFileSync( + path.join(dir, "entry.ts"), + 'export * from "./parts";\nconst theme = 2;\nexport { theme as useAppTheme };\n', + ); + expect( + exportedNames( + path.join(dir, "entry.ts"), + path.join(dir, "tsconfig.json"), + ), + ).toEqual(["Button", "ButtonProps", "useAppTheme"]); + }); +}); diff --git a/scripts/check-test-locations.cjs b/scripts/check-test-locations.cjs new file mode 100644 index 000000000..717192437 --- /dev/null +++ b/scripts/check-test-locations.cjs @@ -0,0 +1,61 @@ +#!/usr/bin/env node +/** + * Tests mirror the source tree in their own directories and never sit next + * to the code they test. A *.test.ts(x) file may only live under + * src/backend/tests/, src/ui/tests/, scripts/ or plugins//tests/. + */ + +const fs = require("node:fs"); +const path = require("node:path"); + +const ROOT = path.resolve(__dirname, ".."); +const SKIP = new Set([ + "node_modules", + ".git", + "dist", + "build", + "release", + "coverage", + ".vite", + ".turbo", +]); +const TEST_FILE = /\.test\.tsx?$/; +const ALLOWED = [ + /^src\/backend\/tests\//, + /^src\/ui\/tests\//, + /^scripts\//, + /^plugins\/[^/]+\/tests\//, +]; + +function walk(dir, root, out) { + for (const entry of fs.readdirSync(dir, { withFileTypes: true })) { + if (SKIP.has(entry.name)) continue; + const full = path.join(dir, entry.name); + if (entry.isDirectory()) walk(full, root, out); + else if (TEST_FILE.test(entry.name)) { + out.push(path.relative(root, full).replaceAll("\\", "/")); + } + } + return out; +} + +/** Test files outside the directories tests belong in. */ +function misplaced(root = ROOT) { + return walk(root, root, []) + .filter((file) => !ALLOWED.some((pattern) => pattern.test(file))) + .sort(); +} + +function main() { + const found = misplaced(); + if (found.length === 0) return; + console.error( + "Tests belong in src/backend/tests/, src/ui/tests/, scripts/ or plugins//tests/, mirroring the source:", + ); + for (const file of found) console.error(` ${file}`); + process.exit(1); +} + +if (require.main === module) main(); + +module.exports = { misplaced }; diff --git a/scripts/check-test-locations.test.ts b/scripts/check-test-locations.test.ts new file mode 100644 index 000000000..6be663004 --- /dev/null +++ b/scripts/check-test-locations.test.ts @@ -0,0 +1,57 @@ +import { afterEach, describe, expect, it } from "vitest"; +import { createRequire } from "node:module"; +import fs from "node:fs"; +import os from "node:os"; +import path from "node:path"; + +const require = createRequire(import.meta.url); +const { misplaced } = require("./check-test-locations.cjs") as { + misplaced: (root: string) => string[]; +}; + +let root: string | null = null; + +afterEach(() => { + if (root) fs.rmSync(root, { recursive: true, force: true }); + root = null; +}); + +function fixture(files: string[]): string { + root = fs.mkdtempSync(path.join(os.tmpdir(), "test-locations-")); + for (const file of files) { + const full = path.join(root, file); + fs.mkdirSync(path.dirname(full), { recursive: true }); + fs.writeFileSync(full, ""); + } + return root; +} + +describe("misplaced", () => { + it("accepts the mirrored test trees", () => { + const dir = fixture([ + "src/backend/tests/utils/a.test.ts", + "src/ui/tests/lib/b.test.tsx", + "scripts/c.test.ts", + "plugins/docker/tests/backend/d.test.ts", + "plugins/docker/node_modules/pkg/e.test.ts", + "plugins/docker/dist/f.test.ts", + ]); + expect(misplaced(dir)).toEqual([]); + }); + + it("refuses a test next to its source", () => { + const dir = fixture([ + "src/backend/utils/a.test.ts", + "src/ui/lib/b.test.tsx", + "plugins/docker/src/frontend/c.test.tsx", + "packages/plugin-sdk/src/d.test.ts", + "src/backend/utils/not-a-test.ts", + ]); + expect(misplaced(dir)).toEqual([ + "packages/plugin-sdk/src/d.test.ts", + "plugins/docker/src/frontend/c.test.tsx", + "src/backend/utils/a.test.ts", + "src/ui/lib/b.test.tsx", + ]); + }); +}); diff --git a/src/backend/database/database.ts b/src/backend/database/database.ts index d15c64f1d..34d63136c 100644 --- a/src/backend/database/database.ts +++ b/src/backend/database/database.ts @@ -721,9 +721,6 @@ app.post("/database/export", authenticateJWT, async (req, res) => { key_password TEXT, key_type TEXT, sudo_password TEXT, - autostart_password TEXT, - autostart_key TEXT, - autostart_key_password TEXT, credential_id INTEGER, override_credential_username INTEGER, jump_hosts TEXT, @@ -817,8 +814,8 @@ app.post("/database/export", authenticateJWT, async (req, res) => { const sshHosts = await createCurrentHostRepository().listDecryptedByUserId(userId); const insertHost = exportDb.prepare(` - INSERT INTO ssh_data (id, user_id, connection_type, name, ip, port, username, folder, tags, pin, auth_type, force_keyboard_interactive, password, key, key_password, key_type, sudo_password, autostart_password, autostart_key, autostart_key_password, credential_id, override_credential_username, jump_hosts, status_check_enabled, status_check_interval, terminal_config, ssh_options, quick_actions, notes, use_socks5, socks5_host, socks5_port, socks5_username, socks5_password, socks5_proxy_chain, port_knock_sequence, created_at, updated_at) - VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) + INSERT INTO ssh_data (id, user_id, connection_type, name, ip, port, username, folder, tags, pin, auth_type, force_keyboard_interactive, password, key, key_password, key_type, sudo_password, credential_id, override_credential_username, jump_hosts, status_check_enabled, status_check_interval, terminal_config, ssh_options, quick_actions, notes, use_socks5, socks5_host, socks5_port, socks5_username, socks5_password, socks5_proxy_chain, port_knock_sequence, created_at, updated_at) + VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) `); for (const decrypted of sshHosts) { @@ -840,9 +837,6 @@ app.post("/database/export", authenticateJWT, async (req, res) => { decrypted.keyPassword || null, decrypted.keyType || null, decrypted.sudoPassword || null, - decrypted.autostartPassword || null, - decrypted.autostartKey || null, - decrypted.autostartKeyPassword || null, decrypted.credentialId || null, decrypted.overrideCredentialUsername ? 1 : 0, decrypted.jumpHosts || null, @@ -1177,9 +1171,6 @@ app.post( keyPassword: host.key_password, keyType: host.key_type, sudoPassword: host.sudo_password, - autostartPassword: host.autostart_password, - autostartKey: host.autostart_key, - autostartKeyPassword: host.autostart_key_password, credentialId: host.credential_id || null, overrideCredentialUsername: Boolean( host.override_credential_username, diff --git a/src/backend/database/db/index.ts b/src/backend/database/db/index.ts index b6f0e5e40..74ade9898 100644 --- a/src/backend/database/db/index.ts +++ b/src/backend/database/db/index.ts @@ -304,9 +304,6 @@ async function initializeCompleteDatabase(): Promise { key TEXT, key_password TEXT, key_type TEXT, - autostart_password TEXT, - autostart_key TEXT, - autostart_key_password TEXT, force_keyboard_interactive TEXT, status_check_enabled INTEGER NOT NULL DEFAULT 1, status_check_interval INTEGER, @@ -910,9 +907,6 @@ const migrateSchema = () => { "TEXT NOT NULL DEFAULT CURRENT_TIMESTAMP", ); addColumnIfNotExists("ssh_data", "force_keyboard_interactive", "TEXT"); - addColumnIfNotExists("ssh_data", "autostart_password", "TEXT"); - addColumnIfNotExists("ssh_data", "autostart_key", "TEXT"); - addColumnIfNotExists("ssh_data", "autostart_key_password", "TEXT"); addColumnIfNotExists( "ssh_data", "credential_id", @@ -924,9 +918,6 @@ const migrateSchema = () => { "INTEGER", ); - addColumnIfNotExists("ssh_data", "autostart_password", "TEXT"); - addColumnIfNotExists("ssh_data", "autostart_key", "TEXT"); - addColumnIfNotExists("ssh_data", "autostart_key_password", "TEXT"); addColumnIfNotExists( "ssh_data", "status_check_enabled", diff --git a/src/backend/database/db/schema.mysql.ts b/src/backend/database/db/schema.mysql.ts index 4ea97b924..5f66c2ddc 100644 --- a/src/backend/database/db/schema.mysql.ts +++ b/src/backend/database/db/schema.mysql.ts @@ -189,10 +189,6 @@ export const hosts = mysqlTable( keyType: text("key_type"), sudoPassword: text("sudo_password"), - autostartPassword: text("autostart_password"), - autostartKey: text("autostart_key"), - autostartKeyPassword: text("autostart_key_password"), - credentialId: int("credential_id").references(() => sshCredentials.id, { onDelete: "set null" }), overrideCredentialUsername: boolean("override_credential_username"), jumpHosts: text("jump_hosts"), diff --git a/src/backend/database/db/schema.pg.ts b/src/backend/database/db/schema.pg.ts index 2bc50afa4..64b4b71c0 100644 --- a/src/backend/database/db/schema.pg.ts +++ b/src/backend/database/db/schema.pg.ts @@ -189,10 +189,6 @@ export const hosts = pgTable( keyType: text("key_type"), sudoPassword: text("sudo_password"), - autostartPassword: text("autostart_password"), - autostartKey: text("autostart_key"), - autostartKeyPassword: text("autostart_key_password"), - credentialId: integer("credential_id").references(() => sshCredentials.id, { onDelete: "set null" }), overrideCredentialUsername: boolean("override_credential_username"), jumpHosts: text("jump_hosts"), diff --git a/src/backend/database/db/schema.ts b/src/backend/database/db/schema.ts index 60e31b056..8ad819b8a 100644 --- a/src/backend/database/db/schema.ts +++ b/src/backend/database/db/schema.ts @@ -179,10 +179,6 @@ export const hosts = sqliteTable( keyType: text("key_type"), sudoPassword: text("sudo_password"), - autostartPassword: text("autostart_password"), - autostartKey: text("autostart_key", { length: 8192 }), - autostartKeyPassword: text("autostart_key_password"), - credentialId: integer("credential_id").references(() => sshCredentials.id, { onDelete: "set null" }), overrideCredentialUsername: integer("override_credential_username", { mode: "boolean", diff --git a/src/backend/database/routes/host-normalizers.ts b/src/backend/database/routes/host-normalizers.ts index 00f01507e..265757932 100644 --- a/src/backend/database/routes/host-normalizers.ts +++ b/src/backend/database/routes/host-normalizers.ts @@ -253,12 +253,9 @@ export function normalizeImportedHost( const SENSITIVE_FIELDS = [ "key", "keyPassword", - "autostartKey", - "autostartKeyPassword", "password", "sudoPassword", "socks5Password", - "autostartPassword", ]; export function stripSensitiveFields( diff --git a/src/backend/database/routes/host-plugin-settings.ts b/src/backend/database/routes/host-plugin-settings.ts index 936f82014..a499e40f2 100644 --- a/src/backend/database/routes/host-plugin-settings.ts +++ b/src/backend/database/routes/host-plugin-settings.ts @@ -15,9 +15,14 @@ import { createCurrentPluginSettingsRepository } from "../repositories/factory.j import type { PluginSettingsRecord } from "../repositories/plugin-settings-repository.js"; import { declaredFields, + findField, resolveFieldValue, setSetting, } from "../../plugins/settings.js"; +import { + coerceSettingValue, + validateSettingValue, +} from "@termix/plugin-sdk/settings"; import { getPluginRuntime } from "../../plugins/index.js"; import { consume } from "../../plugins/registry.js"; import { sshLogger } from "../../utils/logger.js"; @@ -262,6 +267,49 @@ export async function writeHostPluginSettings( } } +/** + * Checks the host settings a ctx.hosts write carries, keyed by plugin id, + * before anything is written. A key the plugin does not declare, or a value + * its field refuses, is an error. A plugin that is not running has nowhere to + * keep them, so its entry is skipped and named in `skipped`. + */ +export function checkHostPluginSettingsInput( + input: Record>, +): { + writes: Array<{ manifest: PluginManifest; values: Record }>; + skipped: string[]; + errors: string[]; +} { + const running = new Map(hostSettingsPlugins().map((m) => [m.id, m])); + const writes: Array<{ + manifest: PluginManifest; + values: Record; + }> = []; + const skipped: string[] = []; + const errors: string[] = []; + for (const [pluginId, values] of Object.entries(input)) { + const manifest = running.get(pluginId); + if (!manifest) { + skipped.push(pluginId); + continue; + } + for (const [key, value] of Object.entries(values)) { + const field = findField(manifest, "host", key); + if (!field) { + errors.push(`${pluginId}.${key} is not a host setting it declares`); + continue; + } + const error = validateSettingValue( + field, + coerceSettingValue(field, value), + ); + if (error) errors.push(`${pluginId}.${key}: ${error}`); + } + writes.push({ manifest, values }); + } + return { writes, skipped, errors }; +} + /** * A plugin's own validator for the fields it accepts inline on a bulk host * import row (host-bulk-routes.ts's Termix-JSON import path). Registered diff --git a/src/backend/hosts/host-resolver.ts b/src/backend/hosts/host-resolver.ts index 5a4317b97..207abd0c3 100644 --- a/src/backend/hosts/host-resolver.ts +++ b/src/backend/hosts/host-resolver.ts @@ -96,9 +96,6 @@ export async function resolveHostById( if (!ownerEquivalent) { // Owner-only operational secrets are never shared. host.sudoPassword = null; - host.autostartPassword = null; - host.autostartKey = null; - host.autostartKeyPassword = null; } // Parse JSON fields diff --git a/src/backend/plugins/ctx-hosts.ts b/src/backend/plugins/ctx-hosts.ts index 5e0a49494..4896c0c30 100644 --- a/src/backend/plugins/ctx-hosts.ts +++ b/src/backend/plugins/ctx-hosts.ts @@ -19,13 +19,18 @@ import type { PluginShareTarget, PluginShareableUser, PluginShareableRole, + PluginHostJumpHost, } from "@termix/plugin-sdk/backend"; +import { PLUGIN_HOST_INPUT_KEYS } from "@termix/plugin-sdk/backend"; import type { PluginManifest } from "@termix/plugin-sdk/manifest"; import { assertCapability, capabilityRefused } from "./permissions.js"; import { hostSessionStatus } from "../hosts/host-session-status.js"; import { getActor } from "./actor.js"; import { hostStatusService } from "../hosts/status/host-status-service.js"; +import { parseSshOptions } from "../hosts/ssh-options.js"; +import { hostTerminalExport } from "../database/routes/host-normalizers.js"; import type { DisposableBag } from "./disposables.js"; +import { pluginLogger } from "../utils/logger.js"; type AuditFn = ( action: string, @@ -76,9 +81,6 @@ export const HOST_SECRET_FIELDS = [ "passphrase", "sudoPassword", "socks5Password", - "autostartPassword", - "autostartKey", - "autostartKeyPassword", "vaultToken", ] as const; @@ -106,30 +108,184 @@ export function redactHostSecrets>( return copy as T; } -/** Columns that say who a host belongs to. ctx.hosts.update never moves them. */ -const PROTECTED_HOST_FIELDS = new Set(["id", "userId", "syncId"]); +function asNumber(value: unknown): number | null { + if (value === null || value === undefined || value === "") return null; + const parsed = Number(value); + return Number.isFinite(parsed) ? parsed : null; +} -function toRecord(host: Record): PluginHostRecord { - return redactHostSecrets({ - id: host.id as number, - userId: host.userId as string, +function asFlag(value: unknown, fallback: boolean): boolean { + if (value === null || value === undefined) return fallback; + return value === true || value === 1 || value === "1" || value === "true"; +} + +function parseJumpHosts(value: unknown): PluginHostJumpHost[] { + let list = value; + if (typeof list === "string") { + try { + list = JSON.parse(list); + } catch { + return []; + } + } + if (!Array.isArray(list)) return []; + return list + .map((entry) => asNumber((entry as { hostId?: unknown })?.hostId)) + .filter((hostId): hostId is number => hostId !== null) + .map((hostId) => ({ hostId })); +} + +/** + * A decrypted ssh_data row as PluginHostRecord. Built field by field: a + * column reaches plugins only once the SDK types it, and no secret column is + * ever copied. + */ +export function toRecord( + host: Record, + pluginSettings: Record, +): PluginHostRecord { + const id = Number(host.id); + const origin = host.connectionOrigin; + return { + id, + userId: String(host.userId), + syncId: (host.syncId as string | null) ?? null, name: (host.name as string | null) ?? null, - ip: host.ip as string, - port: host.port as number, - username: host.username as string, - authType: host.authType as string, - credentialId: (host.credentialId as number | null) ?? null, - overrideCredentialUsername: - (host.overrideCredentialUsername as boolean | null) ?? null, - connectionType: (host.connectionType as string | null) ?? null, + ip: String(host.ip ?? ""), + port: asNumber(host.port) ?? 22, + username: String(host.username ?? ""), + authType: String(host.authType ?? ""), + credentialId: asNumber(host.credentialId), + overrideCredentialUsername: asFlag(host.overrideCredentialUsername, false), + connectionType: (host.connectionType as string | null) || "ssh", tags: (host.tags as string | null) ?? null, folder: (host.folder as string | null) ?? null, - jumpHosts: host.jumpHosts, - enableSsh: (host.enableSsh as boolean | null) ?? null, + parentHostId: asNumber(host.parentHostId), + pin: asFlag(host.pin, false), + notes: (host.notes as string | null) ?? null, + jumpHosts: parseJumpHosts(host.jumpHosts), + enableSsh: asFlag(host.enableSsh, true), + sshPort: asNumber(host.sshPort), + statusCheckEnabled: asFlag(host.statusCheckEnabled, true), + statusCheckInterval: asNumber(host.statusCheckInterval), + connectionOrigin: origin === "local" || origin === "remote" ? origin : null, + sshOptions: hostTerminalExport(host).sshOptions, + pluginSettings, + status: Number.isInteger(id) ? hostStatusService.get(id) : null, + localOnly: asFlag(host.localOnly, false), createdAt: (host.createdAt as string | null) ?? null, updatedAt: (host.updatedAt as string | null) ?? null, - ...host, - }); + }; +} + +/** Thrown when a plugin's host write names a field the SDK does not take. */ +export class PluginHostInputError extends Error { + constructor(message: string) { + super(message); + this.name = "PluginHostInputError"; + } +} + +const INPUT_KEYS = new Set(PLUGIN_HOST_INPUT_KEYS); + +// Stops compiling when PluginHostCreateInput gains a key the list misses. +const inputKeysComplete: [ + Exclude, +] extends [never] + ? true + : never = true; +void inputKeysComplete; + +/** + * The ssh_data columns for a create or update, plus the host settings to + * write afterwards. Refuses any key PluginHostCreateInput does not list, so a + * field that moved into a plugin cannot be written into nothing. + */ +export function toHostWrite(input: PluginHostUpdateInput): { + row: Record; + settings: Record>; +} { + const unknown = Object.keys(input ?? {}).filter( + (key) => !INPUT_KEYS.has(key), + ); + if (unknown.length > 0) { + throw new PluginHostInputError( + `ctx.hosts does not take ${unknown.join(", ")}; host settings go in pluginSettings, keyed by the plugin that declares them`, + ); + } + const row: Record = {}; + const set = (key: string, value: unknown) => { + if (value !== undefined) row[key] = value; + }; + set("name", input.name); + set("ip", input.ip); + set("port", input.port); + set("username", input.username); + set("authType", input.authType); + set("credentialId", input.credentialId); + set("overrideCredentialUsername", input.overrideCredentialUsername); + set("connectionType", input.connectionType); + set( + "tags", + Array.isArray(input.tags) + ? input.tags + .map((tag) => String(tag).trim()) + .filter(Boolean) + .join(",") + : input.tags, + ); + set("folder", input.folder); + set("pin", input.pin); + set("notes", input.notes); + set( + "jumpHosts", + input.jumpHosts === undefined + ? undefined + : input.jumpHosts === null + ? null + : JSON.stringify(parseJumpHosts(input.jumpHosts)), + ); + set("enableSsh", input.enableSsh); + set("sshPort", input.sshPort); + set("statusCheckEnabled", input.statusCheckEnabled); + set("statusCheckInterval", input.statusCheckInterval); + set( + "forceKeyboardInteractive", + input.forceKeyboardInteractive === undefined + ? undefined + : input.forceKeyboardInteractive + ? "true" + : "false", + ); + set( + "sshOptions", + input.sshOptions === undefined + ? undefined + : input.sshOptions === null + ? null + : JSON.stringify(parseSshOptions(input.sshOptions)), + ); + + const settings: Record> = {}; + if (input.pluginSettings !== undefined && input.pluginSettings !== null) { + if ( + typeof input.pluginSettings !== "object" || + Array.isArray(input.pluginSettings) + ) { + throw new PluginHostInputError( + "pluginSettings must map plugin ids to their host settings", + ); + } + for (const [pluginId, values] of Object.entries(input.pluginSettings)) { + if (!values || typeof values !== "object" || Array.isArray(values)) { + throw new PluginHostInputError( + `pluginSettings.${pluginId} must be an object`, + ); + } + settings[pluginId] = values; + } + } + return { row, settings }; } function actingUser(): string { @@ -170,6 +326,53 @@ export function createPluginHosts({ manifest, bag, audit }: Deps): PluginHosts { return access.hasAccess; }; + // The calling plugin's own host settings, one query for the whole list. + const toRecords = async ( + rows: Record[], + ): Promise => { + const { loadHostPluginSettings } = + await import("../database/routes/host-plugin-settings.js"); + const settings = await loadHostPluginSettings( + rows.map((row) => Number(row.id)), + ); + return rows.map((row) => + toRecord(row, settings.get(Number(row.id))?.[pluginId] ?? {}), + ); + }; + + const checkSettings = async ( + settings: Record>, + ) => { + if (Object.keys(settings).length === 0) return []; + const { checkHostPluginSettingsInput } = + await import("../database/routes/host-plugin-settings.js"); + const { writes, skipped, errors } = checkHostPluginSettingsInput(settings); + if (errors.length > 0) throw new PluginHostInputError(errors.join("; ")); + if (skipped.length > 0) { + pluginLogger.warn( + "Host settings for plugins that are not running were skipped", + { + operation: "plugin_hosts_write", + pluginId, + skipped, + }, + ); + } + return writes; + }; + + const writeSettings = async ( + hostId: number, + writes: Awaited>, + ) => { + if (writes.length === 0) return; + const { writeHostPluginSettings } = + await import("../database/routes/host-plugin-settings.js"); + for (const { manifest: owner, values } of writes) { + await writeHostPluginSettings(owner, hostId, values); + } + }; + return { list: async () => { await requireRead(); @@ -254,30 +457,27 @@ export function createPluginHosts({ manifest, bag, audit }: Deps): PluginHosts { try { await requireWrite(); } catch (error) { - await audit("hosts_create", host.name ?? host.ip, { + await audit("hosts_create", host?.name ?? host?.ip ?? "host", { success: false, errorMessage: error instanceof Error ? error.message : String(error), }); throw error; } const userId = actingUser(); + const { row, settings } = toHostWrite(host); + const writes = await checkSettings(settings); const { createCurrentHostRepository } = await import("../database/repositories/factory.js"); const created = await createCurrentHostRepository().createEncryptedForUser(userId, { - ...host, + ...row, userId, }); - // Fields another plugin owns (a remote desktop switch) go to that - // plugin's host settings, the same way a bulk import row's do. - const { applyPluginHostImportSettings } = - await import("../database/routes/host-plugin-settings.js"); - await applyPluginHostImportSettings( - created.id, - host as Record, - ); + await writeSettings(created.id, writes); await audit("hosts_create", `host ${created.id}`, { success: true }); - return toRecord(created as unknown as Record); + return ( + await toRecords([created as unknown as Record]) + )[0]; }, update: async ( @@ -294,24 +494,22 @@ export function createPluginHosts({ manifest, bag, audit }: Deps): PluginHosts { throw error; } const userId = actingUser(); - const allowed = Object.fromEntries( - Object.entries(patch as Record).filter( - ([field]) => !PROTECTED_HOST_FIELDS.has(field), - ), - ) as PluginHostUpdateInput; + const { row, settings } = toHostWrite(patch); + const writes = await checkSettings(settings); const { createCurrentHostRepository } = await import("../database/repositories/factory.js"); const updated = await createCurrentHostRepository().updateEncryptedForUser( userId, hostId, - allowed, + row, ); + if (updated) await writeSettings(hostId, writes); await audit("hosts_update", `host ${hostId}`, { success: updated !== null, }); return updated - ? toRecord(updated as unknown as Record) + ? (await toRecords([updated as unknown as Record]))[0] : null; }, @@ -354,9 +552,7 @@ export function createPluginHosts({ manifest, bag, audit }: Deps): PluginHosts { await audit("hosts_list_owned", `${rows.length} host(s)`, { success: true, }); - return rows.map((row) => - toRecord(row as unknown as Record), - ); + return toRecords(rows as unknown as Record[]); }, share: async ( diff --git a/src/backend/tests/database/routes/host-plugin-settings.test.ts b/src/backend/tests/database/routes/host-plugin-settings.test.ts index 55f67c989..35dbbd2b6 100644 --- a/src/backend/tests/database/routes/host-plugin-settings.test.ts +++ b/src/backend/tests/database/routes/host-plugin-settings.test.ts @@ -78,6 +78,7 @@ const { writeHostPluginSettings, applyPluginHostImportSettings, setHostPluginEnabled, + checkHostPluginSettingsInput, } = await import("../../../database/routes/host-plugin-settings.js"); function manifest(id: string, host: unknown): PluginManifest { @@ -453,3 +454,38 @@ describe("share levels, legacy fields and generic writes", () => { expect(await setHostPluginEnabled("missing", [3], true)).toBe(false); }); }); + +describe("checkHostPluginSettingsInput", () => { + it("passes declared keys through to the plugin that owns them", () => { + loaded.push({ id: "docker", manifest: DOCKER, state: "active" }); + const result = checkHostPluginSettingsInput({ + docker: { enableDocker: true, socketPath: "/run/docker.sock" }, + }); + expect(result.errors).toEqual([]); + expect(result.skipped).toEqual([]); + expect(result.writes).toEqual([ + { + manifest: DOCKER, + values: { enableDocker: true, socketPath: "/run/docker.sock" }, + }, + ]); + }); + + it("refuses a key the plugin does not declare and a value it rejects", () => { + loaded.push({ id: "docker", manifest: DOCKER, state: "active" }); + const { errors } = checkHostPluginSettingsInput({ + docker: { dockerConfig: {}, enableDocker: "sure" }, + }); + expect(errors).toHaveLength(2); + expect(errors[0]).toContain("docker.dockerConfig"); + expect(errors[1]).toContain("docker.enableDocker"); + }); + + it("skips a plugin that is not running", () => { + loaded.push({ id: "docker", manifest: DOCKER, state: "disabled" }); + const result = checkHostPluginSettingsInput({ + docker: { enableDocker: true }, + }); + expect(result).toEqual({ writes: [], skipped: ["docker"], errors: [] }); + }); +}); diff --git a/src/backend/tests/fixtures/upgrade/upgrade-mysql.sql b/src/backend/tests/fixtures/upgrade/upgrade-mysql.sql index 131789b67..b50c108e5 100644 --- a/src/backend/tests/fixtures/upgrade/upgrade-mysql.sql +++ b/src/backend/tests/fixtures/upgrade/upgrade-mysql.sql @@ -443,6 +443,13 @@ ALTER TABLE `host_protocol_auth` ADD CONSTRAINT `host_protocol_auth_credential_i CREATE INDEX `idx_host_protocol_auth_user` ON `host_protocol_auth` (`user_id`);--> statement-breakpoint CREATE INDEX `idx_host_protocol_auth_credential` ON `host_protocol_auth` (`credential_id`); +-- ==== core 0064_flippant_killer_shrike ==== +-- ssh_data.autostart_password, autostart_key and autostart_key_password held +-- copies of a host's login for 2.8's autostart endpoint, which nothing has read +-- since. They leave the schema but stay in place, unused, until 3.0.0, so no +-- install loses what it stored. +SELECT 1; + -- ==== plugin workspaces 0001_adopt_user_workspaces.sql ==== -- workspaces 0001: adopt_user_workspaces -- Generated by termix-plugin migrations. Review before committing. diff --git a/src/backend/tests/fixtures/upgrade/upgrade-postgres.sql b/src/backend/tests/fixtures/upgrade/upgrade-postgres.sql index 9fdc2341b..c727fa3fe 100644 --- a/src/backend/tests/fixtures/upgrade/upgrade-postgres.sql +++ b/src/backend/tests/fixtures/upgrade/upgrade-postgres.sql @@ -462,6 +462,13 @@ CREATE UNIQUE INDEX "idx_host_protocol_auth_host_protocol" ON "host_protocol_aut CREATE INDEX "idx_host_protocol_auth_user" ON "host_protocol_auth" USING btree ("user_id");--> statement-breakpoint CREATE INDEX "idx_host_protocol_auth_credential" ON "host_protocol_auth" USING btree ("credential_id"); +-- ==== core 0064_sticky_pestilence ==== +-- ssh_data.autostart_password, autostart_key and autostart_key_password held +-- copies of a host's login for 2.8's autostart endpoint, which nothing has read +-- since. They leave the schema but stay in place, unused, until 3.0.0, so no +-- install loses what it stored. +SELECT 1; + -- ==== plugin workspaces 0001_adopt_user_workspaces.sql ==== -- workspaces 0001: adopt_user_workspaces -- Generated by termix-plugin migrations. Review before committing. diff --git a/src/backend/tests/hosts/host-resolver.test.ts b/src/backend/tests/hosts/host-resolver.test.ts index 692ec6c1a..94d8ecff3 100644 --- a/src/backend/tests/hosts/host-resolver.test.ts +++ b/src/backend/tests/hosts/host-resolver.test.ts @@ -112,9 +112,6 @@ function baseHost(overrides: Record = {}) { credentialId: null, shareSshAuth: false, sudoPassword: "owner-sudo", - autostartPassword: "auto-pass", - autostartKey: null, - autostartKeyPassword: null, jumpHosts: null, tunnelConnections: null, terminalConfig: null, @@ -519,7 +516,6 @@ describe("resolveHostById", () => { expect(host.username).toBe("cred-user"); // Owner-only operational secrets are NOT stripped for the admin. expect(host.sudoPassword).toBe("owner-sudo"); - expect(host.autostartPassword).toBe("auto-pass"); }); it("audits every admin-bypass host resolution", async () => { diff --git a/src/backend/tests/plugins/ctx-hosts.test.ts b/src/backend/tests/plugins/ctx-hosts.test.ts index 1bf9b936b..7e9cc6a1b 100644 --- a/src/backend/tests/plugins/ctx-hosts.test.ts +++ b/src/backend/tests/plugins/ctx-hosts.test.ts @@ -140,11 +140,40 @@ vi.mock("../../hosts/status/host-status-service.js", () => ({ }, })); vi.mock("../../database/routes/host-plugin-settings.js", () => ({ - applyPluginHostImportSettings: async ( - hostId: number, - row: Record, + loadHostPluginSettings: async (hostIds: number[]) => + new Map( + hostIds.map((id) => [ + id, + { fixture: { mine: `own-${id}` }, other: { theirs: true } }, + ]), + ), + checkHostPluginSettingsInput: ( + input: Record>, ) => { - h.importRows.push({ hostId, row }); + const errors: string[] = []; + const writes: Array<{ + manifest: { id: string }; + values: Record; + }> = []; + const skipped: string[] = []; + for (const [pluginId, values] of Object.entries(input)) { + if (pluginId === "off") { + skipped.push(pluginId); + continue; + } + for (const key of Object.keys(values)) { + if (key === "undeclared") errors.push(`${pluginId}.${key}`); + } + writes.push({ manifest: { id: pluginId }, values }); + } + return { writes, skipped, errors }; + }, + writeHostPluginSettings: async ( + manifest: { id: string }, + hostId: number, + values: Record, + ) => { + h.importRows.push({ hostId, row: { [manifest.id]: values } }); }, })); vi.mock("../../utils/shared-host-secrets-manager.js", () => ({ @@ -361,6 +390,7 @@ describe("ctx.hosts", () => { it("creates a host once granted hosts:write", async () => { h.granted = new Set(["hosts:write"]); + h.importRows = []; const hosts = createPluginHosts({ manifest: manifest(["hosts:write"]), audit: vi.fn(async () => {}), @@ -371,19 +401,92 @@ describe("ctx.hosts", () => { port: 22, username: "root", authType: "password", - enableRdp: true, + tags: ["a", "b"], + jumpHosts: [{ hostId: 3 }], + pluginSettings: { "remote-desktop": { enableRdp: true } }, }); expect(created).toMatchObject({ id: 99, name: "pve-guest", userId: "user-1", + tags: "a,b", + jumpHosts: [{ hostId: 3 }], + pluginSettings: { mine: "own-99" }, }); - expect(h.created).toHaveLength(1); - // Another plugin's fields go through its import normalizer. - expect(h.importRows.at(-1)).toMatchObject({ - hostId: 99, - row: { enableRdp: true }, + expect(h.created[0]).toMatchObject({ + tags: "a,b", + jumpHosts: '[{"hostId":3}]', }); + // Another plugin's settings go to that plugin, validated by core. + expect(h.importRows).toEqual([ + { hostId: 99, row: { "remote-desktop": { enableRdp: true } } }, + ]); + }); + + it("refuses a field the SDK does not take instead of dropping it", async () => { + h.granted = new Set(["hosts:write"]); + const hosts = createPluginHosts({ + manifest: manifest(["hosts:write"]), + audit: vi.fn(async () => {}), + }); + await expect( + hosts.create({ + name: "n", + ip: "10.0.0.1", + port: 22, + username: "root", + authType: "password", + enableRdp: true, + } as never), + ).rejects.toThrow(/enableRdp/); + await expect( + hosts.update(5, { userId: "someone-else" } as never), + ).rejects.toThrow(/userId/); + await expect( + hosts.update(5, { pluginSettings: { docker: { undeclared: 1 } } }), + ).rejects.toThrow(/undeclared/); + expect(h.created).toHaveLength(0); + expect(h.updates).toHaveLength(0); + }); + + it("builds the record field by field, with no secret and no other plugin's settings", async () => { + h.granted = new Set(["hosts:write"]); + h.ownedHosts = [ + { + id: 4, + userId: "user-1", + name: "own", + ip: "10.0.0.4", + port: 22, + username: "root", + authType: "password", + password: "secret", + key: "PRIVATE", + autostartPassword: "x", + terminalConfig: '{"keepaliveInterval":5,"fontSize":14}', + enableDocker: true, + jumpHosts: "[]", + }, + ]; + const hosts = createPluginHosts({ + manifest: manifest(["hosts:write"]), + audit: vi.fn(async () => {}), + }); + const [record] = await hosts.listOwned(); + const loose = record as unknown as Record; + for (const field of [ + "password", + "key", + "autostartPassword", + "terminalConfig", + "enableDocker", + ]) { + expect(loose).not.toHaveProperty(field); + } + expect(record.sshOptions).toEqual({ keepaliveInterval: 5 }); + expect(record.pluginSettings).toEqual({ mine: "own-4" }); + expect(record.status).toEqual({ status: "reachable", lastChecked: "t" }); + expect(record.enableSsh).toBe(true); }); it("updates a host once granted hosts:write", async () => { @@ -398,6 +501,7 @@ describe("ctx.hosts", () => { expect(h.updates).toEqual([ { userId: "user-1", hostId: 5, patch: { name: "new" } }, ]); + expect(updated?.pluginSettings).toEqual({ mine: "own-5" }); }); it("returns null updating a host that does not exist for this user", async () => { diff --git a/src/backend/tests/plugins/security/credential-shapes.test.ts b/src/backend/tests/plugins/security/credential-shapes.test.ts index 4cd3962e0..d0e462bb8 100644 --- a/src/backend/tests/plugins/security/credential-shapes.test.ts +++ b/src/backend/tests/plugins/security/credential-shapes.test.ts @@ -31,9 +31,6 @@ function secretHost(id: number): Record { keyPassword: "s3cret-value", sudoPassword: "s3cret-value", socks5Password: "s3cret-value", - autostartPassword: "s3cret-value", - autostartKey: "s3cret-value", - autostartKeyPassword: "s3cret-value", terminalConfig: { sudoPassword: "s3cret-value", fontSize: 14 }, socks5ProxyChain: [{ host: "p", password: "s3cret-value" }], }; @@ -98,7 +95,7 @@ vi.mock("../../../database/repositories/factory.js", () => ({ }), })); vi.mock("../../../database/routes/host-plugin-settings.js", () => ({ - applyPluginHostImportSettings: async () => {}, + loadHostPluginSettings: async () => new Map(), })); vi.mock("../../../hosts/host-resolver.js", () => ({ resolveHostById: async (id: number) => secretHost(id), diff --git a/src/backend/tests/utils/user-encryption-migration-store.test.ts b/src/backend/tests/utils/user-encryption-migration-store.test.ts index 20308e1d1..3c74374a9 100644 --- a/src/backend/tests/utils/user-encryption-migration-store.test.ts +++ b/src/backend/tests/utils/user-encryption-migration-store.test.ts @@ -36,9 +36,6 @@ describe("RawSqliteUserEncryptionMigrationStore", () => { key: "k", key_password: "kp", key_type: "ed25519", - autostart_password: "ap", - autostart_key: "ak", - autostart_key_password: "akp", sudo_password: "sp", }); store.updateCredentialSensitiveFields(13, { @@ -56,17 +53,7 @@ describe("RawSqliteUserEncryptionMigrationStore", () => { expect(db.prepare).toHaveBeenCalledWith( expect.stringContaining("UPDATE ssh_credentials"), ); - expect(run).toHaveBeenCalledWith( - "p", - "k", - "kp", - "ed25519", - "ap", - "ak", - "akp", - "sp", - 12, - ); + expect(run).toHaveBeenCalledWith("p", "k", "kp", "ed25519", "sp", 12); expect(run).toHaveBeenCalledWith("p", "k", "kp", "priv", "pub", "rsa", 13); }); diff --git a/src/backend/utils/field-crypto.ts b/src/backend/utils/field-crypto.ts index 98ef7d942..5f9a924cc 100644 --- a/src/backend/utils/field-crypto.ts +++ b/src/backend/utils/field-crypto.ts @@ -21,9 +21,6 @@ class FieldCrypto { "key", "keyPassword", "sudoPassword", - "autostartPassword", - "autostartKey", - "autostartKeyPassword", "socks5Password", ]), ssh_credentials: new Set([ diff --git a/src/backend/utils/lazy-field-encryption.ts b/src/backend/utils/lazy-field-encryption.ts index 7f4d5f94e..dfeec04b4 100644 --- a/src/backend/utils/lazy-field-encryption.ts +++ b/src/backend/utils/lazy-field-encryption.ts @@ -7,9 +7,6 @@ export class LazyFieldEncryption { private static readonly LEGACY_FIELD_NAME_MAP: Record = { key_password: "keyPassword", sudo_password: "sudoPassword", - autostart_password: "autostartPassword", - autostart_key: "autostartKey", - autostart_key_password: "autostartKeyPassword", socks5_password: "socks5Password", private_key: "privateKey", public_key: "publicKey", @@ -21,9 +18,6 @@ export class LazyFieldEncryption { keyPassword: "key_password", sudoPassword: "sudo_password", - autostartPassword: "autostart_password", - autostartKey: "autostart_key", - autostartKeyPassword: "autostart_key_password", socks5Password: "socks5_password", privateKey: "private_key", publicKey: "public_key", @@ -98,9 +92,6 @@ export class LazyFieldEncryption { "key", "keyPassword", "sudoPassword", - "autostartPassword", - "autostartKey", - "autostartKeyPassword", "socks5Password", "privateKey", "publicKey", @@ -249,9 +240,6 @@ export class LazyFieldEncryption { privateKey: "private_key", publicKey: "public_key", sudoPassword: "sudo_password", - autostartPassword: "autostart_password", - autostartKey: "autostart_key", - autostartKeyPassword: "autostart_key_password", socks5Password: "socks5_password", clientSecret: "client_secret", oidcIdentifier: "oidc_identifier", @@ -264,9 +252,6 @@ export class LazyFieldEncryption { "key", "keyPassword", "sudoPassword", - "autostartPassword", - "autostartKey", - "autostartKeyPassword", "socks5Password", ], ssh_credentials: [ diff --git a/src/backend/utils/logger.ts b/src/backend/utils/logger.ts index 3edc2c703..d8faa2b06 100644 --- a/src/backend/utils/logger.ts +++ b/src/backend/utils/logger.ts @@ -51,9 +51,6 @@ const SENSITIVE_FIELDS = [ "secret", "clientSecret", "keyPassword", - "autostartPassword", - "autostartKey", - "autostartKeyPassword", "credentialId", "authToken", "jwt", diff --git a/src/backend/utils/user-encryption-migration-store.ts b/src/backend/utils/user-encryption-migration-store.ts index 3232ecce4..c4355b09c 100644 --- a/src/backend/utils/user-encryption-migration-store.ts +++ b/src/backend/utils/user-encryption-migration-store.ts @@ -55,7 +55,7 @@ export class RawSqliteUserEncryptionMigrationStore implements UserEncryptionMigr .prepare( ` UPDATE ssh_data - SET password = ?, key = ?, key_password = ?, key_type = ?, autostart_password = ?, autostart_key = ?, autostart_key_password = ?, sudo_password = ?, updated_at = CURRENT_TIMESTAMP + SET password = ?, key = ?, key_password = ?, key_type = ?, sudo_password = ?, updated_at = CURRENT_TIMESTAMP WHERE id = ? `, ) @@ -64,9 +64,6 @@ export class RawSqliteUserEncryptionMigrationStore implements UserEncryptionMigr record.key || null, record.key_password || null, record.key_type || null, - record.autostart_password || null, - record.autostart_key || null, - record.autostart_key_password || null, record.sudo_password || null, recordId, ); diff --git a/src/types/index.ts b/src/types/index.ts index a5e729d25..baa84a1c8 100644 --- a/src/types/index.ts +++ b/src/types/index.ts @@ -96,10 +96,6 @@ export type Host = { sudoPassword?: string; forceKeyboardInteractive?: boolean; - autostartPassword?: string; - autostartKey?: string; - autostartKeyPassword?: string; - credentialId?: number; overrideCredentialUsername?: boolean; userId?: string; diff --git a/src/ui/locales/en.json b/src/ui/locales/en.json index b43be04ba..a61efc8fb 100644 --- a/src/ui/locales/en.json +++ b/src/ui/locales/en.json @@ -207,10 +207,6 @@ "appearanceIntro": "Pick a theme, an accent color and your language. All three can be changed later in Settings.", "featuresTitle": "What else Termix does", "featuresIntro": "Every server you save can be opened in more than a terminal. Here is what is waiting behind the icons on the left.", - "feature_files": "File manager", - "feature_files_desc": "Browse, upload, download and edit files over SFTP without leaving the app.", - "feature_tunnels": "Tunnels", - "feature_tunnels_desc": "Forward ports through a server to reach services that are not exposed.", "featuresRailHint": "Do not need one of these? Hide any icon from the sidebar in Settings, under Navigation.", "workflowTitle": "Move around faster", "workflowIntro": "A few habits that save the most time once you have a couple of servers.", @@ -335,7 +331,6 @@ "passwordSaved": "Password saved, type to change", "key": "Key", "credential": "Credential", - "none": "None", "sshPrivateKey": "SSH Private Key", "keyType": "Key Type", "uploadFile": "Upload File", @@ -473,14 +468,9 @@ "keepaliveIntervalLabel": "Keepalive Interval (seconds)", "maxKeepaliveMisses": "Max Keepalive Misses", "sameHost": "This host (direct tunnel)", - "bindHost": "Bind Host", "proxmoxLastSyncStatus": { "success": "Success" }, - "proxmoxGuestsSelected_one": "{{count}} guest — {{selected}} selected", - "proxmoxGuestsSelected_other": "{{count}} guests — {{selected}} selected", - "proxmoxImportButton_one": "Import {{count}} host", - "proxmoxImportButton_other": "Import {{count}} hosts", "proxmoxResultSkippedNoIp": "{{count}} skipped (no IP found)", "proxmoxStatsUrlCopied": "Proxmox Stats URL copied to clipboard", "statusChecksLabel": "Status Checks", @@ -738,13 +728,11 @@ "updatedCount": "Updated {{count}} hosts", "friendlyNameLabel": "Friendly Name", "descriptionLabel": "Description", - "loadingHost": "Loading host...", "loadingHosts": "Loading hosts...", "loadingCredentials": "Loading credentials...", "noHostsYet": "No hosts yet", "noHostsYetHint": "Add a server to open terminals, browse files and see metrics.", "noHostsMatchSearch": "No hosts match your search", - "hostNotFound": "Host not found", "searchHosts": "Search hosts...", "sortHosts": "Sort Hosts", "sortDefault": "Default Order", @@ -767,7 +755,6 @@ "filterAuthKey": "SSH Key", "filterAuthCredential": "Credential", "filterAuthNone": "None", - "filterAuthOpkssh": "OPKSSH", "filterAuthStepca": "Step CA", "filterProtocolGroup": "Protocol", "filterProtocolSsh": "SSH", @@ -886,7 +873,6 @@ "copyViewUrlAction": "Copy {{name}} link", "filterAuthAgent": "SSH Agent", "filterAuthVault": "Vault", - "filterAuthTailscale": "Tailscale", "authTypeNeedsPlugin": "This host uses {{type}}, which needs {{plugin}}. It is turned off on this server.", "authTypeUnknown": "This host uses {{type}}, which is not available on this server.", "authFieldsAfterSave": "Save the host first, then fill in these fields.", @@ -1010,13 +996,7 @@ "connect": "Connect to Host", "clear": "Clear", "paste": "Paste", - "connected": "Connected", - "clipboardWriteFailed": "Failed to copy to clipboard. Make sure the page is served over HTTPS or localhost.", - "clipboardReadFailed": "Failed to read from clipboard. Make sure clipboard permissions are granted.", "tmuxDetach": "Detach from tmux session", - "terminalTitle": "Terminal - {{host}}", - "terminalWithPath": "Terminal - {{host}}:{{path}}", - "runTitle": "Running {{command}} - {{host}}", "totpRequired": "Two-Factor Authentication Required", "totpCodeLabel": "Verification Code", "totpVerify": "Verify", @@ -1040,109 +1020,20 @@ "connectionLogCopyFailed": "Failed to copy logs to clipboard" }, "transfer": { - "copyToHost": "Copy to host…", - "moveToHost": "Move to host…", - "copyItemsToHost": "Copy {{count}} items to host…", - "moveItemsToHost": "Move {{count}} items to host…", - "noHostsConnected": "No other file-manager hosts available.", - "noHostsConnectedHint": "Add another SSH host with File Manager enabled in Host Manager.", - "selectDestinationHost": "Select destination host", - "destinationPath": "Destination path", - "recentDestinations": "Recent destinations", "collapseRecentDestinations": "Collapse recent destinations", "expandRecentDestinations": "Expand recent destinations", - "browseFolders": "Browse destination folders", "browseDestination": "Browse or enter path", - "confirmCopy": "Copy", - "confirmMove": "Move", "transferring": "Transferring…", - "progressVerifying": "Verifying file integrity…", - "progressBenchmarking": "Selecting the fastest transfer route…", "compressing": "Compressing…", "extracting": "Extracting…", "transferringItems": "Transferring {{current}} of {{total}} items…", - "transferSuccess": "Transfer complete", - "transferError": "Transfer failed", "transferPartial": "Transfer completed with {{count}} errors", - "transferPartialHint": "Could not transfer: {{paths}}", - "itemsSummary": "{{count}} items", - "destMustBeDirectory": "Destination must be a directory for multi-item transfers", "selectThisFolder": "Select this folder", - "browsePathWillBeCreated": "This folder does not exist yet. It will be created when the transfer starts.", - "browsePathError": "Could not open this path on the destination host.", - "goUp": "Go up", - "copyFolderToHost": "Copy folder to host…", - "moveFolderToHost": "Move folder to host…", - "hostReady": "Ready", - "hostConnecting": "Connecting…", - "hostDisconnected": "Not connected", - "hostAuthRequired": "Authentication required — open File Manager on this host first", - "hostConnectionFailed": "Connection failed", "metricsTitle": "Transfer timings", - "metricsPrepare": "Prepare destination: {{duration}}", - "metricsCompress": "Compress on source: {{duration}}", "metricsHopSourceRead": "Source → server: {{throughput}}", "metricsHopDestSftpWrite": "Server → dest (SFTP): {{throughput}}", "metricsHopDestLocalWrite": "Server → dest (local): {{throughput}}", - "metricsTransfer": "End-to-end: {{throughput}} ({{duration}})", - "metricsExtract": "Extract on destination: {{duration}}", - "metricsVerify": "SHA-256 verified: {{duration}}", - "metricsRouteBenchmark": "Route probe — direct: {{direct}}, relay: {{relay}}", - "metricsSourceDelete": "Remove from source: {{duration}}", - "metricsTotal": "Total: {{duration}}", - "progressCompressing": "Compressing on source host…", - "progressExtracting": "Extracting on destination…", - "progressTransferring": "Transferring data…", - "progressReconnecting": "Reconnecting…", - "parallelSegmentsLabel": "Parallel transfer lanes", - "parallelSegmentsOption": "{{count}} lanes", - "parallelSegmentsHint": "Large files are split into 256 MB chunks. Multiple lanes use separate connections (like starting several transfers) for higher total throughput.", - "progressTotalSpeed": "{{speed}} total ({{lanes}} lanes)", - "progressTransferringItems": "Transferring files ({{current}} of {{total}})…", - "progressBytes": "{{transferred}} / {{total}}", - "progressItems": "{{current}} / {{total}} files", - "sourceNotDeletedPartial": "Source files kept (partial transfer)", - "jumpHostLimitation": "Both hosts must be reachable from the Termix server. Direct host-to-host routing is not supported.", - "cancel": "Cancel", - "methodLabel": "Transfer method", - "methodAuto": "Auto", - "methodTar": "Tar archive", - "methodItemSftp": "Per-file SFTP", - "methodAutoHint": "Picks tar or per-file SFTP based on file count, size, and compressibility. Single files always use streaming SFTP.", - "methodTarHint": "Compress on source, transfer one archive, extract on destination. Requires tar on both Unix hosts.", - "methodItemSftpHint": "Transfer each file individually over SFTP. Works on all hosts including Windows.", - "methodPreviewLoading": "Calculating transfer method…", - "methodPreviewError": "Could not preview transfer method. The server will still pick a method when you start.", - "methodPreviewWillUseTar": "Will use: Tar archive", - "methodPreviewWillUseItemSftp": "Will use: Per-file SFTP", - "methodPreviewScanSummary": "{{fileCount}} files, {{totalSize}} total (scanned on source host).", - "methodItemSftpLimitation": "Each file uses the same SFTP stream as a single-file copy, one after another. Progress is combined across all files, so the bar moves slowly during large files.", - "methodReason": { - "user_item_sftp": "You chose per-file SFTP.", - "user_tar": "You chose tar archive.", - "tar_unavailable": "Tar is not available on one or both hosts — per-file SFTP will be used instead.", - "windows_host": "A Windows host is involved — tar is not used.", - "auto_multi_large": "Auto: multiple files including a large file ({{largestSize}}) with compressible data — tar bundles into one transfer.", - "auto_single_large_in_archive": "Auto: one large file ({{largestSize}}) in this set — per-file SFTP.", - "auto_many_incompressible": "Auto: mostly incompressible data — per-file SFTP.", - "auto_many_files": "Auto: many files ({{fileCount}}) — tar reduces per-file overhead.", - "auto_default": "Auto: per-file SFTP for this set." - }, - "progressCancel": "Cancel", - "progressCancelling": "Cancelling…", - "progressStalled": "Stalled", - "resumedHint": "Reconnected to an active transfer started in another window.", - "transferCancelled": "Transfer cancelled", - "transferCancelledCopyHint": "Partial files may remain on the destination.", - "transferCancelledMoveHint": "Partial files may remain on the destination. Source files were not removed.", - "cleanupDestFiles": "Clean up destination", - "cleanupDestFilesSuccess": "Removed partial files from the destination", - "cleanupDestFilesPartial": "Some partial files could not be removed", - "cleanupDestFilesNothing": "Nothing to clean up on the destination", - "cleanupDestFilesError": "Cleanup failed", - "retryTransfer": "Retry", - "retryTransferError": "Retry failed", - "transferFailedRetryHint": "Partial data was kept on the destination. Retry will resume when the connection is back." + "sourceNotDeletedPartial": "Source files kept (partial transfer)" }, "tunnels": { "connect": "Connect", @@ -1152,8 +1043,6 @@ "endpointSshConfig": "Endpoint SSH Configuration", "clientTunnel": "Client Tunnel", "addClientTunnel": "Add Client Tunnel", - "start": "Start", - "stop": "Stop", "typeServerLocalDesc": "Current host to endpoint.", "typeServerRemoteDesc": "Endpoint back to current host.", "typeClientLocalDesc": "Local computer to endpoint.", @@ -1268,8 +1157,7 @@ "resetCodeRateLimitedWithTime": "Rate limited: Too many verification attempts. Please wait {{time}} seconds before trying again.", "authTokenSaveFailed": "Failed to save authentication token", "authTokenMissing": "The server did not return a new authentication token. Please sign in again.", - "failedToLoadServer": "Failed to load server", - "remoteServerRequired": "Remote server required. Connect a remote server in Settings to use this connection type." + "failedToLoadServer": "Failed to load server" }, "messages": { "registrationDisabled": "New account registration is currently disabled by an admin. Please log in or contact an administrator.", @@ -1714,7 +1602,6 @@ "protocolLabel": "Protocol", "domainLabel": "Domain", "domainPlaceholder": "optional", - "connectToTerminal": "Connect to Terminal", "connectToAction": "Connect to {{name}}", "sshProtocol": "SSH", "noTarget": "Nothing installed can connect to this host type" diff --git a/src/ui/locales/translated/af_ZA.json b/src/ui/locales/translated/af_ZA.json index 76217844c..4f68209a5 100644 --- a/src/ui/locales/translated/af_ZA.json +++ b/src/ui/locales/translated/af_ZA.json @@ -324,10 +324,6 @@ "appearanceIntro": "Kies 'n tema, 'n aksentkleur en jou taal. Al drie kan later in Instellings verander word.", "featuresTitle": "Wat doen Termix nog?", "featuresIntro": "Elke bediener wat jy stoor, kan in meer as 'n terminaal oopgemaak word. Hier is wat agter die ikone aan die linkerkant wag.", - "feature_files": "Lêerbestuurder", - "feature_files_desc": "Blaai, laai op, laai af en wysig lêers via SFTP sonder om die toepassing te verlaat.", - "feature_tunnels": "Tonnels", - "feature_tunnels_desc": "Stuur poorte deur 'n bediener aan om dienste te bereik wat nie blootgestel is nie.", "feature_snippets": "Brokkies", "feature_snippets_desc": "Stoor opdragte wat jy gereeld uitvoer en stuur dit met een klik na 'n terminaal.", "featuresRailHint": "Het jy nie een van hierdie nodig nie? Versteek enige ikoon in die sybalk in Instellings, onder Navigasie.", @@ -449,7 +445,6 @@ "passwordSaved": "Wagwoord gestoor, tik om te verander", "key": "Sleutel", "credential": "Geloofsbrief", - "none": "Geen", "sshPrivateKey": "SSH Privaat Sleutel", "keyType": "Sleuteltipe", "uploadFile": "Laai lêer op", @@ -611,17 +606,12 @@ "keepaliveIntervalLabel": "Lewendige interval (sekondes)", "maxKeepaliveMisses": "Max Keepalive mis", "sameHost": "Hierdie gasheer (direkte tonnel)", - "bindHost": "Bind gasheer", "connectionToolbar": "Verbindingsnutsbalk", "showConnectionToolbar": "Wys verbindingsbalk", "showConnectionToolbarDesc": "Wys die nutsbalk in hierdie gasheer se SSH-, RDP-, VNC- en Telnet-sessies. Jy kan dit ook tydelik van die nutsbalk self versteek.", "proxmoxLastSyncStatus": { "success": "Sukses" }, - "proxmoxGuestsSelected_one": "{{count}} gas — {{selected}} gekies", - "proxmoxGuestsSelected_other": "{{count}} gaste — {{selected}} gekies", - "proxmoxImportButton_one": "Voer {{count}} gasheer in", - "proxmoxImportButton_other": "Voer {{count}} gashere in", "proxmoxResultSkippedNoIp": "{{count}} oorgeslaan (geen IP gevind nie)", "proxmoxStatsUrlCopied": "Proxmox Statistiek URL na knipbord gekopieer", "copyProxmoxStatsUrlAction": "Kopieer Proxmox Statistiek URL", @@ -896,13 +886,11 @@ "updatedCount": "Opgedateerde {{count}} gashere", "friendlyNameLabel": "Vriendelike Naam", "descriptionLabel": "Beskrywing", - "loadingHost": "Laai gasheer...", "loadingHosts": "Laai gashere...", "loadingCredentials": "Laai aanmeldbewyse...", "noHostsYet": "Geen gashere nog nie", "noHostsYetHint": "Voeg 'n bediener by om terminale oop te maak, lêers te blaai en statistieke te sien.", "noHostsMatchSearch": "Geen gashere stem ooreen met jou soektog nie", - "hostNotFound": "Gasheer nie gevind nie", "searchHosts": "Soek gashere...", "sortHosts": "Sorteer gashere", "sortDefault": "Standaardbestelling", @@ -925,7 +913,6 @@ "filterAuthKey": "SSH-sleutel", "filterAuthCredential": "Geloofsbrief", "filterAuthNone": "Geen", - "filterAuthOpkssh": "OPKSSH", "filterAuthStepca": "Stap CA", "filterProtocolGroup": "Protokol", "filterProtocolSsh": "SSH", @@ -1114,13 +1101,7 @@ "connect": "Koppel aan gasheer", "clear": "Duidelik", "paste": "Plak", - "connected": "Verbonde", - "clipboardWriteFailed": "Kon nie na knipbord kopieer nie. Maak seker dat die bladsy oor HTTPS of localhost bedien word.", - "clipboardReadFailed": "Kon nie vanaf knipbord lees nie. Maak seker dat knipbordtoestemmings toegestaan is.", "tmuxDetach": "Ontkoppel van tmux-sessie", - "terminalTitle": "Terminaal - {{host}}", - "terminalWithPath": "Terminaal - {{host}}:{{path}}", - "runTitle": "Hardloop {{command}} - {{host}}", "totpRequired": "Tweefaktor-verifikasie vereis", "totpCodeLabel": "Verifikasiekode", "totpVerify": "Verifieer", @@ -1148,109 +1129,20 @@ } }, "transfer": { - "copyToHost": "Kopieer na gasheer…", - "moveToHost": "Skuif na gasheer…", - "copyItemsToHost": "Kopieer {{count}} items om… aan te bied", - "moveItemsToHost": "Skuif {{count}} items om… te huisves", - "noHostsConnected": "Geen ander lêerbestuurder-gashere beskikbaar nie.", - "noHostsConnectedHint": "Voeg nog 'n SSH-gasheer by met Lêerbestuurder geaktiveer in Gasheerbestuurder.", - "selectDestinationHost": "Kies bestemmingsgasheer", - "destinationPath": "Bestemmingspad", - "recentDestinations": "Onlangse bestemmings", "collapseRecentDestinations": "Vou onlangse bestemmings in", "expandRecentDestinations": "Vou onlangse bestemmings uit", - "browseFolders": "Blaai deur bestemmingsmappe", "browseDestination": "Blaai of voer pad in", - "confirmCopy": "Kopieer", - "confirmMove": "Beweeg", "transferring": "Oordra…", - "progressVerifying": "Verifieer lêerintegriteit…", - "progressBenchmarking": "Die vinnigste oordragroete kies…", "compressing": "Kompressering…", "extracting": "Onttrek…", "transferringItems": "Oordrag van {{current}} van {{total}} items…", - "transferSuccess": "Oordrag voltooi", - "transferError": "Oordrag het misluk", "transferPartial": "Oordrag voltooi met {{count}} foute", - "transferPartialHint": "Kon nie oordra nie: {{paths}}", - "itemsSummary": "{{count}} items", - "destMustBeDirectory": "Bestemming moet 'n gids wees vir oordragte van verskeie items", "selectThisFolder": "Kies hierdie vouer", - "browsePathWillBeCreated": "Hierdie vouer bestaan nog nie. Dit sal geskep word wanneer die oordrag begin.", - "browsePathError": "Kon nie hierdie pad op die bestemmingsgasheer oopmaak nie.", - "goUp": "Gaan op", - "copyFolderToHost": "Kopieer lêergids na gasheer…", - "moveFolderToHost": "Skuif vouer na gasheer…", - "hostReady": "Gereed", - "hostConnecting": "Verbind…", - "hostDisconnected": "Nie gekoppel nie", - "hostAuthRequired": "Verifikasie vereis — maak eers Lêerbestuurder op hierdie gasheer oop", - "hostConnectionFailed": "Verbinding het misluk", "metricsTitle": "Oordragtye", - "metricsPrepare": "Berei bestemming voor: {{duration}}", - "metricsCompress": "Kompresseer op bron: {{duration}}", "metricsHopSourceRead": "Bron → bediener: {{throughput}}", "metricsHopDestSftpWrite": "Bediener → bestemming (SFTP): {{throughput}}", "metricsHopDestLocalWrite": "Bediener → bestemming (plaaslik): {{throughput}}", - "metricsTransfer": "Van begin tot einde: {{throughput}} ({{duration}})", - "metricsExtract": "Uittreksel op bestemming: {{duration}}", - "metricsVerify": "SHA-256 geverifieer: {{duration}}", - "metricsRouteBenchmark": "Roete-sonde — direk: {{direct}}, aflos: {{relay}}", - "metricsSourceDelete": "Verwyder van bron: {{duration}}", - "metricsTotal": "Totaal: {{duration}}", - "progressCompressing": "Kompressering op brongasheer…", - "progressExtracting": "Onttrek op bestemming…", - "progressTransferring": "Oordrag van data…", - "progressReconnecting": "Herverbind…", - "parallelSegmentsLabel": "Parallelle oordragbane", - "parallelSegmentsOption": "{{count}} bane", - "parallelSegmentsHint": "Groot lêers word in 256 MB-stukke verdeel. Verskeie bane gebruik afsonderlike verbindings (soos om verskeie oordragte te begin) vir hoër totale deurset.", - "progressTotalSpeed": "{{speed}} totaal ({{lanes}} bane)", - "progressTransferringItems": "Oordrag van lêers ({{current}} van {{total}})…", - "progressBytes": "{{transferred}} / {{total}}", - "progressItems": "{{current}} / {{total}} lêers", - "sourceNotDeletedPartial": "Bronlêers gehou (gedeeltelike oordrag)", - "jumpHostLimitation": "Beide gashere moet vanaf die Termix-bediener bereikbaar wees. Direkte gasheer-tot-gasheer-roetering word nie ondersteun nie.", - "cancel": "Kanselleer", - "methodLabel": "Oordragmetode", - "methodAuto": "Outomaties", - "methodTar": "Teer-argief", - "methodItemSftp": "SFTP per lêer", - "methodAutoHint": "Kies tar- of per-lêer SFTP gebaseer op lêertelling, grootte en saampersbaarheid. Enkele lêers gebruik altyd stroom-SFTP.", - "methodTarHint": "Komprimeer op bron, dra een argief oor, onttrek op bestemming. Vereis tar op beide Unix-gashere.", - "methodItemSftpHint": "Dra elke lêer individueel oor SFTP. Werk op alle gashere, insluitend Windows.", - "methodPreviewLoading": "Berekening van oordragmetode…", - "methodPreviewError": "Kon nie oordragmetode voorskou nie. Die bediener sal steeds 'n metode kies wanneer jy begin.", - "methodPreviewWillUseTar": "Sal gebruik: Tar-argief", - "methodPreviewWillUseItemSftp": "Sal gebruik: SFTP per lêer", - "methodPreviewScanSummary": "{{fileCount}} lêers, {{totalSize}} totaal (geskandeer op brongasheer).", - "methodItemSftpLimitation": "Elke lêer gebruik dieselfde SFTP-stroom as 'n enkellêerkopie, een na die ander. Vordering word oor alle lêers gekombineer, so die balk beweeg stadig tydens groot lêers.", - "methodReason": { - "user_item_sftp": "Jy het SFTP per lêer gekies.", - "user_tar": "Jy het teer-argief gekies.", - "tar_unavailable": "Teer is nie beskikbaar op een of albei gashere nie — SFTP per lêer sal eerder gebruik word.", - "windows_host": "'n Windows-gasheer is betrokke — teer word nie gebruik nie.", - "auto_multi_large": "Outomaties: veelvuldige lêers, insluitend 'n groot lêer ({{largestSize}}) met saampersbare data — teer bundels in een oordrag.", - "auto_single_large_in_archive": "Outomaties: een groot lêer ({{largestSize}}) in hierdie stel — SFTP per lêer.", - "auto_many_incompressible": "Outomaties: meestal onsaampersbare data — SFTP per lêer.", - "auto_many_files": "Outomaties: baie lêers ({{fileCount}}) — teer verminder oorhoofse koste per lêer.", - "auto_default": "Outomaties: SFTP per lêer vir hierdie stel." - }, - "progressCancel": "Kanselleer", - "progressCancelling": "Kanselleer…", - "progressStalled": "Vasgevang", - "resumedHint": "Herverbind met 'n aktiewe oordrag wat in 'n ander venster begin is.", - "transferCancelled": "Oordrag gekanselleer", - "transferCancelledCopyHint": "Gedeeltelike lêers mag dalk op die bestemming bly.", - "transferCancelledMoveHint": "Gedeeltelike lêers mag dalk op die bestemming bly. Bronlêers is nie verwyder nie.", - "cleanupDestFiles": "Maak bestemming skoon", - "cleanupDestFilesSuccess": "Gedeeltelike lêers van die bestemming verwyder", - "cleanupDestFilesPartial": "Sommige gedeeltelike lêers kon nie verwyder word nie", - "cleanupDestFilesNothing": "Niks om op die bestemming op te ruim nie", - "cleanupDestFilesError": "Opruiming het misluk", - "retryTransfer": "Probeer weer", - "retryTransferError": "Herprobeer het misluk", - "transferFailedRetryHint": "Gedeeltelike data is op die bestemming gehou. Herprobeer sal hervat word wanneer die verbinding terug is." + "sourceNotDeletedPartial": "Bronlêers gehou (gedeeltelike oordrag)" }, "tunnels": { "connect": "Verbind", @@ -1261,8 +1153,6 @@ "clientTunnel": "Kliënttonnel", "addClientTunnel": "Voeg kliënttonnel by", "active": "Aktief", - "start": "Begin", - "stop": "Stop", "typeServerLocalDesc": "Huidige gasheer na eindpunt.", "typeServerRemoteDesc": "Eindpunt terug na huidige gasheer.", "typeClientLocalDesc": "Plaaslike rekenaar na eindpunt.", @@ -1374,8 +1264,7 @@ "resetCodeRateLimitedWithTime": "Tempo beperk: Te veel verifikasiepogings. Wag asseblief {{time}} sekondes voordat u weer probeer.", "authTokenSaveFailed": "Kon nie verifikasietoken stoor nie", "authTokenMissing": "Die bediener het nie 'n nuwe verifikasietoken teruggegee nie. Meld asseblief weer aan.", - "failedToLoadServer": "Kon nie bediener laai nie", - "remoteServerRequired": "Afstandbediener word benodig. Koppel 'n afstandbediener in Instellings om hierdie verbindingstipe te gebruik." + "failedToLoadServer": "Kon nie bediener laai nie" }, "messages": { "registrationDisabled": "Nuwe rekeningregistrasie is tans deur 'n administrateur gedeaktiveer. Meld asseblief aan of kontak 'n administrateur.", @@ -1831,7 +1720,6 @@ "protocolLabel": "Protokol", "domainLabel": "Domein", "domainPlaceholder": "opsioneel", - "connectToTerminal": "Koppel aan terminaal", "connectToFiles": "Koppel aan lêers" }, "splitScreen": { diff --git a/src/ui/locales/translated/ar_SA.json b/src/ui/locales/translated/ar_SA.json index ad47b940b..e66ac069d 100644 --- a/src/ui/locales/translated/ar_SA.json +++ b/src/ui/locales/translated/ar_SA.json @@ -324,10 +324,6 @@ "appearanceIntro": "اختر سمة ولونًا مميزًا ولغتك. يمكنك تغيير كل هذه العناصر لاحقًا من الإعدادات.", "featuresTitle": "ما الذي تقدمه شركة Termix أيضاً؟", "featuresIntro": "يمكن فتح كل خادم تقوم بحفظه في أكثر من مجرد نافذة طرفية. إليك ما ينتظرك خلف الأيقونات الموجودة على اليسار.", - "feature_files": "مدير الملفات", - "feature_files_desc": "تصفح الملفات وقم بتحميلها وتنزيلها وتعديلها عبر بروتوكول SFTP دون مغادرة التطبيق.", - "feature_tunnels": "الأنفاق", - "feature_tunnels_desc": "إعادة توجيه المنافذ عبر خادم للوصول إلى الخدمات غير المكشوفة.", "feature_snippets": "مقتطفات", "feature_snippets_desc": "احفظ الأوامر التي تقوم بتشغيلها بشكل متكرر وأرسلها إلى الطرفية بنقرة واحدة.", "featuresRailHint": "لا تحتاج إلى أحد هذه الخيارات؟ يمكنك إخفاء أي أيقونة من الشريط الجانبي في الإعدادات، ضمن قسم التنقل.", @@ -449,7 +445,6 @@ "passwordSaved": "تم حفظ كلمة المرور، اكتب لتغييرها", "key": "المفتاح", "credential": "بيانات الاعتماد", - "none": "لا يوجد", "sshPrivateKey": "مفتاح SSH الخاص", "keyType": "نوع المفتاح", "uploadFile": "رفع ملف", @@ -611,17 +606,12 @@ "keepaliveIntervalLabel": "فترة إبقاء الاتصال (بالثواني)", "maxKeepaliveMisses": "الحد الأقصى لمرات فقدان إبقاء الاتصال", "sameHost": "هذا المضيف (نفق مباشر)", - "bindHost": "مضيف الربط", "connectionToolbar": "شريط أدوات الاتصال", "showConnectionToolbar": "إظهار شريط أدوات الاتصال", "showConnectionToolbarDesc": "يمكنك إظهار شريط الأدوات في جلسات SSH وRDP وVNC وTelnet الخاصة بهذا المضيف. كما يمكنك إخفاؤه مؤقتًا من شريط الأدوات نفسه.", "proxmoxLastSyncStatus": { "success": "نجاح" }, - "proxmoxGuestsSelected_one": "{{count}} جهاز ضيف — {{selected}} مُحدد", - "proxmoxGuestsSelected_other": "{{count}} أجهزة ضيفة — {{selected}} مُحددة", - "proxmoxImportButton_one": "استيراد {{count}} مضيف", - "proxmoxImportButton_other": "استيراد {{count}} مضيفين", "proxmoxResultSkippedNoIp": "تم تخطي {{count}} (لم يتم العثور على عنوان IP)", "proxmoxStatsUrlCopied": "تم نسخ رابط إحصائيات Proxmox إلى الحافظة", "copyProxmoxStatsUrlAction": "انسخ رابط إحصائيات Proxmox", @@ -896,13 +886,11 @@ "updatedCount": "تم تحديث {{count}} مضيف", "friendlyNameLabel": "الاسم المألوف", "descriptionLabel": "الوصف", - "loadingHost": "جارٍ تحميل المضيف...", "loadingHosts": "جارٍ تحميل المضيفين...", "loadingCredentials": "جارٍ تحميل بيانات الاعتماد...", "noHostsYet": "لا يوجد مضيفون بعد", "noHostsYetHint": "أضف خادمًا لفتح المحطات الطرفية، وتصفح الملفات، وعرض المقاييس.", "noHostsMatchSearch": "لا يوجد مضيفون يطابقون بحثك", - "hostNotFound": "المضيف غير موجود", "searchHosts": "ابحث عن مضيفين...", "sortHosts": "ترتيب المضيفين", "sortDefault": "الترتيب الافتراضي", @@ -925,7 +913,6 @@ "filterAuthKey": "مفتاح SSH", "filterAuthCredential": "بيانات الاعتماد", "filterAuthNone": "بلا", - "filterAuthOpkssh": "OPKSSH", "filterAuthStepca": "الخطوة ج", "filterProtocolGroup": "البروتوكول", "filterProtocolSsh": "SSH", @@ -1114,13 +1101,7 @@ "connect": "الاتصال بالمضيف", "clear": "مسح", "paste": "لصق", - "connected": "متصل", - "clipboardWriteFailed": "فشل النسخ إلى الحافظة. تأكد من تقديم الصفحة عبر HTTPS أو localhost.", - "clipboardReadFailed": "فشلت القراءة من الحافظة. تأكد من منح أذونات الحافظة.", "tmuxDetach": "فصل من جلسة tmux", - "terminalTitle": "الطرفية - {{host}}", - "terminalWithPath": "الطرفية - {{host}}:{{path}}", - "runTitle": "تشغيل {{command}} - {{host}}", "totpRequired": "مطلوب المصادقة الثنائية", "totpCodeLabel": "رمز التحقق", "totpVerify": "تحقق", @@ -1148,109 +1129,20 @@ } }, "transfer": { - "copyToHost": "نسخ إلى المضيف…", - "moveToHost": "نقل إلى المضيف…", - "copyItemsToHost": "نسخ {{count}} عناصر إلى المضيف…", - "moveItemsToHost": "نقل {{count}} عناصر إلى المضيف…", - "noHostsConnected": "لا تتوفر مضيفات أخرى لمدير الملفات.", - "noHostsConnectedHint": "أضف مضيف SSH آخر مع تمكين مدير الملفات في مدير المضيفات.", - "selectDestinationHost": "تحديد المضيف الوجهة", - "destinationPath": "مسار الوجهة", - "recentDestinations": "الوجهات الأخيرة", "collapseRecentDestinations": "طي الوجهات الأخيرة", "expandRecentDestinations": "توسيع الوجهات الأخيرة", - "browseFolders": "تصفح مجلدات الوجهة", "browseDestination": "تصفح المسار أو أدخله", - "confirmCopy": "نسخ", - "confirmMove": "نقل", "transferring": "جارٍ النقل…", - "progressVerifying": "التحقق من سلامة الملف…", - "progressBenchmarking": "اختيار أسرع مسار نقل…", "compressing": "جارٍ الضغط…", "extracting": "جارٍ الاستخراج…", "transferringItems": "جارٍ نقل {{current}} من {{total}} عناصر…", - "transferSuccess": "اكتمل النقل", - "transferError": "فشل النقل", "transferPartial": "اكتمل النقل مع {{count}} أخطاء", - "transferPartialHint": "تعذر النقل: {{paths}}", - "itemsSummary": "{{count}} عنصر", - "destMustBeDirectory": "يجب أن تكون الوجهة مجلدًا لنقل عناصر متعددة", "selectThisFolder": "تحديد هذا المجلد", - "browsePathWillBeCreated": "هذا المجلد غير موجود بعد. سيتم إنشاؤه عند بدء النقل.", - "browsePathError": "تعذر فتح هذا المسار على المضيف الوجهة.", - "goUp": "للأعلى", - "copyFolderToHost": "نسخ المجلد إلى المضيف…", - "moveFolderToHost": "نقل المجلد إلى المضيف…", - "hostReady": "جاهز", - "hostConnecting": "جارٍ الاتصال…", - "hostDisconnected": "غير متصل", - "hostAuthRequired": "المصادقة مطلوبة — افتح مدير الملفات على هذا المضيف أولاً", - "hostConnectionFailed": "فشل الاتصال", "metricsTitle": "توقيتات النقل", - "metricsPrepare": "تحضير الوجهة: {{duration}}", - "metricsCompress": "ضغط على المصدر: {{duration}}", "metricsHopSourceRead": "المصدر → الخادم: {{throughput}}", "metricsHopDestSftpWrite": "الخادم → الوجهة (SFTP): {{throughput}}", "metricsHopDestLocalWrite": "الخادم → الوجهة (محلي): {{throughput}}", - "metricsTransfer": "نقل شامل: {{throughput}} ({{duration}})", - "metricsExtract": "فك على الوجهة: {{duration}}", - "metricsVerify": "تم التحقق من SHA-256: {{duration}}", - "metricsRouteBenchmark": "مسبار المسار — مباشر: {{direct}}، مرحل: {{relay}}", - "metricsSourceDelete": "إزالة من المصدر: {{duration}}", - "metricsTotal": "الإجمالي: {{duration}}", - "progressCompressing": "جارٍ الضغط على المضيف المصدر…", - "progressExtracting": "جارٍ الفك على الوجهة…", - "progressTransferring": "جارٍ نقل البيانات…", - "progressReconnecting": "جارٍ إعادة الاتصال…", - "parallelSegmentsLabel": "مسارات النقل المتوازية", - "parallelSegmentsOption": "{{count}} مسارات", - "parallelSegmentsHint": "تُقسم الملفات الكبيرة إلى أجزاء بحجم 256 ميغابايت. تستخدم المسارات المتعددة اتصالات منفصلة (مثل بدء عدة عمليات نقل) لتحقيق إنتاجية إجمالية أعلى.", - "progressTotalSpeed": "{{speed}} إجمالي ({{lanes}} مسارات)", - "progressTransferringItems": "جارٍ نقل الملفات ({{current}} من {{total}})…", - "progressBytes": "{{transferred}} / {{total}}", - "progressItems": "{{current}} / {{total}} ملفات", - "sourceNotDeletedPartial": "الملفات المصدر محفوظة (نقل جزئي)", - "jumpHostLimitation": "يجب أن يكون كلا المضيفين قابلين للوصول من خادم Termix. التوجيه المباشر من مضيف إلى مضيف غير مدعوم.", - "cancel": "إلغاء", - "methodLabel": "طريقة النقل", - "methodAuto": "تلقائي", - "methodTar": "أرشيف Tar", - "methodItemSftp": "SFTP لكل ملف", - "methodAutoHint": "يختار tar أو SFTP لكل ملف بناءً على عدد الملفات وحجمها وقابلية الضغط. الملفات المفردة تستخدم دائمًا SFTP التدفقي.", - "methodTarHint": "ضغط على المصدر، نقل أرشيف واحد، فك على الوجهة. يتطلب tar على كلا المضيفين Unix.", - "methodItemSftpHint": "نقل كل ملف على حدة عبر SFTP. يعمل على جميع المضيفين بما في ذلك Windows.", - "methodPreviewLoading": "جارٍ حساب طريقة النقل…", - "methodPreviewError": "تعذّر معاينة طريقة النقل. سيختار الخادم طريقة عند بدء النقل.", - "methodPreviewWillUseTar": "سيُستخدم: أرشيف Tar", - "methodPreviewWillUseItemSftp": "سيُستخدم: SFTP لكل ملف", - "methodPreviewScanSummary": "{{fileCount}} ملفات، {{totalSize}} إجمالي (تم المسح على المضيف المصدر).", - "methodItemSftpLimitation": "يستخدم كل ملف نفس تدفق SFTP كنسخ الملف الواحد، واحداً تلو الآخر. يُجمع التقدم عبر جميع الملفات، لذا يتحرك الشريط ببطء أثناء الملفات الكبيرة.", - "methodReason": { - "user_item_sftp": "اخترت SFTP لكل ملف.", - "user_tar": "اخترت أرشيف tar.", - "tar_unavailable": "tar غير متوفر على أحد المضيفين أو كليهما — سيُستخدم SFTP لكل ملف بدلاً من ذلك.", - "windows_host": "يوجد مضيف Windows — لا يُستخدم tar.", - "auto_multi_large": "تلقائي: عدة ملفات بما فيها ملف كبير ({{largestSize}}) ببيانات قابلة للضغط — يجمعها tar في حزمة واحدة.", - "auto_single_large_in_archive": "تلقائي: ملف كبير واحد ({{largestSize}}) في هذه المجموعة — SFTP لكل ملف.", - "auto_many_incompressible": "تلقائي: البيانات غالبًا غير قابلة للضغط — SFTP لكل ملف.", - "auto_many_files": "تلقائي: عدة ملفات ({{fileCount}}) — يقلل tar الحمل لكل ملف.", - "auto_default": "تلقائي: SFTP لكل ملف لهذه المجموعة." - }, - "progressCancel": "إلغاء", - "progressCancelling": "جارٍ الإلغاء…", - "progressStalled": "متوقف", - "resumedHint": "تمت إعادة الاتصال بنقل نشط بدأ في نافذة أخرى.", - "transferCancelled": "تم إلغاء النقل", - "transferCancelledCopyHint": "قد تبقى ملفات جزئية على الوجهة.", - "transferCancelledMoveHint": "قد تبقى ملفات جزئية على الوجهة. لم يتم حذف ملفات المصدر.", - "cleanupDestFiles": "تنظيف الوجهة", - "cleanupDestFilesSuccess": "تمت إزالة الملفات الجزئية من الوجهة", - "cleanupDestFilesPartial": "تعذر إزالة بعض الملفات الجزئية", - "cleanupDestFilesNothing": "لا شيء للتنظيف على الوجهة", - "cleanupDestFilesError": "فشل التنظيف", - "retryTransfer": "إعادة المحاولة", - "retryTransferError": "فشلت إعادة المحاولة", - "transferFailedRetryHint": "تم الاحتفاظ بالبيانات الجزئية على الوجهة. ستُستأنف إعادة المحاولة عند عودة الاتصال." + "sourceNotDeletedPartial": "الملفات المصدر محفوظة (نقل جزئي)" }, "tunnels": { "connect": "اتصل", @@ -1261,8 +1153,6 @@ "clientTunnel": "نفق العميل", "addClientTunnel": "إضافة نفق عميل", "active": "نشط", - "start": "تشغيل", - "stop": "إيقاف", "typeServerLocalDesc": "من المضيف الحالي إلى نقطة النهاية.", "typeServerRemoteDesc": "من نقطة النهاية إلى المضيف الحالي.", "typeClientLocalDesc": "من الكمبيوتر المحلي إلى نقطة النهاية.", @@ -1374,8 +1264,7 @@ "resetCodeRateLimitedWithTime": "محدودية المعدل: عدد كبير جداً من محاولات التحقق. يرجى الانتظار {{time}} ثانية قبل المحاولة مرة أخرى.", "authTokenSaveFailed": "فشل في حفظ رمز المصادقة", "authTokenMissing": "لم يُرسل الخادم رمز مصادقة جديدًا. يُرجى تسجيل الدخول مرة أخرى.", - "failedToLoadServer": "فشل في تحميل الخادم", - "remoteServerRequired": "يلزم وجود خادم بعيد. قم بتوصيل خادم بعيد في الإعدادات لاستخدام نوع الاتصال هذا." + "failedToLoadServer": "فشل في تحميل الخادم" }, "messages": { "registrationDisabled": "تسجيل الحسابات الجديدة معطل حالياً من قبل المسؤول. يرجى تسجيل الدخول أو الاتصال بالمسؤول.", @@ -1831,7 +1720,6 @@ "protocolLabel": "بروتوكول", "domainLabel": "اِختِصاص", "domainPlaceholder": "خياري", - "connectToTerminal": "اتصل بالطرفية", "connectToFiles": "اتصل بالملفات" }, "splitScreen": { diff --git a/src/ui/locales/translated/bg_BG.json b/src/ui/locales/translated/bg_BG.json index 2d5ce268a..eb7586370 100644 --- a/src/ui/locales/translated/bg_BG.json +++ b/src/ui/locales/translated/bg_BG.json @@ -324,10 +324,6 @@ "appearanceIntro": "Изберете тема, цвят за акцент и език. И трите могат да бъдат променени по-късно в „Настройки“.", "featuresTitle": "Какво друго прави Termix", "featuresIntro": "Всеки сървър, който запазите, може да бъде отворен в повече от терминал. Ето какво ви очаква зад иконите вляво.", - "feature_files": "Файлов мениджър", - "feature_files_desc": "Преглеждайте, качвайте, изтегляйте и редактирайте файлове през SFTP, без да напускате приложението.", - "feature_tunnels": "Тунели", - "feature_tunnels_desc": "Пренасочване на портове през сървър, за да се достигне до услуги, които не са изложени на риск.", "feature_snippets": "Откъси", "feature_snippets_desc": "Запазвайте команди, които изпълнявате често, и ги изпращайте към терминал с едно щракване.", "featuresRailHint": "Не ви е нужно едно от тях? Скрийте всяка икона от страничната лента в „Настройки“, под „Навигация“.", @@ -449,7 +445,6 @@ "passwordSaved": "Паролата е запазена, въведете, за да я промените", "key": "Ключ", "credential": "Пълномощия", - "none": "Няма", "sshPrivateKey": "SSH частен ключ", "keyType": "Тип ключ", "uploadFile": "Качване на файл", @@ -611,17 +606,12 @@ "keepaliveIntervalLabel": "Интервал за поддържане на активност (секунди)", "maxKeepaliveMisses": "Максимални пропуски на Keepalive", "sameHost": "Този хост (директен тунел)", - "bindHost": "Свързване на хост", "connectionToolbar": "Инструменти за свързване", "showConnectionToolbar": "Показване на лентата с инструменти за връзки", "showConnectionToolbarDesc": "Показване на лентата с инструменти в SSH, RDP, VNC и Telnet сесиите на този хост. Можете също така временно да я скриете от самата лента с инструменти.", "proxmoxLastSyncStatus": { "success": "Успех" }, - "proxmoxGuestsSelected_one": "{{count}} гост — {{selected}} избран", - "proxmoxGuestsSelected_other": "{{count}} гости — {{selected}} избрани", - "proxmoxImportButton_one": "Импортиране на хост {{count}}", - "proxmoxImportButton_other": "Импортиране на {{count}} хостове", "proxmoxResultSkippedNoIp": "{{count}} пропуснато (не е намерен IP адрес)", "proxmoxStatsUrlCopied": "URL адресът на статистиката на Proxmox е копиран в клипборда", "copyProxmoxStatsUrlAction": "Копиране на URL адреса на статистиката на Proxmox", @@ -896,13 +886,11 @@ "updatedCount": "Актуализирани {{count}} хостове", "friendlyNameLabel": "Приятелско име", "descriptionLabel": "Описание", - "loadingHost": "Зареждане на хоста...", "loadingHosts": "Зареждане на хостове...", "loadingCredentials": "Зареждане на идентификационни данни...", "noHostsYet": "Все още няма домакини", "noHostsYetHint": "Добавете сървър, за да отваряте терминали, да преглеждате файлове и да виждате показатели.", "noHostsMatchSearch": "Няма хостове, които да отговарят на вашето търсене", - "hostNotFound": "Хостът не е намерен", "searchHosts": "Търсене на хостове...", "sortHosts": "Сортиране на хостове", "sortDefault": "По подразбиране ред", @@ -925,7 +913,6 @@ "filterAuthKey": "SSH ключ", "filterAuthCredential": "Пълномощия", "filterAuthNone": "Няма", - "filterAuthOpkssh": "ОПКСШ", "filterAuthStepca": "Стъпка CA", "filterProtocolGroup": "Протокол", "filterProtocolSsh": "SSH", @@ -1114,13 +1101,7 @@ "connect": "Свързване с хоста", "clear": "Изчисти", "paste": "Паста", - "connected": "Свързан", - "clipboardWriteFailed": "Копирането в буфера не бе успешно. Уверете се, че страницата се предоставя през HTTPS или localhost.", - "clipboardReadFailed": "Четенето от клипборда не бе успешно. Уверете се, че са предоставени разрешения за достъп до клипборда.", "tmuxDetach": "Отделяне от tmux сесия", - "terminalTitle": "Терминал - {{host}}", - "terminalWithPath": "Терминал - {{host}}:{{path}}", - "runTitle": "Изпълнява се {{command}} - {{host}}", "totpRequired": "Изисква се двуфакторно удостоверяване", "totpCodeLabel": "Код за потвърждение", "totpVerify": "Проверка", @@ -1148,109 +1129,20 @@ } }, "transfer": { - "copyToHost": "Копиране към хост…", - "moveToHost": "Преместване към хост…", - "copyItemsToHost": "Копиране на {{count}} елементи за хостване на…", - "moveItemsToHost": "Преместете {{count}} елементи, за да хоствате…", - "noHostsConnected": "Няма други налични хостове за файлови мениджъри.", - "noHostsConnectedHint": "Добавете друг SSH хост с активиран файлов мениджър в Host Manager.", - "selectDestinationHost": "Изберете целеви хост", - "destinationPath": "Път на местоназначението", - "recentDestinations": "Последни дестинации", "collapseRecentDestinations": "Свиване на скорошни дестинации", "expandRecentDestinations": "Разгъване на скорошни дестинации", - "browseFolders": "Преглед на целевите папки", "browseDestination": "Преглед или въвеждане на път", - "confirmCopy": "Копиране", - "confirmMove": "Преместване", "transferring": "Прехвърляне…", - "progressVerifying": "Проверка на целостта на файла…", - "progressBenchmarking": "Избор на най-бързия маршрут за трансфер…", "compressing": "Компресиране…", "extracting": "Извличане…", "transferringItems": "Прехвърляне на {{current}} от {{total}} елементи…", - "transferSuccess": "Прехвърлянето е завършено", - "transferError": "Прехвърлянето не бе успешно", "transferPartial": "Прехвърлянето е завършено с {{count}} грешки", - "transferPartialHint": "Не можа да се прехвърли: {{paths}}", - "itemsSummary": "{{count}} артикули", - "destMustBeDirectory": "Дестинацията трябва да е директория за прехвърляне на множество елементи", "selectThisFolder": "Изберете тази папка", - "browsePathWillBeCreated": "Тази папка все още не съществува. Тя ще бъде създадена, когато започне прехвърлянето.", - "browsePathError": "Не можа да се отвори този път на целевия хост.", - "goUp": "Качи се нагоре", - "copyFolderToHost": "Копиране на папката на хост…", - "moveFolderToHost": "Преместване на папката на хост…", - "hostReady": "Готов", - "hostConnecting": "Свързване…", - "hostDisconnected": "Няма връзка", - "hostAuthRequired": "Изисква се удостоверяване — първо отворете Файловия мениджър на този хост", - "hostConnectionFailed": "Връзката не бе успешна", "metricsTitle": "Времетраене на трансферите", - "metricsPrepare": "Подготовка на дестинацията: {{duration}}", - "metricsCompress": "Компресиране при източника: {{duration}}", "metricsHopSourceRead": "Източник → сървър: {{throughput}}", "metricsHopDestSftpWrite": "Сървър → дестинация (SFTP): {{throughput}}", "metricsHopDestLocalWrite": "Сървър → дестинация (локална): {{throughput}}", - "metricsTransfer": "От край до край: {{throughput}} ({{duration}})", - "metricsExtract": "Извличане в местоназначението: {{duration}}", - "metricsVerify": "SHA-256 проверен: {{duration}}", - "metricsRouteBenchmark": "Сонда за маршрут — директна: {{direct}}, релейна: {{relay}}", - "metricsSourceDelete": "Премахване от източника: {{duration}}", - "metricsTotal": "Общо: {{duration}}", - "progressCompressing": "Компресиране на изходния хост…", - "progressExtracting": "Извличане в местоназначението…", - "progressTransferring": "Прехвърляне на данни…", - "progressReconnecting": "Повторно свързване…", - "parallelSegmentsLabel": "Паралелни трансферни ленти", - "parallelSegmentsOption": "{{count}} ленти", - "parallelSegmentsHint": "Големите файлове се разделят на парчета от 256 MB. Няколко канала използват отделни връзки (като стартиране на няколко трансфера) за по-висока обща пропускателна способност.", - "progressTotalSpeed": "{{speed}} общо ({{lanes}} ленти)", - "progressTransferringItems": "Прехвърляне на файлове ({{current}} от {{total}})…", - "progressBytes": "{{transferred}} / {{total}}", - "progressItems": "{{current}} / {{total}} файлове", - "sourceNotDeletedPartial": "Изходните файлове са запазени (частично прехвърляне)", - "jumpHostLimitation": "И двата хоста трябва да са достъпни от Termix сървъра. Директното маршрутизиране от хост към хост не се поддържа.", - "cancel": "Отказ", - "methodLabel": "Метод на прехвърляне", - "methodAuto": "Автоматично", - "methodTar": "Тар архив", - "methodItemSftp": "SFTP за всеки файл", - "methodAutoHint": "Избира tar или SFTP за всеки файл въз основа на броя, размера и компресируемостта на файловете. Отделните файлове винаги използват стрийминг SFTP.", - "methodTarHint": "Компресиране при източника, прехвърляне на един архив, разархивиране при местоназначението. Изисква tar и на двата Unix хоста.", - "methodItemSftpHint": "Прехвърляйте всеки файл поотделно през SFTP. Работи на всички хостове, включително Windows.", - "methodPreviewLoading": "Метод за изчисляване на трансфер…", - "methodPreviewError": "Не можа да се прегледа методът за прехвърляне. Сървърът все пак ще избере метод, когато стартирате.", - "methodPreviewWillUseTar": "Ще използвам: Tar архив", - "methodPreviewWillUseItemSftp": "Ще използва: SFTP за всеки файл", - "methodPreviewScanSummary": "{{fileCount}} файлове, {{totalSize}} общо (сканирани на изходния хост).", - "methodItemSftpLimitation": "Всеки файл използва същия SFTP поток като копие на един файл, следвани един след друг. Напредъкът се комбинира във всички файлове, така че лентата се движи бавно при големи файлове.", - "methodReason": { - "user_item_sftp": "Избрали сте SFTP за всеки файл.", - "user_tar": "Избрахте tar архив.", - "tar_unavailable": "Tar не е наличен на единия или и на двата хоста — вместо това ще се използва SFTP за всеки файл.", - "windows_host": "Включен е хост на Windows — tar не се използва.", - "auto_multi_large": "Автоматично: множество файлове, включително голям файл ({{largestSize}}) със свиваеми данни — tar пакети в един трансфер.", - "auto_single_large_in_archive": "Автоматично: един голям файл ({{largestSize}}) в този набор — SFTP за всеки файл.", - "auto_many_incompressible": "Автоматично: предимно некомпресируеми данни — SFTP за всеки файл.", - "auto_many_files": "Автоматично: много файлове ({{fileCount}}) — tar намалява натоварването на всеки файл.", - "auto_default": "Автоматично: SFTP за всеки файл за този набор." - }, - "progressCancel": "Отказ", - "progressCancelling": "Анулиране…", - "progressStalled": "Застоял", - "resumedHint": "Възстановена е връзка с активно прехвърляне, започнато в друг прозорец.", - "transferCancelled": "Прехвърлянето е анулирано", - "transferCancelledCopyHint": "Частични файлове може да останат в местоназначението.", - "transferCancelledMoveHint": "Възможно е част от файловете да са останали в местоназначението. Изходните файлове не са премахнати.", - "cleanupDestFiles": "Почистване на дестинацията", - "cleanupDestFilesSuccess": "Премахнати частични файлове от местоназначението", - "cleanupDestFilesPartial": "Някои частични файлове не можаха да бъдат премахнати", - "cleanupDestFilesNothing": "Няма нищо за почистване на дестинацията", - "cleanupDestFilesError": "Почистването не бе успешно", - "retryTransfer": "Опитай отново", - "retryTransferError": "Повторният опит не бе успешен", - "transferFailedRetryHint": "В местоназначението са запазени частични данни. Повторният опит ще се възобнови, когато връзката се възстанови." + "sourceNotDeletedPartial": "Изходните файлове са запазени (частично прехвърляне)" }, "tunnels": { "connect": "Свържете се", @@ -1261,8 +1153,6 @@ "clientTunnel": "Клиентски тунел", "addClientTunnel": "Добавяне на клиентски тунел", "active": "Активен", - "start": "Старт", - "stop": "Спри", "typeServerLocalDesc": "Текущ хост към крайна точка.", "typeServerRemoteDesc": "Крайна точка обратно към текущия хост.", "typeClientLocalDesc": "Локален компютър към крайна точка.", @@ -1374,8 +1264,7 @@ "resetCodeRateLimitedWithTime": "Ограничена скорост: Твърде много опити за потвърждение. Моля, изчакайте {{time}} секунди, преди да опитате отново.", "authTokenSaveFailed": "Запазването на токена за удостоверяване не бе успешно", "authTokenMissing": "Сървърът не върна нов токен за удостоверяване. Моля, влезте отново.", - "failedToLoadServer": "Зареждането на сървъра не бе успешно", - "remoteServerRequired": "Изисква се отдалечен сървър. Свържете се с отдалечен сървър в „Настройки“, за да използвате този тип връзка." + "failedToLoadServer": "Зареждането на сървъра не бе успешно" }, "messages": { "registrationDisabled": "Регистрацията на нов акаунт в момента е деактивирана от администратор. Моля, влезте или се свържете с администратор.", @@ -1831,7 +1720,6 @@ "protocolLabel": "Протокол", "domainLabel": "Домейн", "domainPlaceholder": "по избор", - "connectToTerminal": "Свързване с терминала", "connectToFiles": "Свързване с файлове" }, "splitScreen": { diff --git a/src/ui/locales/translated/bn_BD.json b/src/ui/locales/translated/bn_BD.json index bd66e5978..eaf0ff00f 100644 --- a/src/ui/locales/translated/bn_BD.json +++ b/src/ui/locales/translated/bn_BD.json @@ -324,10 +324,6 @@ "appearanceIntro": "একটি থিম, একটি অ্যাকসেন্ট কালার এবং আপনার ভাষা বেছে নিন। এই তিনটিই পরে সেটিংস থেকে পরিবর্তন করা যাবে।", "featuresTitle": "টারমিক্স আর কী কী করে", "featuresIntro": "আপনার সেভ করা প্রতিটি সার্ভার একাধিক টার্মিনালে খোলা যেতে পারে। বাম দিকের আইকনগুলোর পেছনে যা অপেক্ষা করছে তা এখানে দেওয়া হলো।", - "feature_files": "ফাইল ম্যানেজার", - "feature_files_desc": "অ্যাপ থেকে বের না হয়েই SFTP-এর মাধ্যমে ফাইল ব্রাউজ, আপলোড, ডাউনলোড এবং সম্পাদনা করুন।", - "feature_tunnels": "টানেল", - "feature_tunnels_desc": "যেসব পরিষেবা উন্মুক্ত নয়, সেগুলোতে পৌঁছানোর জন্য পোর্টগুলো একটি সার্ভারের মাধ্যমে ফরওয়ার্ড করুন।", "feature_snippets": "খণ্ডাংশ", "feature_snippets_desc": "আপনার প্রায়শই ব্যবহৃত কমান্ডগুলো সংরক্ষণ করুন এবং এক ক্লিকে টার্মিনালে পাঠিয়ে দিন।", "featuresRailHint": "এগুলোর কোনোটি প্রয়োজন নেই? সেটিংস-এর নেভিগেশন বিভাগ থেকে সাইডবারের যেকোনো আইকন লুকান।", @@ -449,7 +445,6 @@ "passwordSaved": "পাসওয়ার্ড সংরক্ষিত আছে, পরিবর্তন করতে টাইপ করুন", "key": "চাবি", "credential": "শংসাপত্র", - "none": "কোনোটিই না", "sshPrivateKey": "SSH ব্যক্তিগত কী", "keyType": "চাবির ধরন", "uploadFile": "ফাইল আপলোড করুন", @@ -611,17 +606,12 @@ "keepaliveIntervalLabel": "কিপঅ্যালাইভ ব্যবধান (সেকেন্ড)", "maxKeepaliveMisses": "ম্যাক্স কিপঅ্যালাইভ মিস করে", "sameHost": "এই হোস্ট (সরাসরি টানেল)", - "bindHost": "হোস্টকে বাঁধুন", "connectionToolbar": "সংযোগ টুলবার", "showConnectionToolbar": "সংযোগ টুলবার দেখান", "showConnectionToolbarDesc": "এই হোস্টের SSH, RDP, VNC, এবং Telnet সেশনগুলিতে টুলবারটি দেখান। আপনি টুলবারটি থেকেই এটিকে সাময়িকভাবে লুকাতেও পারেন।", "proxmoxLastSyncStatus": { "success": "সাফল্য" }, - "proxmoxGuestsSelected_one": "{{count}} অতিথি — {{selected}} নির্বাচিত", - "proxmoxGuestsSelected_other": "{{count}} জন অতিথি — {{selected}} জন নির্বাচিত", - "proxmoxImportButton_one": "{{count}} হোস্ট আমদানি করুন", - "proxmoxImportButton_other": "{{count}} হোস্ট আমদানি করুন", "proxmoxResultSkippedNoIp": "{{count}} বাদ দেওয়া হয়েছে (কোন আইপি পাওয়া যায়নি)", "proxmoxStatsUrlCopied": "Proxmox Stats URL ক্লিপবোর্ডে কপি করা হয়েছে", "copyProxmoxStatsUrlAction": "Proxmox Stats URL কপি করুন", @@ -896,13 +886,11 @@ "updatedCount": "আপডেট করা {{count}} হোস্ট", "friendlyNameLabel": "বন্ধুত্বপূর্ণ নাম", "descriptionLabel": "বর্ণনা", - "loadingHost": "হোস্ট লোড হচ্ছে...", "loadingHosts": "হোস্ট লোড হচ্ছে...", "loadingCredentials": "পরিচয়পত্র লোড হচ্ছে...", "noHostsYet": "এখনো কোনো হোস্ট নেই", "noHostsYetHint": "টার্মিনাল খুলতে, ফাইল ব্রাউজ করতে এবং মেট্রিক্স দেখতে একটি সার্ভার যোগ করুন।", "noHostsMatchSearch": "আপনার অনুসন্ধানের সাথে কোনো হোস্ট মেলে না।", - "hostNotFound": "হোস্ট খুঁজে পাওয়া যায়নি", "searchHosts": "হোস্ট অনুসন্ধান করুন...", "sortHosts": "হোস্ট বাছাই করুন", "sortDefault": "ডিফল্ট অর্ডার", @@ -925,7 +913,6 @@ "filterAuthKey": "SSH কী", "filterAuthCredential": "শংসাপত্র", "filterAuthNone": "কোনোটিই না", - "filterAuthOpkssh": "OPKSSH", "filterAuthStepca": "স্টেপ সিএ", "filterProtocolGroup": "প্রোটোকল", "filterProtocolSsh": "এসএসএইচ", @@ -1114,13 +1101,7 @@ "connect": "হোস্টের সাথে সংযোগ করুন", "clear": "পরিষ্কার", "paste": "পেস্ট", - "connected": "সংযুক্ত", - "clipboardWriteFailed": "ক্লিপবোর্ডে কপি করা সম্ভব হয়নি। নিশ্চিত করুন যে পৃষ্ঠাটি HTTPS বা লোকালহোস্টের মাধ্যমে পরিবেশিত হচ্ছে।", - "clipboardReadFailed": "ক্লিপবোর্ড থেকে পড়তে ব্যর্থ হয়েছে। নিশ্চিত করুন যে ক্লিপবোর্ডের অনুমতি দেওয়া আছে।", "tmuxDetach": "tmux সেশন থেকে বিচ্ছিন্ন করুন", - "terminalTitle": "টার্মিনাল - {{host}}", - "terminalWithPath": "টার্মিনাল - {{host}}:{{path}}", - "runTitle": "দৌড়ানো {{command}} - {{host}}", "totpRequired": "দ্বি-স্তরীয় প্রমাণীকরণ আবশ্যক", "totpCodeLabel": "যাচাইকরণ কোড", "totpVerify": "যাচাই করুন", @@ -1148,109 +1129,20 @@ } }, "transfer": { - "copyToHost": "হোস্টে কপি করুন…", - "moveToHost": "হোস্টে যান…", - "copyItemsToHost": "{{count}} টি আইটেম হোস্টে কপি করুন…", - "moveItemsToHost": "{{count}} টি আইটেম… টি হোস্টে সরান", - "noHostsConnected": "অন্য কোনো ফাইল-ম্যানেজার হোস্ট উপলব্ধ নেই।", - "noHostsConnectedHint": "হোস্ট ম্যানেজারে ফাইল ম্যানেজার সক্রিয় করা আছে এমন আরেকটি SSH হোস্ট যোগ করুন।", - "selectDestinationHost": "গন্তব্য হোস্ট নির্বাচন করুন", - "destinationPath": "গন্তব্য পথ", - "recentDestinations": "সাম্প্রতিক গন্তব্যস্থল", "collapseRecentDestinations": "সাম্প্রতিক গন্তব্যগুলি সংকুচিত করুন", "expandRecentDestinations": "সাম্প্রতিক গন্তব্যস্থলগুলি প্রসারিত করুন", - "browseFolders": "গন্তব্য ফোল্ডারগুলি ব্রাউজ করুন", "browseDestination": "ব্রাউজ করুন অথবা পথ লিখুন", - "confirmCopy": "অনুলিপি", - "confirmMove": "স্থানান্তর", "transferring": "… স্থানান্তর করা হচ্ছে", - "progressVerifying": "ফাইলের অখণ্ডতা যাচাই করা হচ্ছে…", - "progressBenchmarking": "দ্রুততম স্থানান্তর পথ নির্বাচন করা হচ্ছে…", "compressing": "… সংকুচিত করা হচ্ছে", "extracting": "… নিষ্কাশন করা হচ্ছে", "transferringItems": "{{current}} টি {{total}} টি আইটেম… টি স্থানান্তর করা হচ্ছে", - "transferSuccess": "স্থানান্তর সম্পন্ন হয়েছে", - "transferError": "স্থানান্তর ব্যর্থ হয়েছে", "transferPartial": "{{count}} টি ত্রুটি সহ স্থানান্তর সম্পন্ন হয়েছে।", - "transferPartialHint": "স্থানান্তর করা যায়নি: {{paths}}", - "itemsSummary": "{{count}} আইটেম", - "destMustBeDirectory": "একাধিক আইটেম স্থানান্তরের জন্য গন্তব্য অবশ্যই একটি ডিরেক্টরি হতে হবে।", "selectThisFolder": "এই ফোল্ডারটি নির্বাচন করুন", - "browsePathWillBeCreated": "এই ফোল্ডারটি এখনও তৈরি হয়নি। স্থানান্তর শুরু হলে এটি তৈরি হয়ে যাবে।", - "browsePathError": "গন্তব্য হোস্টে এই পাথটি খোলা সম্ভব হয়নি।", - "goUp": "উপরে যান", - "copyFolderToHost": "ফোল্ডারটি হোস্টে কপি করুন…", - "moveFolderToHost": "ফোল্ডারটি হোস্টে সরান…", - "hostReady": "প্রস্তুত", - "hostConnecting": "… সংযোগ করা হচ্ছে", - "hostDisconnected": "সংযুক্ত নয়", - "hostAuthRequired": "প্রমাণীকরণ আবশ্যক — প্রথমে এই হোস্টে ফাইল ম্যানেজার খুলুন।", - "hostConnectionFailed": "সংযোগ ব্যর্থ হয়েছে", "metricsTitle": "স্থানান্তর সময়", - "metricsPrepare": "গন্তব্য প্রস্তুত করুন: {{duration}}", - "metricsCompress": "উৎস থেকে সংকুচিত করুন: {{duration}}", "metricsHopSourceRead": "উৎস → সার্ভার: {{throughput}}", "metricsHopDestSftpWrite": "সার্ভার → গন্তব্য (SFTP): {{throughput}}", "metricsHopDestLocalWrite": "সার্ভার → গন্তব্য (স্থানীয়): {{throughput}}", - "metricsTransfer": "প্রান্ত থেকে প্রান্ত: {{throughput}} ({{duration}})", - "metricsExtract": "গন্তব্যে নিষ্কাশন: {{duration}}", - "metricsVerify": "SHA-256 দ্বারা যাচাইকৃত: {{duration}}", - "metricsRouteBenchmark": "রুট প্রোব — সরাসরি: {{direct}}, রিলে: {{relay}}", - "metricsSourceDelete": "উৎস থেকে সরান: {{duration}}", - "metricsTotal": "মোট: {{duration}}", - "progressCompressing": "উৎস হোস্টে সংকুচিত করা হচ্ছে…", - "progressExtracting": "গন্তব্য… থেকে নিষ্কাশন করা হচ্ছে", - "progressTransferring": "ডেটা স্থানান্তর করা হচ্ছে…", - "progressReconnecting": "পুনরায় সংযোগ স্থাপন…", - "parallelSegmentsLabel": "সমান্তরাল স্থানান্তর লেন", - "parallelSegmentsOption": "{{count}} লেন", - "parallelSegmentsHint": "বড় ফাইলগুলোকে ২৫৬ মেগাবাইটের খণ্ডে ভাগ করা হয়। মোট থ্রুপুট বাড়ানোর জন্য একাধিক লেন আলাদা সংযোগ ব্যবহার করে (যেমন কয়েকটি ট্রান্সফার শুরু করা)।", - "progressTotalSpeed": "{{speed}} মোট ({{lanes}} লেন)", - "progressTransferringItems": "ফাইল স্থানান্তর করা হচ্ছে ({{current}} {{total}})…", - "progressBytes": "{{transferred}} / {{total}}", - "progressItems": "{{current}} / {{total}} ফাইল", - "sourceNotDeletedPartial": "উৎস ফাইলগুলি রাখা হয়েছে (আংশিক স্থানান্তর)", - "jumpHostLimitation": "উভয় হোস্টকেই টারমিক্স সার্ভার থেকে পৌঁছানো সম্ভব হতে হবে। সরাসরি হোস্ট-টু-হোস্ট রাউটিং সমর্থিত নয়।", - "cancel": "বাতিল করুন", - "methodLabel": "স্থানান্তর পদ্ধতি", - "methodAuto": "অটো", - "methodTar": "টার আর্কাইভ", - "methodItemSftp": "প্রতি-ফাইল এসএফটিপি", - "methodAutoHint": "ফাইলের সংখ্যা, আকার এবং সংকোচনযোগ্যতার উপর ভিত্তি করে tar অথবা ফাইল-ভিত্তিক SFTP নির্বাচন করে। একক ফাইলের ক্ষেত্রে সর্বদা স্ট্রিমিং SFTP ব্যবহৃত হয়।", - "methodTarHint": "উৎসস্থলে কম্প্রেস করুন, একটি আর্কাইভ স্থানান্তর করুন, এবং গন্তব্যে এক্সট্র্যাক্ট করুন। উভয় ইউনিক্স হোস্টে tar প্রয়োজন।", - "methodItemSftpHint": "SFTP-এর মাধ্যমে প্রতিটি ফাইল আলাদাভাবে স্থানান্তর করুন। উইন্ডোজ সহ সকল হোস্টে কাজ করে।", - "methodPreviewLoading": "স্থানান্তর পদ্ধতি গণনা করা হচ্ছে…", - "methodPreviewError": "স্থানান্তর পদ্ধতির প্রিভিউ দেখা সম্ভব হয়নি। আপনি চালু করার সময় সার্ভার নিজেই একটি পদ্ধতি বেছে নেবে।", - "methodPreviewWillUseTar": "ব্যবহৃত হবে: টার আর্কাইভ", - "methodPreviewWillUseItemSftp": "ব্যবহার করা হবে: প্রতি-ফাইল এসএফটিপি", - "methodPreviewScanSummary": "{{fileCount}} টি ফাইল, {{totalSize}} টি মোট (উৎস হোস্টে স্ক্যান করা হয়েছে)।", - "methodItemSftpLimitation": "প্রতিটি ফাইল একই SFTP স্ট্রিম ব্যবহার করে একটির পর একটি একক-ফাইল কপি হিসেবে তৈরি হয়। সমস্ত ফাইলের অগ্রগতি একত্রিত করা হয়, তাই বড় ফাইলের ক্ষেত্রে বারটি ধীরে চলে।", - "methodReason": { - "user_item_sftp": "আপনি ফাইল-ভিত্তিক এসএফটিপি বেছে নিয়েছেন।", - "user_tar": "আপনি tar আর্কাইভটি বেছে নিয়েছেন।", - "tar_unavailable": "এক বা উভয় হোস্টে Tar উপলব্ধ না থাকায়, এর পরিবর্তে ফাইল-ভিত্তিক SFTP ব্যবহার করা হবে।", - "windows_host": "এখানে একটি উইন্ডোজ হোস্ট জড়িত — tar ব্যবহৃত হয় না।", - "auto_multi_large": "স্বয়ংক্রিয়: সংকোচনযোগ্য ডেটা সহ একটি বড় ফাইল ({{largestSize}}) সহ একাধিক ফাইল — tar বান্ডেল করে একটি একক স্থানান্তরে পাঠানো হয়।", - "auto_single_large_in_archive": "স্বয়ংক্রিয়: এই সেটে একটি বড় ফাইল ({{largestSize}}) — ফাইল-ভিত্তিক SFTP।", - "auto_many_incompressible": "স্বয়ংক্রিয়: প্রধানত অসংকোচনযোগ্য ডেটা — ফাইল-ভিত্তিক এসএফটিপি।", - "auto_many_files": "স্বয়ংক্রিয়: একাধিক ফাইল ({{fileCount}}) — tar প্রতি-ফাইল ওভারহেড কমায়।", - "auto_default": "স্বয়ংক্রিয়: এই সেটের জন্য প্রতি-ফাইল এসএফটিপি।" - }, - "progressCancel": "বাতিল করুন", - "progressCancelling": "বাতিল করা হচ্ছে…", - "progressStalled": "স্থবির", - "resumedHint": "অন্য একটি উইন্ডোতে শুরু হওয়া একটি সক্রিয় ট্রান্সফারের সাথে পুনরায় সংযুক্ত হওয়া গেছে।", - "transferCancelled": "স্থানান্তর বাতিল করা হয়েছে", - "transferCancelledCopyHint": "গন্তব্যে আংশিক ফাইল থেকে যেতে পারে।", - "transferCancelledMoveHint": "গন্তব্যে আংশিক ফাইল থেকে যেতে পারে। মূল ফাইলগুলো সরানো হয়নি।", - "cleanupDestFiles": "পরিষ্কার করার গন্তব্য", - "cleanupDestFilesSuccess": "গন্তব্য থেকে আংশিক ফাইল সরানো হয়েছে", - "cleanupDestFilesPartial": "কিছু আংশিক ফাইল সরানো যায়নি", - "cleanupDestFilesNothing": "গন্তব্যে পরিষ্কার করার কিছু নেই।", - "cleanupDestFilesError": "পরিষ্কার করা ব্যর্থ হয়েছে", - "retryTransfer": "পুনরায় চেষ্টা করুন", - "retryTransferError": "পুনরায় চেষ্টা ব্যর্থ হয়েছে", - "transferFailedRetryHint": "গন্তব্যে আংশিক ডেটা সংরক্ষিত হয়েছে। সংযোগ ফিরে এলে পুনরায় চেষ্টা শুরু হবে।" + "sourceNotDeletedPartial": "উৎস ফাইলগুলি রাখা হয়েছে (আংশিক স্থানান্তর)" }, "tunnels": { "connect": "সংযোগ করুন", @@ -1261,8 +1153,6 @@ "clientTunnel": "ক্লায়েন্ট টানেল", "addClientTunnel": "ক্লায়েন্ট টানেল যোগ করুন", "active": "সক্রিয়", - "start": "শুরু করুন", - "stop": "থামুন", "typeServerLocalDesc": "বর্তমান হোস্ট থেকে এন্ডপয়েন্ট।", "typeServerRemoteDesc": "এন্ডপয়েন্টটি বর্তমান হোস্টে ফিরে যাচ্ছে।", "typeClientLocalDesc": "স্থানীয় কম্পিউটার থেকে এন্ডপয়েন্ট পর্যন্ত।", @@ -1374,8 +1264,7 @@ "resetCodeRateLimitedWithTime": "রেট সীমিত: অনেক বেশি যাচাইকরণ প্রচেষ্টা করা হয়েছে। অনুগ্রহ করে আবার চেষ্টা করার আগে {{time}} সেকেন্ড অপেক্ষা করুন।", "authTokenSaveFailed": "প্রমাণীকরণ টোকেন সংরক্ষণ করতে ব্যর্থ হয়েছে", "authTokenMissing": "সার্ভারটি নতুন কোনো প্রমাণীকরণ টোকেন ফেরত দেয়নি। অনুগ্রহ করে আবার সাইন ইন করুন।", - "failedToLoadServer": "সার্ভার লোড করতে ব্যর্থ হয়েছে", - "remoteServerRequired": "রিমোট সার্ভার প্রয়োজন। এই সংযোগের ধরণটি ব্যবহার করতে সেটিংস-এ একটি রিমোট সার্ভার সংযুক্ত করুন।" + "failedToLoadServer": "সার্ভার লোড করতে ব্যর্থ হয়েছে" }, "messages": { "registrationDisabled": "অ্যাডমিন কর্তৃক নতুন অ্যাকাউন্ট নিবন্ধন বর্তমানে বন্ধ রাখা হয়েছে। অনুগ্রহ করে লগ ইন করুন অথবা কোনো প্রশাসকের সাথে যোগাযোগ করুন।", @@ -1831,7 +1720,6 @@ "protocolLabel": "প্রোটোকল", "domainLabel": "ডোমেইন", "domainPlaceholder": "ঐচ্ছিক", - "connectToTerminal": "টার্মিনালের সাথে সংযোগ করুন", "connectToFiles": "ফাইলগুলির সাথে সংযোগ করুন" }, "splitScreen": { diff --git a/src/ui/locales/translated/ca_ES.json b/src/ui/locales/translated/ca_ES.json index 8c94d2cd6..b5a622432 100644 --- a/src/ui/locales/translated/ca_ES.json +++ b/src/ui/locales/translated/ca_ES.json @@ -324,10 +324,6 @@ "appearanceIntro": "Trieu un tema, un color d'accent i el vostre idioma. Tots tres es poden canviar més tard a Configuració.", "featuresTitle": "Què més fa Termix?", "featuresIntro": "Cada servidor que deseu es pot obrir en més d'un terminal. Això és el que hi ha darrere de les icones de l'esquerra.", - "feature_files": "Gestor de fitxers", - "feature_files_desc": "Navegueu, pengeu, descarregueu i editeu fitxers a través de SFTP sense sortir de l'aplicació.", - "feature_tunnels": "Túnels", - "feature_tunnels_desc": "Reenvia ports a través d'un servidor per arribar a serveis que no estan exposats.", "feature_snippets": "Fragments", "feature_snippets_desc": "Desa les ordres que executes sovint i envia-les a un terminal amb un sol clic.", "featuresRailHint": "No necessiteu cap d'aquestes? Amagueu qualsevol icona de la barra lateral a Configuració, a Navegació.", @@ -449,7 +445,6 @@ "passwordSaved": "Contrasenya desada, escriu per canviar-la", "key": "Clau", "credential": "Credencial", - "none": "Cap", "sshPrivateKey": "Clau privada SSH", "keyType": "Tipus de clau", "uploadFile": "Puja el fitxer", @@ -611,17 +606,12 @@ "keepaliveIntervalLabel": "Interval de manteniment (segons)", "maxKeepaliveMisses": "Màxims errors de manteniment en directe", "sameHost": "Aquest host (túnel directe)", - "bindHost": "Vincula l'amfitrió", "connectionToolbar": "Barra d'eines de connexió", "showConnectionToolbar": "Mostra la barra d'eines de connexió", "showConnectionToolbarDesc": "Mostra la barra d'eines a les sessions SSH, RDP, VNC i Telnet d'aquest amfitrió. També la pots ocultar temporalment des de la barra d'eines.", "proxmoxLastSyncStatus": { "success": "Èxit" }, - "proxmoxGuestsSelected_one": "{{count}} convidat — {{selected}} seleccionat", - "proxmoxGuestsSelected_other": "{{count}} convidats — {{selected}} seleccionats", - "proxmoxImportButton_one": "Importa l'amfitrió {{count}}", - "proxmoxImportButton_other": "Importa els amfitrions {{count}}", "proxmoxResultSkippedNoIp": "{{count}} omès (no s'ha trobat cap IP)", "proxmoxStatsUrlCopied": "URL de les estadístiques de Proxmox copiada al porta-retalls", "copyProxmoxStatsUrlAction": "Copia l'URL de les estadístiques de Proxmox", @@ -896,13 +886,11 @@ "updatedCount": "Amfitrions {{count}} actualitzats", "friendlyNameLabel": "Nom amigable", "descriptionLabel": "Descripció", - "loadingHost": "S'està carregant l'amfitrió...", "loadingHosts": "S'estan carregant els amfitrions...", "loadingCredentials": "S'estan carregant les credencials...", "noHostsYet": "Encara no hi ha amfitrions", "noHostsYetHint": "Afegeix un servidor per obrir terminals, navegar per fitxers i veure mètriques.", "noHostsMatchSearch": "No hi ha amfitrions que coincideixin amb la teva cerca", - "hostNotFound": "No s'ha trobat l'amfitrió", "searchHosts": "Cerca amfitrions...", "sortHosts": "Ordena els hosts", "sortDefault": "Ordre per defecte", @@ -925,7 +913,6 @@ "filterAuthKey": "Clau SSH", "filterAuthCredential": "Credencial", "filterAuthNone": "Cap", - "filterAuthOpkssh": "OPKSSH", "filterAuthStepca": "Pas CA", "filterProtocolGroup": "Protocol", "filterProtocolSsh": "SSH", @@ -1114,13 +1101,7 @@ "connect": "Connecta't a l'amfitrió", "clear": "Clar", "paste": "Enganxa", - "connected": "Connectat", - "clipboardWriteFailed": "No s'ha pogut copiar al porta-retalls. Assegureu-vos que la pàgina es serveix per HTTPS o localhost.", - "clipboardReadFailed": "No s'ha pogut llegir del porta-retalls. Assegureu-vos que els permisos del porta-retalls estiguin concedits.", "tmuxDetach": "Desconnecta de la sessió de tmux", - "terminalTitle": "Terminal - {{host}}", - "terminalWithPath": "Terminal - {{host}}:{{path}}", - "runTitle": "Executant {{command}} - {{host}}", "totpRequired": "Cal autenticació de dos factors", "totpCodeLabel": "Codi de verificació", "totpVerify": "Verifica", @@ -1148,109 +1129,20 @@ } }, "transfer": { - "copyToHost": "Copia a l'amfitrió…", - "moveToHost": "Moure a l'amfitrió…", - "copyItemsToHost": "Copia els elements {{count}} a l'amfitrió…", - "moveItemsToHost": "Mou els elements {{count}} a l'amfitrió…", - "noHostsConnected": "No hi ha altres amfitrions de gestors de fitxers disponibles.", - "noHostsConnectedHint": "Afegiu un altre amfitrió SSH amb el Gestor de fitxers habilitat al Gestor d'amfitrions.", - "selectDestinationHost": "Selecciona l'amfitrió de destinació", - "destinationPath": "Camí de destinació", - "recentDestinations": "Destinacions recents", "collapseRecentDestinations": "Replega les destinacions recents", "expandRecentDestinations": "Expandeix les destinacions recents", - "browseFolders": "Navega per les carpetes de destinació", "browseDestination": "Navega o introdueix la ruta", - "confirmCopy": "Còpia", - "confirmMove": "Moure", "transferring": "Transferint…", - "progressVerifying": "Verificació de la integritat del fitxer…", - "progressBenchmarking": "Selecció de la ruta de transferència més ràpida…", "compressing": "Comprimint…", "extracting": "Extraient…", "transferringItems": "Transferint {{current}} de {{total}} elements…", - "transferSuccess": "Transferència completada", - "transferError": "La transferència ha fallat", "transferPartial": "Transferència completada amb errors {{count}}", - "transferPartialHint": "No s'ha pogut transferir: {{paths}}", - "itemsSummary": "{{count}} elements", - "destMustBeDirectory": "La destinació ha de ser un directori per a transferències de diversos elements", "selectThisFolder": "Selecciona aquesta carpeta", - "browsePathWillBeCreated": "Aquesta carpeta encara no existeix. Es crearà quan comenci la transferència.", - "browsePathError": "No s'ha pogut obrir aquesta ruta a l'amfitrió de destinació.", - "goUp": "Puja", - "copyFolderToHost": "Copia la carpeta a l'amfitrió…", - "moveFolderToHost": "Mou la carpeta a l'amfitrió…", - "hostReady": "Llest", - "hostConnecting": "Connectant…", - "hostDisconnected": "No connectat", - "hostAuthRequired": "Cal autenticació: obriu primer el Gestor de fitxers en aquest amfitrió.", - "hostConnectionFailed": "La connexió ha fallat", "metricsTitle": "Horaris de transferència", - "metricsPrepare": "Prepara la destinació: {{duration}}", - "metricsCompress": "Comprimir a la font: {{duration}}", "metricsHopSourceRead": "Font → servidor: {{throughput}}", "metricsHopDestSftpWrite": "Servidor → destí (SFTP): {{throughput}}", "metricsHopDestLocalWrite": "Servidor → destí (local): {{throughput}}", - "metricsTransfer": "Extrem a extrem: {{throughput}} ({{duration}})", - "metricsExtract": "Extracte a la destinació: {{duration}}", - "metricsVerify": "SHA-256 verificat: {{duration}}", - "metricsRouteBenchmark": "Sonda de ruta — directa: {{direct}}, relé: {{relay}}", - "metricsSourceDelete": "Elimina de la font: {{duration}}", - "metricsTotal": "Total: {{duration}}", - "progressCompressing": "Compressió a l'amfitrió d'origen…", - "progressExtracting": "Extraient a la destinació…", - "progressTransferring": "Transferència de dades…", - "progressReconnecting": "Reconnectant…", - "parallelSegmentsLabel": "Carrils de transferència paral·lels", - "parallelSegmentsOption": "carrils {{count}}", - "parallelSegmentsHint": "Els fitxers grans es divideixen en blocs de 256 MB. Els carrils múltiples utilitzen connexions separades (com ara iniciar diverses transferències) per a un rendiment total més alt.", - "progressTotalSpeed": "{{speed}} total ({{lanes}} carrils)", - "progressTransferringItems": "Transferència de fitxers ({{current}} de {{total}})…", - "progressBytes": "{{transferred}} / {{total}}", - "progressItems": "{{current}} / {{total}} fitxers", - "sourceNotDeletedPartial": "Fitxers font conservats (transferència parcial)", - "jumpHostLimitation": "Tots dos hosts han de ser accessibles des del servidor Termix. No s'admet l'encaminament directe d'host a host.", - "cancel": "Cancel·la", - "methodLabel": "Mètode de transferència", - "methodAuto": "Automàtic", - "methodTar": "Arxiu Tar", - "methodItemSftp": "SFTP per fitxer", - "methodAutoHint": "Tria SFTP tar o per fitxer en funció del nombre de fitxers, la mida i la compressibilitat. Els fitxers individuals sempre utilitzen SFTP en temps real.", - "methodTarHint": "Comprimir a l'origen, transferir un arxiu, extreure a la destinació. Requereix tar en ambdós hosts Unix.", - "methodItemSftpHint": "Transfereix cada fitxer individualment per SFTP. Funciona en tots els hosts, inclòs Windows.", - "methodPreviewLoading": "Càlcul del mètode de transferència…", - "methodPreviewError": "No s'ha pogut previsualitzar el mètode de transferència. El servidor encara triarà un mètode quan l'inicieu.", - "methodPreviewWillUseTar": "Utilitzarà: Arxiu Tar", - "methodPreviewWillUseItemSftp": "Utilitzarà: SFTP per fitxer", - "methodPreviewScanSummary": "{{fileCount}} fitxers, {{totalSize}} total (escanejats a l'amfitrió d'origen).", - "methodItemSftpLimitation": "Cada fitxer utilitza el mateix flux SFTP com una còpia d'un sol fitxer, un darrere l'altre. El progrés es combina en tots els fitxers, de manera que la barra es mou lentament durant els fitxers grans.", - "methodReason": { - "user_item_sftp": "Heu triat SFTP per fitxer.", - "user_tar": "Has triat l'arxiu tar.", - "tar_unavailable": "Tar no està disponible en un o tots dos hosts; s'utilitzarà SFTP per fitxer.", - "windows_host": "Hi ha un host de Windows implicat; no s'utilitza tar.", - "auto_multi_large": "Automàtic: diversos fitxers, inclòs un fitxer gran ({{largestSize}}) amb dades compressibles: paquets de fitxers tar en una sola transferència.", - "auto_single_large_in_archive": "Automàtic: un fitxer gran ({{largestSize}}) en aquest conjunt — SFTP per fitxer.", - "auto_many_incompressible": "Automàtic: dades majoritàriament incompressibles — SFTP per fitxer.", - "auto_many_files": "Automàtic: molts fitxers ({{fileCount}}) — tar redueix la sobrecàrrega per fitxer.", - "auto_default": "Automàtic: SFTP per fitxer per a aquest conjunt." - }, - "progressCancel": "Cancel·la", - "progressCancelling": "Cancel·lant…", - "progressStalled": "Estancat", - "resumedHint": "S'ha tornat a connectar a una transferència activa iniciada en una altra finestra.", - "transferCancelled": "Transferència cancel·lada", - "transferCancelledCopyHint": "És possible que hi hagi fitxers parcials a la destinació.", - "transferCancelledMoveHint": "És possible que hi hagi fitxers parcials a la destinació. No s'han eliminat els fitxers d'origen.", - "cleanupDestFiles": "Neteja la destinació", - "cleanupDestFilesSuccess": "S'han eliminat fitxers parcials de la destinació", - "cleanupDestFilesPartial": "No s'han pogut eliminar alguns fitxers parcials", - "cleanupDestFilesNothing": "Res a netejar a la destinació", - "cleanupDestFilesError": "La neteja ha fallat", - "retryTransfer": "Torna-ho a intentar", - "retryTransferError": "No s'ha pogut reintentar.", - "transferFailedRetryHint": "S'han conservat dades parcials a la destinació. El reintent es reprendrà quan es restableixi la connexió." + "sourceNotDeletedPartial": "Fitxers font conservats (transferència parcial)" }, "tunnels": { "connect": "Connecta", @@ -1261,8 +1153,6 @@ "clientTunnel": "Túnel del client", "addClientTunnel": "Afegeix un túnel de client", "active": "Actiu", - "start": "Inici", - "stop": "Atura", "typeServerLocalDesc": "De l'amfitrió actual al punt final.", "typeServerRemoteDesc": "Punt final torna a l'amfitrió actual.", "typeClientLocalDesc": "Ordinador local al punt final.", @@ -1374,8 +1264,7 @@ "resetCodeRateLimitedWithTime": "Taxa limitada: massa intents de verificació. Espereu {{time}} segons abans de tornar-ho a intentar.", "authTokenSaveFailed": "No s'ha pogut desar el testimoni d'autenticació", "authTokenMissing": "El servidor no ha retornat un testimoni d'autenticació nou. Si us plau, torneu a iniciar la sessió.", - "failedToLoadServer": "No s'ha pogut carregar el servidor", - "remoteServerRequired": "Cal un servidor remot. Connecteu un servidor remot a Configuració per utilitzar aquest tipus de connexió." + "failedToLoadServer": "No s'ha pogut carregar el servidor" }, "messages": { "registrationDisabled": "El registre de comptes nous està desactivat actualment per un administrador. Si us plau, inicia la sessió o contacta amb un administrador.", @@ -1831,7 +1720,6 @@ "protocolLabel": "Protocol", "domainLabel": "Domini", "domainPlaceholder": "opcional", - "connectToTerminal": "Connecta't al terminal", "connectToFiles": "Connecta't a fitxers" }, "splitScreen": { diff --git a/src/ui/locales/translated/cs_CZ.json b/src/ui/locales/translated/cs_CZ.json index 40603f063..e218241c8 100644 --- a/src/ui/locales/translated/cs_CZ.json +++ b/src/ui/locales/translated/cs_CZ.json @@ -324,10 +324,6 @@ "appearanceIntro": "Vyberte si téma, barvu zvýraznění a jazyk. Všechny tři možnosti lze později změnit v Nastavení.", "featuresTitle": "Co dalšího Termix dělá", "featuresIntro": "Každý server, který uložíte, lze otevřít ve více než jen terminálu. Zde je to, co čeká za ikonami vlevo.", - "feature_files": "Správce souborů", - "feature_files_desc": "Procházejte, nahrávejte, stahujte a upravujte soubory přes SFTP, aniž byste museli opustit aplikaci.", - "feature_tunnels": "Tunely", - "feature_tunnels_desc": "Přesměrování portů přes server pro přístup ke službám, které nejsou vystaveny.", "feature_snippets": "Úryvky", "feature_snippets_desc": "Uložte si často spouštíné příkazy a odešlete je do terminálu jedním kliknutím.", "featuresRailHint": "Nepotřebujete jeden z nich? Skrýt libovolnou ikonu z postranního panelu v Nastavení v části Navigace.", @@ -449,7 +445,6 @@ "passwordSaved": "Heslo uloženo, zadejte heslo pro změnu", "key": "Klíč", "credential": "Pověření", - "none": "Žádný", "sshPrivateKey": "Soukromý klíč SSH", "keyType": "Typ klíče", "uploadFile": "Nahrát soubor", @@ -611,17 +606,12 @@ "keepaliveIntervalLabel": "Interval udržování aktivity (sekundy)", "maxKeepaliveMisses": "Max. chyb v Keepalive", "sameHost": "Tento hostitel (přímý tunel)", - "bindHost": "Vázat hostitele", "connectionToolbar": "Panel nástrojů pro připojení", "showConnectionToolbar": "Zobrazit panel nástrojů pro připojení", "showConnectionToolbarDesc": "Zobrazit panel nástrojů v relacích SSH, RDP, VNC a Telnet tohoto hostitele. Můžete jej také dočasně skrýt přímo v panelu nástrojů.", "proxmoxLastSyncStatus": { "success": "Úspěch" }, - "proxmoxGuestsSelected_one": "{{count}} host — {{selected}} vybráno", - "proxmoxGuestsSelected_other": "{{count}} hosté — {{selected}} vybráno", - "proxmoxImportButton_one": "Importovat hostitele {{count}}", - "proxmoxImportButton_other": "Importovat hostitele {{count}}", "proxmoxResultSkippedNoIp": "{{count}} přeskočeno (nenalezena žádná IP adresa)", "proxmoxStatsUrlCopied": "URL statistik Proxmoxu zkopírována do schránky", "copyProxmoxStatsUrlAction": "Kopírovat URL statistik Proxmoxu", @@ -896,13 +886,11 @@ "updatedCount": "Aktualizovaní hostitelé {{count}}", "friendlyNameLabel": "Přátelský název", "descriptionLabel": "Popis", - "loadingHost": "Načítání hostitele...", "loadingHosts": "Načítání hostitelů...", "loadingCredentials": "Načítání přihlašovacích údajů...", "noHostsYet": "Zatím žádní hostitelé", "noHostsYetHint": "Přidejte server pro otevírání terminálů, procházení souborů a zobrazení metrik.", "noHostsMatchSearch": "Vašemu vyhledávání neodpovídají žádní hostitelé", - "hostNotFound": "Hostitel nenalezen", "searchHosts": "Hledat hostitele...", "sortHosts": "Seřadit hostitele", "sortDefault": "Výchozí pořadí", @@ -925,7 +913,6 @@ "filterAuthKey": "SSH klíč", "filterAuthCredential": "Pověření", "filterAuthNone": "Žádný", - "filterAuthOpkssh": "OPKSSH", "filterAuthStepca": "Krok CA", "filterProtocolGroup": "Protokol", "filterProtocolSsh": "SSH", @@ -1114,13 +1101,7 @@ "connect": "Připojení k hostiteli", "clear": "Jasný", "paste": "Pasta", - "connected": "Připojeno", - "clipboardWriteFailed": "Kopírování do schránky se nezdařilo. Ujistěte se, že stránka je zobrazována přes HTTPS nebo localhost.", - "clipboardReadFailed": "Čtení ze schránky se nezdařilo. Ujistěte se, že máte povolena přístup ke schránce.", "tmuxDetach": "Odpojit se od relace tmux", - "terminalTitle": "Terminál - {{host}}", - "terminalWithPath": "Terminál - {{host}}:{{path}}", - "runTitle": "Spuštěno {{command}} - {{host}}", "totpRequired": "Vyžadováno dvoufaktorové ověřování", "totpCodeLabel": "Ověřovací kód", "totpVerify": "Ověřit", @@ -1148,109 +1129,20 @@ } }, "transfer": { - "copyToHost": "Kopírovat na hostitele…", - "moveToHost": "Přesunout na hostitele…", - "copyItemsToHost": "Zkopírovat {{count}} položek pro hostování…", - "moveItemsToHost": "Přesunout {{count}} položek na hostitele…", - "noHostsConnected": "Žádní další hostitelé souborů nejsou k dispozici.", - "noHostsConnectedHint": "Přidejte dalšího hostitele SSH s povoleným Správcem souborů ve Správci hostitelů.", - "selectDestinationHost": "Vyberte cílového hostitele", - "destinationPath": "Cílová cesta", - "recentDestinations": "Nedávné destinace", "collapseRecentDestinations": "Sbalit nedávné cíle", "expandRecentDestinations": "Rozbalit nedávné destinace", - "browseFolders": "Procházet cílové složky", "browseDestination": "Procházet nebo zadat cestu", - "confirmCopy": "Kopie", - "confirmMove": "Pohyb", "transferring": "Přenos…", - "progressVerifying": "Ověřování integrity souboru…", - "progressBenchmarking": "Výběr nejrychlejší trasy přestupu…", "compressing": "Komprese…", "extracting": "Extrahování…", "transferringItems": "Přenos {{current}} z {{total}} položek…", - "transferSuccess": "Převod dokončen", - "transferError": "Přenos se nezdařil", "transferPartial": "Přenos dokončen s {{count}} chybami", - "transferPartialHint": "Nepodařilo se přenést: {{paths}}", - "itemsSummary": "{{count}} položek", - "destMustBeDirectory": "Cíl musí být adresář pro přenosy více položek.", "selectThisFolder": "Vyberte tuto složku", - "browsePathWillBeCreated": "Tato složka zatím neexistuje. Bude vytvořena po zahájení přenosu.", - "browsePathError": "Tuto cestu se nepodařilo otevřít na cílovém hostiteli.", - "goUp": "Jdi nahoru", - "copyFolderToHost": "Zkopírovat složku na hostitele…", - "moveFolderToHost": "Přesunout složku na hostitele…", - "hostReady": "Připraveno", - "hostConnecting": "Připojování…", - "hostDisconnected": "Nepřipojeno", - "hostAuthRequired": "Vyžadováno ověření – nejprve otevřete Správce souborů na tomto hostiteli.", - "hostConnectionFailed": "Připojení se nezdařilo", "metricsTitle": "Časy přestupů", - "metricsPrepare": "Připravit cíl: {{duration}}", - "metricsCompress": "Komprimovat u zdroje: {{duration}}", "metricsHopSourceRead": "Zdroj → server: {{throughput}}", "metricsHopDestSftpWrite": "Server → cíl (SFTP): {{throughput}}", "metricsHopDestLocalWrite": "Server → cíl (lokální): {{throughput}}", - "metricsTransfer": "Konec od konce: {{throughput}} ({{duration}})", - "metricsExtract": "Extrahovat v cíli: {{duration}}", - "metricsVerify": "SHA-256 ověřeno: {{duration}}", - "metricsRouteBenchmark": "Sonda trasy — přímá: {{direct}}, relé: {{relay}}", - "metricsSourceDelete": "Odebrat ze zdroje: {{duration}}", - "metricsTotal": "Celkem: {{duration}}", - "progressCompressing": "Komprese na zdrojovém hostiteli…", - "progressExtracting": "Extrahování v cíli…", - "progressTransferring": "Přenos dat…", - "progressReconnecting": "Opětovné připojení…", - "parallelSegmentsLabel": "Paralelní přestupní pruhy", - "parallelSegmentsOption": "{{count}} jízdních pruhů", - "parallelSegmentsHint": "Velké soubory jsou rozděleny na bloky o velikosti 256 MB. Více linek používá samostatná připojení (například spuštění několika přenosů) pro vyšší celkovou propustnost.", - "progressTotalSpeed": "{{speed}} celkem ({{lanes}} pruhů)", - "progressTransferringItems": "Přenos souborů ({{current}} z {{total}})…", - "progressBytes": "{{transferred}} / {{total}}", - "progressItems": "{{current}} / {{total}} souborů", - "sourceNotDeletedPartial": "Zdrojové soubory zachovány (částečný přenos)", - "jumpHostLimitation": "Oba hostitelé musí být dosažitelné ze serveru Termix. Přímé směrování mezi hostiteli není podporováno.", - "cancel": "Zrušit", - "methodLabel": "Způsob přenosu", - "methodAuto": "Auto", - "methodTar": "Archiv Tar", - "methodItemSftp": "SFTP pro jednotlivé soubory", - "methodAutoHint": "Vybírá tar nebo SFTP pro jednotlivé soubory na základě počtu souborů, velikosti a komprimovatelnosti. Jednotlivé soubory vždy používají streamovaný SFTP.", - "methodTarHint": "Komprimace ve zdroji, přenos jednoho archivu, extrakce v cíli. Vyžaduje tar na obou unixových hostitelích.", - "methodItemSftpHint": "Přeneste každý soubor jednotlivě přes SFTP. Funguje na všech hostitelích včetně Windows.", - "methodPreviewLoading": "Výpočet metody převodu…", - "methodPreviewError": "Nepodařilo se zobrazit náhled metody přenosu. Server si metodu vybere i po spuštění.", - "methodPreviewWillUseTar": "Použiji: archiv Tar", - "methodPreviewWillUseItemSftp": "Použije se: SFTP pro jednotlivé soubory", - "methodPreviewScanSummary": "{{fileCount}} souborů, {{totalSize}} celkem (naskenováno na zdrojovém hostiteli).", - "methodItemSftpLimitation": "Každý soubor používá stejný SFTP stream jako kopie jednoho souboru, jeden po druhém. Průběh je sloučen napříč všemi soubory, takže se ukazatel u velkých souborů pohybuje pomalu.", - "methodReason": { - "user_item_sftp": "Zvolili jste SFTP pro jednotlivé soubory.", - "user_tar": "Zvolili jste archiv tar.", - "tar_unavailable": "Tar není k dispozici na jednom nebo obou hostitelích — místo toho bude použit protokol SFTP pro jednotlivé soubory.", - "windows_host": "Je zapojen hostitelský systém Windows – tar se nepoužívá.", - "auto_multi_large": "Automaticky: více souborů včetně velkého souboru ({{largestSize}}) s komprimovatelnými daty — tar se sbalí do jednoho přenosu.", - "auto_single_large_in_archive": "Automaticky: jeden velký soubor ({{largestSize}}) v této sadě – SFTP pro každý soubor.", - "auto_many_incompressible": "Auto: většinou nekomprimovatelná data – SFTP pro jednotlivé soubory.", - "auto_many_files": "Automaticky: mnoho souborů ({{fileCount}}) – tar snižuje režii pro každý soubor.", - "auto_default": "Automaticky: SFTP pro jednotlivé soubory pro tuto sadu." - }, - "progressCancel": "Zrušit", - "progressCancelling": "Zrušení…", - "progressStalled": "Zastaveno", - "resumedHint": "Znovu připojeno k aktivnímu přenosu zahájenému v jiném okně.", - "transferCancelled": "Převod zrušen", - "transferCancelledCopyHint": "V cílovém úložišti mohou zůstat jen částečné soubory.", - "transferCancelledMoveHint": "V cílovém umístění mohou zůstat jen některé soubory. Zdrojové soubory nebyly odstraněny.", - "cleanupDestFiles": "Vyčistit cíl", - "cleanupDestFilesSuccess": "Z cílového umístění byly odstraněny částečné soubory.", - "cleanupDestFilesPartial": "Některé částečné soubory se nepodařilo odstranit.", - "cleanupDestFilesNothing": "Na cílové destinaci není co uklízet", - "cleanupDestFilesError": "Vyčištění se nezdařilo", - "retryTransfer": "Zkusit znovu", - "retryTransferError": "Opakovaný pokus se nezdařil", - "transferFailedRetryHint": "V cíli byla uložena částečná data. Po obnovení připojení bude pokus pokračovat." + "sourceNotDeletedPartial": "Zdrojové soubory zachovány (částečný přenos)" }, "tunnels": { "connect": "Připojit", @@ -1261,8 +1153,6 @@ "clientTunnel": "Klientský tunel", "addClientTunnel": "Přidat klientský tunel", "active": "Aktivní", - "start": "Start", - "stop": "Zastávka", "typeServerLocalDesc": "Aktuální hostitel ke koncovému bodu.", "typeServerRemoteDesc": "Koncový bod zpět k aktuálnímu hostiteli.", "typeClientLocalDesc": "Místní počítač ke koncovému bodu.", @@ -1374,8 +1264,7 @@ "resetCodeRateLimitedWithTime": "Omezená rychlost: Příliš mnoho pokusů o ověření. Před dalším pokusem prosím počkejte {{time}} sekund.", "authTokenSaveFailed": "Uložení ověřovacího tokenu se nezdařilo", "authTokenMissing": "Server nevrátil nový ověřovací token. Přihlaste se prosím znovu.", - "failedToLoadServer": "Nepodařilo se načíst server", - "remoteServerRequired": "Je vyžadován vzdálený server. Pro použití tohoto typu připojení se připojte ke vzdálenému serveru v Nastavení." + "failedToLoadServer": "Nepodařilo se načíst server" }, "messages": { "registrationDisabled": "Registrace nového účtu je momentálně zakázána administrátorem. Přihlaste se prosím nebo kontaktujte administrátora.", @@ -1831,7 +1720,6 @@ "protocolLabel": "Protokol", "domainLabel": "Doména", "domainPlaceholder": "volitelný", - "connectToTerminal": "Připojení k terminálu", "connectToFiles": "Připojení k souborům" }, "splitScreen": { diff --git a/src/ui/locales/translated/da_DK.json b/src/ui/locales/translated/da_DK.json index 8d4b1174a..0666a19fe 100644 --- a/src/ui/locales/translated/da_DK.json +++ b/src/ui/locales/translated/da_DK.json @@ -324,10 +324,6 @@ "appearanceIntro": "Vælg et tema, en accentfarve og dit sprog. Alle tre kan ændres senere i Indstillinger.", "featuresTitle": "Hvad Termix ellers gør", "featuresIntro": "Hver server, du gemmer, kan åbnes i mere end én terminal. Her er, hvad der venter bag ikonerne til venstre.", - "feature_files": "Filhåndtering", - "feature_files_desc": "Gennemse, upload, download og rediger filer via SFTP uden at forlade appen.", - "feature_tunnels": "Tunneler", - "feature_tunnels_desc": "Videresend porte via en server for at nå tjenester, der ikke er eksponerede.", "feature_snippets": "Uddrag", "feature_snippets_desc": "Gem kommandoer, du kører ofte, og send dem til en terminal med et enkelt klik.", "featuresRailHint": "Har du ikke brug for en af disse? Skjul et hvilket som helst ikon fra sidebjælken i Indstillinger under Navigation.", @@ -449,7 +445,6 @@ "passwordSaved": "Adgangskode gemt, skriv for at ændre", "key": "Nøgle", "credential": "Legitimationsoplysninger", - "none": "Ingen", "sshPrivateKey": "SSH privat nøgle", "keyType": "Nøgletype", "uploadFile": "Upload fil", @@ -611,17 +606,12 @@ "keepaliveIntervalLabel": "Keepalive-interval (sekunder)", "maxKeepaliveMisses": "Max Keepalive misser", "sameHost": "Denne vært (direkte tunnel)", - "bindHost": "Bind vært", "connectionToolbar": "Forbindelsesværktøjslinje", "showConnectionToolbar": "Vis forbindelsesværktøjslinjen", "showConnectionToolbarDesc": "Vis værktøjslinjen i denne værts SSH-, RDP-, VNC- og Telnet-sessioner. Du kan også skjule den midlertidigt fra selve værktøjslinjen.", "proxmoxLastSyncStatus": { "success": "Succes" }, - "proxmoxGuestsSelected_one": "{{count}} gæst — {{selected}} valgt", - "proxmoxGuestsSelected_other": "{{count}} gæster — {{selected}} valgt", - "proxmoxImportButton_one": "Importér {{count}} vært", - "proxmoxImportButton_other": "Importér {{count}} værter", "proxmoxResultSkippedNoIp": "{{count}} sprunget over (ingen IP fundet)", "proxmoxStatsUrlCopied": "Proxmox Stats URL kopieret til udklipsholder", "copyProxmoxStatsUrlAction": "Kopiér Proxmox Stats URL", @@ -896,13 +886,11 @@ "updatedCount": "Opdaterede {{count}} værter", "friendlyNameLabel": "Venligt navn", "descriptionLabel": "Beskrivelse", - "loadingHost": "Indlæser vært...", "loadingHosts": "Indlæser værter...", "loadingCredentials": "Indlæser loginoplysninger...", "noHostsYet": "Ingen værter endnu", "noHostsYetHint": "Tilføj en server for at åbne terminaler, gennemse filer og se målinger.", "noHostsMatchSearch": "Ingen værter matcher din søgning", - "hostNotFound": "Værten blev ikke fundet", "searchHosts": "Søg efter værter...", "sortHosts": "Sortér værter", "sortDefault": "Standardordre", @@ -925,7 +913,6 @@ "filterAuthKey": "SSH-nøgle", "filterAuthCredential": "Legitimationsoplysninger", "filterAuthNone": "Ingen", - "filterAuthOpkssh": "OPKSSH", "filterAuthStepca": "Trin CA", "filterProtocolGroup": "Protokol", "filterProtocolSsh": "SSH", @@ -1114,13 +1101,7 @@ "connect": "Opret forbindelse til vært", "clear": "Klar", "paste": "Indsæt", - "connected": "Forbundet", - "clipboardWriteFailed": "Kunne ikke kopiere til udklipsholder. Sørg for, at siden serveres via HTTPS eller localhost.", - "clipboardReadFailed": "Kunne ikke læse fra udklipsholderen. Sørg for, at der er givet tilladelse til udklipsholderen.", "tmuxDetach": "Afbryd forbindelsen til tmux-sessionen", - "terminalTitle": "Terminal - {{host}}", - "terminalWithPath": "Terminal - {{host}}:{{path}}", - "runTitle": "Kører {{command}} - {{host}}", "totpRequired": "Tofaktorgodkendelse påkrævet", "totpCodeLabel": "Bekræftelseskode", "totpVerify": "Verificere", @@ -1148,109 +1129,20 @@ } }, "transfer": { - "copyToHost": "Kopiér til vært…", - "moveToHost": "Flyt til vært…", - "copyItemsToHost": "Kopiér {{count}} elementer til at være vært for…", - "moveItemsToHost": "Flyt {{count}} elementer til at være vært for…", - "noHostsConnected": "Ingen andre filhåndteringsværter tilgængelige.", - "noHostsConnectedHint": "Tilføj en anden SSH-vært med Filhåndtering aktiveret i Værtshåndtering.", - "selectDestinationHost": "Vælg destinationsvært", - "destinationPath": "Destinationssti", - "recentDestinations": "Seneste destinationer", "collapseRecentDestinations": "Skjul de seneste destinationer", "expandRecentDestinations": "Udvid de seneste destinationer", - "browseFolders": "Gennemse destinationsmapper", "browseDestination": "Gennemse eller indtast sti", - "confirmCopy": "Kopi", - "confirmMove": "Flytte", "transferring": "Overfører…", - "progressVerifying": "Bekræfter filintegritet…", - "progressBenchmarking": "Valg af den hurtigste overførselsrute…", "compressing": "Komprimering…", "extracting": "Udtrækker…", "transferringItems": "Overførsel af {{current}} af {{total}} elementer…", - "transferSuccess": "Overførsel fuldført", - "transferError": "Overførslen mislykkedes", "transferPartial": "Overførsel fuldført med {{count}} fejl", - "transferPartialHint": "Kunne ikke overføre: {{paths}}", - "itemsSummary": "{{count}} elementer", - "destMustBeDirectory": "Destinationen skal være en mappe for overførsler af flere elementer", "selectThisFolder": "Vælg denne mappe", - "browsePathWillBeCreated": "Denne mappe findes ikke endnu. Den vil blive oprettet, når overførslen starter.", - "browsePathError": "Kunne ikke åbne denne sti på destinationsværten.", - "goUp": "Gå op", - "copyFolderToHost": "Kopiér mappe til vært…", - "moveFolderToHost": "Flyt mappe til vært…", - "hostReady": "Parat", - "hostConnecting": "Forbinder…", - "hostDisconnected": "Ikke forbundet", - "hostAuthRequired": "Godkendelse kræves — åbn først Filhåndtering på denne vært", - "hostConnectionFailed": "Forbindelsen mislykkedes", "metricsTitle": "Overførselstider", - "metricsPrepare": "Forbered destination: {{duration}}", - "metricsCompress": "Komprimer på kilde: {{duration}}", "metricsHopSourceRead": "Kilde → server: {{throughput}}", "metricsHopDestSftpWrite": "Server → destination (SFTP): {{throughput}}", "metricsHopDestLocalWrite": "Server → destination (lokal): {{throughput}}", - "metricsTransfer": "End-to-end: {{throughput}} ({{duration}})", - "metricsExtract": "Udtræk på destination: {{duration}}", - "metricsVerify": "SHA-256 verificeret: {{duration}}", - "metricsRouteBenchmark": "Rutesonde — direkte: {{direct}}, relæ: {{relay}}", - "metricsSourceDelete": "Fjern fra kilde: {{duration}}", - "metricsTotal": "I alt: {{duration}}", - "progressCompressing": "Komprimering på kildevært…", - "progressExtracting": "Udpakning på destination…", - "progressTransferring": "Overførsel af data…", - "progressReconnecting": "Genopretter forbindelse…", - "parallelSegmentsLabel": "Parallelle overførselsbaner", - "parallelSegmentsOption": "{{count}} baner", - "parallelSegmentsHint": "Store filer opdeles i bidder på 256 MB. Flere baner bruger separate forbindelser (f.eks. at starte flere overførsler) for at opnå en højere samlet gennemløbshastighed.", - "progressTotalSpeed": "{{speed}} i alt ({{lanes}} baner)", - "progressTransferringItems": "Overførsel af filer ({{current}} af {{total}})…", - "progressBytes": "{{transferred}} / {{total}}", - "progressItems": "{{current}} / {{total}} filer", - "sourceNotDeletedPartial": "Kildefiler gemt (delvis overførsel)", - "jumpHostLimitation": "Begge værter skal kunne nås fra Termix-serveren. Direkte vært-til-vært-routing understøttes ikke.", - "cancel": "Ophæve", - "methodLabel": "Overførselsmetode", - "methodAuto": "Bil", - "methodTar": "Tar-arkiv", - "methodItemSftp": "SFTP pr. fil", - "methodAutoHint": "Vælger tar eller SFTP pr. fil baseret på antal filer, størrelse og komprimerbarhed. Enkeltfiler bruger altid streaming SFTP.", - "methodTarHint": "Komprimer ved kildekode, overfør ét arkiv, udpak ved destination. Kræver tar på begge Unix-værter.", - "methodItemSftpHint": "Overfør hver fil individuelt via SFTP. Fungerer på alle værter, inklusive Windows.", - "methodPreviewLoading": "Beregning af overførselsmetode…", - "methodPreviewError": "Kunne ikke forhåndsvise overførselsmetoden. Serveren vil stadig vælge en metode, når du starter.", - "methodPreviewWillUseTar": "Vil bruge: Tar-arkiv", - "methodPreviewWillUseItemSftp": "Vil bruge: SFTP pr. fil", - "methodPreviewScanSummary": "{{fileCount}} filer, {{totalSize}} i alt (scannet på kildevært).", - "methodItemSftpLimitation": "Hver fil bruger den samme SFTP-strøm som en enkelt filkopi, én efter én. Status kombineres på tværs af alle filer, så bjælken bevæger sig langsomt under store filer.", - "methodReason": { - "user_item_sftp": "Du valgte SFTP pr. fil.", - "user_tar": "Du valgte tar-arkivet.", - "tar_unavailable": "Tar er ikke tilgængelig på en eller begge værter — SFTP pr. fil vil blive brugt i stedet.", - "windows_host": "En Windows-vært er involveret — tar bruges ikke.", - "auto_multi_large": "Auto: flere filer inklusive en stor fil ({{largestSize}}) med komprimerbare data — tar samler filer i én overførsel.", - "auto_single_large_in_archive": "Auto: én stor fil ({{largestSize}}) i dette sæt — SFTP pr. fil.", - "auto_many_incompressible": "Auto: for det meste inkomprimerbare data — SFTP pr. fil.", - "auto_many_files": "Auto: mange filer ({{fileCount}}) — tar reducerer overhead pr. fil.", - "auto_default": "Auto: SFTP pr. fil for dette sæt." - }, - "progressCancel": "Ophæve", - "progressCancelling": "Annullerer…", - "progressStalled": "Standset", - "resumedHint": "Genoprettet forbindelse til en aktiv overførsel, der er startet i et andet vindue.", - "transferCancelled": "Overførsel annulleret", - "transferCancelledCopyHint": "Delvise filer kan forblive på destinationen.", - "transferCancelledMoveHint": "Delvise filer kan forblive på destinationen. Kildefilerne blev ikke fjernet.", - "cleanupDestFiles": "Oprydningsdestination", - "cleanupDestFilesSuccess": "Fjernede delvise filer fra destinationen", - "cleanupDestFilesPartial": "Nogle delvise filer kunne ikke fjernes", - "cleanupDestFilesNothing": "Intet at rydde op på destinationen", - "cleanupDestFilesError": "Oprydning mislykkedes", - "retryTransfer": "Prøv igen", - "retryTransferError": "Genforsøg mislykkedes", - "transferFailedRetryHint": "Delvise data blev gemt på destinationen. Forsøget genoptages, når forbindelsen er tilbage." + "sourceNotDeletedPartial": "Kildefiler gemt (delvis overførsel)" }, "tunnels": { "connect": "Forbinde", @@ -1261,8 +1153,6 @@ "clientTunnel": "Klienttunnel", "addClientTunnel": "Tilføj klienttunnel", "active": "Aktiv", - "start": "Starte", - "stop": "Stop", "typeServerLocalDesc": "Nuværende vært til slutpunkt.", "typeServerRemoteDesc": "Slutpunkt tilbage til nuværende vært.", "typeClientLocalDesc": "Lokal computer til slutpunkt.", @@ -1374,8 +1264,7 @@ "resetCodeRateLimitedWithTime": "Begrænset hastighed: For mange bekræftelsesforsøg. Vent {{time}} sekunder, før du prøver igen.", "authTokenSaveFailed": "Kunne ikke gemme godkendelsestoken", "authTokenMissing": "Serveren returnerede ikke et nyt godkendelsestoken. Log venligst ind igen.", - "failedToLoadServer": "Kunne ikke indlæse serveren", - "remoteServerRequired": "Fjernserver kræves. Opret forbindelse til en fjernserver i Indstillinger for at bruge denne forbindelsestype." + "failedToLoadServer": "Kunne ikke indlæse serveren" }, "messages": { "registrationDisabled": "Registrering af nye kontoer er i øjeblikket deaktiveret af en administrator. Log venligst ind eller kontakt en administrator.", @@ -1831,7 +1720,6 @@ "protocolLabel": "Protokol", "domainLabel": "Domæne", "domainPlaceholder": "valgfri", - "connectToTerminal": "Opret forbindelse til terminalen", "connectToFiles": "Opret forbindelse til filer" }, "splitScreen": { diff --git a/src/ui/locales/translated/de_DE.json b/src/ui/locales/translated/de_DE.json index 9b191bde7..3551012a2 100644 --- a/src/ui/locales/translated/de_DE.json +++ b/src/ui/locales/translated/de_DE.json @@ -324,10 +324,6 @@ "appearanceIntro": "Wählen Sie ein Design, eine Akzentfarbe und Ihre Sprache. Alle drei können später in den Einstellungen geändert werden.", "featuresTitle": "Was Termix sonst noch tut", "featuresIntro": "Jeder gespeicherte Server kann in mehr als nur einem Terminal geöffnet werden. Hier ist, was sich hinter den Symbolen auf der linken Seite verbirgt.", - "feature_files": "Dateimanager", - "feature_files_desc": "Durchsuchen, hochladen, herunterladen und bearbeiten Sie Dateien über SFTP, ohne die App zu verlassen.", - "feature_tunnels": "Tunnel", - "feature_tunnels_desc": "Leiten Sie Ports über einen Server weiter, um Dienste zu erreichen, die nicht öffentlich zugänglich sind.", "feature_snippets": "Ausschnitte", "feature_snippets_desc": "Speichern Sie häufig ausgeführte Befehle und senden Sie sie mit einem Klick an ein Terminal.", "featuresRailHint": "Sie benötigen keines dieser Symbole? Blenden Sie beliebige Symbole in der Seitenleiste unter Einstellungen > Navigation aus.", @@ -449,7 +445,6 @@ "passwordSaved": "Passwort gespeichert, zum Ändern eingeben", "key": "Schlüssel", "credential": "Anmeldedaten", - "none": "Keine", "sshPrivateKey": "Privater SSH-Schlüssel", "keyType": "Schlüsseltyp", "uploadFile": "Datei hochladen", @@ -611,17 +606,12 @@ "keepaliveIntervalLabel": "Keepalive-Intervall (Sekunden)", "maxKeepaliveMisses": "Max. Keepalive-Fehlschläge", "sameHost": "Dieser Host (direkter Tunnel)", - "bindHost": "Bind-Host", "connectionToolbar": "Verbindungssymbolleiste", "showConnectionToolbar": "Verbindungssymbolleiste anzeigen", "showConnectionToolbarDesc": "Die Symbolleiste wird in den SSH-, RDP-, VNC- und Telnet-Sitzungen dieses Hosts angezeigt. Sie kann auch vorübergehend in der Symbolleiste selbst ausgeblendet werden.", "proxmoxLastSyncStatus": { "success": "Erfolg" }, - "proxmoxGuestsSelected_one": "{{count}} Gast — {{selected}} ausgewählt", - "proxmoxGuestsSelected_other": "{{count}} Gäste — {{selected}} ausgewählt", - "proxmoxImportButton_one": "{{count}} Host importieren", - "proxmoxImportButton_other": "{{count}} Hosts importieren", "proxmoxResultSkippedNoIp": "{{count}} übersprungen (keine IP-Adresse gefunden)", "proxmoxStatsUrlCopied": "Proxmox-Statistik-URL in die Zwischenablage kopiert", "copyProxmoxStatsUrlAction": "Proxmox-Statistik-URL kopieren", @@ -896,13 +886,11 @@ "updatedCount": "{{count}} Hosts aktualisiert", "friendlyNameLabel": "Anzeigename", "descriptionLabel": "Beschreibung", - "loadingHost": "Host wird geladen...", "loadingHosts": "Hosts werden geladen...", "loadingCredentials": "Anmeldedaten werden geladen...", "noHostsYet": "Noch keine Hosts", "noHostsYetHint": "Füge einen Server hinzu, um Terminals zu öffnen, Dateien zu durchsuchen und Metriken anzuzeigen.", "noHostsMatchSearch": "Keine Hosts entsprechen Ihrer Suche", - "hostNotFound": "Host nicht gefunden", "searchHosts": "Hosts suchen...", "sortHosts": "Hosts sortieren", "sortDefault": "Standardreihenfolge", @@ -925,7 +913,6 @@ "filterAuthKey": "SSH-Schlüssel", "filterAuthCredential": "Anmeldeinformation", "filterAuthNone": "Keine", - "filterAuthOpkssh": "OPKSSH", "filterAuthStepca": "Schritt CA", "filterProtocolGroup": "Protokoll", "filterProtocolSsh": "SSH", @@ -1114,13 +1101,7 @@ "connect": "Mit Host verbinden", "clear": "Löschen", "paste": "Einfügen", - "connected": "Verbunden", - "clipboardWriteFailed": "Kopieren in die Zwischenablage fehlgeschlagen. Stellen Sie sicher, dass die Seite über HTTPS oder localhost bereitgestellt wird.", - "clipboardReadFailed": "Lesen aus der Zwischenablage fehlgeschlagen. Stellen Sie sicher, dass die Zwischenablageberechtigungen erteilt wurden.", "tmuxDetach": "Von tmux-Sitzung trennen", - "terminalTitle": "Terminal - {{host}}", - "terminalWithPath": "Terminal - {{host}}:{{path}}", - "runTitle": "Ausführung: {{command}} - {{host}}", "totpRequired": "Zwei-Faktor-Authentifizierung erforderlich", "totpCodeLabel": "Verifizierungscode", "totpVerify": "Verifizieren", @@ -1148,109 +1129,20 @@ } }, "transfer": { - "copyToHost": "Auf Host kopieren…", - "moveToHost": "Auf Host verschieben…", - "copyItemsToHost": "{{count}} Elemente auf Host kopieren…", - "moveItemsToHost": "{{count}} Elemente zum Host verschieben…", - "noHostsConnected": "Keine weiteren Dateimanager-Hosts verfügbar.", - "noHostsConnectedHint": "Fügen Sie einen weiteren SSH-Host mit aktiviertem Dateimanager im Host-Manager hinzu.", - "selectDestinationHost": "Zielhost auswählen", - "destinationPath": "Zielpfad", - "recentDestinations": "Letzte Ziele", "collapseRecentDestinations": "Letzte Ziele einklappen", "expandRecentDestinations": "Letzte Ziele ausklappen", - "browseFolders": "Zielordner durchsuchen", "browseDestination": "Pfad durchsuchen oder eingeben", - "confirmCopy": "Kopieren", - "confirmMove": "Verschieben", "transferring": "Übertragen …", - "progressVerifying": "Dateiintegrität wird überprüft…", - "progressBenchmarking": "Auswahl der schnellsten Transferroute…", "compressing": "Komprimieren …", "extracting": "Entpacken …", "transferringItems": "{{current}} von {{total}} Elementen übertragen …", - "transferSuccess": "Übertragung abgeschlossen", - "transferError": "Übertragung fehlgeschlagen", "transferPartial": "Übertragung mit {{count}} Fehlern abgeschlossen", - "transferPartialHint": "Konnte nicht übertragen werden: {{paths}}", - "itemsSummary": "{{count}} Elemente", - "destMustBeDirectory": "Bei Übertragung mehrerer Elemente muss das Ziel ein Verzeichnis sein.", "selectThisFolder": "Diesen Ordner auswählen", - "browsePathWillBeCreated": "Dieser Ordner existiert noch nicht. Er wird beim Start der Übertragung erstellt.", - "browsePathError": "Dieser Pfad konnte auf dem Zielhost nicht geöffnet werden.", - "goUp": "Nach oben", - "copyFolderToHost": "Ordner zum Host kopieren …", - "moveFolderToHost": "Ordner zum Host verschieben …", - "hostReady": "Bereit", - "hostConnecting": "Verbinden …", - "hostDisconnected": "Nicht verbunden", - "hostAuthRequired": "Authentifizierung erforderlich — öffnen Sie zuerst den Dateimanager auf diesem Host", - "hostConnectionFailed": "Verbindung fehlgeschlagen", "metricsTitle": "Übertragungszeiten", - "metricsPrepare": "Ziel vorbereiten: {{duration}}", - "metricsCompress": "Komprimieren auf der Quelle: {{duration}}", "metricsHopSourceRead": "Quelle → Server: {{throughput}}", "metricsHopDestSftpWrite": "Server → Ziel (SFTP): {{throughput}}", "metricsHopDestLocalWrite": "Server → Ziel (lokal): {{throughput}}", - "metricsTransfer": "Ende-zu-Ende: {{throughput}} ({{duration}})", - "metricsExtract": "Entpacken auf dem Ziel: {{duration}}", - "metricsVerify": "SHA-256 verifiziert: {{duration}}", - "metricsRouteBenchmark": "Routenprüfung — direkt: {{direct}}, Relay: {{relay}}", - "metricsSourceDelete": "Löschen von der Quelle: {{duration}}", - "metricsTotal": "Gesamt: {{duration}}", - "progressCompressing": "Komprimieren auf dem Quellhost…", - "progressExtracting": "Entpacken auf dem Zielhost…", - "progressTransferring": "Daten übertragen…", - "progressReconnecting": "Neu verbinden…", - "parallelSegmentsLabel": "Parallele Übertragungskanäle", - "parallelSegmentsOption": "{{count}} Kanäle", - "parallelSegmentsHint": "Große Dateien werden in 256-MB-Blöcke aufgeteilt. Mehrere Kanäle verwenden eigene Verbindungen (ähnlich wie mehrere gleichzeitige Übertragungen) für einen höheren Gesamtdurchsatz.", - "progressTotalSpeed": "{{speed}} gesamt ({{lanes}} Kanäle)", - "progressTransferringItems": "Übertragen von Dateien ({{current}} von {{total}})…", - "progressBytes": "{{transferred}} / {{total}}", - "progressItems": "{{current}} / {{total}} Dateien", - "sourceNotDeletedPartial": "Quelldateien beibehalten (teilweise Übertragung)", - "jumpHostLimitation": "Beide Hosts müssen vom Termix-Server aus erreichbar sein. Direktes Host-zu-Host-Routing wird nicht unterstützt.", - "cancel": "Abbrechen", - "methodLabel": "Übertragungsmethode", - "methodAuto": "Automatisch", - "methodTar": "Tar-Archiv", - "methodItemSftp": "Dateiweise SFTP", - "methodAutoHint": "Wählt Tar-Archiv oder dateiweise SFTP basierend auf Dateianzahl, Größe und Komprimierbarkeit. Einzelne Dateien verwenden immer Streaming-SFTP.", - "methodTarHint": "Komprimieren auf der Quelle, ein Archiv übertragen, auf dem Ziel entpacken. Erfordert tar auf beiden Unix-Hosts.", - "methodItemSftpHint": "Jede Datei einzeln per SFTP übertragen. Funktioniert auf allen Hosts einschließlich Windows.", - "methodPreviewLoading": "Übertragungsmethode wird berechnet…", - "methodPreviewError": "Vorschau der Übertragungsmethode nicht möglich. Der Server wählt beim Start trotzdem eine Methode.", - "methodPreviewWillUseTar": "Verwendet: Tar-Archiv", - "methodPreviewWillUseItemSftp": "Verwendet: Dateiweise SFTP", - "methodPreviewScanSummary": "{{fileCount}} Dateien, {{totalSize}} gesamt (auf Quellhost gescannt).", - "methodItemSftpLimitation": "Jede Datei verwendet denselben SFTP-Stream wie bei einer Einzeldatei-Kopie, eine nach der anderen. Der Fortschritt wird über alle Dateien kombiniert, sodass der Balken bei großen Dateien nur langsam voranschreitet.", - "methodReason": { - "user_item_sftp": "Sie haben dateiweises SFTP ausgewählt.", - "user_tar": "Sie haben tar-Archiv ausgewählt.", - "tar_unavailable": "Tar ist auf einem oder beiden Hosts nicht verfügbar – stattdessen wird dateiweises SFTP verwendet.", - "windows_host": "Ein Windows-Host ist beteiligt – tar wird nicht verwendet.", - "auto_multi_large": "Automatisch: mehrere Dateien, darunter eine große Datei ({{largestSize}}) mit komprimierbaren Daten – tar bündelt sie in eine Übertragung.", - "auto_single_large_in_archive": "Automatisch: eine große Datei ({{largestSize}}) in diesem Satz – dateiweises SFTP.", - "auto_many_incompressible": "Automatisch: überwiegend nicht komprimierbare Daten – dateiweises SFTP.", - "auto_many_files": "Automatisch: viele Dateien ({{fileCount}}) – tar reduziert den Overhead pro Datei.", - "auto_default": "Automatisch: dateiweises SFTP für diesen Satz." - }, - "progressCancel": "Abbrechen", - "progressCancelling": "Wird abgebrochen…", - "progressStalled": "Stockt", - "resumedHint": "Erneut mit einer aktiven Übertragung verbunden, die in einem anderen Fenster gestartet wurde.", - "transferCancelled": "Übertragung abgebrochen", - "transferCancelledCopyHint": "Unvollständige Dateien können am Zielort verbleiben.", - "transferCancelledMoveHint": "Unvollständige Dateien können am Zielort verbleiben. Quelldateien wurden nicht entfernt.", - "cleanupDestFiles": "Ziel bereinigen", - "cleanupDestFilesSuccess": "Unvollständige Dateien vom Ziel entfernt.", - "cleanupDestFilesPartial": "Einige unvollständige Dateien konnten nicht entfernt werden.", - "cleanupDestFilesNothing": "Nichts zum Bereinigen am Ziel.", - "cleanupDestFilesError": "Bereinigung fehlgeschlagen.", - "retryTransfer": "Wiederholen", - "retryTransferError": "Wiederholung fehlgeschlagen.", - "transferFailedRetryHint": "Unvollständige Daten wurden am Ziel beibehalten. Die Wiederholung wird fortgesetzt, sobald die Verbindung wiederhergestellt ist." + "sourceNotDeletedPartial": "Quelldateien beibehalten (teilweise Übertragung)" }, "tunnels": { "connect": "Verbinden", @@ -1261,8 +1153,6 @@ "clientTunnel": "Client-Tunnel", "addClientTunnel": "Client-Tunnel hinzufügen", "active": "Aktiv", - "start": "Start", - "stop": "Stop", "typeServerLocalDesc": "Vom aktuellen Host zum Endpunkt.", "typeServerRemoteDesc": "Vom Endpunkt zurück zum aktuellen Host.", "typeClientLocalDesc": "Vom lokalen Computer zum Endpunkt.", @@ -1374,8 +1264,7 @@ "resetCodeRateLimitedWithTime": "Ratenbegrenzung: Zu viele Verifizierungsversuche. Bitte warten Sie {{time}} Sekunden, bevor Sie es erneut versuchen.", "authTokenSaveFailed": "Fehler beim Speichern des Authentifizierungstokens", "authTokenMissing": "Der Server hat kein neues Authentifizierungstoken zurückgegeben. Bitte melden Sie sich erneut an.", - "failedToLoadServer": "Server konnte nicht geladen werden", - "remoteServerRequired": "Remote-Server erforderlich. Um diesen Verbindungstyp zu verwenden, verbinden Sie einen Remote-Server in den Einstellungen." + "failedToLoadServer": "Server konnte nicht geladen werden" }, "messages": { "registrationDisabled": "Die Registrierung neuer Konten ist derzeit durch einen Administrator deaktiviert. Bitte melden Sie sich an oder wenden Sie sich an einen Administrator.", @@ -1831,7 +1720,6 @@ "protocolLabel": "Protokoll", "domainLabel": "Domain", "domainPlaceholder": "optional", - "connectToTerminal": "Mit Terminal verbinden", "connectToFiles": "Mit Dateien verbinden" }, "splitScreen": { diff --git a/src/ui/locales/translated/el_GR.json b/src/ui/locales/translated/el_GR.json index 9021ffc9d..60820a5f1 100644 --- a/src/ui/locales/translated/el_GR.json +++ b/src/ui/locales/translated/el_GR.json @@ -324,10 +324,6 @@ "appearanceIntro": "Επιλέξτε ένα θέμα, ένα χρώμα έμφασης και τη γλώσσα σας. Και τα τρία μπορούν να αλλάξουν αργότερα στις Ρυθμίσεις.", "featuresTitle": "Τι άλλο κάνει το Termix;", "featuresIntro": "Κάθε διακομιστής που αποθηκεύετε μπορεί να ανοιχτεί σε περισσότερα από ένα τερματικά. Δείτε τι σας περιμένει πίσω από τα εικονίδια στα αριστερά.", - "feature_files": "Διαχειριστής αρχείων", - "feature_files_desc": "Περιηγηθείτε, ανεβάστε, κατεβάστε και επεξεργαστείτε αρχεία μέσω SFTP χωρίς να φύγετε από την εφαρμογή.", - "feature_tunnels": "Σήραγγες", - "feature_tunnels_desc": "Προώθηση θυρών μέσω ενός διακομιστή για πρόσβαση σε υπηρεσίες που δεν είναι εκτεθειμένες.", "feature_snippets": "Αποσπάσματα", "feature_snippets_desc": "Αποθηκεύστε τις εντολές που εκτελείτε συχνά και στείλτε τις σε ένα τερματικό με ένα κλικ.", "featuresRailHint": "Δεν χρειάζεστε κάποιο από αυτά; Αποκρύψτε οποιοδήποτε εικονίδιο από την πλαϊνή γραμμή στις Ρυθμίσεις, στην περιοχή Πλοήγηση.", @@ -449,7 +445,6 @@ "passwordSaved": "Ο κωδικός πρόσβασης αποθηκεύτηκε, πληκτρολογήστε για να τον αλλάξετε", "key": "Κλειδί", "credential": "Πιστοποιητικό", - "none": "Κανένας", "sshPrivateKey": "Ιδιωτικό κλειδί SSH", "keyType": "Τύπος κλειδιού", "uploadFile": "Μεταφόρτωση αρχείου", @@ -611,17 +606,12 @@ "keepaliveIntervalLabel": "Διάστημα διατήρησης ζωντανής λειτουργίας (δευτερόλεπτα)", "maxKeepaliveMisses": "Ο Max Keepalive αστοχεί", "sameHost": "Αυτός ο κεντρικός υπολογιστής (άμεση σήραγγα)", - "bindHost": "Bind Host", "connectionToolbar": "Γραμμή εργαλείων σύνδεσης", "showConnectionToolbar": "Εμφάνιση γραμμής εργαλείων σύνδεσης", "showConnectionToolbarDesc": "Εμφάνιση της γραμμής εργαλείων στις συνεδρίες SSH, RDP, VNC και Telnet αυτού του κεντρικού υπολογιστή. Μπορείτε επίσης να την αποκρύψετε προσωρινά από την ίδια τη γραμμή εργαλείων.", "proxmoxLastSyncStatus": { "success": "Επιτυχία" }, - "proxmoxGuestsSelected_one": "{{count}} επισκέπτης — {{selected}} επιλεγμένος", - "proxmoxGuestsSelected_other": "{{count}} επισκέπτες — {{selected}} επιλεγμένοι", - "proxmoxImportButton_one": "Εισαγωγή κεντρικού υπολογιστή {{count}}", - "proxmoxImportButton_other": "Εισαγωγή {{count}} κεντρικών υπολογιστών", "proxmoxResultSkippedNoIp": "{{count}} παραλείφθηκε (δεν βρέθηκε IP)", "proxmoxStatsUrlCopied": "Η διεύθυνση URL των στατιστικών του Proxmox αντιγράφηκε στο πρόχειρο", "copyProxmoxStatsUrlAction": "Αντιγραφή URL Στατιστικών Proxmox", @@ -896,13 +886,11 @@ "updatedCount": "Ενημερώθηκαν οι {{count}} κεντρικοί υπολογιστές", "friendlyNameLabel": "Φιλικό όνομα", "descriptionLabel": "Περιγραφή", - "loadingHost": "Φόρτωση κεντρικού υπολογιστή...", "loadingHosts": "Φόρτωση κεντρικών υπολογιστών...", "loadingCredentials": "Φόρτωση διαπιστευτηρίων...", "noHostsYet": "Δεν υπάρχουν ακόμη οικοδεσπότες", "noHostsYetHint": "Προσθέστε έναν διακομιστή για να ανοίγετε τερματικά, να περιηγείστε σε αρχεία και να βλέπετε μετρήσεις.", "noHostsMatchSearch": "Δεν υπάρχουν κεντρικοί υπολογιστές που να ταιριάζουν με την αναζήτησή σας", - "hostNotFound": "Δεν βρέθηκε κεντρικός υπολογιστής", "searchHosts": "Αναζήτηση κεντρικών υπολογιστών...", "sortHosts": "Ταξινόμηση κεντρικών υπολογιστών", "sortDefault": "Προεπιλεγμένη παραγγελία", @@ -925,7 +913,6 @@ "filterAuthKey": "Κλειδί SSH", "filterAuthCredential": "Πιστοποιητικό", "filterAuthNone": "Κανένας", - "filterAuthOpkssh": "OPKSSH", "filterAuthStepca": "Βήμα CA", "filterProtocolGroup": "Πρωτόκολλο", "filterProtocolSsh": "SSH", @@ -1114,13 +1101,7 @@ "connect": "Σύνδεση με τον κεντρικό υπολογιστή", "clear": "Σαφής", "paste": "Πάστα", - "connected": "Συνδεδεμένος", - "clipboardWriteFailed": "Αποτυχία αντιγραφής στο πρόχειρο. Βεβαιωθείτε ότι η σελίδα προβάλλεται μέσω HTTPS ή localhost.", - "clipboardReadFailed": "Αποτυχία ανάγνωσης από το πρόχειρο. Βεβαιωθείτε ότι έχουν εκχωρηθεί δικαιώματα στο πρόχειρο.", "tmuxDetach": "Αποσύνδεση από την περίοδο λειτουργίας tmux", - "terminalTitle": "Τερματικό - {{host}}", - "terminalWithPath": "Τερματικό - {{host}}:{{path}}", - "runTitle": "Εκτέλεση {{command}} - {{host}}", "totpRequired": "Απαιτείται έλεγχος ταυτότητας δύο παραγόντων", "totpCodeLabel": "Κωδικός επαλήθευσης", "totpVerify": "Επαληθεύω", @@ -1148,109 +1129,20 @@ } }, "transfer": { - "copyToHost": "Αντιγραφή στον κεντρικό υπολογιστή…", - "moveToHost": "Μετακίνηση στον κεντρικό υπολογιστή…", - "copyItemsToHost": "Αντιγραφή στοιχείων {{count}} για φιλοξενία…", - "moveItemsToHost": "Μετακίνηση στοιχείων {{count}} για να φιλοξενήσει το…", - "noHostsConnected": "Δεν υπάρχουν άλλοι διαθέσιμοι κεντρικοί υπολογιστές διαχείρισης αρχείων.", - "noHostsConnectedHint": "Προσθέστε έναν άλλο κεντρικό υπολογιστή SSH με ενεργοποιημένο το File Manager στο Host Manager.", - "selectDestinationHost": "Επιλέξτε κεντρικό υπολογιστή προορισμού", - "destinationPath": "Διαδρομή προορισμού", - "recentDestinations": "Πρόσφατοι προορισμοί", "collapseRecentDestinations": "Σύμπτυξη πρόσφατων προορισμών", "expandRecentDestinations": "Ανάπτυξη πρόσφατων προορισμών", - "browseFolders": "Αναζήτηση φακέλων προορισμού", "browseDestination": "Περιήγηση ή εισαγωγή διαδρομής", - "confirmCopy": "Αντίγραφο", - "confirmMove": "Κίνηση", "transferring": "Μεταφορά…", - "progressVerifying": "Επαλήθευση ακεραιότητας αρχείου…", - "progressBenchmarking": "Επιλογή της ταχύτερης διαδρομής μεταφοράς…", "compressing": "Συμπίεση…", "extracting": "Εξαγωγή…", "transferringItems": "Μεταφορά {{current}} από {{total}} στοιχεία…", - "transferSuccess": "Η μεταφορά ολοκληρώθηκε", - "transferError": "Η μεταφορά απέτυχε", "transferPartial": "Η μεταφορά ολοκληρώθηκε με σφάλματα {{count}}", - "transferPartialHint": "Δεν ήταν δυνατή η μεταφορά: {{paths}}", - "itemsSummary": "{{count}} στοιχεία", - "destMustBeDirectory": "Ο προορισμός πρέπει να είναι ένας κατάλογος για μεταφορές πολλαπλών στοιχείων", "selectThisFolder": "Επιλέξτε αυτόν τον φάκελο", - "browsePathWillBeCreated": "Αυτός ο φάκελος δεν υπάρχει ακόμη. Θα δημιουργηθεί όταν ξεκινήσει η μεταφορά.", - "browsePathError": "Δεν ήταν δυνατό το άνοιγμα αυτής της διαδρομής στον κεντρικό υπολογιστή προορισμού.", - "goUp": "Ανεβαίνω", - "copyFolderToHost": "Αντιγραφή φακέλου στον κεντρικό υπολογιστή…", - "moveFolderToHost": "Μετακίνηση φακέλου στον κεντρικό υπολογιστή…", - "hostReady": "Ετοιμος", - "hostConnecting": "Σύνδεση…", - "hostDisconnected": "Δεν είναι συνδεδεμένο", - "hostAuthRequired": "Απαιτείται έλεγχος ταυτότητας — ανοίξτε πρώτα τη Διαχείριση αρχείων σε αυτόν τον κεντρικό υπολογιστή", - "hostConnectionFailed": "Η σύνδεση απέτυχε", "metricsTitle": "Χρόνοι μεταφοράς", - "metricsPrepare": "Προετοιμασία προορισμού: {{duration}}", - "metricsCompress": "Συμπίεση στην πηγή: {{duration}}", "metricsHopSourceRead": "Πηγή → διακομιστής: {{throughput}}", "metricsHopDestSftpWrite": "Διακομιστής → προορισμός (SFTP): {{throughput}}", "metricsHopDestLocalWrite": "Διακομιστής → προορισμός (τοπικός): {{throughput}}", - "metricsTransfer": "Από άκρο σε άκρο: {{throughput}} ({{duration}})", - "metricsExtract": "Εξαγωγή στον προορισμό: {{duration}}", - "metricsVerify": "Επαληθεύτηκε το SHA-256: {{duration}}", - "metricsRouteBenchmark": "Δρομολόγηση ανιχνευτή — άμεση: {{direct}}, αναμετάδοση: {{relay}}", - "metricsSourceDelete": "Αφαίρεση από την πηγή: {{duration}}", - "metricsTotal": "Σύνολο: {{duration}}", - "progressCompressing": "Συμπίεση στον κεντρικό υπολογιστή προέλευσης…", - "progressExtracting": "Εξαγωγή στον προορισμό…", - "progressTransferring": "Μεταφορά δεδομένων…", - "progressReconnecting": "Επανασύνδεση…", - "parallelSegmentsLabel": "Παράλληλες λωρίδες μετεπιβίβασης", - "parallelSegmentsOption": "{{count}} λωρίδες", - "parallelSegmentsHint": "Τα μεγάλα αρχεία χωρίζονται σε κομμάτια των 256 MB. Πολλαπλές λωρίδες χρησιμοποιούν ξεχωριστές συνδέσεις (όπως η έναρξη αρκετών μεταφορών) για υψηλότερη συνολική απόδοση.", - "progressTotalSpeed": "{{speed}} σύνολο ({{lanes}} λωρίδες)", - "progressTransferringItems": "Μεταφορά αρχείων ({{current}} από {{total}})…", - "progressBytes": "{{transferred}} / {{total}}", - "progressItems": "{{current}} / {{total}} αρχεία", - "sourceNotDeletedPartial": "Τα αρχεία προέλευσης διατηρούνται (μερική μεταφορά)", - "jumpHostLimitation": "Και οι δύο κεντρικοί υπολογιστές πρέπει να είναι προσβάσιμοι από τον διακομιστή Termix. Δεν υποστηρίζεται η άμεση δρομολόγηση από κεντρικό υπολογιστή σε κεντρικό υπολογιστή.", - "cancel": "Ματαίωση", - "methodLabel": "Μέθοδος μεταφοράς", - "methodAuto": "Αυτο", - "methodTar": "Αρχείο Tar", - "methodItemSftp": "SFTP ανά αρχείο", - "methodAutoHint": "Επιλέγει SFTP tar ή ανά αρχείο με βάση τον αριθμό αρχείων, το μέγεθος και τη συμπιεστότητα. Τα μεμονωμένα αρχεία χρησιμοποιούν πάντα SFTP ροής.", - "methodTarHint": "Συμπίεση στην πηγή, μεταφορά ενός αρχείου, εξαγωγή στον προορισμό. Απαιτείται tar και στους δύο κεντρικούς υπολογιστές Unix.", - "methodItemSftpHint": "Μεταφέρετε κάθε αρχείο ξεχωριστά μέσω SFTP. Λειτουργεί σε όλους τους κεντρικούς υπολογιστές, συμπεριλαμβανομένων των Windows.", - "methodPreviewLoading": "Υπολογισμός μεθόδου μεταφοράς…", - "methodPreviewError": "Δεν ήταν δυνατή η προεπισκόπηση της μεθόδου μεταφοράς. Ο διακομιστής θα επιλέξει μια μέθοδο κατά την εκκίνηση.", - "methodPreviewWillUseTar": "Θα χρησιμοποιηθεί: Αρχείο Tar", - "methodPreviewWillUseItemSftp": "Θα χρησιμοποιηθεί: SFTP ανά αρχείο", - "methodPreviewScanSummary": "{{fileCount}} αρχεία, {{totalSize}} συνολικά (σαρωμένα στον κεντρικό υπολογιστή προέλευσης).", - "methodItemSftpLimitation": "Κάθε αρχείο χρησιμοποιεί την ίδια ροή SFTP ως αντίγραφο ενός μόνο αρχείου, το ένα μετά το άλλο. Η πρόοδος συνδυάζεται σε όλα τα αρχεία, επομένως η γραμμή κινείται αργά κατά τη διάρκεια μεγάλων αρχείων.", - "methodReason": { - "user_item_sftp": "Επιλέξατε SFTP ανά αρχείο.", - "user_tar": "Επιλέξατε το αρχείο tar.", - "tar_unavailable": "Το Tar δεν είναι διαθέσιμο σε έναν ή και στους δύο κεντρικούς υπολογιστές — θα χρησιμοποιηθεί αντ' αυτού το SFTP ανά αρχείο.", - "windows_host": "Εμπλέκεται ένας κεντρικός υπολογιστής των Windows — δεν χρησιμοποιείται το tar.", - "auto_multi_large": "Αυτόματα: πολλά αρχεία, συμπεριλαμβανομένου ενός μεγάλου αρχείου ({{largestSize}}) με συμπιέσιμα δεδομένα — tar ομαδοποιεί σε μία μεταφορά.", - "auto_single_large_in_archive": "Αυτόματα: ένα μεγάλο αρχείο ({{largestSize}}) σε αυτό το σύνολο — ανά αρχείο SFTP.", - "auto_many_incompressible": "Αυτόματα: ως επί το πλείστον ασυμπίεστα δεδομένα — SFTP ανά αρχείο.", - "auto_many_files": "Αυτόματα: πολλά αρχεία ({{fileCount}}) — το tar μειώνει την επιβάρυνση ανά αρχείο.", - "auto_default": "Αυτόματα: SFTP ανά αρχείο για αυτό το σύνολο." - }, - "progressCancel": "Ματαίωση", - "progressCancelling": "Ακύρωση…", - "progressStalled": "Σταματημένο", - "resumedHint": "Επανασύνδεση με μια ενεργή μεταφορά που ξεκίνησε σε άλλο παράθυρο.", - "transferCancelled": "Η μεταφορά ακυρώθηκε.", - "transferCancelledCopyHint": "Ενδέχεται να παραμείνουν μερικά αρχεία στον προορισμό.", - "transferCancelledMoveHint": "Ενδέχεται να παραμείνουν μερικά αρχεία στον προορισμό. Τα αρχεία προέλευσης δεν καταργήθηκαν.", - "cleanupDestFiles": "Καθαρισμός προορισμού", - "cleanupDestFilesSuccess": "Αφαιρέθηκαν μερικά αρχεία από τον προορισμό", - "cleanupDestFilesPartial": "Δεν ήταν δυνατή η κατάργηση ορισμένων τμηματικών αρχείων", - "cleanupDestFilesNothing": "Δεν υπάρχει τίποτα προς διόρθωση στον προορισμό", - "cleanupDestFilesError": "Ο καθαρισμός απέτυχε", - "retryTransfer": "Δοκιμάζω πάλι", - "retryTransferError": "Η επανάληψη απέτυχε", - "transferFailedRetryHint": "Μερικά δεδομένα διατηρήθηκαν στον προορισμό. Η επανάληψη θα συνεχιστεί όταν αποκατασταθεί η σύνδεση." + "sourceNotDeletedPartial": "Τα αρχεία προέλευσης διατηρούνται (μερική μεταφορά)" }, "tunnels": { "connect": "Συνδέω", @@ -1261,8 +1153,6 @@ "clientTunnel": "Σήραγγα Πελάτη", "addClientTunnel": "Προσθήκη σήραγγας πελάτη", "active": "Ενεργός", - "start": "Αρχή", - "stop": "Στάση", "typeServerLocalDesc": "Τρέχων κεντρικός υπολογιστής προς τελικό σημείο.", "typeServerRemoteDesc": "Επιστροφή στο τελικό σημείο στον τρέχοντα κεντρικό υπολογιστή.", "typeClientLocalDesc": "Τοπικός υπολογιστής προς τελικό σημείο.", @@ -1374,8 +1264,7 @@ "resetCodeRateLimitedWithTime": "Περιορισμένος ρυθμός: Πάρα πολλές προσπάθειες επαλήθευσης. Παρακαλώ περιμένετε {{time}} δευτερόλεπτα πριν προσπαθήσετε ξανά.", "authTokenSaveFailed": "Αποτυχία αποθήκευσης διακριτικού ελέγχου ταυτότητας", "authTokenMissing": "Ο διακομιστής δεν επέστρεψε νέο διακριτικό ελέγχου ταυτότητας. Συνδεθείτε ξανά.", - "failedToLoadServer": "Αποτυχία φόρτωσης διακομιστή", - "remoteServerRequired": "Απαιτείται απομακρυσμένος διακομιστής. Συνδέστε έναν απομακρυσμένο διακομιστή στις Ρυθμίσεις για να χρησιμοποιήσετε αυτόν τον τύπο σύνδεσης." + "failedToLoadServer": "Αποτυχία φόρτωσης διακομιστή" }, "messages": { "registrationDisabled": "Η εγγραφή νέου λογαριασμού έχει απενεργοποιηθεί αυτήν τη στιγμή από έναν διαχειριστή. Συνδεθείτε ή επικοινωνήστε με έναν διαχειριστή.", @@ -1831,7 +1720,6 @@ "protocolLabel": "Πρωτόκολλο", "domainLabel": "Πεδίο ορισμού", "domainPlaceholder": "προαιρετικός", - "connectToTerminal": "Σύνδεση με τερματικό", "connectToFiles": "Σύνδεση με αρχεία" }, "splitScreen": { diff --git a/src/ui/locales/translated/es_ES.json b/src/ui/locales/translated/es_ES.json index 3a196aea3..728c90876 100644 --- a/src/ui/locales/translated/es_ES.json +++ b/src/ui/locales/translated/es_ES.json @@ -324,10 +324,6 @@ "appearanceIntro": "Elige un tema, un color de acento y tu idioma. Puedes cambiar los tres posteriormente en Ajustes.", "featuresTitle": "¿Qué más hace Termix?", "featuresIntro": "Cada servidor que guardes se puede abrir en más de una terminal. Esto es lo que te espera tras los iconos de la izquierda.", - "feature_files": "Gestor de archivos", - "feature_files_desc": "Navega, sube, descarga y edita archivos a través de SFTP sin salir de la aplicación.", - "feature_tunnels": "Túneles", - "feature_tunnels_desc": "Reenvía puertos a través de un servidor para acceder a servicios que no están expuestos.", "feature_snippets": "Fragmentos", "feature_snippets_desc": "Guarda los comandos que ejecutas con frecuencia y envíalos a una terminal con un solo clic.", "featuresRailHint": "¿No necesitas ninguno de estos? Oculta cualquier icono de la barra lateral en Ajustes, en Navegación.", @@ -449,7 +445,6 @@ "passwordSaved": "Contraseña guardada, escriba para cambiarla", "key": "Clave", "credential": "Credencial", - "none": "Ninguno", "sshPrivateKey": "Clave privada SSH", "keyType": "Tipo de clave", "uploadFile": "Subir archivo", @@ -611,17 +606,12 @@ "keepaliveIntervalLabel": "Intervalo de keepalive (segundos)", "maxKeepaliveMisses": "Máximo de fallos de keepalive", "sameHost": "Este host (túnel directo)", - "bindHost": "Host de enlace", "connectionToolbar": "Barra de herramientas de conexión", "showConnectionToolbar": "Mostrar barra de herramientas de conexión", "showConnectionToolbarDesc": "Muestra la barra de herramientas en las sesiones SSH, RDP, VNC y Telnet de este host. También puedes ocultarla temporalmente desde la propia barra de herramientas.", "proxmoxLastSyncStatus": { "success": "Correcto" }, - "proxmoxGuestsSelected_one": "{{count}} invitado — {{selected}} seleccionado", - "proxmoxGuestsSelected_other": "{{count}} invitados — {{selected}} seleccionados", - "proxmoxImportButton_one": "Importar {{count}} host", - "proxmoxImportButton_other": "Importar {{count}} hosts", "proxmoxResultSkippedNoIp": "{{count}} omitido (no se encontró ninguna IP)", "proxmoxStatsUrlCopied": "Se copió al portapapeles la URL de estadísticas de Proxmox.", "copyProxmoxStatsUrlAction": "Copiar la URL de estadísticas de Proxmox", @@ -896,13 +886,11 @@ "updatedCount": "{{count}} hosts actualizados", "friendlyNameLabel": "Nombre descriptivo", "descriptionLabel": "Descripción", - "loadingHost": "Cargando host...", "loadingHosts": "Cargando hosts...", "loadingCredentials": "Cargando credenciales...", "noHostsYet": "Aún no hay hosts", "noHostsYetHint": "Agregue un servidor para abrir terminales, explorar archivos y ver métricas.", "noHostsMatchSearch": "Ningún host coincide con tu búsqueda", - "hostNotFound": "Host no encontrado", "searchHosts": "Buscar hosts...", "sortHosts": "Ordenar hosts", "sortDefault": "Orden predeterminado", @@ -925,7 +913,6 @@ "filterAuthKey": "Clave SSH", "filterAuthCredential": "Credencial", "filterAuthNone": "Ninguno", - "filterAuthOpkssh": "OPKSSH", "filterAuthStepca": "Paso CA", "filterProtocolGroup": "Protocolo", "filterProtocolSsh": "SSH", @@ -1114,13 +1101,7 @@ "connect": "Conectar al host", "clear": "Limpiar", "paste": "Pegar", - "connected": "Conectado", - "clipboardWriteFailed": "Error al copiar al portapapeles. Asegúrese de que la página se sirva a través de HTTPS o en localhost.", - "clipboardReadFailed": "No se pudo leer del portapapeles. Asegúrese de que los permisos del portapapeles estén concedidos.", "tmuxDetach": "Desconectar de la sesión tmux", - "terminalTitle": "Terminal - {{host}}", - "terminalWithPath": "Terminal - {{host}}:{{path}}", - "runTitle": "Ejecutando {{command}} - {{host}}", "totpRequired": "Autenticación de dos factores requerida", "totpCodeLabel": "Código de verificación", "totpVerify": "Verificar", @@ -1148,109 +1129,20 @@ } }, "transfer": { - "copyToHost": "Copiar al host…", - "moveToHost": "Mover al host…", - "copyItemsToHost": "Copiar {{count}} elementos al host…", - "moveItemsToHost": "Mover {{count}} elementos al host…", - "noHostsConnected": "No hay otros hosts de gestor de archivos disponibles.", - "noHostsConnectedHint": "Añade otro host SSH con el Gestor de Archivos habilitado en el Administrador de Hosts.", - "selectDestinationHost": "Seleccionar host de destino", - "destinationPath": "Ruta de destino", - "recentDestinations": "Destinos recientes", "collapseRecentDestinations": "Contraer destinos recientes", "expandRecentDestinations": "Expandir destinos recientes", - "browseFolders": "Examinar carpetas de destino", "browseDestination": "Examinar o introducir ruta", - "confirmCopy": "Copiar", - "confirmMove": "Mover", "transferring": "Transfiriendo…", - "progressVerifying": "Verificando la integridad del archivo…", - "progressBenchmarking": "Seleccionar la ruta de transferencia más rápida…", "compressing": "Comprimiendo…", "extracting": "Extrayendo…", "transferringItems": "Transfiriendo {{current}} de {{total}} elementos…", - "transferSuccess": "Transferencia completada", - "transferError": "Transferencia fallida", "transferPartial": "Transferencia completada con {{count}} errores", - "transferPartialHint": "No se pudo transferir: {{paths}}", - "itemsSummary": "{{count}} elementos", - "destMustBeDirectory": "El destino debe ser un directorio para transferencias de múltiples elementos", "selectThisFolder": "Seleccionar esta carpeta", - "browsePathWillBeCreated": "Esta carpeta no existe aún. Se creará al iniciar la transferencia.", - "browsePathError": "No se pudo abrir esta ruta en el host de destino.", - "goUp": "Subir", - "copyFolderToHost": "Copiar carpeta al host…", - "moveFolderToHost": "Mover carpeta al host…", - "hostReady": "Listo", - "hostConnecting": "Conectando…", - "hostDisconnected": "No conectado", - "hostAuthRequired": "Se requiere autenticación — abre primero el Gestor de Archivos en este host", - "hostConnectionFailed": "Conexión fallida", "metricsTitle": "Tiempos de transferencia", - "metricsPrepare": "Preparar destino: {{duration}}", - "metricsCompress": "Compresión en origen: {{duration}}", "metricsHopSourceRead": "Origen → servidor: {{throughput}}", "metricsHopDestSftpWrite": "Servidor → destino (SFTP): {{throughput}}", "metricsHopDestLocalWrite": "Servidor → destino (local): {{throughput}}", - "metricsTransfer": "Extremo a extremo: {{throughput}} ({{duration}})", - "metricsExtract": "Extracción en destino: {{duration}}", - "metricsVerify": "SHA-256 verificado: {{duration}}", - "metricsRouteBenchmark": "Sondeo de ruta: directo: {{direct}}, retransmisión: {{relay}}", - "metricsSourceDelete": "Eliminación del origen: {{duration}}", - "metricsTotal": "Total: {{duration}}", - "progressCompressing": "Comprimiendo en el equipo de origen…", - "progressExtracting": "Extrayendo en el destino…", - "progressTransferring": "Transfiriendo datos…", - "progressReconnecting": "Reconectando…", - "parallelSegmentsLabel": "Vías de transferencia en paralelo", - "parallelSegmentsOption": "{{count}} vías", - "parallelSegmentsHint": "Los archivos grandes se dividen en fragmentos de 256 MB. Varias vías utilizan conexiones separadas (como iniciar varias transferencias) para un mayor rendimiento total.", - "progressTotalSpeed": "{{speed}} total ({{lanes}} vías)", - "progressTransferringItems": "Transfiriendo archivos ({{current}} de {{total}})…", - "progressBytes": "{{transferred}} / {{total}}", - "progressItems": "{{current}} / {{total}} archivos", - "sourceNotDeletedPartial": "Archivos de origen conservados (transferencia parcial)", - "jumpHostLimitation": "Ambos equipos deben ser accesibles desde el servidor de Termix. No se admite el enrutamiento directo entre equipos.", - "cancel": "Cancelar", - "methodLabel": "Método de transferencia", - "methodAuto": "Automático", - "methodTar": "Archivo Tar", - "methodItemSftp": "SFTP por archivo", - "methodAutoHint": "Elige tar o SFTP por archivo según el número de archivos, tamaño y compresibilidad. Los archivos individuales siempre usan SFTP por transmisión continua.", - "methodTarHint": "Comprime en origen, transfiere un archivo, extrae en destino. Necesita tar en ambos equipos Unix.", - "methodItemSftpHint": "Transfiere cada archivo individualmente por SFTP. Funciona en todos los equipos, incluido Windows.", - "methodPreviewLoading": "Calculando el método de transferencia…", - "methodPreviewError": "No se pudo previsualizar el método de transferencia. El servidor seleccionará un método al iniciar.", - "methodPreviewWillUseTar": "Se usará: Archivo Tar", - "methodPreviewWillUseItemSftp": "Se usará: SFTP por archivo", - "methodPreviewScanSummary": "{{fileCount}} archivos, {{totalSize}} total (analizado en el equipo de origen).", - "methodItemSftpLimitation": "Cada archivo usa el mismo flujo SFTP que una copia de un solo archivo, uno tras otro. El progreso se combina en todos los archivos, por lo que la barra se mueve lentamente durante archivos grandes.", - "methodReason": { - "user_item_sftp": "Has elegido SFTP por archivo.", - "user_tar": "Has elegido archivo tar.", - "tar_unavailable": "Tar no está disponible en uno o ambos hosts; se usará SFTP por archivo.", - "windows_host": "Hay un host Windows implicado; no se usa tar.", - "auto_multi_large": "Auto: múltiples archivos incluido uno grande ({{largestSize}}) con datos comprimibles; tar los agrupa en una sola transferencia.", - "auto_single_large_in_archive": "Auto: un archivo grande ({{largestSize}}) en este conjunto; SFTP por archivo.", - "auto_many_incompressible": "Auto: datos mayoritariamente incompresibles; SFTP por archivo.", - "auto_many_files": "Auto: muchos archivos ({{fileCount}}); tar reduce la sobrecarga por archivo.", - "auto_default": "Auto: SFTP por archivo para este conjunto." - }, - "progressCancel": "Cancelar", - "progressCancelling": "Cancelando…", - "progressStalled": "Estancado", - "resumedHint": "Reconectado a una transferencia activa iniciada en otra ventana.", - "transferCancelled": "Transferencia cancelada", - "transferCancelledCopyHint": "Pueden quedar archivos parciales en el destino.", - "transferCancelledMoveHint": "Pueden quedar archivos parciales en el destino. Los archivos de origen no se eliminaron.", - "cleanupDestFiles": "Limpiar destino", - "cleanupDestFilesSuccess": "Se eliminaron los archivos parciales del destino", - "cleanupDestFilesPartial": "Algunos archivos parciales no se pudieron eliminar", - "cleanupDestFilesNothing": "Nada que limpiar en el destino", - "cleanupDestFilesError": "Error al limpiar", - "retryTransfer": "Reintentar", - "retryTransferError": "Error al reintentar", - "transferFailedRetryHint": "Se conservaron datos parciales en el destino. El reintento se reanudará cuando se restablezca la conexión." + "sourceNotDeletedPartial": "Archivos de origen conservados (transferencia parcial)" }, "tunnels": { "connect": "Conectar", @@ -1261,8 +1153,6 @@ "clientTunnel": "Túnel de cliente", "addClientTunnel": "Añadir túnel de cliente", "active": "Activo", - "start": "Iniciar", - "stop": "Detener", "typeServerLocalDesc": "Del host actual al endpoint.", "typeServerRemoteDesc": "Del endpoint al host actual.", "typeClientLocalDesc": "Del equipo local al endpoint.", @@ -1374,8 +1264,7 @@ "resetCodeRateLimitedWithTime": "Límite de intentos: Demasiados intentos de verificación. Espere {{time}} segundos antes de volver a intentarlo.", "authTokenSaveFailed": "Error al guardar el token de autenticación", "authTokenMissing": "El servidor no devolvió un nuevo token de autenticación. Inicie sesión de nuevo.", - "failedToLoadServer": "Error al cargar el servidor", - "remoteServerRequired": "Se requiere un servidor remoto. Conecte un servidor remoto en Configuración para usar este tipo de conexión." + "failedToLoadServer": "Error al cargar el servidor" }, "messages": { "registrationDisabled": "El registro de nuevas cuentas está deshabilitado por un administrador. Inicie sesión o contacte con un administrador.", @@ -1831,7 +1720,6 @@ "protocolLabel": "Protocolo", "domainLabel": "Dominio", "domainPlaceholder": "opcional", - "connectToTerminal": "Conectar a Terminal", "connectToFiles": "Conectar a Archivos" }, "splitScreen": { diff --git a/src/ui/locales/translated/fi_FI.json b/src/ui/locales/translated/fi_FI.json index 90af8afab..d40416fcb 100644 --- a/src/ui/locales/translated/fi_FI.json +++ b/src/ui/locales/translated/fi_FI.json @@ -324,10 +324,6 @@ "appearanceIntro": "Valitse teema, korostusväri ja kielesi. Voit muuttaa kaikkia kolmea myöhemmin asetuksissa.", "featuresTitle": "Mitä muuta Termix tekee", "featuresIntro": "Jokainen tallentamasi palvelin voidaan avata useammassakin kuin vain terminaalissa. Tässä on vasemmalla olevien kuvakkeiden takana olevat tiedot.", - "feature_files": "Tiedostonhallinta", - "feature_files_desc": "Selaa, lähetä, lataa ja muokkaa tiedostoja SFTP:n kautta poistumatta sovelluksesta.", - "feature_tunnels": "Tunnelit", - "feature_tunnels_desc": "Lähetä portteja palvelimen kautta tavoittaaksesi palvelut, jotka eivät ole alttiina.", "feature_snippets": "Katkelmat", "feature_snippets_desc": "Tallenna usein käyttämäsi komennot ja lähetä ne terminaaliin yhdellä napsautuksella.", "featuresRailHint": "Etkö tarvitse jotakin näistä? Piilota kaikki kuvakkeet sivupalkista asetuksissa, kohdassa Navigointi.", @@ -449,7 +445,6 @@ "passwordSaved": "Salasana tallennettu, kirjoita muuttaaksesi", "key": "Avain", "credential": "Valtakirja", - "none": "Ei mitään", "sshPrivateKey": "SSH-yksityinen avain", "keyType": "Avaimen tyyppi", "uploadFile": "Lähetä tiedosto", @@ -611,17 +606,12 @@ "keepaliveIntervalLabel": "Säilytysaika (sekuntia)", "maxKeepaliveMisses": "Max Keepalive -heitot", "sameHost": "Tämä isäntä (suora tunneli)", - "bindHost": "Sido isäntä", "connectionToolbar": "Yhteystyökalurivi", "showConnectionToolbar": "Näytä yhteystyökalurivi", "showConnectionToolbarDesc": "Näytä työkalupalkki tämän isännän SSH-, RDP-, VNC- ja Telnet-istunnoissa. Voit myös piilottaa sen tilapäisesti itse työkalupalkista.", "proxmoxLastSyncStatus": { "success": "Menestys" }, - "proxmoxGuestsSelected_one": "{{count}} vieras — {{selected}} valittu", - "proxmoxGuestsSelected_other": "{{count}} vieraat — {{selected}} valittu", - "proxmoxImportButton_one": "Tuo {{count}} isäntä", - "proxmoxImportButton_other": "Tuo {{count}} isäntiä", "proxmoxResultSkippedNoIp": "{{count}} ohitettu (IP-osoitetta ei löytynyt)", "proxmoxStatsUrlCopied": "Proxmox-tilastojen URL-osoite kopioitu leikepöydälle", "copyProxmoxStatsUrlAction": "Kopioi Proxmox-tilastojen URL-osoite", @@ -896,13 +886,11 @@ "updatedCount": "Päivitetyt {{count}} isännät", "friendlyNameLabel": "Ystävällinen nimi", "descriptionLabel": "Kuvaus", - "loadingHost": "Ladataan isäntää...", "loadingHosts": "Ladataan isäntiä...", "loadingCredentials": "Tunnistetietoja ladataan...", "noHostsYet": "Ei vielä isäntiä", "noHostsYetHint": "Lisää palvelin avataksesi päätteitä, selataksesi tiedostoja ja nähdäksesi mittareita.", "noHostsMatchSearch": "Hakuasi vastaavia isäntiä ei löytynyt", - "hostNotFound": "Isäntää ei löydy", "searchHosts": "Hae isäntiä...", "sortHosts": "Lajittele isännät", "sortDefault": "Oletusjärjestys", @@ -925,7 +913,6 @@ "filterAuthKey": "SSH-avain", "filterAuthCredential": "Valtakirja", "filterAuthNone": "Ei mitään", - "filterAuthOpkssh": "OPKSSH", "filterAuthStepca": "Vaihe CA", "filterProtocolGroup": "Protokolla", "filterProtocolSsh": "SSH", @@ -1114,13 +1101,7 @@ "connect": "Yhdistä isäntään", "clear": "Tyhjennä", "paste": "Liitä", - "connected": "Yhdistetty", - "clipboardWriteFailed": "Kopiointi leikepöydälle epäonnistui. Varmista, että sivua käytetään HTTPS:n tai paikallisen isännän kautta.", - "clipboardReadFailed": "Leikepöydän lukeminen epäonnistui. Varmista, että leikepöydän käyttöoikeudet on myönnetty.", "tmuxDetach": "Irrota tmux-istunnosta", - "terminalTitle": "Pääte - {{host}}", - "terminalWithPath": "Pääte - {{host}}:{{path}}", - "runTitle": "Juoksemassa {{command}} - {{host}}", "totpRequired": "Kaksivaiheinen todennus vaaditaan", "totpCodeLabel": "Vahvistuskoodi", "totpVerify": "Vahvista", @@ -1148,109 +1129,20 @@ } }, "transfer": { - "copyToHost": "Kopioi isäntäkoneeseen…", - "moveToHost": "Siirrä isäntäkoneeseen…", - "copyItemsToHost": "Kopioi {{count}} kohdetta isäntään…", - "moveItemsToHost": "Siirrä {{count}} kohdetta isäntään…", - "noHostsConnected": "Muita tiedostonhallintaohjelmia ei ole saatavilla.", - "noHostsConnectedHint": "Lisää toinen SSH-isäntä, jonka tiedostonhallinta on käytössä isäntähallinnassa.", - "selectDestinationHost": "Valitse kohdeisäntä", - "destinationPath": "Kohdepolku", - "recentDestinations": "Viimeaikaiset kohteet", "collapseRecentDestinations": "Pienennä viimeisimmät kohteet", "expandRecentDestinations": "Laajenna viimeisimmät kohteet", - "browseFolders": "Selaa kohdekansioita", "browseDestination": "Selaa tai anna polku", - "confirmCopy": "Kopioida", - "confirmMove": "Liikkua", "transferring": "Siirretään…", - "progressVerifying": "Tiedoston eheyden tarkistaminen…", - "progressBenchmarking": "Nopeimman vaihtoreitin valitseminen…", "compressing": "Pakkaamalla…", "extracting": "Poimitaan…", "transferringItems": "Siirretään {{current}} / {{total}} kohdetta…", - "transferSuccess": "Siirto valmis", - "transferError": "Siirto epäonnistui", "transferPartial": "Siirto suoritettu, mutta virheitä on {{count}}", - "transferPartialHint": "Siirto epäonnistui: {{paths}}", - "itemsSummary": "{{count}} kohdetta", - "destMustBeDirectory": "Määränpään on oltava hakemisto useiden kohteiden siirtoja varten", "selectThisFolder": "Valitse tämä kansio", - "browsePathWillBeCreated": "Tätä kansiota ei ole vielä olemassa. Se luodaan, kun siirto alkaa.", - "browsePathError": "Tätä polkua ei voitu avata kohdepalvelimella.", - "goUp": "Mene ylös", - "copyFolderToHost": "Kopioi kansio isäntään…", - "moveFolderToHost": "Siirrä kansio isäntään…", - "hostReady": "Valmis", - "hostConnecting": "Yhdistetään…", - "hostDisconnected": "Ei yhdistetty", - "hostAuthRequired": "Todennus vaaditaan — avaa ensin tiedostonhallinta tällä isännöintikoneella", - "hostConnectionFailed": "Yhteys epäonnistui", "metricsTitle": "Siirtoajat", - "metricsPrepare": "Valmistele kohde: {{duration}}", - "metricsCompress": "Pakkaa lähdekoodissa: {{duration}}", "metricsHopSourceRead": "Lähde → palvelin: {{throughput}}", "metricsHopDestSftpWrite": "Palvelin → kohde (SFTP): {{throughput}}", "metricsHopDestLocalWrite": "Palvelin → kohde (paikallinen): {{throughput}}", - "metricsTransfer": "Päästä päähän: {{throughput}} ({{duration}})", - "metricsExtract": "Ote määränpäässä: {{duration}}", - "metricsVerify": "SHA-256 vahvistettu: {{duration}}", - "metricsRouteBenchmark": "Reitityskoetin — suora: {{direct}}, välitys: {{relay}}", - "metricsSourceDelete": "Poista lähteestä: {{duration}}", - "metricsTotal": "Yhteensä: {{duration}}", - "progressCompressing": "Pakkaus lähdepalvelimella…", - "progressExtracting": "Puretaan kohteessa…", - "progressTransferring": "Tiedon siirtäminen…", - "progressReconnecting": "Yhdistetään uudelleen…", - "parallelSegmentsLabel": "Rinnakkaiset siirtokaistat", - "parallelSegmentsOption": "{{count}} kaistaa", - "parallelSegmentsHint": "Suuret tiedostot jaetaan 256 Mt:n osiin. Useat kaistat käyttävät erillisiä yhteyksiä (kuten useiden siirtojen aloittaminen) suuremman kokonaisläpivirtauksen saavuttamiseksi.", - "progressTotalSpeed": "{{speed}} yhteensä ({{lanes}} kaistaa)", - "progressTransferringItems": "Tiedostojen siirtäminen ({{current}} / {{total}})…", - "progressBytes": "{{transferred}} / {{total}}", - "progressItems": "{{current}} / {{total}} tiedostoa", - "sourceNotDeletedPartial": "Lähdetiedostot säilytetään (osittainen siirto)", - "jumpHostLimitation": "Molempien isäntien on oltava tavoitettavissa Termix-palvelimelta. Suoraa isäntien välistä reititystä ei tueta.", - "cancel": "Peruuttaa", - "methodLabel": "Siirtotapa", - "methodAuto": "Auto", - "methodTar": "Tar-arkisto", - "methodItemSftp": "Tiedostokohtainen SFTP", - "methodAutoHint": "Valitsee tar- tai tiedostokohtaisen SFTP:n tiedostomäärän, koon ja pakkautuvuuden perusteella. Yksittäiset tiedostot käyttävät aina suoratoistettavaa SFTP:tä.", - "methodTarHint": "Pakkaa lähdekoodissa, siirrä yksi arkisto, pura kohdetiedostossa. Vaatii tar-tiedoston molemmissa Unix-koneissa.", - "methodItemSftpHint": "Siirrä jokainen tiedosto erikseen SFTP:n kautta. Toimii kaikilla isännöintijärjestelmillä, mukaan lukien Windows.", - "methodPreviewLoading": "Siirtomenetelmän laskeminen…", - "methodPreviewError": "Siirtomenetelmän esikatselu ei onnistunut. Palvelin valitsee silti menetelmän käynnistyksen yhteydessä.", - "methodPreviewWillUseTar": "Käytetään: Tar-arkistoa", - "methodPreviewWillUseItemSftp": "Käytetään: Tiedostokohtaista SFTP:tä", - "methodPreviewScanSummary": "{{fileCount}} tiedostoa, {{totalSize}} yhteensä (skannattu lähdepalvelimella).", - "methodItemSftpLimitation": "Jokainen tiedosto käyttää samaa SFTP-tietovirtaa kuin yksittäiset tiedostokopiot, yksi kerrallaan. Edistyminen yhdistetään kaikkien tiedostojen välillä, joten palkki liikkuu hitaasti suurten tiedostojen käsittelyssä.", - "methodReason": { - "user_item_sftp": "Valitsit tiedostokohtaisen SFTP:n.", - "user_tar": "Valitsit tar-arkiston.", - "tar_unavailable": "Tar ei ole käytettävissä yhdellä tai molemmilla isännillä — sen sijaan käytetään tiedostokohtaista SFTP:tä.", - "windows_host": "Windows-isäntä on mukana – tar-tiedostoa ei käytetä.", - "auto_multi_large": "Automaattinen: useita tiedostoja, mukaan lukien suuri tiedosto ({{largestSize}}), jossa on pakattavaa dataa — tar niputtaa yhdeksi siirroksi.", - "auto_single_large_in_archive": "Automaattinen: yksi suuri tiedosto ({{largestSize}}) tässä joukossa — tiedostokohtainen SFTP.", - "auto_many_incompressible": "Automaattinen: enimmäkseen pakkaamatonta dataa — tiedostokohtainen SFTP.", - "auto_many_files": "Automaattinen: monta tiedostoa ({{fileCount}}) — tar vähentää tiedostokohtaista laskentatehoa.", - "auto_default": "Automaattinen: tiedostokohtainen SFTP tälle joukolle." - }, - "progressCancel": "Peruuttaa", - "progressCancelling": "Peruutetaan…", - "progressStalled": "Pysähtynyt", - "resumedHint": "Yhdistetty uudelleen toisessa ikkunassa aloitettuun aktiiviseen siirtoon.", - "transferCancelled": "Siirto peruttu", - "transferCancelledCopyHint": "Osittaisia tiedostoja voi jäädä kohteeseen.", - "transferCancelledMoveHint": "Kohdekansioon saattaa jäädä osittaisia tiedostoja. Lähdetiedostoja ei poistettu.", - "cleanupDestFiles": "Siivouskohde", - "cleanupDestFilesSuccess": "Osittainen tiedosto poistettu kohteesta", - "cleanupDestFilesPartial": "Joitakin osittaisia tiedostoja ei voitu poistaa", - "cleanupDestFilesNothing": "Ei mitään siivottavaa määränpäässä", - "cleanupDestFilesError": "Siivous epäonnistui", - "retryTransfer": "Yritä uudelleen", - "retryTransferError": "Uudelleenyritys epäonnistui", - "transferFailedRetryHint": "Kohteessa säilytettiin vain osa tiedoista. Uudelleenyritys jatkuu, kun yhteys on palannut." + "sourceNotDeletedPartial": "Lähdetiedostot säilytetään (osittainen siirto)" }, "tunnels": { "connect": "Yhdistä", @@ -1261,8 +1153,6 @@ "clientTunnel": "Asiakastunneli", "addClientTunnel": "Lisää asiakastunneli", "active": "Aktiivinen", - "start": "Aloita", - "stop": "Stop", "typeServerLocalDesc": "Nykyisestä isännästä päätepisteeseen.", "typeServerRemoteDesc": "Päätepiste takaisin nykyiseen isäntään.", "typeClientLocalDesc": "Paikallinen tietokone päätepisteeseen.", @@ -1374,8 +1264,7 @@ "resetCodeRateLimitedWithTime": "Nopeus rajoitettu: Liian monta vahvistusyritystä. Odota {{time}} sekuntia ennen kuin yrität uudelleen.", "authTokenSaveFailed": "Todennustunnuksen tallennus epäonnistui", "authTokenMissing": "Palvelin ei palauttanut uutta todennustunnusta. Kirjaudu uudelleen sisään.", - "failedToLoadServer": "Palvelimen lataus epäonnistui", - "remoteServerRequired": "Etäpalvelin vaaditaan. Yhdistä etäpalvelin asetuksissa käyttääksesi tätä yhteystyyppiä." + "failedToLoadServer": "Palvelimen lataus epäonnistui" }, "messages": { "registrationDisabled": "Ylläpitäjä on tällä hetkellä poistanut käytöstä uuden tilin rekisteröinnin. Kirjaudu sisään tai ota yhteyttä ylläpitäjään.", @@ -1831,7 +1720,6 @@ "protocolLabel": "Protokolla", "domainLabel": "Verkkotunnus", "domainPlaceholder": "valinnainen", - "connectToTerminal": "Yhdistä terminaaliin", "connectToFiles": "Yhdistä tiedostoihin" }, "splitScreen": { diff --git a/src/ui/locales/translated/fr_FR.json b/src/ui/locales/translated/fr_FR.json index 39ebba9d3..80acd7ba8 100644 --- a/src/ui/locales/translated/fr_FR.json +++ b/src/ui/locales/translated/fr_FR.json @@ -324,10 +324,6 @@ "appearanceIntro": "Choisissez un thème, une couleur d'accentuation et votre langue. Vous pourrez modifier ces trois éléments ultérieurement dans les paramètres.", "featuresTitle": "Quelles sont les autres activités de Termix ?", "featuresIntro": "Chaque serveur que vous sauvegardez peut être ouvert dans plusieurs navigateurs, et pas seulement dans un terminal. Voici ce qui se cache derrière les icônes à gauche.", - "feature_files": "Gestionnaire de fichiers", - "feature_files_desc": "Parcourez, téléchargez, chargez et modifiez des fichiers via SFTP sans quitter l'application.", - "feature_tunnels": "Tunnels", - "feature_tunnels_desc": "Redirigez les ports via un serveur pour accéder aux services non exposés.", "feature_snippets": "Extraits", "feature_snippets_desc": "Enregistrez les commandes que vous exécutez fréquemment et envoyez-les à un terminal en un seul clic.", "featuresRailHint": "Vous n'en avez pas besoin ? Masquez n'importe quelle icône de la barre latérale dans les Paramètres, sous Navigation.", @@ -449,7 +445,6 @@ "passwordSaved": "Mot de passe enregistré, saisissez-le pour le modifier", "key": "Clé", "credential": "Identifiant", - "none": "Aucun", "sshPrivateKey": "Clé privée SSH", "keyType": "Type de clé", "uploadFile": "Téléverser un fichier", @@ -611,17 +606,12 @@ "keepaliveIntervalLabel": "Intervalle de keepalive (secondes)", "maxKeepaliveMisses": "Nombre maximal d'échecs de keepalive", "sameHost": "Cet hôte (tunnel direct)", - "bindHost": "Hôte de liaison", "connectionToolbar": "Barre d'outils de connexion", "showConnectionToolbar": "Afficher la barre d'outils de connexion", "showConnectionToolbarDesc": "Afficher la barre d'outils dans les sessions SSH, RDP, VNC et Telnet de cet hôte. Vous pouvez également la masquer temporairement depuis la barre d'outils elle-même.", "proxmoxLastSyncStatus": { "success": "Succès" }, - "proxmoxGuestsSelected_one": "{{count}} invité — {{selected}} sélectionné", - "proxmoxGuestsSelected_other": "{{count}} invités — {{selected}} sélectionnés", - "proxmoxImportButton_one": "Importer {{count}} hôte", - "proxmoxImportButton_other": "Importer {{count}} hôtes", "proxmoxResultSkippedNoIp": "{{count}} ignoré (aucune adresse IP trouvée)", "proxmoxStatsUrlCopied": "URL des statistiques Proxmox copiée dans le presse-papiers", "copyProxmoxStatsUrlAction": "Copier l'URL des statistiques Proxmox", @@ -896,13 +886,11 @@ "updatedCount": "{{count}} hôtes mis à jour", "friendlyNameLabel": "Nom convivial", "descriptionLabel": "Description", - "loadingHost": "Chargement de l'hôte...", "loadingHosts": "Chargement des hôtes...", "loadingCredentials": "Chargement des identifiants...", "noHostsYet": "Aucun hôte pour le moment", "noHostsYetHint": "Ajoutez un serveur pour ouvrir des terminaux, parcourir des fichiers et consulter des statistiques.", "noHostsMatchSearch": "Aucun hôte ne correspond à votre recherche", - "hostNotFound": "Hôte introuvable", "searchHosts": "Rechercher des hôtes...", "sortHosts": "Trier les hôtes", "sortDefault": "Ordre par défaut", @@ -925,7 +913,6 @@ "filterAuthKey": "Clé SSH", "filterAuthCredential": "Identifiant", "filterAuthNone": "Aucun", - "filterAuthOpkssh": "OPKSSH", "filterAuthStepca": "Étape CA", "filterProtocolGroup": "Protocole", "filterProtocolSsh": "SSH", @@ -1114,13 +1101,7 @@ "connect": "Se connecter à l'hôte", "clear": "Effacer", "paste": "Coller", - "connected": "Connecté", - "clipboardWriteFailed": "Échec de la copie dans le presse-papiers. Assurez-vous que la page est servie en HTTPS ou localhost.", - "clipboardReadFailed": "Échec de la lecture du presse-papiers. Assurez-vous que les autorisations du presse-papiers sont accordées.", "tmuxDetach": "Se détacher de la session tmux", - "terminalTitle": "Terminal - {{host}}", - "terminalWithPath": "Terminal - {{host}}:{{path}}", - "runTitle": "Exécution de {{command}} - {{host}}", "totpRequired": "Authentification à deux facteurs requise", "totpCodeLabel": "Code de vérification", "totpVerify": "Vérifier", @@ -1148,109 +1129,20 @@ } }, "transfer": { - "copyToHost": "Copier vers l’hôte…", - "moveToHost": "Déplacer vers l’hôte…", - "copyItemsToHost": "Copier {{count}} éléments vers l’hôte…", - "moveItemsToHost": "Déplacer {{count}} éléments vers l’hôte…", - "noHostsConnected": "Aucun autre hôte de gestionnaire de fichiers disponible.", - "noHostsConnectedHint": "Ajoutez un autre hôte SSH avec le gestionnaire de fichiers activé dans le gestionnaire d’hôtes.", - "selectDestinationHost": "Sélectionner l’hôte de destination", - "destinationPath": "Chemin de destination", - "recentDestinations": "Destinations récentes", "collapseRecentDestinations": "Réduire les destinations récentes", "expandRecentDestinations": "Développer les destinations récentes", - "browseFolders": "Parcourir les dossiers de destination", "browseDestination": "Parcourir ou saisir un chemin", - "confirmCopy": "Copier", - "confirmMove": "Déplacer", "transferring": "Transfert en cours…", - "progressVerifying": "Vérification de l'intégrité du fichier…", - "progressBenchmarking": "Sélection de l'itinéraire de transfert le plus rapide…", "compressing": "Compression en cours…", "extracting": "Extraction en cours…", "transferringItems": "Transfert de {{current}} sur {{total}} éléments…", - "transferSuccess": "Transfert terminé", - "transferError": "Échec du transfert", "transferPartial": "Transfert terminé avec {{count}} erreurs", - "transferPartialHint": "Impossible de transférer : {{paths}}", - "itemsSummary": "{{count}} éléments", - "destMustBeDirectory": "La destination doit être un dossier pour les transferts de plusieurs éléments", "selectThisFolder": "Sélectionner ce dossier", - "browsePathWillBeCreated": "Ce dossier n’existe pas encore. Il sera créé au début du transfert.", - "browsePathError": "Impossible d’ouvrir ce chemin sur l’hôte de destination.", - "goUp": "Remonter", - "copyFolderToHost": "Copier le dossier vers l’hôte…", - "moveFolderToHost": "Déplacer le dossier vers l’hôte…", - "hostReady": "Prêt", - "hostConnecting": "Connexion en cours…", - "hostDisconnected": "Non connecté", - "hostAuthRequired": "Authentification requise — ouvrez d’abord le gestionnaire de fichiers sur cet hôte", - "hostConnectionFailed": "Échec de la connexion", "metricsTitle": "Durées de transfert", - "metricsPrepare": "Préparation de la destination : {{duration}}", - "metricsCompress": "Compression sur la source : {{duration}}", "metricsHopSourceRead": "Source → serveur : {{throughput}}", "metricsHopDestSftpWrite": "Serveur → dest (SFTP) : {{throughput}}", "metricsHopDestLocalWrite": "Serveur → dest (local) : {{throughput}}", - "metricsTransfer": "De bout en bout : {{throughput}} ({{duration}})", - "metricsExtract": "Extraction sur la destination : {{duration}}", - "metricsVerify": "Vérification SHA-256 : {{duration}}", - "metricsRouteBenchmark": "Sonde d'itinéraire — direct : {{direct}}, relais : {{relay}}", - "metricsSourceDelete": "Suppression depuis la source : {{duration}}", - "metricsTotal": "Total : {{duration}}", - "progressCompressing": "Compression sur l’hôte source…", - "progressExtracting": "Extraction sur la destination…", - "progressTransferring": "Transfert des données…", - "progressReconnecting": "Reconnexion…", - "parallelSegmentsLabel": "Voies de transfert parallèles", - "parallelSegmentsOption": "{{count}} voies", - "parallelSegmentsHint": "Les fichiers volumineux sont divisés en segments de 256 Mo. Les voies multiples utilisent des connexions distinctes (comme lancer plusieurs transferts) pour un débit total plus élevé.", - "progressTotalSpeed": "{{speed}} au total ({{lanes}} voies)", - "progressTransferringItems": "Transfert des fichiers ({{current}} sur {{total}})…", - "progressBytes": "{{transferred}} / {{total}}", - "progressItems": "{{current}} / {{total}} fichiers", - "sourceNotDeletedPartial": "Fichiers sources conservés (transfert partiel)", - "jumpHostLimitation": "Les deux hôtes doivent être accessibles depuis le serveur Termix. Le routage direct d’hôte à hôte n’est pas pris en charge.", - "cancel": "Annuler", - "methodLabel": "Méthode de transfert", - "methodAuto": "Auto", - "methodTar": "Archive tar", - "methodItemSftp": "SFTP par fichier", - "methodAutoHint": "Choisit l’archive tar ou le SFTP par fichier selon le nombre de fichiers, leur taille et leur compressibilité. Les fichiers uniques utilisent toujours le SFTP en continu (streaming).", - "methodTarHint": "Compresse sur la source, transfère une archive, extrait sur la destination. Nécessite tar sur les deux hôtes Unix.", - "methodItemSftpHint": "Transfère chaque fichier individuellement via SFTP. Fonctionne sur tous les hôtes, y compris Windows.", - "methodPreviewLoading": "Calcul de la méthode de transfert…", - "methodPreviewError": "Impossible de prévisualiser la méthode de transfert. Le serveur choisira tout de même une méthode au lancement.", - "methodPreviewWillUseTar": "Utilisera : Archive tar", - "methodPreviewWillUseItemSftp": "Utilisera : SFTP par fichier", - "methodPreviewScanSummary": "{{fileCount}} fichiers, {{totalSize}} au total (analysés sur l’hôte source).", - "methodItemSftpLimitation": "Chaque fichier utilise le même flux SFTP qu’une copie de fichier unique, l’un après l’autre. La progression est combinée pour tous les fichiers, donc la barre avance lentement lors de gros fichiers.", - "methodReason": { - "user_item_sftp": "Vous avez choisi SFTP par fichier.", - "user_tar": "Vous avez choisi l'archive tar.", - "tar_unavailable": "Tar n'est pas disponible sur l'un ou les deux hôtes — SFTP par fichier sera utilisé à la place.", - "windows_host": "Un hôte Windows est impliqué — tar n'est pas utilisé.", - "auto_multi_large": "Auto : plusieurs fichiers dont un fichier volumineux ({{largestSize}}) avec des données compressibles — tar regroupe en un seul transfert.", - "auto_single_large_in_archive": "Auto : un fichier volumineux ({{largestSize}}) dans cet ensemble — SFTP par fichier.", - "auto_many_incompressible": "Auto : données principalement incompressibles — SFTP par fichier.", - "auto_many_files": "Auto : nombreux fichiers ({{fileCount}}) — tar réduit la surcharge par fichier.", - "auto_default": "Auto : SFTP par fichier pour cet ensemble." - }, - "progressCancel": "Annuler", - "progressCancelling": "Annulation en cours…", - "progressStalled": "Bloqué", - "resumedHint": "Reconnecté à un transfert actif démarré dans une autre fenêtre.", - "transferCancelled": "Transfert annulé", - "transferCancelledCopyHint": "Des fichiers partiels peuvent subsister sur la destination.", - "transferCancelledMoveHint": "Des fichiers partiels peuvent subsister sur la destination. Les fichiers sources n'ont pas été supprimés.", - "cleanupDestFiles": "Nettoyer la destination", - "cleanupDestFilesSuccess": "Fichiers partiels supprimés de la destination", - "cleanupDestFilesPartial": "Certains fichiers partiels n'ont pas pu être supprimés", - "cleanupDestFilesNothing": "Rien à nettoyer sur la destination", - "cleanupDestFilesError": "Échec du nettoyage", - "retryTransfer": "Réessayer", - "retryTransferError": "Échec de la nouvelle tentative", - "transferFailedRetryHint": "Des données partielles ont été conservées sur la destination. La nouvelle tentative reprendra lorsque la connexion sera rétablie." + "sourceNotDeletedPartial": "Fichiers sources conservés (transfert partiel)" }, "tunnels": { "connect": "Connecter", @@ -1261,8 +1153,6 @@ "clientTunnel": "Tunnel client", "addClientTunnel": "Ajouter un tunnel client", "active": "Actif", - "start": "Démarrer", - "stop": "Arrêter", "typeServerLocalDesc": "De l’hôte actuel vers le point de terminaison.", "typeServerRemoteDesc": "Du point de terminaison vers l’hôte actuel.", "typeClientLocalDesc": "De l’ordinateur local vers le point de terminaison.", @@ -1374,8 +1264,7 @@ "resetCodeRateLimitedWithTime": "Limitation de débit : trop de tentatives de vérification. Veuillez patienter {{time}} secondes avant de réessayer.", "authTokenSaveFailed": "Échec de l'enregistrement du jeton d'authentification", "authTokenMissing": "Le serveur n'a pas renvoyé de nouveau jeton d'authentification. Veuillez vous reconnecter.", - "failedToLoadServer": "Échec du chargement du serveur", - "remoteServerRequired": "Serveur distant requis. Connectez un serveur distant dans les paramètres pour utiliser ce type de connexion." + "failedToLoadServer": "Échec du chargement du serveur" }, "messages": { "registrationDisabled": "L'inscription de nouveaux comptes est actuellement désactivée par un administrateur. Veuillez vous connecter ou contacter un administrateur.", @@ -1831,7 +1720,6 @@ "protocolLabel": "Protocole", "domainLabel": "Domaine", "domainPlaceholder": "facultatif", - "connectToTerminal": "Se connecter au terminal", "connectToFiles": "Se connecter aux fichiers" }, "splitScreen": { diff --git a/src/ui/locales/translated/he_IL.json b/src/ui/locales/translated/he_IL.json index 3f7e781f6..4cd7a8919 100644 --- a/src/ui/locales/translated/he_IL.json +++ b/src/ui/locales/translated/he_IL.json @@ -324,10 +324,6 @@ "appearanceIntro": "בחרו ערכת נושא, צבע הדגשה ושפה. ניתן לשנות את שלושתם מאוחר יותר בהגדרות.", "featuresTitle": "מה עוד עושה טרמיקס", "featuresIntro": "כל שרת שתשמרו ניתן לפתוח ביותר מטרמינל אחד. הנה מה שמחכה מאחורי הסמלים משמאל.", - "feature_files": "מנהל הקבצים", - "feature_files_desc": "דפדף, העלה, הורד וערוך קבצים דרך SFTP מבלי לצאת מהאפליקציה.", - "feature_tunnels": "מנהרות", - "feature_tunnels_desc": "העברת פורטים דרך שרת כדי להגיע לשירותים שאינם חשופים.", "feature_snippets": "קטעי טקסט", "feature_snippets_desc": "שמור פקודות שאתה מפעיל לעתים קרובות ושלח אותן למסוף בלחיצה אחת.", "featuresRailHint": "לא צריך אחד מאלה? הסתר כל סמל בסרגל הצד בהגדרות, תחת ניווט.", @@ -449,7 +445,6 @@ "passwordSaved": "הסיסמה נשמרה, הקלד כדי לשנות", "key": "מַפְתֵחַ", "credential": "תְעוּדָה", - "none": "אַף לֹא אֶחָד", "sshPrivateKey": "מפתח פרטי SSH", "keyType": "סוג מפתח", "uploadFile": "העלאת קובץ", @@ -611,17 +606,12 @@ "keepaliveIntervalLabel": "מרווח זמן שמירה (שניות)", "maxKeepaliveMisses": "מקס קיפלייב מחמיץ", "sameHost": "מארח זה (מנהרה ישירה)", - "bindHost": "מארח קשירה", "connectionToolbar": "סרגל הכלים לחיבור", "showConnectionToolbar": "הצג סרגל הכלים של החיבור", "showConnectionToolbarDesc": "הצג את סרגל הכלים בהפעלות SSH, RDP, VNC ו-Telnet של מחשב מארח זה. ניתן גם להסתיר אותו באופן זמני מסרגל הכלים עצמו.", "proxmoxLastSyncStatus": { "success": "הַצלָחָה" }, - "proxmoxGuestsSelected_one": "{{count}} אורח — {{selected}} נבחר", - "proxmoxGuestsSelected_other": "{{count}} אורחים — {{selected}} נבחרו", - "proxmoxImportButton_one": "ייבוא מארח {{count}}", - "proxmoxImportButton_other": "ייבוא מארחים {{count}}", "proxmoxResultSkippedNoIp": "{{count}} דילג (לא נמצאה כתובת IP)", "proxmoxStatsUrlCopied": "כתובת האתר של סטטיסטיקות Proxmox הועתקה ללוח", "copyProxmoxStatsUrlAction": "העתק כתובת URL של סטטיסטיקות Proxmox", @@ -896,13 +886,11 @@ "updatedCount": "מארחים מעודכנים {{count}}", "friendlyNameLabel": "שם ידידותי", "descriptionLabel": "תֵאוּר", - "loadingHost": "טוען מארח...", "loadingHosts": "טוען מארחים...", "loadingCredentials": "טוען אישורים...", "noHostsYet": "עדיין אין מארחים", "noHostsYetHint": "הוסף שרת כדי לפתוח טרמינלים, לעיין בקבצים ולראות מדדים.", "noHostsMatchSearch": "אין מארחים התואמים את החיפוש שלך", - "hostNotFound": "המארח לא נמצא", "searchHosts": "חיפוש מארחים...", "sortHosts": "מיין מארחים", "sortDefault": "סדר ברירת מחדל", @@ -925,7 +913,6 @@ "filterAuthKey": "מפתח SSH", "filterAuthCredential": "תְעוּדָה", "filterAuthNone": "אַף לֹא אֶחָד", - "filterAuthOpkssh": "אופקש", "filterAuthStepca": "שלב CA", "filterProtocolGroup": "פּרוֹטוֹקוֹל", "filterProtocolSsh": "SSH", @@ -1114,13 +1101,7 @@ "connect": "התחברות למארח", "clear": "בָּרוּר", "paste": "לְהַדבִּיק", - "connected": "מְחוּבָּר", - "clipboardWriteFailed": "ההעתקה ללוח נכשלה. ודא שהדף מוגש דרך HTTPS או localhost.", - "clipboardReadFailed": "הקריאה מהלוח נכשלה. ודא שהרשאות הלוח ניתנות.", "tmuxDetach": "ניתוק מסשן tmux", - "terminalTitle": "טרמינל - {{host}}", - "terminalWithPath": "טרמינל - {{host}}:{{path}}", - "runTitle": "ריצה {{command}} - {{host}}", "totpRequired": "נדרש אימות דו-שלבי", "totpCodeLabel": "קוד אימות", "totpVerify": "לְאַמֵת", @@ -1148,109 +1129,20 @@ } }, "transfer": { - "copyToHost": "העתק למארח…", - "moveToHost": "מעבר למארח…", - "copyItemsToHost": "העתק את הפריטים {{count}} לאירוח…", - "moveItemsToHost": "העבר {{count}} פריטים לאירוח…", - "noHostsConnected": "אין מארחי מנהל קבצים אחרים זמינים.", - "noHostsConnectedHint": "הוסף מארח SSH נוסף כאשר מנהל הקבצים מופעל במנהל המארחים.", - "selectDestinationHost": "בחר מארח יעד", - "destinationPath": "נתיב היעד", - "recentDestinations": "יעדים אחרונים", "collapseRecentDestinations": "כיווץ יעדים אחרונים", "expandRecentDestinations": "הרחב יעדים אחרונים", - "browseFolders": "עיון בתיקיות יעד", "browseDestination": "עיון או הזנת נתיב", - "confirmCopy": "לְהַעְתִיק", - "confirmMove": "מַהֲלָך", "transferring": "מעביר…", - "progressVerifying": "אימות שלמות הקובץ…", - "progressBenchmarking": "בחירת נתיב ההעברה המהיר ביותר…", "compressing": "דחיסת…", "extracting": "מחלץ…", "transferringItems": "העברת {{current}} מתוך {{total}} פריטים…", - "transferSuccess": "ההעברה הושלמה", - "transferError": "ההעברה נכשלה", "transferPartial": "ההעברה הושלמה עם שגיאות {{count}}", - "transferPartialHint": "לא ניתן היה להעביר: {{paths}}", - "itemsSummary": "פריטים {{count}}", - "destMustBeDirectory": "היעד חייב להיות ספרייה עבור העברות מרובות פריטים", "selectThisFolder": "בחר תיקייה זו", - "browsePathWillBeCreated": "תיקייה זו עדיין לא קיימת. היא תיווצר כאשר ההעברה תתחיל.", - "browsePathError": "לא ניתן היה לפתוח נתיב זה במארח היעד.", - "goUp": "לַעֲלוֹת", - "copyFolderToHost": "העתקת תיקייה למארח…", - "moveFolderToHost": "העברת תיקייה למארח…", - "hostReady": "מוּכָן", - "hostConnecting": "חיבור…", - "hostDisconnected": "לא מחובר", - "hostAuthRequired": "נדרש אימות - פתח תחילה את מנהל הקבצים במארח זה", - "hostConnectionFailed": "החיבור נכשל", "metricsTitle": "זמני העברה", - "metricsPrepare": "הכנת יעד: {{duration}}", - "metricsCompress": "דחיסה במקור: {{duration}}", "metricsHopSourceRead": "מקור → שרת: {{throughput}}", "metricsHopDestSftpWrite": "שרת → יעד (SFTP): {{throughput}}", "metricsHopDestLocalWrite": "שרת → יעד (מקומי): {{throughput}}", - "metricsTransfer": "מקצה לקצה: {{throughput}} ({{duration}})", - "metricsExtract": "חילוץ ביעד: {{duration}}", - "metricsVerify": "SHA-256 אומת: {{duration}}", - "metricsRouteBenchmark": "גשש מסלול — ישיר: {{direct}}, ממסר: {{relay}}", - "metricsSourceDelete": "הסר מהמקור: {{duration}}", - "metricsTotal": "סה\"כ: {{duration}}", - "progressCompressing": "דחיסה במארח המקור…", - "progressExtracting": "מחלץ ביעד…", - "progressTransferring": "העברת נתונים…", - "progressReconnecting": "מתחבר מחדש…", - "parallelSegmentsLabel": "נתיבי מעבר מקבילים", - "parallelSegmentsOption": "נתיבים {{count}}", - "parallelSegmentsHint": "קבצים גדולים מחולקים לחתיכות של 256 מגה-בייט. מספר נתיבים משתמשים בחיבורים נפרדים (כמו התחלת מספר העברות) לקבלת תפוקה כוללת גבוהה יותר.", - "progressTotalSpeed": "סה\"כ {{speed}} (נתיבים{{lanes}})", - "progressTransferringItems": "העברת קבצים ({{current}} מתוך {{total}})…", - "progressBytes": "{{transferred}} / {{total}}", - "progressItems": "קבצים {{current}} / {{total}}", - "sourceNotDeletedPartial": "קבצי המקור נשמרו (העברה חלקית)", - "jumpHostLimitation": "שני המארחים חייבים להיות נגישים משרת Termix. ניתוב ישיר ממארח למארח אינו נתמך.", - "cancel": "לְבַטֵל", - "methodLabel": "שיטת העברה", - "methodAuto": "אוטומטי", - "methodTar": "ארכיון טאר", - "methodItemSftp": "SFTP לפי קובץ", - "methodAutoHint": "בוחר SFTP לפי קובץ או tar בהתבסס על ספירת הקבצים, גודלם ויכולת הדחיסה. קבצים בודדים תמיד משתמשים ב-SFTP בסטרימינג.", - "methodTarHint": "דחיסה במקור, העברת ארכיון אחד, חילוץ ביעד. דורש tar בשני מארחי יוניקס.", - "methodItemSftpHint": "העבר כל קובץ בנפרד דרך SFTP. עובד על כל המארחים כולל Windows.", - "methodPreviewLoading": "חישוב שיטת ההעברה…", - "methodPreviewError": "לא ניתן היה להציג תצוגה מקדימה של שיטת ההעברה. השרת עדיין יבחר שיטה כשתתחיל.", - "methodPreviewWillUseTar": "אשתמש ב: ארכיון Tar", - "methodPreviewWillUseItemSftp": "ישתמש ב: SFTP לפי קובץ", - "methodPreviewScanSummary": "{{fileCount}} קבצים, {{totalSize}} סה\"כ (נסרק במארח המקור).", - "methodItemSftpLimitation": "כל קובץ משתמש באותו זרם SFTP כעותק של קובץ בודד, אחד אחרי השני. ההתקדמות משולבת על פני כל הקבצים, כך שהסרגל נע לאט במהלך קבצים גדולים.", - "methodReason": { - "user_item_sftp": "בחרת SFTP לפי קובץ.", - "user_tar": "בחרת בארכיון tar.", - "tar_unavailable": "Tar אינו זמין באחד המארחים או בשניהם - במקום זאת ייעשה שימוש ב-SFTP לפי קובץ.", - "windows_host": "מחשב מארח של Windows מעורב - tar אינו בשימוש.", - "auto_multi_large": "אוטומטי: קבצים מרובים כולל קובץ גדול ({{largestSize}}) עם נתונים דחוסים - tar מאחד את הנתונים להעברה אחת.", - "auto_single_large_in_archive": "אוטומטי: קובץ גדול אחד ({{largestSize}}) בקבוצה זו - SFTP לכל קובץ.", - "auto_many_incompressible": "אוטומטי: נתונים לרוב בלתי ניתנים לדחיסה - SFTP לכל קובץ.", - "auto_many_files": "אוטומטי: קבצים רבים ({{fileCount}}) — tar מפחית את התקורה של כל קובץ.", - "auto_default": "אוטומטי: SFTP לכל קובץ עבור קבוצה זו." - }, - "progressCancel": "לְבַטֵל", - "progressCancelling": "מבטל…", - "progressStalled": "אָבוּס", - "resumedHint": "התחבר מחדש להעברה פעילה שהתחילה בחלון אחר.", - "transferCancelled": "ההעברה בוטלה", - "transferCancelledCopyHint": "ייתכן שיישארו קבצים חלקיים ביעד.", - "transferCancelledMoveHint": "ייתכן שיישארו קבצים חלקיים ביעד. קבצי המקור לא הוסרו.", - "cleanupDestFiles": "יעד ניקוי", - "cleanupDestFilesSuccess": "הוסרו קבצים חלקיים מהיעד", - "cleanupDestFilesPartial": "לא ניתן היה להסיר חלק מהקבצים", - "cleanupDestFilesNothing": "אין מה לנקות ביעד", - "cleanupDestFilesError": "הניקוי נכשל", - "retryTransfer": "נסה שוב", - "retryTransferError": "ניסיון חוזר נכשל", - "transferFailedRetryHint": "נתונים חלקיים נשמרו ביעד. ניסיון חוזר יחודש כאשר החיבור יחזור." + "sourceNotDeletedPartial": "קבצי המקור נשמרו (העברה חלקית)" }, "tunnels": { "connect": "לְחַבֵּר", @@ -1261,8 +1153,6 @@ "clientTunnel": "מנהרת לקוח", "addClientTunnel": "הוסף מנהרת לקוח", "active": "פָּעִיל", - "start": "הַתחָלָה", - "stop": "לְהַפְסִיק", "typeServerLocalDesc": "מהמארח הנוכחי לנקודת הקצה.", "typeServerRemoteDesc": "נקודת הקצה חזרה למארח הנוכחי.", "typeClientLocalDesc": "מחשב מקומי לנקודת קצה.", @@ -1374,8 +1264,7 @@ "resetCodeRateLimitedWithTime": "קצב מוגבל: יותר מדי ניסיונות אימות. אנא המתן {{time}} שניות לפני שתנסה שוב.", "authTokenSaveFailed": "נכשלה שמירת אסימון האימות", "authTokenMissing": "השרת לא החזיר אסימון אימות חדש. אנא היכנס שוב.", - "failedToLoadServer": "טעינת השרת נכשלה", - "remoteServerRequired": "נדרש שרת מרוחק. יש להתחבר לשרת מרוחק בהגדרות כדי להשתמש בסוג חיבור זה." + "failedToLoadServer": "טעינת השרת נכשלה" }, "messages": { "registrationDisabled": "רישום חשבון חדש מושבת כעת על ידי מנהל. אנא התחבר או צור קשר עם מנהל.", @@ -1831,7 +1720,6 @@ "protocolLabel": "פּרוֹטוֹקוֹל", "domainLabel": "תְחוּם", "domainPlaceholder": "אופציונלי", - "connectToTerminal": "התחברות לטרמינל", "connectToFiles": "התחברות לקבצים" }, "splitScreen": { diff --git a/src/ui/locales/translated/hi_IN.json b/src/ui/locales/translated/hi_IN.json index 9afae74db..cbe3b6e1e 100644 --- a/src/ui/locales/translated/hi_IN.json +++ b/src/ui/locales/translated/hi_IN.json @@ -324,10 +324,6 @@ "appearanceIntro": "एक थीम, एक एक्सेंट कलर और अपनी भाषा चुनें। इन तीनों को बाद में सेटिंग्स में बदला जा सकता है।", "featuresTitle": "टर्मिक्स और क्या करता है?", "featuresIntro": "आपके द्वारा सहेजे गए प्रत्येक सर्वर को टर्मिनल के अलावा अन्य माध्यमों में भी खोला जा सकता है। बाईं ओर के आइकनों के पीछे क्या है, यह नीचे दिया गया है।", - "feature_files": "फ़ाइल मैनेजर", - "feature_files_desc": "ऐप छोड़े बिना SFTP के माध्यम से फाइलों को ब्राउज़ करें, अपलोड करें, डाउनलोड करें और संपादित करें।", - "feature_tunnels": "सुरंगों", - "feature_tunnels_desc": "सर्वर के माध्यम से पोर्ट को फॉरवर्ड करके उन सेवाओं तक पहुंचें जो उपलब्ध नहीं हैं।", "feature_snippets": "स्निपेट्स", "feature_snippets_desc": "आप जिन कमांड्स को अक्सर चलाते हैं उन्हें सेव करें और एक क्लिक में उन्हें टर्मिनल पर भेजें।", "featuresRailHint": "इनमें से किसी आइकन की आवश्यकता नहीं है? सेटिंग में जाकर नेविगेशन के अंतर्गत साइडबार से किसी भी आइकन को छिपा दें।", @@ -449,7 +445,6 @@ "passwordSaved": "पासवर्ड सहेज लिया गया है, बदलने के लिए टाइप करें", "key": "कुंजी", "credential": "क्रेडेंशियल", - "none": "कोई नहीं", "sshPrivateKey": "SSH निजी कुंजी", "keyType": "कुंजी प्रकार", "uploadFile": "फ़ाइल अपलोड करें", @@ -611,17 +606,12 @@ "keepaliveIntervalLabel": "कीपअलाइव अंतराल (सेकंड)", "maxKeepaliveMisses": "अधिकतम कीपअलाइव मिस", "sameHost": "यह होस्ट (डायरेक्ट टनल)", - "bindHost": "बाइंड होस्ट", "connectionToolbar": "कनेक्शन टूलबार", "showConnectionToolbar": "कनेक्शन टूलबार दिखाएँ", "showConnectionToolbarDesc": "इस होस्ट के SSH, RDP, VNC और Telnet सेशन में टूलबार दिखाएँ। आप इसे टूलबार से अस्थायी रूप से छिपा भी सकते हैं।", "proxmoxLastSyncStatus": { "success": "सफलता" }, - "proxmoxGuestsSelected_one": "{{count}} अतिथि — {{selected}} चयनित", - "proxmoxGuestsSelected_other": "{{count}} अतिथि — {{selected}} चयनित", - "proxmoxImportButton_one": "{{count}} होस्ट आयात करें", - "proxmoxImportButton_other": "{{count}} होस्ट आयात करें", "proxmoxResultSkippedNoIp": "{{count}} को छोड़ दिया गया (कोई आईपी नहीं मिला)", "proxmoxStatsUrlCopied": "Proxmox Stats URL क्लिपबोर्ड पर कॉपी हो गया है", "copyProxmoxStatsUrlAction": "Proxmox Stats URL कॉपी करें", @@ -896,13 +886,11 @@ "updatedCount": "{{count}} होस्ट अपडेट किए गए", "friendlyNameLabel": "अनुकूल नाम", "descriptionLabel": "विवरण", - "loadingHost": "होस्ट लोड हो रहा है...", "loadingHosts": "होस्ट लोड हो रहे हैं...", "loadingCredentials": "क्रेडेंशियल लोड हो रहे हैं...", "noHostsYet": "अभी तक कोई होस्ट नहीं है", "noHostsYetHint": "टर्मिनल खोलने, फाइलों को ब्राउज़ करने और मेट्रिक्स देखने के लिए एक सर्वर जोड़ें।", "noHostsMatchSearch": "आपकी खोज से मेल खाने वाले कोई होस्ट नहीं हैं", - "hostNotFound": "होस्ट नहीं मिला", "searchHosts": "होस्ट खोजें...", "sortHosts": "होस्ट क्रमबद्ध करें", "sortDefault": "डिफ़ॉल्ट क्रम", @@ -925,7 +913,6 @@ "filterAuthKey": "SSH कुंजी", "filterAuthCredential": "क्रेडेंशियल", "filterAuthNone": "कोई नहीं", - "filterAuthOpkssh": "OPKSSH", "filterAuthStepca": "स्टेप सीए", "filterProtocolGroup": "प्रोटोकॉल", "filterProtocolSsh": "SSH", @@ -1114,13 +1101,7 @@ "connect": "होस्ट से कनेक्ट करें", "clear": "साफ़ करें", "paste": "चिपकाएँ", - "connected": "कनेक्टेड", - "clipboardWriteFailed": "क्लिपबोर्ड पर कॉपी करने में विफल। सुनिश्चित करें कि पेज HTTPS या लोकलहोस्ट पर सर्व किया गया है।", - "clipboardReadFailed": "क्लिपबोर्ड से पढ़ने में विफल। सुनिश्चित करें कि क्लिपबोर्ड अनुमतियाँ दी गई हैं।", "tmuxDetach": "tmux सत्र से डिटैच करें", - "terminalTitle": "टर्मिनल - {{host}}", - "terminalWithPath": "टर्मिनल - {{host}}:{{path}}", - "runTitle": "{{command}} चल रहा है - {{host}}", "totpRequired": "दो-कारक प्रमाणीकरण आवश्यक है", "totpCodeLabel": "सत्यापन कोड", "totpVerify": "सत्यापित करें", @@ -1148,109 +1129,20 @@ } }, "transfer": { - "copyToHost": "होस्ट पर कॉपी करें…", - "moveToHost": "होस्ट पर ले जाएँ…", - "copyItemsToHost": "{{count}} आइटम होस्ट पर कॉपी करें…", - "moveItemsToHost": "{{count}} आइटम होस्ट पर स्थानांतरित करें…", - "noHostsConnected": "कोई अन्य फ़ाइल प्रबंधक होस्ट उपलब्ध नहीं है।", - "noHostsConnectedHint": "होस्ट प्रबंधक में फ़ाइल प्रबंधक सक्षम किए हुए एक और SSH होस्ट जोड़ें।", - "selectDestinationHost": "गंतव्य होस्ट चुनें", - "destinationPath": "गंतव्य पथ", - "recentDestinations": "हाल के गंतव्य", "collapseRecentDestinations": "हाल के गंतव्य संकुचित करें", "expandRecentDestinations": "हाल के गंतव्य विस्तारित करें", - "browseFolders": "गंतव्य फ़ोल्डर ब्राउज़ करें", "browseDestination": "पथ ब्राउज़ करें या दर्ज करें", - "confirmCopy": "कॉपी करें", - "confirmMove": "स्थानांतरित करें", "transferring": "स्थानांतरित हो रहा है…", - "progressVerifying": "फ़ाइल की अखंडता का सत्यापन…", - "progressBenchmarking": "सबसे तेज़ स्थानांतरण मार्ग का चयन करना…", "compressing": "संपीड़ित किया जा रहा है…", "extracting": "निकाला जा रहा है…", "transferringItems": "{{total}} में से {{current}} आइटम स्थानांतरित हो रहे हैं…", - "transferSuccess": "स्थानांतरण पूर्ण", - "transferError": "स्थानांतरण विफल", "transferPartial": "स्थानांतरण {{count}} त्रुटियों के साथ पूर्ण हुआ", - "transferPartialHint": "स्थानांतरित नहीं किया जा सका: {{paths}}", - "itemsSummary": "{{count}} आइटम", - "destMustBeDirectory": "कई आइटम स्थानांतरण के लिए गंतव्य एक निर्देशिका होना चाहिए", "selectThisFolder": "यह फ़ोल्डर चुनें", - "browsePathWillBeCreated": "यह फ़ोल्डर अभी मौजूद नहीं है। स्थानांतरण शुरू होने पर इसे बनाया जाएगा।", - "browsePathError": "गंतव्य होस्ट पर यह पथ नहीं खोला जा सका।", - "goUp": "ऊपर जाएं", - "copyFolderToHost": "फ़ोल्डर होस्ट पर कॉपी करें…", - "moveFolderToHost": "फ़ोल्डर होस्ट पर स्थानांतरित करें…", - "hostReady": "तैयार", - "hostConnecting": "कनेक्ट हो रहा है…", - "hostDisconnected": "कनेक्ट नहीं है", - "hostAuthRequired": "प्रमाणीकरण आवश्यक है — पहले इस होस्ट पर फ़ाइल प्रबंधक खोलें", - "hostConnectionFailed": "कनेक्शन विफल", "metricsTitle": "स्थानांतरण समय", - "metricsPrepare": "गंतव्य तैयारी: {{duration}}", - "metricsCompress": "स्रोत पर संपीड़न: {{duration}}", "metricsHopSourceRead": "स्रोत → सर्वर: {{throughput}}", "metricsHopDestSftpWrite": "सर्वर → गंतव्य (SFTP): {{throughput}}", "metricsHopDestLocalWrite": "सर्वर → गंतव्य (स्थानीय): {{throughput}}", - "metricsTransfer": "एंड-टू-एंड: {{throughput}} ({{duration}})", - "metricsExtract": "गंतव्य पर निष्कर्षण: {{duration}}", - "metricsVerify": "SHA-256 सत्यापित: {{duration}}", - "metricsRouteBenchmark": "रूट प्रोब — डायरेक्ट: {{direct}}, रिले: {{relay}}", - "metricsSourceDelete": "स्रोत से हटाना: {{duration}}", - "metricsTotal": "कुल: {{duration}}", - "progressCompressing": "स्रोत होस्ट पर संपीड़ित कर रहा है…", - "progressExtracting": "गंतव्य पर निष्कर्षण कर रहा है…", - "progressTransferring": "डेटा स्थानांतरित कर रहा है…", - "progressReconnecting": "पुनः कनेक्ट हो रहा है…", - "parallelSegmentsLabel": "समानांतर स्थानांतरण लेन", - "parallelSegmentsOption": "{{count}} लेन", - "parallelSegmentsHint": "बड़ी फ़ाइलें 256 MB टुकड़ों में विभाजित होती हैं। एकाधिक लेन उच्च कुल थ्रूपुट के लिए अलग-अलग कनेक्शन का उपयोग करती हैं (जैसे कई स्थानांतरण प्रारंभ करना)।", - "progressTotalSpeed": "{{speed}} कुल ({{lanes}} लेन)", - "progressTransferringItems": "फ़ाइलें स्थानांतरित कर रहा है ({{current}} / {{total}})…", - "progressBytes": "{{transferred}} / {{total}}", - "progressItems": "{{current}} / {{total}} फ़ाइलें", - "sourceNotDeletedPartial": "स्रोत फ़ाइलें रखी गईं (आंशिक स्थानांतरण)", - "jumpHostLimitation": "दोनों होस्ट Termix सर्वर से पहुँच योग्य होने चाहिए। सीधा होस्ट-से-होस्ट रूटिंग समर्थित नहीं है।", - "cancel": "रद्द करें", - "methodLabel": "स्थानांतरण विधि", - "methodAuto": "स्वचालित", - "methodTar": "Tar संग्रह", - "methodItemSftp": "प्रति-फ़ाइल SFTP", - "methodAutoHint": "फ़ाइलों की संख्या, आकार और संपीड़न क्षमता के आधार पर tar या प्रति-फ़ाइल SFTP चुनता है। एकल फ़ाइलें हमेशा स्ट्रीमिंग SFTP का उपयोग करती हैं।", - "methodTarHint": "स्रोत पर संपीड़ित करें, एक संग्रह स्थानांतरित करें, गंतव्य पर निष्कर्षण करें। दोनों यूनिक्स होस्ट पर tar आवश्यक है।", - "methodItemSftpHint": "प्रत्येक फ़ाइल को SFTP पर अलग-अलग स्थानांतरित करें। विंडोज़ सहित सभी होस्ट पर काम करता है।", - "methodPreviewLoading": "स्थानांतरण विधि की गणना कर रहा है…", - "methodPreviewError": "स्थानांतरण विधि का पूर्वावलोकन नहीं किया जा सका। प्रारंभ करने पर सर्वर फिर भी एक विधि चुनेगा।", - "methodPreviewWillUseTar": "उपयोग करेगा: Tar संग्रह", - "methodPreviewWillUseItemSftp": "उपयोग करेगा: प्रति-फ़ाइल SFTP", - "methodPreviewScanSummary": "{{fileCount}} फ़ाइलें, कुल {{totalSize}} (स्रोत होस्ट पर स्कैन किया गया)।", - "methodItemSftpLimitation": "प्रत्येक फ़ाइल एक-एक करके एकल-फ़ाइल प्रतिलिपि के रूप में समान SFTP स्ट्रीम का उपयोग करती है। सभी फ़ाइलों में प्रगति संयुक्त होती है, इसलिए बड़ी फ़ाइलों के दौरान बार धीरे-धीरे चलता है।", - "methodReason": { - "user_item_sftp": "आपने प्रति-फ़ाइल SFTP चुना।", - "user_tar": "आपने tar संग्रह चुना।", - "tar_unavailable": "Tar एक या दोनों होस्ट पर उपलब्ध नहीं है — इसके बजाय प्रति-फ़ाइल SFTP का उपयोग किया जाएगा।", - "windows_host": "कोई Windows होस्ट शामिल है — tar का उपयोग नहीं होता।", - "auto_multi_large": "ऑटो: संपीड़न योग्य डेटा वाली एक बड़ी फ़ाइल ({{largestSize}}) सहित अनेक फ़ाइलें — tar एकल स्थानांतरण में बंडल करता है।", - "auto_single_large_in_archive": "ऑटो: इस सेट में एक बड़ी फ़ाइल ({{largestSize}}) — प्रति-फ़ाइल SFTP।", - "auto_many_incompressible": "ऑटो: अधिकतर असंपीड़नीय डेटा — प्रति-फ़ाइल SFTP।", - "auto_many_files": "ऑटो: बहुत सारी फ़ाइलें ({{fileCount}}) — tar प्रति-फ़ाइल ओवरहेड कम करता है।", - "auto_default": "ऑटो: इस सेट के लिए प्रति-फ़ाइल SFTP।" - }, - "progressCancel": "रद्द करें", - "progressCancelling": "रद्द कर रहा है…", - "progressStalled": "रुका हुआ", - "resumedHint": "किसी अन्य विंडो में शुरू हुए सक्रिय स्थानांतरण से पुनः जुड़ा।", - "transferCancelled": "स्थानांतरण रद्द किया गया।", - "transferCancelledCopyHint": "आंशिक फ़ाइलें गंतव्य पर रह सकती हैं।", - "transferCancelledMoveHint": "आंशिक फ़ाइलें गंतव्य पर रह सकती हैं। स्रोत फ़ाइलें नहीं हटाई गईं।", - "cleanupDestFiles": "गंतव्य साफ करें", - "cleanupDestFilesSuccess": "गंतव्य से आंशिक फ़ाइलें हटा दी गईं।", - "cleanupDestFilesPartial": "कुछ आंशिक फ़ाइलें नहीं हटाई जा सकीं।", - "cleanupDestFilesNothing": "गंतव्य पर साफ करने के लिए कुछ नहीं।", - "cleanupDestFilesError": "सफाई विफल रही।", - "retryTransfer": "पुनः प्रयास करें", - "retryTransferError": "पुनः प्रयास विफल रहा।", - "transferFailedRetryHint": "आंशिक डेटा गंतव्य पर रखा गया था। कनेक्शन वापस आने पर पुनः प्रयास फिर से शुरू होगा।" + "sourceNotDeletedPartial": "स्रोत फ़ाइलें रखी गईं (आंशिक स्थानांतरण)" }, "tunnels": { "connect": "कनेक्ट करें", @@ -1261,8 +1153,6 @@ "clientTunnel": "क्लाइंट टनल", "addClientTunnel": "क्लाइंट टनल जोड़ें", "active": "सक्रिय", - "start": "शुरू करें", - "stop": "बंद करें", "typeServerLocalDesc": "वर्तमान होस्ट से एंडपॉइंट तक।", "typeServerRemoteDesc": "एंडपॉइंट से वर्तमान होस्ट तक वापस।", "typeClientLocalDesc": "स्थानीय कंप्यूटर से एंडपॉइंट तक।", @@ -1374,8 +1264,7 @@ "resetCodeRateLimitedWithTime": "दर सीमित: बहुत अधिक सत्यापन प्रयास। कृपया पुनः प्रयास करने से पहले {{time}} सेकंड प्रतीक्षा करें।", "authTokenSaveFailed": "प्रमाणीकरण टोकन सहेजने में विफल", "authTokenMissing": "सर्वर ने नया प्रमाणीकरण टोकन नहीं भेजा। कृपया दोबारा साइन इन करें।", - "failedToLoadServer": "सर्वर लोड करने में विफल", - "remoteServerRequired": "रिमोट सर्वर आवश्यक है। इस कनेक्शन प्रकार का उपयोग करने के लिए सेटिंग्स में जाकर रिमोट सर्वर कनेक्ट करें।" + "failedToLoadServer": "सर्वर लोड करने में विफल" }, "messages": { "registrationDisabled": "नया खाता पंजीकरण वर्तमान में व्यवस्थापक द्वारा अक्षम है। कृपया लॉग इन करें या व्यवस्थापक से संपर्क करें।", @@ -1831,7 +1720,6 @@ "protocolLabel": "शिष्टाचार", "domainLabel": "कार्यक्षेत्र", "domainPlaceholder": "वैकल्पिक", - "connectToTerminal": "टर्मिनल से कनेक्ट करें", "connectToFiles": "फ़ाइलों से कनेक्ट करें" }, "splitScreen": { diff --git a/src/ui/locales/translated/hu_HU.json b/src/ui/locales/translated/hu_HU.json index 890d18396..13e35ded3 100644 --- a/src/ui/locales/translated/hu_HU.json +++ b/src/ui/locales/translated/hu_HU.json @@ -324,10 +324,6 @@ "appearanceIntro": "Válassz egy témát, egy kiemelőszínt és a nyelvet. Mindhármat később módosíthatod a Beállításokban.", "featuresTitle": "Mit csinál még a Termix?", "featuresIntro": "Minden mentett szerver megnyitható nem csak terminálban. Íme, mi vár a bal oldali ikonok mögött.", - "feature_files": "Fájlkezelő", - "feature_files_desc": "Böngésszen, töltsön fel, töltsön le és szerkeszthessen fájlokat SFTP-n keresztül az alkalmazás elhagyása nélkül.", - "feature_tunnels": "Alagutak", - "feature_tunnels_desc": "Portok továbbítása egy szerveren keresztül a nem elérhető szolgáltatások eléréséhez.", "feature_snippets": "Kódrészletek", "feature_snippets_desc": "Mentsd el a gyakran futtatott parancsokat, és küldd el őket egy terminálba egyetlen kattintással.", "featuresRailHint": "Nincs szükséged ezekre? Rejtsd el az ikonokat az oldalsávon a Beállításokban, a Navigáció alatt.", @@ -449,7 +445,6 @@ "passwordSaved": "Jelszó mentve, gépelje be a módosításhoz", "key": "Kulcsfontosságú", "credential": "Hitelesítő adat", - "none": "Egyik sem", "sshPrivateKey": "SSH privát kulcs", "keyType": "Kulcstípus", "uploadFile": "Fájl feltöltése", @@ -611,17 +606,12 @@ "keepaliveIntervalLabel": "Életben tartási időköz (másodperc)", "maxKeepaliveMisses": "Max Keepalive kihagyások", "sameHost": "Ez a gazdagép (közvetlen alagút)", - "bindHost": "Kötőállomás", "connectionToolbar": "Kapcsolat eszköztár", "showConnectionToolbar": "Kapcsolat eszköztár megjelenítése", "showConnectionToolbarDesc": "Eszköztár megjelenítése a gazdagép SSH, RDP, VNC és Telnet munkameneteiben. Ideiglenesen el is rejtheti magáról az eszköztárról.", "proxmoxLastSyncStatus": { "success": "Siker" }, - "proxmoxGuestsSelected_one": "{{count}} vendég — {{selected}} kiválasztva", - "proxmoxGuestsSelected_other": "{{count}} vendégek — {{selected}} kiválasztva", - "proxmoxImportButton_one": "Importálja a {{count}} gazdagépet", - "proxmoxImportButton_other": "{{count}} hosztok importálása", "proxmoxResultSkippedNoIp": "{{count}} kihagyva (nem található IP cím)", "proxmoxStatsUrlCopied": "Proxmox Statisztikai URL a vágólapra másolva", "copyProxmoxStatsUrlAction": "Proxmox Statisztika URL másolása", @@ -896,13 +886,11 @@ "updatedCount": "Frissített {{count}} gazdagépek", "friendlyNameLabel": "Barátságos név", "descriptionLabel": "Leírás", - "loadingHost": "Gazdagép betöltése...", "loadingHosts": "Gazdagépek betöltése...", "loadingCredentials": "Hitelesítő adatok betöltése...", "noHostsYet": "Még nincsenek házigazdák", "noHostsYetHint": "Adjon hozzá egy szervert terminálok megnyitásához, fájlok böngészéséhez és metrikák megtekintéséhez.", "noHostsMatchSearch": "Nincsenek a keresésnek megfelelő házigazdák", - "hostNotFound": "Nem található gazdagép", "searchHosts": "Gazdagépek keresése...", "sortHosts": "Gazdagépek rendezése", "sortDefault": "Alapértelmezett sorrend", @@ -925,7 +913,6 @@ "filterAuthKey": "SSH-kulcs", "filterAuthCredential": "Hitelesítő adat", "filterAuthNone": "Egyik sem", - "filterAuthOpkssh": "OPKSSH", "filterAuthStepca": "CA lépés", "filterProtocolGroup": "Jegyzőkönyv", "filterProtocolSsh": "SSH", @@ -1114,13 +1101,7 @@ "connect": "Csatlakozás a gazdagéphez", "clear": "Világos", "paste": "Paszta", - "connected": "Csatlakoztatva", - "clipboardWriteFailed": "Nem sikerült a vágólapra másolni. Győződjön meg arról, hogy az oldal HTTPS vagy localhost protokollon keresztül jelenik meg.", - "clipboardReadFailed": "Nem sikerült beolvasni a vágólapról. Győződjön meg arról, hogy a vágólapra vonatkozó engedélyek meg vannak adva.", "tmuxDetach": "Leválasztás a tmux munkamenetről", - "terminalTitle": "Terminál - {{host}}", - "terminalWithPath": "Terminál - {{host}}:{{path}}", - "runTitle": "Futás {{command}} - {{host}}", "totpRequired": "Kétfaktoros hitelesítés szükséges", "totpCodeLabel": "Ellenőrző kód", "totpVerify": "Ellenőrzés", @@ -1148,109 +1129,20 @@ } }, "transfer": { - "copyToHost": "Másolás a… gazdagépre", - "moveToHost": "Áthelyezés a… gazdagépre", - "copyItemsToHost": "Másolja a {{count}} elemet a… hosztba", - "moveItemsToHost": "Áthelyez {{count}} elemet a… tárhelyre", - "noHostsConnected": "Nincsenek más elérhető fájlkezelő gazdagépek.", - "noHostsConnectedHint": "Adjon hozzá egy másik SSH-hosztot, amelynél a Fájlkezelő engedélyezve van a Host Managerben.", - "selectDestinationHost": "Célállomás kiválasztása", - "destinationPath": "Célútvonal", - "recentDestinations": "Legutóbbi úti célok", "collapseRecentDestinations": "Legutóbbi úti célok összecsukása", "expandRecentDestinations": "Legutóbbi úti célok kibontása", - "browseFolders": "Célmappák böngészése", "browseDestination": "Böngészés vagy elérési út megadása", - "confirmCopy": "Másolat", - "confirmMove": "Mozog", "transferring": "… átvitele", - "progressVerifying": "Fájl integritásának ellenőrzése…", - "progressBenchmarking": "A leggyorsabb átszállási útvonal kiválasztása…", "compressing": "Tömörítés…", "extracting": "… kinyerése", "transferringItems": "{{current}} {{total}} elem… átvitele", - "transferSuccess": "Átvitel befejezve", - "transferError": "Átvitel sikertelen", "transferPartial": "Az átvitel {{count}} hibával fejeződött be.", - "transferPartialHint": "Nem sikerült átvinni: {{paths}}", - "itemsSummary": "{{count}} elem", - "destMustBeDirectory": "Több elem átviteléhez a célnak egy könyvtárnak kell lennie", "selectThisFolder": "Jelölje ki ezt a mappát", - "browsePathWillBeCreated": "Ez a mappa még nem létezik. Létrejön, amikor az átvitel megkezdődik.", - "browsePathError": "Nem sikerült megnyitni ezt az elérési utat a célgépen.", - "goUp": "Felmegy", - "copyFolderToHost": "Mappa másolása a… gazdagépre", - "moveFolderToHost": "Mappa áthelyezése a… gazdagépre", - "hostReady": "Kész", - "hostConnecting": "… csatlakoztatása", - "hostDisconnected": "Nincs csatlakoztatva", - "hostAuthRequired": "Hitelesítés szükséges — először nyissa meg a Fájlkezelőt ezen a gépen", - "hostConnectionFailed": "Kapcsolódás sikertelen", "metricsTitle": "Átszállási idők", - "metricsPrepare": "Célhely előkészítése: {{duration}}", - "metricsCompress": "Tömörítés forráskód szerint: {{duration}}", "metricsHopSourceRead": "Forrás → szerver: {{throughput}}", "metricsHopDestSftpWrite": "Szerver → cél (SFTP): {{throughput}}", "metricsHopDestLocalWrite": "Szerver → cél (helyi): {{throughput}}", - "metricsTransfer": "Végtől végig: {{throughput}} ({{duration}})", - "metricsExtract": "Kivonat a rendeltetési helyen: {{duration}}", - "metricsVerify": "SHA-256 ellenőrizve: {{duration}}", - "metricsRouteBenchmark": "Útvonalszonda — közvetlen: {{direct}}, relé: {{relay}}", - "metricsSourceDelete": "Eltávolítás a forrásból: {{duration}}", - "metricsTotal": "Összesen: {{duration}}", - "progressCompressing": "Tömörítés a forrásgépen…", - "progressExtracting": "Kibontás a célállomáson…", - "progressTransferring": "Adatátvitel…", - "progressReconnecting": "Újracsatlakozás…", - "parallelSegmentsLabel": "Párhuzamos átszállósávok", - "parallelSegmentsOption": "{{count}} sávok", - "parallelSegmentsHint": "A nagy fájlokat 256 MB-os darabokra osztja a rendszer. Több sáv külön kapcsolatokat használ (például több átvitel indítása) a nagyobb összátviteli sebesség érdekében.", - "progressTotalSpeed": "{{speed}} összesen ({{lanes}} sávok)", - "progressTransferringItems": "Fájlok átvitele ({{current}} / {{total}})…", - "progressBytes": "{{transferred}} / {{total}}", - "progressItems": "{{current}} / {{total}} fájlok", - "sourceNotDeletedPartial": "Forrásfájlok megtartása (részleges átvitel)", - "jumpHostLimitation": "Mindkét gépnek elérhetőnek kell lennie a Termix szerverről. A közvetlen gépközi útvonalválasztás nem támogatott.", - "cancel": "Mégsem", - "methodLabel": "Átviteli módszer", - "methodAuto": "Autó", - "methodTar": "Tar archívum", - "methodItemSftp": "Fájlonkénti SFTP", - "methodAutoHint": "A fájlok száma, mérete és tömöríthetősége alapján választja ki a tar vagy a fájlonkénti SFTP protokollt. Az egyes fájlok mindig folyamatos SFTP-t használnak.", - "methodTarHint": "Tömörítés a forráskódban, egy archívum átvitele, kibontás a célkódban. Tar fájlt igényel mindkét Unix gépen.", - "methodItemSftpHint": "Minden fájlt külön-külön átvihet SFTP-n keresztül. Minden gazdagépen működik, beleértve a Windowst is.", - "methodPreviewLoading": "Átviteli módszer kiszámítása…", - "methodPreviewError": "Nem sikerült megtekinteni az átviteli módot. A szerver továbbra is kiválaszt egy módszert az indításkor.", - "methodPreviewWillUseTar": "Felhasználás: Tar archívum", - "methodPreviewWillUseItemSftp": "Használat: Fájlonkénti SFTP", - "methodPreviewScanSummary": "{{fileCount}} fájl, {{totalSize}} összesen (a forrásgépen beolvasva).", - "methodItemSftpLimitation": "Minden fájl ugyanazt az SFTP-folyamot használja, mint egyetlen fájl másolata, egymás után. A folyamat az összes fájlban összevonódik, így a sáv lassan mozog nagy fájlok esetén.", - "methodReason": { - "user_item_sftp": "Fájlonkénti SFTP-t választottál.", - "user_tar": "A tar archívumot választottad.", - "tar_unavailable": "A Tar nem érhető el az egyik vagy mindkét hoszton – helyette fájlonkénti SFTP-t fog használni.", - "windows_host": "Egy Windows gazdagép érintett – tar-t nem használunk.", - "auto_multi_large": "Automatikus: több fájl, beleértve egy nagy fájlt ({{largestSize}}) tömöríthető adatokkal — a tar egyetlen átvitelbe csomagolja.", - "auto_single_large_in_archive": "Automatikus: egy nagy fájl ({{largestSize}}) ebben a készletben — fájlonként SFTP.", - "auto_many_incompressible": "Automatikus: többnyire tömöríthetetlen adatok — fájlonkénti SFTP.", - "auto_many_files": "Auto: sok fájl ({{fileCount}}) — a tar csökkenti a fájlonkénti terhelést.", - "auto_default": "Automatikus: fájlonkénti SFTP ehhez a készlethez." - }, - "progressCancel": "Mégsem", - "progressCancelling": "Törlés…", - "progressStalled": "Elakadt", - "resumedHint": "Újracsatlakozva egy másik ablakban indított aktív átvitelhez.", - "transferCancelled": "Átutalás törölve", - "transferCancelledCopyHint": "Részleges fájlok maradhatnak a célhelyen.", - "transferCancelledMoveHint": "Részleges fájlok maradhatnak a célhelyen. A forrásfájlok nem lettek eltávolítva.", - "cleanupDestFiles": "Takarítási célpont", - "cleanupDestFilesSuccess": "Részleges fájlok eltávolítva a célhelyről", - "cleanupDestFilesPartial": "Néhány részleges fájlt nem sikerült eltávolítani", - "cleanupDestFilesNothing": "Nincs mit takarítani a célállomáson", - "cleanupDestFilesError": "A tisztítás sikertelen", - "retryTransfer": "Újrapróbálkozás", - "retryTransferError": "Újrapróbálkozás sikertelen", - "transferFailedRetryHint": "Részleges adatok maradtak a célállomáson. Az újrapróbálkozás a kapcsolat helyreállásakor folytatódik." + "sourceNotDeletedPartial": "Forrásfájlok megtartása (részleges átvitel)" }, "tunnels": { "connect": "Csatlakozás", @@ -1261,8 +1153,6 @@ "clientTunnel": "Ügyfél alagút", "addClientTunnel": "Ügyfélalagút hozzáadása", "active": "Aktív", - "start": "Indul", - "stop": "Stop", "typeServerLocalDesc": "Aktuális gazdagéptől a végpontig.", "typeServerRemoteDesc": "Végpont vissza az aktuális gazdagépre.", "typeClientLocalDesc": "Helyi számítógépről a végpontra.", @@ -1374,8 +1264,7 @@ "resetCodeRateLimitedWithTime": "Korlátozott sebesség: Túl sok ellenőrzési kísérlet. Kérjük, várjon {{time}} másodpercet, mielőtt újra próbálkozik.", "authTokenSaveFailed": "Nem sikerült menteni a hitelesítési tokent", "authTokenMissing": "A szerver nem adott vissza új hitelesítési tokent. Kérjük, jelentkezzen be újra.", - "failedToLoadServer": "Nem sikerült betölteni a szervert", - "remoteServerRequired": "Távoli szerver szükséges. Csatlakoztasson egy távoli szervert a Beállításokban a kapcsolattípus használatához." + "failedToLoadServer": "Nem sikerült betölteni a szervert" }, "messages": { "registrationDisabled": "Az új fiók regisztrációját jelenleg egy adminisztrátor letiltotta. Kérjük, jelentkezzen be, vagy vegye fel a kapcsolatot egy adminisztrátorral.", @@ -1831,7 +1720,6 @@ "protocolLabel": "Jegyzőkönyv", "domainLabel": "Domain", "domainPlaceholder": "választható", - "connectToTerminal": "Csatlakozás a terminálhoz", "connectToFiles": "Kapcsolódás fájlokhoz" }, "splitScreen": { diff --git a/src/ui/locales/translated/id_ID.json b/src/ui/locales/translated/id_ID.json index 47554000e..369cca563 100644 --- a/src/ui/locales/translated/id_ID.json +++ b/src/ui/locales/translated/id_ID.json @@ -324,10 +324,6 @@ "appearanceIntro": "Pilih tema, warna aksen, dan bahasa Anda. Ketiganya dapat diubah nanti di Pengaturan.", "featuresTitle": "Apa lagi yang dilakukan Termix?", "featuresIntro": "Setiap server yang Anda simpan dapat dibuka di lebih dari satu terminal. Berikut adalah apa yang ada di balik ikon di sebelah kiri.", - "feature_files": "Pengelola berkas", - "feature_files_desc": "Jelajahi, unggah, unduh, dan edit file melalui SFTP tanpa meninggalkan aplikasi.", - "feature_tunnels": "Terowongan", - "feature_tunnels_desc": "Meneruskan port melalui server untuk mengakses layanan yang tidak terekspos.", "feature_snippets": "Cuplikan", "feature_snippets_desc": "Simpan perintah yang sering Anda jalankan dan kirimkan ke terminal hanya dengan satu klik.", "featuresRailHint": "Tidak membutuhkan salah satu dari ini? Sembunyikan ikon apa pun dari bilah sisi di Pengaturan, di bawah Navigasi.", @@ -449,7 +445,6 @@ "passwordSaved": "Kata sandi tersimpan, ketik untuk mengubahnya", "key": "Kunci", "credential": "Mandat", - "none": "Tidak ada", "sshPrivateKey": "Kunci Pribadi SSH", "keyType": "Jenis Kunci", "uploadFile": "Unggah File", @@ -611,17 +606,12 @@ "keepaliveIntervalLabel": "Interval Keepalive (detik)", "maxKeepaliveMisses": "Max Keepalive Gagal", "sameHost": "Host ini (terowongan langsung)", - "bindHost": "Host Terikat", "connectionToolbar": "Toolbar Koneksi", "showConnectionToolbar": "Tampilkan bilah alat koneksi", "showConnectionToolbarDesc": "Tampilkan toolbar di sesi SSH, RDP, VNC, dan Telnet host ini. Anda juga dapat menyembunyikannya sementara dari toolbar itu sendiri.", "proxmoxLastSyncStatus": { "success": "Kesuksesan" }, - "proxmoxGuestsSelected_one": "{{count}} tamu — {{selected}} terpilih", - "proxmoxGuestsSelected_other": "{{count}} tamu — {{selected}} terpilih", - "proxmoxImportButton_one": "Impor {{count}} host", - "proxmoxImportButton_other": "Impor {{count}} host", "proxmoxResultSkippedNoIp": "{{count}} dilewati (tidak ditemukan IP)", "proxmoxStatsUrlCopied": "URL Statistik Proxmox disalin ke papan klip", "copyProxmoxStatsUrlAction": "Salin URL Statistik Proxmox", @@ -896,13 +886,11 @@ "updatedCount": "Host {{count}} yang diperbarui", "friendlyNameLabel": "Nama yang Ramah", "descriptionLabel": "Keterangan", - "loadingHost": "Memuat host...", "loadingHosts": "Memuat host...", "loadingCredentials": "Sedang memuat kredensial...", "noHostsYet": "Belum ada host", "noHostsYetHint": "Tambahkan server untuk membuka terminal, menelusuri file, dan melihat metrik.", "noHostsMatchSearch": "Tidak ada host yang sesuai dengan pencarian Anda.", - "hostNotFound": "Host tidak ditemukan", "searchHosts": "Cari host...", "sortHosts": "Urutkan Host", "sortDefault": "Urutan Default", @@ -925,7 +913,6 @@ "filterAuthKey": "Kunci SSH", "filterAuthCredential": "Mandat", "filterAuthNone": "Tidak ada", - "filterAuthOpkssh": "OPKSSH", "filterAuthStepca": "Langkah CA", "filterProtocolGroup": "Protokol", "filterProtocolSsh": "SSH", @@ -1114,13 +1101,7 @@ "connect": "Terhubung ke Host", "clear": "Jernih", "paste": "Pasta", - "connected": "Terhubung", - "clipboardWriteFailed": "Gagal menyalin ke papan klip. Pastikan halaman disajikan melalui HTTPS atau localhost.", - "clipboardReadFailed": "Gagal membaca dari clipboard. Pastikan izin clipboard telah diberikan.", "tmuxDetach": "Lepaskan diri dari sesi tmux", - "terminalTitle": "Terminal - {{host}}", - "terminalWithPath": "Terminal - {{host}}:{{path}}", - "runTitle": "Menjalankan {{command}} - {{host}}", "totpRequired": "Diperlukan Otentikasi Dua Faktor", "totpCodeLabel": "Kode Verifikasi", "totpVerify": "Memeriksa", @@ -1148,109 +1129,20 @@ } }, "transfer": { - "copyToHost": "Salin ke host…", - "moveToHost": "Pindah ke host…", - "copyItemsToHost": "Salin {{count}} item ke host…", - "moveItemsToHost": "Pindahkan {{count}} item ke host…", - "noHostsConnected": "Tidak ada penyedia pengelola file lain yang tersedia.", - "noHostsConnectedHint": "Tambahkan host SSH lain dengan File Manager diaktifkan di Host Manager.", - "selectDestinationHost": "Pilih host tujuan", - "destinationPath": "Jalur tujuan", - "recentDestinations": "Destinasi terkini", "collapseRecentDestinations": "Ciutkan destinasi terbaru", "expandRecentDestinations": "Perluas destinasi terbaru", - "browseFolders": "Telusuri folder tujuan", "browseDestination": "Telusuri atau masukkan jalur", - "confirmCopy": "Menyalin", - "confirmMove": "Bergerak", "transferring": "Mentransfer…", - "progressVerifying": "Memverifikasi integritas file…", - "progressBenchmarking": "Memilih rute transfer tercepat…", "compressing": "Mengompresi…", "extracting": "Mengekstrak…", "transferringItems": "Memindahkan {{current}} dari {{total}} item…", - "transferSuccess": "Transfer selesai", - "transferError": "Transfer gagal", "transferPartial": "Transfer selesai dengan {{count}} kesalahan", - "transferPartialHint": "Tidak dapat mentransfer: {{paths}}", - "itemsSummary": "{{count}} item", - "destMustBeDirectory": "Tujuan harus berupa direktori untuk transfer multi-item.", "selectThisFolder": "Pilih folder ini", - "browsePathWillBeCreated": "Folder ini belum ada. Folder ini akan dibuat saat transfer dimulai.", - "browsePathError": "Tidak dapat membuka jalur ini pada host tujuan.", - "goUp": "Naik", - "copyFolderToHost": "Salin folder ke host…", - "moveFolderToHost": "Pindahkan folder ke host…", - "hostReady": "Siap", - "hostConnecting": "Menghubungkan…", - "hostDisconnected": "Tidak terhubung", - "hostAuthRequired": "Diperlukan autentikasi — buka File Manager di host ini terlebih dahulu.", - "hostConnectionFailed": "Koneksi gagal", "metricsTitle": "Waktu transfer", - "metricsPrepare": "Siapkan tujuan: {{duration}}", - "metricsCompress": "Kompres pada sumber: {{duration}}", "metricsHopSourceRead": "Sumber → server: {{throughput}}", "metricsHopDestSftpWrite": "Server → tujuan (SFTP): {{throughput}}", "metricsHopDestLocalWrite": "Server → tujuan (lokal): {{throughput}}", - "metricsTransfer": "Ujung ke ujung: {{throughput}} ({{duration}})", - "metricsExtract": "Ekstrak pada tujuan: {{duration}}", - "metricsVerify": "SHA-256 terverifikasi: {{duration}}", - "metricsRouteBenchmark": "Pemeriksaan rute — langsung: {{direct}}, relai: {{relay}}", - "metricsSourceDelete": "Hapus dari sumber: {{duration}}", - "metricsTotal": "Total: {{duration}}", - "progressCompressing": "Kompresi pada host sumber…", - "progressExtracting": "Mengekstraksi pada tujuan…", - "progressTransferring": "Mentransfer data…", - "progressReconnecting": "Menghubungkan kembali…", - "parallelSegmentsLabel": "Jalur transfer paralel", - "parallelSegmentsOption": "{{count}} jalur", - "parallelSegmentsHint": "File berukuran besar dibagi menjadi bagian-bagian berukuran 256 MB. Beberapa jalur menggunakan koneksi terpisah (seperti memulai beberapa transfer) untuk throughput total yang lebih tinggi.", - "progressTotalSpeed": "{{speed}} total ({{lanes}} lajur)", - "progressTransferringItems": "Mentransfer berkas ({{current}} dari {{total}})…", - "progressBytes": "{{transferred}} / {{total}}", - "progressItems": "berkas {{current}} / {{total}}", - "sourceNotDeletedPartial": "Berkas sumber tetap disimpan (transfer sebagian)", - "jumpHostLimitation": "Kedua host harus dapat dijangkau dari server Termix. Perutean langsung antar host tidak didukung.", - "cancel": "Membatalkan", - "methodLabel": "Metode transfer", - "methodAuto": "Mobil", - "methodTar": "Arsip Tar", - "methodItemSftp": "SFTP per file", - "methodAutoHint": "Memilih antara tar atau SFTP per-file berdasarkan jumlah file, ukuran, dan kemampuan kompresi. File tunggal selalu menggunakan SFTP streaming.", - "methodTarHint": "Kompres di sumber, transfer satu arsip, ekstrak di tujuan. Membutuhkan tar di kedua host Unix.", - "methodItemSftpHint": "Transfer setiap file secara individual melalui SFTP. Berfungsi di semua host termasuk Windows.", - "methodPreviewLoading": "Metode perhitungan transfer…", - "methodPreviewError": "Metode transfer tidak dapat dipratinjau. Server akan tetap memilih metode saat Anda memulai.", - "methodPreviewWillUseTar": "Akan menggunakan: Arsip Tar", - "methodPreviewWillUseItemSftp": "Akan menggunakan: SFTP per file", - "methodPreviewScanSummary": "{{fileCount}} berkas, {{totalSize}} total (dipindai pada host sumber).", - "methodItemSftpLimitation": "Setiap berkas menggunakan aliran SFTP yang sama sebagai salinan berkas tunggal, satu demi satu. Kemajuan digabungkan di semua berkas, sehingga bilah kemajuan bergerak lambat selama pemrosesan berkas berukuran besar.", - "methodReason": { - "user_item_sftp": "Anda memilih SFTP per-file.", - "user_tar": "Anda memilih arsip tar.", - "tar_unavailable": "Tar tidak tersedia di salah satu atau kedua host — SFTP per-file akan digunakan sebagai gantinya.", - "windows_host": "Sistem operasi yang digunakan adalah Windows — tar tidak digunakan.", - "auto_multi_large": "Otomatis: beberapa file termasuk file besar ({{largestSize}}) dengan data yang dapat dikompresi — tar menggabungkan menjadi satu transfer.", - "auto_single_large_in_archive": "Otomatis: satu file besar ({{largestSize}}) dalam set ini — SFTP per file.", - "auto_many_incompressible": "Otomatis: sebagian besar data tidak dapat dikompresi — SFTP per file.", - "auto_many_files": "Otomatis: banyak file ({{fileCount}}) — tar mengurangi overhead per file.", - "auto_default": "Otomatis: SFTP per-file untuk set ini." - }, - "progressCancel": "Membatalkan", - "progressCancelling": "Membatalkan…", - "progressStalled": "Terhenti", - "resumedHint": "Terhubung kembali ke transfer aktif yang dimulai di jendela lain.", - "transferCancelled": "Transfer dibatalkan", - "transferCancelledCopyHint": "File yang tidak lengkap mungkin masih tersisa di tujuan.", - "transferCancelledMoveHint": "Sebagian berkas mungkin masih tersisa di tujuan. Berkas sumber tidak dihapus.", - "cleanupDestFiles": "Tujuan pembersihan", - "cleanupDestFilesSuccess": "File parsial telah dihapus dari tujuan.", - "cleanupDestFilesPartial": "Beberapa file parsial tidak dapat dihapus.", - "cleanupDestFilesNothing": "Tidak ada yang perlu dibersihkan di tempat tujuan.", - "cleanupDestFilesError": "Pembersihan gagal", - "retryTransfer": "Mencoba kembali", - "retryTransferError": "Percobaan ulang gagal.", - "transferFailedRetryHint": "Sebagian data tersimpan di tujuan. Upaya pengulangan akan dilanjutkan saat koneksi kembali pulih." + "sourceNotDeletedPartial": "Berkas sumber tetap disimpan (transfer sebagian)" }, "tunnels": { "connect": "Menghubungkan", @@ -1261,8 +1153,6 @@ "clientTunnel": "Terowongan Klien", "addClientTunnel": "Tambahkan Terowongan Klien", "active": "Aktif", - "start": "Awal", - "stop": "Berhenti", "typeServerLocalDesc": "Host saat ini ke titik akhir.", "typeServerRemoteDesc": "Endpoint kembali ke host saat ini.", "typeClientLocalDesc": "Komputer lokal ke titik akhir.", @@ -1374,8 +1264,7 @@ "resetCodeRateLimitedWithTime": "Pembatasan laju: Terlalu banyak upaya verifikasi. Harap tunggu {{time}} detik sebelum mencoba lagi.", "authTokenSaveFailed": "Gagal menyimpan token otentikasi.", "authTokenMissing": "Server tidak mengembalikan token otentikasi baru. Silakan masuk kembali.", - "failedToLoadServer": "Server gagal dimuat.", - "remoteServerRequired": "Diperlukan server jarak jauh. Hubungkan server jarak jauh di Pengaturan untuk menggunakan jenis koneksi ini." + "failedToLoadServer": "Server gagal dimuat." }, "messages": { "registrationDisabled": "Pendaftaran akun baru saat ini dinonaktifkan oleh administrator. Silakan masuk atau hubungi administrator.", @@ -1831,7 +1720,6 @@ "protocolLabel": "Protokol", "domainLabel": "Domain", "domainPlaceholder": "opsional", - "connectToTerminal": "Hubungkan ke Terminal", "connectToFiles": "Menghubungkan ke File" }, "splitScreen": { diff --git a/src/ui/locales/translated/it_IT.json b/src/ui/locales/translated/it_IT.json index 6274fbaa4..3a1fa84d8 100644 --- a/src/ui/locales/translated/it_IT.json +++ b/src/ui/locales/translated/it_IT.json @@ -324,10 +324,6 @@ "appearanceIntro": "Scegli un tema, un colore principale e la lingua. Tutti e tre possono essere modificati in seguito nelle Impostazioni.", "featuresTitle": "Cos'altro fa Termix?", "featuresIntro": "Ogni server salvato può essere aperto in più di un terminale. Ecco cosa si nasconde dietro le icone a sinistra.", - "feature_files": "Gestore file", - "feature_files_desc": "Esplora, carica, scarica e modifica file tramite SFTP senza uscire dall'applicazione.", - "feature_tunnels": "Gallerie", - "feature_tunnels_desc": "Inoltrare le porte attraverso un server per raggiungere servizi non esposti.", "feature_snippets": "Frammenti", "feature_snippets_desc": "Salva i comandi che esegui più spesso e inviali a un terminale con un solo clic.", "featuresRailHint": "Non ti serve una di queste icone? Nascondi qualsiasi icona dalla barra laterale in Impostazioni, alla voce Navigazione.", @@ -449,7 +445,6 @@ "passwordSaved": "Password salvata, digita per modificarla", "key": "Chiave", "credential": "Credenziale", - "none": "Nessuna", "sshPrivateKey": "Chiave privata SSH", "keyType": "Tipo di chiave", "uploadFile": "Carica file", @@ -611,17 +606,12 @@ "keepaliveIntervalLabel": "Intervallo keepalive (secondi)", "maxKeepaliveMisses": "Numero massimo di mancate keepalive", "sameHost": "Questo host (tunnel diretto)", - "bindHost": "Host di bind", "connectionToolbar": "Barra degli strumenti di connessione", "showConnectionToolbar": "Mostra la barra degli strumenti di connessione", "showConnectionToolbarDesc": "Mostra la barra degli strumenti nelle sessioni SSH, RDP, VNC e Telnet di questo host. Puoi anche nasconderla temporaneamente dalla barra degli strumenti stessa.", "proxmoxLastSyncStatus": { "success": "Riuscita" }, - "proxmoxGuestsSelected_one": "{{count}} guest — {{selected}} selezionato", - "proxmoxGuestsSelected_other": "{{count}} guest — {{selected}} selezionati", - "proxmoxImportButton_one": "Importa {{count}} host", - "proxmoxImportButton_other": "Importa {{count}} host", "proxmoxResultSkippedNoIp": "{{count}} saltato (nessun IP trovato)", "proxmoxStatsUrlCopied": "URL delle statistiche di Proxmox copiato negli appunti", "copyProxmoxStatsUrlAction": "Copia l'URL delle statistiche di Proxmox", @@ -896,13 +886,11 @@ "updatedCount": "Aggiornati {{count}} host", "friendlyNameLabel": "Nome descrittivo", "descriptionLabel": "Descrizione", - "loadingHost": "Caricamento host...", "loadingHosts": "Caricamento host...", "loadingCredentials": "Caricamento credenziali...", "noHostsYet": "Nessun host ancora", "noHostsYetHint": "Aggiungi un server per aprire terminali, sfogliare file e visualizzare metriche.", "noHostsMatchSearch": "Nessun host corrisponde alla ricerca", - "hostNotFound": "Host non trovato", "searchHosts": "Cerca host...", "sortHosts": "Ordina host", "sortDefault": "Ordine predefinito", @@ -925,7 +913,6 @@ "filterAuthKey": "Chiave SSH", "filterAuthCredential": "Credenziale", "filterAuthNone": "Nessuna", - "filterAuthOpkssh": "OPKSSH", "filterAuthStepca": "Passo CA", "filterProtocolGroup": "Protocollo", "filterProtocolSsh": "SSH", @@ -1114,13 +1101,7 @@ "connect": "Connetti all'host", "clear": "Cancella", "paste": "Incolla", - "connected": "Connesso", - "clipboardWriteFailed": "Copia negli appunti non riuscita. Assicurati che la pagina sia servita via HTTPS o localhost.", - "clipboardReadFailed": "Lettura dagli appunti non riuscita. Assicurati che i permessi degli appunti siano stati concessi.", "tmuxDetach": "Scollegati dalla sessione tmux", - "terminalTitle": "Terminale - {{host}}", - "terminalWithPath": "Terminale - {{host}}:{{path}}", - "runTitle": "Esecuzione {{command}} - {{host}}", "totpRequired": "Autenticazione a due fattori richiesta", "totpCodeLabel": "Codice di verifica", "totpVerify": "Verifica", @@ -1148,109 +1129,20 @@ } }, "transfer": { - "copyToHost": "Copia su host…", - "moveToHost": "Sposta su host…", - "copyItemsToHost": "Copia {{count}} elementi su host…", - "moveItemsToHost": "Sposta {{count}} elementi sull'host…", - "noHostsConnected": "Nessun altro host con File Manager disponibile.", - "noHostsConnectedHint": "Aggiungi un altro host SSH con File Manager abilitato nella Gestione Host.", - "selectDestinationHost": "Seleziona host di destinazione", - "destinationPath": "Percorso di destinazione", - "recentDestinations": "Destinazioni recenti", "collapseRecentDestinations": "Comprimi destinazioni recenti", "expandRecentDestinations": "Espandi destinazioni recenti", - "browseFolders": "Sfoglia cartelle di destinazione", "browseDestination": "Sfoglia o inserisci percorso", - "confirmCopy": "Copia", - "confirmMove": "Sposta", "transferring": "Trasferimento in corso…", - "progressVerifying": "Verifica dell'integrità del file…", - "progressBenchmarking": "Selezione del percorso di trasferimento più veloce…", "compressing": "Compressione in corso…", "extracting": "Estrazione in corso…", "transferringItems": "Trasferimento {{current}} su {{total}} elementi…", - "transferSuccess": "Trasferimento completato", - "transferError": "Trasferimento non riuscito", "transferPartial": "Trasferimento completato con {{count}} errori", - "transferPartialHint": "Impossibile trasferire: {{paths}}", - "itemsSummary": "{{count}} elementi", - "destMustBeDirectory": "La destinazione deve essere una directory per il trasferimento di più elementi", "selectThisFolder": "Seleziona questa cartella", - "browsePathWillBeCreated": "Questa cartella non esiste ancora. Verrà creata all'avvio del trasferimento.", - "browsePathError": "Impossibile aprire questo percorso sull'host di destinazione.", - "goUp": "Salire", - "copyFolderToHost": "Copia cartella sull'host…", - "moveFolderToHost": "Sposta cartella sull'host…", - "hostReady": "Pronto", - "hostConnecting": "Connessione in corso…", - "hostDisconnected": "Non connesso", - "hostAuthRequired": "Autenticazione richiesta — aprire prima File Manager su questo host", - "hostConnectionFailed": "Connessione non riuscita", "metricsTitle": "Tempi di trasferimento", - "metricsPrepare": "Prepara destinazione: {{duration}}", - "metricsCompress": "Compressione sul sorgente: {{duration}}", "metricsHopSourceRead": "Sorgente → server: {{throughput}}", "metricsHopDestSftpWrite": "Server → dest (SFTP): {{throughput}}", "metricsHopDestLocalWrite": "Server → dest (locale): {{throughput}}", - "metricsTransfer": "End-to-end: {{throughput}} ({{duration}})", - "metricsExtract": "Estrazione sulla destinazione: {{duration}}", - "metricsVerify": "SHA-256 verificato: {{duration}}", - "metricsRouteBenchmark": "Sondaggio di percorso — diretto: {{direct}}, relè: {{relay}}", - "metricsSourceDelete": "Rimozione dal sorgente: {{duration}}", - "metricsTotal": "Totale: {{duration}}", - "progressCompressing": "Compressione sull'host sorgente…", - "progressExtracting": "Estrazione sulla destinazione…", - "progressTransferring": "Trasferimento dati…", - "progressReconnecting": "Riconnessione…", - "parallelSegmentsLabel": "Corsie di trasferimento parallele", - "parallelSegmentsOption": "{{count}} corsie", - "parallelSegmentsHint": "I file di grandi dimensioni vengono suddivisi in blocchi da 256 MB. Più corsie utilizzano connessioni separate (come avviare più trasferimenti) per una maggiore velocità complessiva.", - "progressTotalSpeed": "{{speed}} totale ({{lanes}} corsie)", - "progressTransferringItems": "Trasferimento file ({{current}} di {{total}})…", - "progressBytes": "{{transferred}} / {{total}}", - "progressItems": "{{current}} / {{total}} file", - "sourceNotDeletedPartial": "File sorgente mantenuti (trasferimento parziale)", - "jumpHostLimitation": "Entrambi gli host devono essere raggiungibili dal server Termix. Il routing diretto host-to-host non è supportato.", - "cancel": "Annulla", - "methodLabel": "Metodo di trasferimento", - "methodAuto": "Auto", - "methodTar": "Archivio Tar", - "methodItemSftp": "SFTP per file", - "methodAutoHint": "Sceglie tar o SFTP per file in base al numero, dimensione e comprimibilità dei file. I file singoli usano sempre SFTP in streaming.", - "methodTarHint": "Comprime sul sorgente, trasferisce un archivio, estrae sulla destinazione. Richiede tar su entrambi gli host Unix.", - "methodItemSftpHint": "Trasferisce ogni file singolarmente tramite SFTP. Funziona su tutti gli host, incluso Windows.", - "methodPreviewLoading": "Calcolo del metodo di trasferimento…", - "methodPreviewError": "Impossibile visualizzare l'anteprima del metodo di trasferimento. Il server sceglierà comunque un metodo all'avvio.", - "methodPreviewWillUseTar": "Userà: Archivio Tar", - "methodPreviewWillUseItemSftp": "Userà: SFTP per file", - "methodPreviewScanSummary": "{{fileCount}} file, {{totalSize}} in totale (scansionati sull'host sorgente).", - "methodItemSftpLimitation": "Ogni file utilizza lo stesso flusso SFTP come una copia di file singolo, uno dopo l'altro. L'avanzamento è combinato su tutti i file, quindi la barra si muove lentamente durante i file di grandi dimensioni.", - "methodReason": { - "user_item_sftp": "Hai scelto SFTP per-file.", - "user_tar": "Hai scelto archivio tar.", - "tar_unavailable": "Tar non è disponibile su uno o entrambi gli host — verrà utilizzato SFTP per-file.", - "windows_host": "È coinvolto un host Windows — tar non viene utilizzato.", - "auto_multi_large": "Auto: più file, incluso un file grande ({{largestSize}}) con dati comprimibili — tar li raggruppa in un unico trasferimento.", - "auto_single_large_in_archive": "Auto: un file grande ({{largestSize}}) in questo set — SFTP per-file.", - "auto_many_incompressible": "Auto: dati per lo più incomprimibili — SFTP per-file.", - "auto_many_files": "Auto: molti file ({{fileCount}}) — tar riduce il sovraccarico per-file.", - "auto_default": "Auto: SFTP per-file per questo set." - }, - "progressCancel": "Annulla", - "progressCancelling": "Annullamento in corso…", - "progressStalled": "Bloccato", - "resumedHint": "Riconnesso a un trasferimento attivo avviato in un'altra finestra.", - "transferCancelled": "Trasferimento annullato", - "transferCancelledCopyHint": "Potrebbero rimanere file parziali sulla destinazione.", - "transferCancelledMoveHint": "Potrebbero rimanere file parziali sulla destinazione. I file sorgente non sono stati rimossi.", - "cleanupDestFiles": "Pulisci destinazione", - "cleanupDestFilesSuccess": "File parziali rimossi dalla destinazione", - "cleanupDestFilesPartial": "Alcuni file parziali non sono stati rimossi", - "cleanupDestFilesNothing": "Niente da pulire sulla destinazione", - "cleanupDestFilesError": "Pulizia fallita", - "retryTransfer": "Riprova", - "retryTransferError": "Riprova fallita", - "transferFailedRetryHint": "I dati parziali sono stati conservati sulla destinazione. Il nuovo tentativo riprenderà quando la connessione sarà ripristinata." + "sourceNotDeletedPartial": "File sorgente mantenuti (trasferimento parziale)" }, "tunnels": { "connect": "Connetti", @@ -1261,8 +1153,6 @@ "clientTunnel": "Tunnel client", "addClientTunnel": "Aggiungi tunnel client", "active": "Attivo", - "start": "Avvia", - "stop": "Ferma", "typeServerLocalDesc": "Dall'host attuale all'endpoint.", "typeServerRemoteDesc": "Dall'endpoint all'host attuale.", "typeClientLocalDesc": "Dal computer locale all'endpoint.", @@ -1374,8 +1264,7 @@ "resetCodeRateLimitedWithTime": "Limite di tentativi raggiunto: troppi tentativi di verifica. Attendere {{time}} secondi prima di riprovare.", "authTokenSaveFailed": "Salvataggio del token di autenticazione non riuscito", "authTokenMissing": "Il server non ha restituito un nuovo token di autenticazione. Effettua nuovamente l'accesso.", - "failedToLoadServer": "Caricamento del server non riuscito", - "remoteServerRequired": "È necessario un server remoto. Per utilizzare questo tipo di connessione, collega un server remoto nelle Impostazioni." + "failedToLoadServer": "Caricamento del server non riuscito" }, "messages": { "registrationDisabled": "La registrazione di nuovi account è attualmente disabilitata da un amministratore. Effettua il login o contatta un amministratore.", @@ -1831,7 +1720,6 @@ "protocolLabel": "Protocollo", "domainLabel": "Dominio", "domainPlaceholder": "opzionale", - "connectToTerminal": "Connetti al terminale", "connectToFiles": "Connetti ai file" }, "splitScreen": { diff --git a/src/ui/locales/translated/ja_JP.json b/src/ui/locales/translated/ja_JP.json index 759ad6ad9..22acdce19 100644 --- a/src/ui/locales/translated/ja_JP.json +++ b/src/ui/locales/translated/ja_JP.json @@ -324,10 +324,6 @@ "appearanceIntro": "テーマ、アクセントカラー、言語を選択してください。これら3つは後から設定画面で変更できます。", "featuresTitle": "Termixは他にどんなことをしているのでしょうか?", "featuresIntro": "保存したサーバーは、ターミナル以外のアプリケーションでも開くことができます。左側のアイコンをクリックすると、以下の機能が利用できます。", - "feature_files": "ファイルマネージャー", - "feature_files_desc": "アプリを離れることなく、SFTP経由でファイルの閲覧、アップロード、ダウンロード、編集が可能です。", - "feature_tunnels": "トンネル", - "feature_tunnels_desc": "公開されていないサービスにアクセスできるように、サーバー経由でポートを転送します。", "feature_snippets": "断片", "feature_snippets_desc": "よく使うコマンドを保存して、ワンクリックでターミナルに送信できます。", "featuresRailHint": "これらのアイコンが不要な場合は、設定の「ナビゲーション」からサイドバーのアイコンを非表示にできます。", @@ -449,7 +445,6 @@ "passwordSaved": "パスワードが保存されました。変更するには入力してください。", "key": "鍵", "credential": "認証情報", - "none": "なし", "sshPrivateKey": "SSH秘密鍵", "keyType": "鍵の種類", "uploadFile": "ファイルをアップロード", @@ -611,17 +606,12 @@ "keepaliveIntervalLabel": "キープアライブ間隔(秒)", "maxKeepaliveMisses": "最大キープアライブミス回数", "sameHost": "このホスト(直接トンネル)", - "bindHost": "バインドホスト", "connectionToolbar": "接続ツールバー", "showConnectionToolbar": "接続ツールバーを表示する", "showConnectionToolbarDesc": "このホストのSSH、RDP、VNC、およびTelnetセッションでツールバーを表示します。ツールバー自体から一時的に非表示にすることもできます。", "proxmoxLastSyncStatus": { "success": "成功" }, - "proxmoxGuestsSelected_one": "{{count}} ゲスト — {{selected}} 選択中", - "proxmoxGuestsSelected_other": "{{count}} ゲスト — {{selected}} 選択中", - "proxmoxImportButton_one": "{{count}} ホストをインポート", - "proxmoxImportButton_other": "{{count}} 台のホストをインポート", "proxmoxResultSkippedNoIp": "{{count}} スキップしました(IPアドレスが見つかりませんでした)", "proxmoxStatsUrlCopied": "Proxmox Stats URL がクリップボードにコピーされました", "copyProxmoxStatsUrlAction": "Proxmox統計情報のURLをコピーする", @@ -896,13 +886,11 @@ "updatedCount": "{{count}} ホストを更新しました", "friendlyNameLabel": "表示名", "descriptionLabel": "説明", - "loadingHost": "ホストを読み込み中...", "loadingHosts": "ホストを読み込み中...", "loadingCredentials": "資格情報を読み込み中...", "noHostsYet": "ホストがまだありません", "noHostsYetHint": "サーバーを追加して、ターミナルを開いたり、ファイルを参照したり、メトリクスを確認したりできるようにします。", "noHostsMatchSearch": "検索に一致するホストはありません", - "hostNotFound": "ホストが見つかりません", "searchHosts": "ホストを検索...", "sortHosts": "ホストの並べ替え", "sortDefault": "デフォルトの順序", @@ -925,7 +913,6 @@ "filterAuthKey": "SSHキー", "filterAuthCredential": "資格情報", "filterAuthNone": "なし", - "filterAuthOpkssh": "OPKSSH", "filterAuthStepca": "ステップCA", "filterProtocolGroup": "プロトコル", "filterProtocolSsh": "SSH", @@ -1114,13 +1101,7 @@ "connect": "ホストに接続", "clear": "クリア", "paste": "貼り付け", - "connected": "接続中", - "clipboardWriteFailed": "クリップボードへのコピーに失敗しました。ページがHTTPSまたはlocalhostで提供されていることを確認してください。", - "clipboardReadFailed": "クリップボードからの読み取りに失敗しました。クリップボードのアクセス許可が付与されていることを確認してください。", "tmuxDetach": "tmuxセッションからデタッチ", - "terminalTitle": "ターミナル - {{host}}", - "terminalWithPath": "ターミナル - {{host}}:{{path}}", - "runTitle": "{{command}} 実行中 - {{host}}", "totpRequired": "二要素認証が必要です", "totpCodeLabel": "確認コード", "totpVerify": "確認", @@ -1148,109 +1129,20 @@ } }, "transfer": { - "copyToHost": "ホストにコピー...", - "moveToHost": "ホストに移動...", - "copyItemsToHost": "{{count}}個のアイテムをホストにコピー...", - "moveItemsToHost": "{{count}} アイテムをホストへ移動…", - "noHostsConnected": "利用可能な他のファイルマネージャホストがありません。", - "noHostsConnectedHint": "ホストマネージャでファイルマネージャが有効なSSHホストを追加してください。", - "selectDestinationHost": "転送先ホストを選択", - "destinationPath": "転送先パス", - "recentDestinations": "最近の転送先", "collapseRecentDestinations": "最近の転送先を折りたたむ", "expandRecentDestinations": "最近の転送先を展開する", - "browseFolders": "転送先フォルダを参照", "browseDestination": "パスを参照または入力", - "confirmCopy": "コピー", - "confirmMove": "移動", "transferring": "転送中…", - "progressVerifying": "ファイルの整合性を検証中…", - "progressBenchmarking": "最速の転送ルートを選択…", "compressing": "圧縮中…", "extracting": "展開中…", "transferringItems": "{{total}} 個中 {{current}} 個のアイテムを転送中…", - "transferSuccess": "転送が完了しました", - "transferError": "転送に失敗しました", "transferPartial": "{{count}} 件のエラーで転送が完了しました", - "transferPartialHint": "転送できませんでした: {{paths}}", - "itemsSummary": "{{count}} アイテム", - "destMustBeDirectory": "複数アイテムの転送では転送先はディレクトリである必要があります", "selectThisFolder": "このフォルダを選択", - "browsePathWillBeCreated": "このフォルダはまだ存在しません。転送開始時に作成されます。", - "browsePathError": "転送先ホストでこのパスを開けませんでした。", - "goUp": "上へ", - "copyFolderToHost": "フォルダをホストにコピー…", - "moveFolderToHost": "フォルダをホストに移動…", - "hostReady": "準備完了", - "hostConnecting": "接続中…", - "hostDisconnected": "未接続", - "hostAuthRequired": "認証が必要です — まずこのホストでファイルマネージャを開いてください", - "hostConnectionFailed": "接続に失敗しました", "metricsTitle": "転送タイミング", - "metricsPrepare": "転送先の準備: {{duration}}", - "metricsCompress": "送信元での圧縮: {{duration}}", "metricsHopSourceRead": "送信元 → サーバー: {{throughput}}", "metricsHopDestSftpWrite": "サーバー → 送信先 (SFTP): {{throughput}}", "metricsHopDestLocalWrite": "サーバー → 送信先 (ローカル): {{throughput}}", - "metricsTransfer": "エンドツーエンド: {{throughput}} ({{duration}})", - "metricsExtract": "送信先で展開: {{duration}}", - "metricsVerify": "SHA-256検証済み: {{duration}}", - "metricsRouteBenchmark": "ルートプローブ — 直接: {{direct}}、リレー: {{relay}}", - "metricsSourceDelete": "送信元から削除: {{duration}}", - "metricsTotal": "合計: {{duration}}", - "progressCompressing": "ソースホストで圧縮中…", - "progressExtracting": "送信先で展開中…", - "progressTransferring": "データ転送中…", - "progressReconnecting": "再接続中…", - "parallelSegmentsLabel": "並列転送レーン", - "parallelSegmentsOption": "{{count}} レーン", - "parallelSegmentsHint": "大きなファイルは 256 MB のチャンクに分割されます。複数レーンでは個別の接続を使用し (複数の転送を開始するように)、合計スループットが向上します。", - "progressTotalSpeed": "合計 {{speed}} ({{lanes}} レーン)", - "progressTransferringItems": "ファイル転送中 ({{current}} / {{total}})…", - "progressBytes": "{{transferred}} / {{total}}", - "progressItems": "{{current}} / {{total}} ファイル", - "sourceNotDeletedPartial": "ソースファイルを保持 (部分転送)", - "jumpHostLimitation": "両方のホストが Termix サーバーから到達可能である必要があります。ホスト間直接ルーティングはサポートされていません。", - "cancel": "キャンセル", - "methodLabel": "転送方式", - "methodAuto": "自動", - "methodTar": "Tar アーカイブ", - "methodItemSftp": "ファイル単位 SFTP", - "methodAutoHint": "ファイル数、サイズ、圧縮可能性に基づいて tar またはファイル単位 SFTP を選択します。単一ファイルは常にストリーミング SFTP を使用します。", - "methodTarHint": "ソースで圧縮し、1つのアーカイブを転送し、送信先で展開します。両方の Unix ホストに tar が必要です。", - "methodItemSftpHint": "各ファイルを個別に SFTP で転送します。Windows を含むすべてのホストで動作します。", - "methodPreviewLoading": "転送方式を計算中…", - "methodPreviewError": "転送方式をプレビューできませんでした。開始時にサーバーが方式を選択します。", - "methodPreviewWillUseTar": "使用方式: Tar アーカイブ", - "methodPreviewWillUseItemSftp": "使用方式: ファイル単位 SFTP", - "methodPreviewScanSummary": "{{fileCount}} ファイル、合計 {{totalSize}} (ソースホストでスキャン)。", - "methodItemSftpLimitation": "各ファイルは単一ファイルコピーと同じ SFTP ストリームを順次使用します。進捗は全ファイルで統合されるため、大きなファイルではバーの動きが遅くなります。", - "methodReason": { - "user_item_sftp": "ファイルごとのSFTPを選択しました。", - "user_tar": "tarアーカイブを選択しました。", - "tar_unavailable": "一方または両方のホストでtarが利用できないため、代わりにファイルごとのSFTPが使用されます。", - "windows_host": "Windows ホストが含まれているため、tar は使用されません。", - "auto_multi_large": "自動: 複数ファイルに大きな圧縮可能なファイル ({{largestSize}}) が含まれるため、tarで1回の転送にまとめます。", - "auto_single_large_in_archive": "自動: このセットに1つの大きなファイル ({{largestSize}}) があるため、ファイルごとのSFTPです。", - "auto_many_incompressible": "自動: ほとんど圧縮不可能なデータのため、ファイルごとのSFTPです。", - "auto_many_files": "自動: 多数のファイル ({{fileCount}}) があるため、tarでファイルごとのオーバーヘッドを削減します。", - "auto_default": "自動: このセットではファイルごとのSFTPです。" - }, - "progressCancel": "キャンセル", - "progressCancelling": "キャンセル中…", - "progressStalled": "停滞中", - "resumedHint": "別のウィンドウで開始されたアクティブな転送に再接続しました。", - "transferCancelled": "転送がキャンセルされました", - "transferCancelledCopyHint": "部分的なファイルが宛先に残る可能性があります。", - "transferCancelledMoveHint": "部分的なファイルが宛先に残る可能性があります。ソースファイルは削除されていません。", - "cleanupDestFiles": "宛先をクリーンアップ", - "cleanupDestFilesSuccess": "宛先から部分的なファイルを削除しました", - "cleanupDestFilesPartial": "一部の部分的なファイルを削除できませんでした", - "cleanupDestFilesNothing": "宛先にクリーンアップするものはありません", - "cleanupDestFilesError": "クリーンアップに失敗しました", - "retryTransfer": "再試行", - "retryTransferError": "再試行に失敗しました", - "transferFailedRetryHint": "部分的なデータが宛先に保持されました。接続が復旧したら再試行が再開されます。" + "sourceNotDeletedPartial": "ソースファイルを保持 (部分転送)" }, "tunnels": { "connect": "接続", @@ -1261,8 +1153,6 @@ "clientTunnel": "クライアントトンネル", "addClientTunnel": "クライアントトンネルを追加", "active": "アクティブ", - "start": "開始", - "stop": "停止", "typeServerLocalDesc": "現在のホストからエンドポイントへ。", "typeServerRemoteDesc": "エンドポイントから現在のホストへ。", "typeClientLocalDesc": "ローカルコンピューターからエンドポイントへ。", @@ -1374,8 +1264,7 @@ "resetCodeRateLimitedWithTime": "レート制限: 認証試行が多すぎます。{{time}}秒待ってから再試行してください。", "authTokenSaveFailed": "認証トークンの保存に失敗しました", "authTokenMissing": "サーバーから新しい認証トークンが返されませんでした。再度ログインしてください。", - "failedToLoadServer": "サーバーの読み込みに失敗しました", - "remoteServerRequired": "リモートサーバーが必要です。この接続タイプを使用するには、設定でリモートサーバーを接続してください。" + "failedToLoadServer": "サーバーの読み込みに失敗しました" }, "messages": { "registrationDisabled": "現在、管理者が新規アカウント登録を無効にしています。ログインするか、管理者にお問い合わせください。", @@ -1831,7 +1720,6 @@ "protocolLabel": "プロトコル", "domainLabel": "ドメイン", "domainPlaceholder": "オプション", - "connectToTerminal": "ターミナルに接続", "connectToFiles": "ファイルに接続" }, "splitScreen": { diff --git a/src/ui/locales/translated/ko_KR.json b/src/ui/locales/translated/ko_KR.json index 022c4ada5..f907414c0 100644 --- a/src/ui/locales/translated/ko_KR.json +++ b/src/ui/locales/translated/ko_KR.json @@ -324,10 +324,6 @@ "appearanceIntro": "테마, 강조 색상 및 언어를 선택하세요. 이 세 가지 모두 나중에 설정에서 변경할 수 있습니다.", "featuresTitle": "Termix는 그 외에도 무엇을 할까요?", "featuresIntro": "저장한 모든 서버는 터미널 외에도 다양한 방법으로 열 수 있습니다. 왼쪽에 있는 아이콘들을 클릭하면 더 자세한 내용을 확인할 수 있습니다.", - "feature_files": "파일 관리자", - "feature_files_desc": "앱을 종료하지 않고 SFTP를 통해 파일을 검색, 업로드, 다운로드 및 편집할 수 있습니다.", - "feature_tunnels": "터널", - "feature_tunnels_desc": "서버를 통해 포트를 포워딩하여 외부에 노출되지 않은 서비스에 접근할 수 있습니다.", "feature_snippets": "짧은 발췌", "feature_snippets_desc": "자주 실행하는 명령어를 저장하고 한 번의 클릭으로 터미널에 전송하세요.", "featuresRailHint": "이 중 어느 것도 필요하지 않으신가요? 설정 > 탐색에서 사이드바의 아이콘을 숨길 수 있습니다.", @@ -449,7 +445,6 @@ "passwordSaved": "비밀번호가 저장되었습니다. 변경하려면 입력하세요.", "key": "키", "credential": "자격 증명", - "none": "없음", "sshPrivateKey": "SSH 개인 키", "keyType": "키 유형", "uploadFile": "파일 업로드", @@ -611,17 +606,12 @@ "keepaliveIntervalLabel": "연결 유지 간격(초)", "maxKeepaliveMisses": "최대 연결 유지 미스", "sameHost": "이 호스트 (직접 터널)", - "bindHost": "바인드 호스트", "connectionToolbar": "연결 도구 모음", "showConnectionToolbar": "연결 도구 모음 표시", "showConnectionToolbarDesc": "이 호스트의 SSH, RDP, VNC 및 Telnet 세션에 툴바를 표시합니다. 툴바 자체에서 툴바를 일시적으로 숨길 수도 있습니다.", "proxmoxLastSyncStatus": { "success": "성공" }, - "proxmoxGuestsSelected_one": "게스트 {{count}}개 — {{selected}}개 선택됨", - "proxmoxGuestsSelected_other": "게스트 {{count}}개 — {{selected}}개 선택됨", - "proxmoxImportButton_one": "호스트 {{count}}개 가져오기", - "proxmoxImportButton_other": "{{count}}개 호스트 가져오기", "proxmoxResultSkippedNoIp": "{{count}} 건너뛰었습니다(IP 주소를 찾을 수 없음)", "proxmoxStatsUrlCopied": "Proxmox 통계 URL이 클립보드에 복사되었습니다.", "copyProxmoxStatsUrlAction": "Proxmox 통계 URL 복사", @@ -896,13 +886,11 @@ "updatedCount": "{{count}}개의 호스트를 업데이트했습니다", "friendlyNameLabel": "별칭", "descriptionLabel": "설명", - "loadingHost": "호스트 로드 중...", "loadingHosts": "호스트 로드 중...", "loadingCredentials": "인증 정보 로드 중...", "noHostsYet": "아직 호스트가 없습니다", "noHostsYetHint": "터미널을 열고, 파일을 탐색하고, 지표를 확인하려면 서버를 추가하세요.", "noHostsMatchSearch": "검색과 일치하는 호스트가 없습니다", - "hostNotFound": "호스트를 찾을 수 없습니다", "searchHosts": "호스트 검색...", "sortHosts": "호스트 정렬", "sortDefault": "기본 순서", @@ -925,7 +913,6 @@ "filterAuthKey": "SSH 키", "filterAuthCredential": "인증 정보", "filterAuthNone": "없음", - "filterAuthOpkssh": "OPKSSH", "filterAuthStepca": "스텝 CA", "filterProtocolGroup": "프로토콜", "filterProtocolSsh": "SSH", @@ -1114,13 +1101,7 @@ "connect": "호스트에 연결", "clear": "지우기", "paste": "붙여넣기", - "connected": "연결됨", - "clipboardWriteFailed": "클립보드에 복사하지 못했습니다. 페이지가 HTTPS 또는 localhost에서 제공되는지 확인하세요.", - "clipboardReadFailed": "클립보드에서 읽지 못했습니다. 클립보드 권한이 허용되었는지 확인하세요.", "tmuxDetach": "tmux 세션에서 분리", - "terminalTitle": "터미널 - {{host}}", - "terminalWithPath": "터미널 - {{host}}:{{path}}", - "runTitle": "{{command}} 실행 중 - {{host}}", "totpRequired": "2단계 인증 필요", "totpCodeLabel": "인증 코드", "totpVerify": "인증", @@ -1148,109 +1129,20 @@ } }, "transfer": { - "copyToHost": "호스트로 복사…", - "moveToHost": "호스트로 이동…", - "copyItemsToHost": "{{count}}개 항목을 호스트로 복사…", - "moveItemsToHost": "{{count}}개 항목을 호스트로 이동…", - "noHostsConnected": "사용 가능한 다른 파일 관리자 호스트가 없습니다.", - "noHostsConnectedHint": "호스트 관리자에서 파일 관리자가 활성화된 다른 SSH 호스트를 추가하세요.", - "selectDestinationHost": "대상 호스트 선택", - "destinationPath": "대상 경로", - "recentDestinations": "최근 대상", "collapseRecentDestinations": "최근 대상 접기", "expandRecentDestinations": "최근 대상 펼치기", - "browseFolders": "대상 폴더 찾아보기", "browseDestination": "경로 찾아보기 또는 입력", - "confirmCopy": "복사", - "confirmMove": "이동", "transferring": "전송 중…", - "progressVerifying": "파일 무결성 확인 중…", - "progressBenchmarking": "가장 빠른 이동 경로 선택…", "compressing": "압축 중…", "extracting": "압축 해제 중…", "transferringItems": "{{total}}개 중 {{current}}개 항목 전송 중…", - "transferSuccess": "전송 완료", - "transferError": "전송 실패", "transferPartial": "{{count}}개의 오류와 함께 전송 완료", - "transferPartialHint": "전송할 수 없습니다: {{paths}}", - "itemsSummary": "{{count}}개 항목", - "destMustBeDirectory": "여러 항목 전송 시 대상은 디렉터리여야 합니다.", "selectThisFolder": "이 폴더 선택", - "browsePathWillBeCreated": "이 폴더가 아직 존재하지 않습니다. 전송 시작 시 생성됩니다.", - "browsePathError": "대상 호스트에서 이 경로를 열 수 없습니다.", - "goUp": "위로", - "copyFolderToHost": "폴더를 호스트로 복사…", - "moveFolderToHost": "폴더를 호스트로 이동…", - "hostReady": "준비됨", - "hostConnecting": "연결 중…", - "hostDisconnected": "연결되지 않음", - "hostAuthRequired": "인증 필요 — 먼저 이 호스트에서 파일 관리자를 여십시오.", - "hostConnectionFailed": "연결 실패", "metricsTitle": "전송 시간", - "metricsPrepare": "대상 준비: {{duration}}", - "metricsCompress": "소스에서 압축: {{duration}}", "metricsHopSourceRead": "소스 → 서버: {{throughput}}", "metricsHopDestSftpWrite": "서버 → 목적지 (SFTP): {{throughput}}", "metricsHopDestLocalWrite": "서버 → 목적지 (로컬): {{throughput}}", - "metricsTransfer": "엔드 투 엔드: {{throughput}} ({{duration}})", - "metricsExtract": "목적지에서 추출: {{duration}}", - "metricsVerify": "SHA-256 검증 완료: {{duration}}", - "metricsRouteBenchmark": "경로 탐색 — 직접: {{direct}}, 중계: {{relay}}", - "metricsSourceDelete": "소스에서 제거: {{duration}}", - "metricsTotal": "총 시간: {{duration}}", - "progressCompressing": "소스 호스트에서 압축 중…", - "progressExtracting": "목적지에서 추출 중…", - "progressTransferring": "데이터 전송 중…", - "progressReconnecting": "재연결 중…", - "parallelSegmentsLabel": "병렬 전송 레인", - "parallelSegmentsOption": "{{count}}개 레인", - "parallelSegmentsHint": "대용량 파일은 256 MB 청크로 분할됩니다. 여러 레인은 별도 연결을 사용하여 (여러 전송을 시작하는 것처럼) 총 처리량을 높입니다.", - "progressTotalSpeed": "총 {{speed}} ({{lanes}}개 레인)", - "progressTransferringItems": "파일 전송 중 ({{current}}/{{total}})…", - "progressBytes": "{{transferred}} / {{total}}", - "progressItems": "{{current}} / {{total}} 파일", - "sourceNotDeletedPartial": "소스 파일 유지 (부분 전송)", - "jumpHostLimitation": "두 호스트 모두 Termix 서버에서 접근 가능해야 합니다. 호스트 간 직접 라우팅은 지원되지 않습니다.", - "cancel": "취소", - "methodLabel": "전송 방법", - "methodAuto": "자동", - "methodTar": "Tar 아카이브", - "methodItemSftp": "파일별 SFTP", - "methodAutoHint": "파일 수, 크기 및 압축 가능성을 기준으로 tar 또는 파일별 SFTP를 선택합니다. 단일 파일은 항상 스트리밍 SFTP를 사용합니다.", - "methodTarHint": "소스에서 압축, 하나의 아카이브 전송, 목적지에서 추출. 두 Unix 호스트에 tar가 필요합니다.", - "methodItemSftpHint": "SFTP를 통해 각 파일을 개별적으로 전송합니다. Windows를 포함한 모든 호스트에서 작동합니다.", - "methodPreviewLoading": "전송 방법 계산 중…", - "methodPreviewError": "전송 방법을 미리 볼 수 없습니다. 시작 시 서버가 방법을 선택합니다.", - "methodPreviewWillUseTar": "사용 예정: Tar 아카이브", - "methodPreviewWillUseItemSftp": "사용 예정: 파일별 SFTP", - "methodPreviewScanSummary": "{{fileCount}}개 파일, 총 {{totalSize}} (소스 호스트에서 스캔됨).", - "methodItemSftpLimitation": "각 파일은 단일 파일 복사와 동일한 SFTP 스트림을 순차적으로 사용합니다. 진행률이 모든 파일에 걸쳐 결합되므로 대용량 파일에서는 진행 막대가 느리게 움직입니다.", - "methodReason": { - "user_item_sftp": "파일별 SFTP를 선택하셨습니다.", - "user_tar": "tar 아카이브를 선택하셨습니다.", - "tar_unavailable": "한쪽 또는 양쪽 호스트에서 tar를 사용할 수 없어 대신 파일별 SFTP를 사용합니다.", - "windows_host": "Windows 호스트가 포함되어 tar를 사용하지 않습니다.", - "auto_multi_large": "자동: 압축 가능한 대용량 파일({{largestSize}})을 포함한 여러 파일 — tar로 하나의 전송으로 묶습니다.", - "auto_single_large_in_archive": "자동: 이 세트에 대용량 파일({{largestSize}}) 하나 — 파일별 SFTP.", - "auto_many_incompressible": "자동: 대부분 압축 불가능한 데이터 — 파일별 SFTP.", - "auto_many_files": "자동: 다수의 파일({{fileCount}}) — tar로 파일별 오버헤드를 줄입니다.", - "auto_default": "자동: 이 세트에 대해 파일별 SFTP." - }, - "progressCancel": "취소", - "progressCancelling": "취소 중…", - "progressStalled": "지연됨", - "resumedHint": "다른 창에서 시작된 활성 전송에 다시 연결되었습니다.", - "transferCancelled": "전송 취소됨", - "transferCancelledCopyHint": "대상에 부분 파일이 남아 있을 수 있습니다.", - "transferCancelledMoveHint": "대상에 부분 파일이 남아 있을 수 있습니다. 원본 파일은 제거되지 않았습니다.", - "cleanupDestFiles": "대상 정리", - "cleanupDestFilesSuccess": "대상에서 부분 파일을 제거했습니다.", - "cleanupDestFilesPartial": "일부 부분 파일을 제거할 수 없었습니다.", - "cleanupDestFilesNothing": "대상에 정리할 항목이 없습니다.", - "cleanupDestFilesError": "정리 실패", - "retryTransfer": "재시도", - "retryTransferError": "재시도 실패", - "transferFailedRetryHint": "대상에 부분 데이터가 유지되었습니다. 연결이 복구되면 다시 시도하면 이어서 전송됩니다." + "sourceNotDeletedPartial": "소스 파일 유지 (부분 전송)" }, "tunnels": { "connect": "연결", @@ -1261,8 +1153,6 @@ "clientTunnel": "클라이언트 터널", "addClientTunnel": "클라이언트 터널 추가", "active": "활성", - "start": "시작", - "stop": "중지", "typeServerLocalDesc": "현재 호스트에서 엔드포인트로.", "typeServerRemoteDesc": "엔드포인트에서 현재 호스트로 역방향 연결.", "typeClientLocalDesc": "로컬 컴퓨터에서 엔드포인트로.", @@ -1374,8 +1264,7 @@ "resetCodeRateLimitedWithTime": "속도 제한: 너무 많은 인증 시도가 있었습니다. 다시 시도하기 전에 {{time}}초 동안 기다려 주세요.", "authTokenSaveFailed": "인증 토큰 저장에 실패했습니다.", "authTokenMissing": "서버에서 새 인증 토큰을 반환하지 않았습니다. 다시 로그인해 주세요.", - "failedToLoadServer": "서버를 불러오지 못했습니다.", - "remoteServerRequired": "원격 서버가 필요합니다. 이 연결 유형을 사용하려면 설정에서 원격 서버를 연결하세요." + "failedToLoadServer": "서버를 불러오지 못했습니다." }, "messages": { "registrationDisabled": "현재 관리자가 신규 계정 등록을 비활성화했습니다. 로그인하거나 관리자에게 문의하세요.", @@ -1831,7 +1720,6 @@ "protocolLabel": "규약", "domainLabel": "도메인", "domainPlaceholder": "선택 과목", - "connectToTerminal": "터미널에 연결", "connectToFiles": "파일에 연결" }, "splitScreen": { diff --git a/src/ui/locales/translated/nl_NL.json b/src/ui/locales/translated/nl_NL.json index a0efbc47c..e3db7ff30 100644 --- a/src/ui/locales/translated/nl_NL.json +++ b/src/ui/locales/translated/nl_NL.json @@ -324,10 +324,6 @@ "appearanceIntro": "Kies een thema, een accentkleur en je taal. Je kunt deze drie later allemaal wijzigen in de instellingen.", "featuresTitle": "Wat doet Termix nog meer?", "featuresIntro": "Elke server die je opslaat, kan op meer manieren dan alleen via een terminal worden geopend. Dit is wat er achter de pictogrammen aan de linkerkant te zien is.", - "feature_files": "Bestandsbeheerder", - "feature_files_desc": "Blader door bestanden, upload ze, download ze en bewerk ze via SFTP zonder de app te verlaten.", - "feature_tunnels": "Tunnels", - "feature_tunnels_desc": "Poorten doorsturen via een server om toegang te krijgen tot services die niet openbaar toegankelijk zijn.", "feature_snippets": "Fragmenten", "feature_snippets_desc": "Sla de commando's die je vaak gebruikt op en verstuur ze met één klik naar een terminal.", "featuresRailHint": "Heb je er geen nodig? Verberg dan elk pictogram in de zijbalk via Instellingen, onder Navigatie.", @@ -449,7 +445,6 @@ "passwordSaved": "Wachtwoord opgeslagen, typ om te wijzigen", "key": "Sleutel", "credential": "Referentie", - "none": "Geen", "sshPrivateKey": "SSH-privésleutel", "keyType": "Sleuteltype", "uploadFile": "Bestand uploaden", @@ -611,17 +606,12 @@ "keepaliveIntervalLabel": "Keepalive-interval (seconden)", "maxKeepaliveMisses": "Max Keepalive mist", "sameHost": "Deze host (directe tunnel)", - "bindHost": "Bind Host", "connectionToolbar": "Verbindingswerkbalk", "showConnectionToolbar": "Verbindingswerkbalk weergeven", "showConnectionToolbarDesc": "Toon de werkbalk in de SSH-, RDP-, VNC- en Telnet-sessies van deze host. Je kunt de werkbalk ook tijdelijk verbergen via de werkbalk zelf.", "proxmoxLastSyncStatus": { "success": "Succes" }, - "proxmoxGuestsSelected_one": "{{count}} gast — {{selected}} geselecteerd", - "proxmoxGuestsSelected_other": "{{count}} gasten — {{selected}} geselecteerd", - "proxmoxImportButton_one": "Importeer {{count}} host", - "proxmoxImportButton_other": "Importeer {{count}} hosts", "proxmoxResultSkippedNoIp": "{{count}} overgeslagen (geen IP-adres gevonden)", "proxmoxStatsUrlCopied": "De URL van Proxmox Stats is naar het klembord gekopieerd.", "copyProxmoxStatsUrlAction": "Kopieer de URL van Proxmox-statistieken", @@ -896,13 +886,11 @@ "updatedCount": "Bijgewerkte {{count}} hosts", "friendlyNameLabel": "Vriendelijke naam", "descriptionLabel": "Beschrijving", - "loadingHost": "Host wordt geladen...", "loadingHosts": "Hosts worden geladen...", "loadingCredentials": "Inloggegevens worden geladen...", "noHostsYet": "Nog geen hosts beschikbaar", "noHostsYetHint": "Voeg een server toe om terminals te openen, bestanden te bekijken en statistieken in te zien.", "noHostsMatchSearch": "Er zijn geen hosts gevonden die aan uw zoekopdracht voldoen.", - "hostNotFound": "Host niet gevonden", "searchHosts": "Zoek hosts...", "sortHosts": "Sorteer hosts", "sortDefault": "Standaardbestelling", @@ -925,7 +913,6 @@ "filterAuthKey": "SSH-sleutel", "filterAuthCredential": "Referentie", "filterAuthNone": "Geen", - "filterAuthOpkssh": "OPKSSH", "filterAuthStepca": "Stap CA", "filterProtocolGroup": "Protocol", "filterProtocolSsh": "SSH", @@ -1114,13 +1101,7 @@ "connect": "Verbinden met de host", "clear": "Duidelijk", "paste": "Plakken", - "connected": "Aangesloten", - "clipboardWriteFailed": "Kopiëren naar klembord mislukt. Zorg ervoor dat de pagina via HTTPS of localhost wordt aangeboden.", - "clipboardReadFailed": "Het lezen van het klembord is mislukt. Zorg ervoor dat de juiste klembordrechten zijn verleend.", "tmuxDetach": "Ontkoppel van de tmux-sessie", - "terminalTitle": "Terminal - {{host}}", - "terminalWithPath": "Terminal - {{host}}:{{path}}", - "runTitle": "Bezig met uitvoeren van {{command}} - {{host}}", "totpRequired": "Tweefactorauthenticatie vereist", "totpCodeLabel": "Verificatiecode", "totpVerify": "Verifiëren", @@ -1148,109 +1129,20 @@ } }, "transfer": { - "copyToHost": "Kopiëren naar host…", - "moveToHost": "Verplaats naar host…", - "copyItemsToHost": "Kopieer {{count}} items naar host…", - "moveItemsToHost": "Verplaats {{count}} items naar host…", - "noHostsConnected": "Er zijn geen andere bestandsbeheerhosts beschikbaar.", - "noHostsConnectedHint": "Voeg een andere SSH-host toe met Bestandsbeheer ingeschakeld in Hostbeheer.", - "selectDestinationHost": "Selecteer de bestemmingshost", - "destinationPath": "Bestemmingspad", - "recentDestinations": "Recente bestemmingen", "collapseRecentDestinations": "Recente bestemmingen inklappen", "expandRecentDestinations": "Recente bestemmingen uitbreiden", - "browseFolders": "Blader door bestemmingsmappen", "browseDestination": "Bladeren of pad invoeren", - "confirmCopy": "Kopiëren", - "confirmMove": "Beweging", "transferring": "Overdracht…", - "progressVerifying": "Bestandsintegriteit controleren…", - "progressBenchmarking": "De snelste overstaproute selecteren…", "compressing": "Comprimeren…", "extracting": "Extractie van…", "transferringItems": "Overdracht van {{current}} van {{total}} items…", - "transferSuccess": "Overdracht voltooid", - "transferError": "Overdracht mislukt", "transferPartial": "Overdracht voltooid met {{count}} fouten", - "transferPartialHint": "Overdracht mislukt: {{paths}}", - "itemsSummary": "{{count}} items", - "destMustBeDirectory": "De bestemming moet een adresboek zijn voor overdrachten van meerdere items.", "selectThisFolder": "Selecteer deze map", - "browsePathWillBeCreated": "Deze map bestaat nog niet. Hij wordt aangemaakt zodra de overdracht start.", - "browsePathError": "Dit pad kon niet worden geopend op de doelhost.", - "goUp": "Ga omhoog", - "copyFolderToHost": "Kopieer de map naar de host…", - "moveFolderToHost": "Map verplaatsen naar host…", - "hostReady": "Klaar", - "hostConnecting": "Verbinding maken…", - "hostDisconnected": "Niet verbonden", - "hostAuthRequired": "Authenticatie vereist — open eerst Bestandsbeheer op deze host.", - "hostConnectionFailed": "Verbinding mislukt", "metricsTitle": "Transfertijden", - "metricsPrepare": "Bestemming voorbereiden: {{duration}}", - "metricsCompress": "Comprimeren op bron: {{duration}}", "metricsHopSourceRead": "Bron → server: {{throughput}}", "metricsHopDestSftpWrite": "Server → bestemming (SFTP): {{throughput}}", "metricsHopDestLocalWrite": "Server → bestemming (lokaal): {{throughput}}", - "metricsTransfer": "Einde tot einde: {{throughput}} ({{duration}})", - "metricsExtract": "Uitpakken op bestemming: {{duration}}", - "metricsVerify": "SHA-256 geverifieerd: {{duration}}", - "metricsRouteBenchmark": "Route probe — direct: {{direct}}, relay: {{relay}}", - "metricsSourceDelete": "Verwijderen uit de bron: {{duration}}", - "metricsTotal": "Totaal: {{duration}}", - "progressCompressing": "Comprimeren op de bronhost…", - "progressExtracting": "Uitpakken op bestemming…", - "progressTransferring": "Gegevens overdragen…", - "progressReconnecting": "Opnieuw verbinding maken…", - "parallelSegmentsLabel": "Parallelle transferstroken", - "parallelSegmentsOption": "{{count}} rijstroken", - "parallelSegmentsHint": "Grote bestanden worden opgesplitst in blokken van 256 MB. Meerdere lanes gebruiken aparte verbindingen (alsof er meerdere overdrachten worden gestart) voor een hogere totale doorvoer.", - "progressTotalSpeed": "{{speed}} totaal ({{lanes}} rijstroken)", - "progressTransferringItems": "Bestanden overdragen ({{current}} van {{total}})…", - "progressBytes": "{{transferred}} / {{total}}", - "progressItems": "{{current}} / {{total}} bestanden", - "sourceNotDeletedPartial": "Bronbestanden behouden (gedeeltelijke overdracht)", - "jumpHostLimitation": "Beide hosts moeten bereikbaar zijn vanaf de Termix-server. Directe routering tussen hosts wordt niet ondersteund.", - "cancel": "Annuleren", - "methodLabel": "Overdrachtsmethode", - "methodAuto": "Auto", - "methodTar": "Tar-archief", - "methodItemSftp": "SFTP per bestand", - "methodAutoHint": "Selecteert tar of SFTP per bestand op basis van het aantal bestanden, de grootte en de comprimeerbaarheid. Voor afzonderlijke bestanden wordt altijd streaming SFTP gebruikt.", - "methodTarHint": "Comprimeer op de bron, verstuur één archiefbestand en pak het uit op de bestemming. Vereist tar op beide Unix-hosts.", - "methodItemSftpHint": "Verstuur elk bestand afzonderlijk via SFTP. Werkt op alle besturingssystemen, inclusief Windows.", - "methodPreviewLoading": "Berekeningsmethode voor overdracht…", - "methodPreviewError": "De overdrachtsmethode kon niet worden bekeken. De server kiest nog steeds een methode wanneer u start.", - "methodPreviewWillUseTar": "Zal gebruiken: Tar-archief", - "methodPreviewWillUseItemSftp": "Zal gebruikmaken van: SFTP per bestand", - "methodPreviewScanSummary": "{{fileCount}} bestanden, {{totalSize}} totaal (gescand op de bronhost).", - "methodItemSftpLimitation": "Elk bestand gebruikt dezelfde SFTP-stream als een kopie van een enkel bestand, de een na de ander. De voortgang wordt gecombineerd voor alle bestanden, waardoor de voortgangsbalk langzaam beweegt bij grote bestanden.", - "methodReason": { - "user_item_sftp": "Je hebt gekozen voor SFTP per bestand.", - "user_tar": "Je hebt gekozen voor een tar-archief.", - "tar_unavailable": "Tar is niet beschikbaar op een of beide hosts; in plaats daarvan wordt SFTP per bestand gebruikt.", - "windows_host": "Er wordt gebruikgemaakt van een Windows-host; tar wordt niet gebruikt.", - "auto_multi_large": "Automatisch: meerdere bestanden, waaronder een groot bestand ({{largestSize}}) met comprimeerbare gegevens — tar bundelt deze tot één overdracht.", - "auto_single_large_in_archive": "Auto: één groot bestand ({{largestSize}}) in deze set — SFTP per bestand.", - "auto_many_incompressible": "Automatisch: voornamelijk niet-comprimeerbare gegevens — SFTP per bestand.", - "auto_many_files": "Auto: veel bestanden ({{fileCount}}) — tar vermindert de overhead per bestand.", - "auto_default": "Automatisch: SFTP per bestand voor deze set." - }, - "progressCancel": "Annuleren", - "progressCancelling": "Annuleren…", - "progressStalled": "Vastgelopen", - "resumedHint": "De verbinding met een actieve overdracht die in een ander venster is gestart, is hersteld.", - "transferCancelled": "Overdracht geannuleerd", - "transferCancelledCopyHint": "Er kunnen gedeeltelijke bestanden op de bestemming achterblijven.", - "transferCancelledMoveHint": "Er kunnen gedeeltelijke bestanden op de bestemming achterblijven. De bronbestanden zijn niet verwijderd.", - "cleanupDestFiles": "Opruimbestemming", - "cleanupDestFilesSuccess": "Gedeeltelijke bestanden verwijderd van de bestemming.", - "cleanupDestFilesPartial": "Sommige gedeeltelijke bestanden konden niet worden verwijderd.", - "cleanupDestFilesNothing": "Niets op te ruimen op de bestemming.", - "cleanupDestFilesError": "Opruimen mislukt", - "retryTransfer": "Opnieuw proberen", - "retryTransferError": "Opnieuw proberen mislukt", - "transferFailedRetryHint": "Er zijn gedeeltelijke gegevens op de bestemming bewaard gebleven. De herhaalpoging wordt hervat zodra de verbinding hersteld is." + "sourceNotDeletedPartial": "Bronbestanden behouden (gedeeltelijke overdracht)" }, "tunnels": { "connect": "Verbinden", @@ -1261,8 +1153,6 @@ "clientTunnel": "Clienttunnel", "addClientTunnel": "Clienttunnel toevoegen", "active": "Actief", - "start": "Begin", - "stop": "Stop", "typeServerLocalDesc": "Huidige host naar eindpunt.", "typeServerRemoteDesc": "Eindpunt terug naar de huidige host.", "typeClientLocalDesc": "Lokale computer naar eindpunt.", @@ -1374,8 +1264,7 @@ "resetCodeRateLimitedWithTime": "Snelheid beperkt: Te veel verificatiepogingen. Wacht {{time}} seconden voordat u het opnieuw probeert.", "authTokenSaveFailed": "Het opslaan van het authenticatietoken is mislukt.", "authTokenMissing": "De server heeft geen nieuw authenticatietoken teruggestuurd. Meld u alstublieft opnieuw aan.", - "failedToLoadServer": "Server laden mislukt", - "remoteServerRequired": "Externe server vereist. Verbind een externe server in de instellingen om dit verbindingstype te gebruiken." + "failedToLoadServer": "Server laden mislukt" }, "messages": { "registrationDisabled": "Het registreren van nieuwe accounts is momenteel uitgeschakeld door een beheerder. Log in of neem contact op met een beheerder.", @@ -1831,7 +1720,6 @@ "protocolLabel": "Protocol", "domainLabel": "Domein", "domainPlaceholder": "optioneel", - "connectToTerminal": "Verbinden met de terminal", "connectToFiles": "Verbinding maken met bestanden" }, "splitScreen": { diff --git a/src/ui/locales/translated/no_NO.json b/src/ui/locales/translated/no_NO.json index 9788affcd..7eb0a1c13 100644 --- a/src/ui/locales/translated/no_NO.json +++ b/src/ui/locales/translated/no_NO.json @@ -324,10 +324,6 @@ "appearanceIntro": "Velg et tema, en aksentfarge og språk. Alle tre kan endres senere i Innstillinger.", "featuresTitle": "Hva annet gjør Termix", "featuresIntro": "Hver server du lagrer kan åpnes i mer enn én terminal. Her er hva som venter bak ikonene til venstre.", - "feature_files": "Filbehandler", - "feature_files_desc": "Bla gjennom, last opp, last ned og rediger filer via SFTP uten å forlate appen.", - "feature_tunnels": "Tunneler", - "feature_tunnels_desc": "Videresend porter gjennom en server for å nå tjenester som ikke er eksponert.", "feature_snippets": "Utdrag", "feature_snippets_desc": "Lagre kommandoer du kjører ofte og send dem til en terminal med ett klikk.", "featuresRailHint": "Trenger du ikke en av disse? Skjul et hvilket som helst ikon fra sidefeltet i Innstillinger, under Navigasjon.", @@ -449,7 +445,6 @@ "passwordSaved": "Passord lagret, skriv inn for å endre", "key": "Nøkkel", "credential": "Legitimasjon", - "none": "Ingen", "sshPrivateKey": "SSH privat nøkkel", "keyType": "Nøkkeltype", "uploadFile": "Last opp fil", @@ -611,17 +606,12 @@ "keepaliveIntervalLabel": "Keepalive-intervall (sekunder)", "maxKeepaliveMisses": "Max Keepalive bommer", "sameHost": "Denne verten (direkte tunnel)", - "bindHost": "Bind vert", "connectionToolbar": "Tilkoblingsverktøylinje", "showConnectionToolbar": "Vis tilkoblingsverktøylinjen", "showConnectionToolbarDesc": "Vis verktøylinjen i denne vertens SSH-, RDP-, VNC- og Telnet-økter. Du kan også skjule den midlertidig fra selve verktøylinjen.", "proxmoxLastSyncStatus": { "success": "Suksess" }, - "proxmoxGuestsSelected_one": "{{count}} gjest — {{selected}} valgt", - "proxmoxGuestsSelected_other": "{{count}} gjester — {{selected}} valgt", - "proxmoxImportButton_one": "Importer {{count}} vert", - "proxmoxImportButton_other": "Importer {{count}} verter", "proxmoxResultSkippedNoIp": "{{count}} hoppet over (ingen IP-adresse funnet)", "proxmoxStatsUrlCopied": "Proxmox-statistikk-URL kopiert til utklippstavlen", "copyProxmoxStatsUrlAction": "Kopier URL-adressen til Proxmox-statistikken", @@ -896,13 +886,11 @@ "updatedCount": "Oppdaterte {{count}} verter", "friendlyNameLabel": "Vennlig navn", "descriptionLabel": "Beskrivelse", - "loadingHost": "Laster inn vert ...", "loadingHosts": "Laster inn verter ...", "loadingCredentials": "Laster inn legitimasjon ...", "noHostsYet": "Ingen verter ennå", "noHostsYetHint": "Legg til en server for å åpne terminaler, bla gjennom filer og se målinger.", "noHostsMatchSearch": "Ingen verter samsvarer med søket ditt", - "hostNotFound": "Verten ble ikke funnet", "searchHosts": "Søk etter verter...", "sortHosts": "Sorter verter", "sortDefault": "Standardordre", @@ -925,7 +913,6 @@ "filterAuthKey": "SSH-nøkkel", "filterAuthCredential": "Legitimasjon", "filterAuthNone": "Ingen", - "filterAuthOpkssh": "OPKSSH", "filterAuthStepca": "Trinn CA", "filterProtocolGroup": "Protokoll", "filterProtocolSsh": "SSH", @@ -1114,13 +1101,7 @@ "connect": "Koble til vert", "clear": "Klar", "paste": "Lim inn", - "connected": "Tilkoblet", - "clipboardWriteFailed": "Kunne ikke kopiere til utklippstavlen. Sørg for at siden serveres via HTTPS eller localhost.", - "clipboardReadFailed": "Kunne ikke lese fra utklippstavlen. Sørg for at utklippstavlen har tillatelser.", "tmuxDetach": "Koble fra tmux-økten", - "terminalTitle": "Terminal - {{host}}", - "terminalWithPath": "Terminal - {{host}}:{{path}}", - "runTitle": "Kjører {{command}} - {{host}}", "totpRequired": "Tofaktorautentisering kreves", "totpCodeLabel": "Verifiseringskode", "totpVerify": "Verifisere", @@ -1148,109 +1129,20 @@ } }, "transfer": { - "copyToHost": "Kopier til vert…", - "moveToHost": "Flytt til vert…", - "copyItemsToHost": "Kopier {{count}} elementer til å være vert for…", - "moveItemsToHost": "Flytt {{count}} elementer til vert for…", - "noHostsConnected": "Ingen andre filbehandlerverter tilgjengelig.", - "noHostsConnectedHint": "Legg til en annen SSH-vert med Filbehandling aktivert i Vertsbehandling.", - "selectDestinationHost": "Velg destinasjonsvert", - "destinationPath": "Destinasjonssti", - "recentDestinations": "Nylige destinasjoner", "collapseRecentDestinations": "Skjul nylige destinasjoner", "expandRecentDestinations": "Utvid nylige destinasjoner", - "browseFolders": "Bla gjennom målmapper", "browseDestination": "Bla gjennom eller skriv inn bane", - "confirmCopy": "Kopiere", - "confirmMove": "Flytte", "transferring": "Overfører…", - "progressVerifying": "Verifiserer filintegritet…", - "progressBenchmarking": "Velge den raskeste overgangsruten…", "compressing": "Komprimering…", "extracting": "Uttrekker…", "transferringItems": "Overføring av {{current}} av {{total}} elementer…", - "transferSuccess": "Overføringen er fullført", - "transferError": "Overføringen mislyktes", "transferPartial": "Overføringen er fullført med {{count}} feil", - "transferPartialHint": "Kunne ikke overføre: {{paths}}", - "itemsSummary": "{{count}} elementer", - "destMustBeDirectory": "Destinasjonen må være en katalog for overføringer av flere elementer", "selectThisFolder": "Velg denne mappen", - "browsePathWillBeCreated": "Denne mappen finnes ikke ennå. Den vil bli opprettet når overføringen starter.", - "browsePathError": "Kunne ikke åpne denne banen på målverten.", - "goUp": "Gå opp", - "copyFolderToHost": "Kopier mappe til vert…", - "moveFolderToHost": "Flytt mappen til verten…", - "hostReady": "Ferdig", - "hostConnecting": "Kobler til…", - "hostDisconnected": "Ikke tilkoblet", - "hostAuthRequired": "Autentisering kreves – åpne Filbehandler på denne verten først", - "hostConnectionFailed": "Tilkoblingen mislyktes", "metricsTitle": "Overføringstider", - "metricsPrepare": "Forbered destinasjon: {{duration}}", - "metricsCompress": "Komprimer på kilde: {{duration}}", "metricsHopSourceRead": "Kilde → server: {{throughput}}", "metricsHopDestSftpWrite": "Server → destinasjon (SFTP): {{throughput}}", "metricsHopDestLocalWrite": "Server → dest (lokal): {{throughput}}", - "metricsTransfer": "Ende-til-ende: {{throughput}} ({{duration}})", - "metricsExtract": "Uttrekk på destinasjon: {{duration}}", - "metricsVerify": "SHA-256 bekreftet: {{duration}}", - "metricsRouteBenchmark": "Rutesonde — direkte: {{direct}}, relé: {{relay}}", - "metricsSourceDelete": "Fjern fra kilden: {{duration}}", - "metricsTotal": "Totalt: {{duration}}", - "progressCompressing": "Komprimering på kildevert…", - "progressExtracting": "Uttrekker på destinasjon…", - "progressTransferring": "Overføring av data…", - "progressReconnecting": "Kobler til igjen…", - "parallelSegmentsLabel": "Parallelle overføringsfelt", - "parallelSegmentsOption": "{{count}} baner", - "parallelSegmentsHint": "Store filer deles inn i deler på 256 MB. Flere baner bruker separate tilkoblinger (som å starte flere overføringer) for høyere total gjennomstrømning.", - "progressTotalSpeed": "{{speed}} totalt ({{lanes}} baner)", - "progressTransferringItems": "Overføring av filer ({{current}} av {{total}})…", - "progressBytes": "{{transferred}} / {{total}}", - "progressItems": "{{current}} / {{total}} filer", - "sourceNotDeletedPartial": "Kildefiler beholdt (delvis overføring)", - "jumpHostLimitation": "Begge vertene må være tilgjengelige fra Termix-serveren. Direkte vert-til-vert-ruting støttes ikke.", - "cancel": "Kansellere", - "methodLabel": "Overføringsmetode", - "methodAuto": "Bil", - "methodTar": "Tar-arkiv", - "methodItemSftp": "SFTP per fil", - "methodAutoHint": "Velger tar eller SFTP per fil basert på antall filer, størrelse og komprimerbarhet. Enkeltfiler bruker alltid strømme-SFTP.", - "methodTarHint": "Komprimer på kildekode, overfør ett arkiv, pakk ut på destinasjon. Krever tar på begge Unix-vertene.", - "methodItemSftpHint": "Overfør hver fil individuelt via SFTP. Fungerer på alle verter, inkludert Windows.", - "methodPreviewLoading": "Beregning av overføringsmetode…", - "methodPreviewError": "Kunne ikke forhåndsvise overføringsmetoden. Serveren vil fortsatt velge en metode når du starter.", - "methodPreviewWillUseTar": "Vil bruke: Tar-arkiv", - "methodPreviewWillUseItemSftp": "Vil bruke: SFTP per fil", - "methodPreviewScanSummary": "{{fileCount}} filer, {{totalSize}} totalt (skannet på kildeverten).", - "methodItemSftpLimitation": "Hver fil bruker den samme SFTP-strømmen som en enkeltfilskopi, én etter én. Fremdriften kombineres på tvers av alle filene, så linjen beveger seg sakte under store filer.", - "methodReason": { - "user_item_sftp": "Du valgte SFTP per fil.", - "user_tar": "Du valgte tar-arkiv.", - "tar_unavailable": "Tar er ikke tilgjengelig på én eller begge vertene – SFTP per fil vil bli brukt i stedet.", - "windows_host": "En Windows-vert er involvert – tar brukes ikke.", - "auto_multi_large": "Auto: flere filer, inkludert en stor fil ({{largestSize}}) med komprimerbare data — tar-pakker i én overføring.", - "auto_single_large_in_archive": "Auto: én stor fil ({{largestSize}}) i dette settet — SFTP per fil.", - "auto_many_incompressible": "Auto: stort sett inkomprimerbare data — SFTP per fil.", - "auto_many_files": "Auto: mange filer ({{fileCount}}) — tar reduserer overhead per fil.", - "auto_default": "Auto: SFTP per fil for dette settet." - }, - "progressCancel": "Kansellere", - "progressCancelling": "Avbryter…", - "progressStalled": "Fastlåst", - "resumedHint": "Koblet til igjen en aktiv overføring som startet i et annet vindu.", - "transferCancelled": "Overføringen er avbrutt", - "transferCancelledCopyHint": "Delvise filer kan bli liggende igjen på destinasjonen.", - "transferCancelledMoveHint": "Delvise filer kan bli liggende igjen på destinasjonen. Kildefilene ble ikke fjernet.", - "cleanupDestFiles": "Rydd opp destinasjonen", - "cleanupDestFilesSuccess": "Fjernet delvise filer fra destinasjonen", - "cleanupDestFilesPartial": "Kunne ikke fjerne noen delvise filer", - "cleanupDestFilesNothing": "Ingenting å rydde opp i på destinasjonen", - "cleanupDestFilesError": "Opprydding mislyktes", - "retryTransfer": "Prøv på nytt", - "retryTransferError": "Forsøk på nytt mislyktes", - "transferFailedRetryHint": "Delvise data ble lagret på destinasjonen. Forsøket gjenopptas når forbindelsen er tilbake." + "sourceNotDeletedPartial": "Kildefiler beholdt (delvis overføring)" }, "tunnels": { "connect": "Koble til", @@ -1261,8 +1153,6 @@ "clientTunnel": "Klienttunnel", "addClientTunnel": "Legg til klienttunnel", "active": "Aktiv", - "start": "Start", - "stop": "Stoppe", "typeServerLocalDesc": "Gjeldende vert til endepunkt.", "typeServerRemoteDesc": "Endepunkt tilbake til nåværende vert.", "typeClientLocalDesc": "Lokal datamaskin til endepunkt.", @@ -1374,8 +1264,7 @@ "resetCodeRateLimitedWithTime": "Frekvens begrenset: For mange bekreftelsesforsøk. Vent {{time}} sekunder før du prøver på nytt.", "authTokenSaveFailed": "Kunne ikke lagre autentiseringstokenet", "authTokenMissing": "Serveren returnerte ikke et nytt autentiseringstoken. Vennligst logg inn på nytt.", - "failedToLoadServer": "Kunne ikke laste inn serveren", - "remoteServerRequired": "Ekstern server kreves. Koble til en ekstern server i Innstillinger for å bruke denne tilkoblingstypen." + "failedToLoadServer": "Kunne ikke laste inn serveren" }, "messages": { "registrationDisabled": "Registrering av ny konto er for øyeblikket deaktivert av en administrator. Vennligst logg inn eller kontakt en administrator.", @@ -1831,7 +1720,6 @@ "protocolLabel": "Protokoll", "domainLabel": "Domene", "domainPlaceholder": "valgfri", - "connectToTerminal": "Koble til terminalen", "connectToFiles": "Koble til filer" }, "splitScreen": { diff --git a/src/ui/locales/translated/pl_PL.json b/src/ui/locales/translated/pl_PL.json index 50d95b414..e03294f8b 100644 --- a/src/ui/locales/translated/pl_PL.json +++ b/src/ui/locales/translated/pl_PL.json @@ -324,10 +324,6 @@ "appearanceIntro": "Wybierz motyw, kolor akcentu i język. Wszystkie trzy można później zmienić w Ustawieniach.", "featuresTitle": "Co jeszcze robi Termix", "featuresIntro": "Każdy zapisany serwer można otworzyć nie tylko jako terminal. Oto, co kryje się za ikonami po lewej stronie.", - "feature_files": "Menedżer plików", - "feature_files_desc": "Przeglądaj, przesyłaj, pobieraj i edytuj pliki przez SFTP bez opuszczania aplikacji.", - "feature_tunnels": "Tunele", - "feature_tunnels_desc": "Przekierowuj porty przez serwer, aby dotrzeć do usług niewystawionych na zewnątrz.", "feature_snippets": "Snippety", "feature_snippets_desc": "Zapisuj często uruchamiane polecenia i wysyłaj je do terminala jednym kliknięciem.", "featuresRailHint": "Któraś z nich niepotrzebna? Ukryj dowolną ikonę na pasku bocznym w Ustawieniach, w sekcji Nawigacja.", @@ -449,7 +445,6 @@ "passwordSaved": "Hasło zapisane, wpisz, aby zmienić", "key": "Klucz", "credential": "Poświadczenie", - "none": "Brak", "sshPrivateKey": "Klucz prywatny SSH", "keyType": "Typ klucza", "uploadFile": "Prześlij plik", @@ -611,17 +606,12 @@ "keepaliveIntervalLabel": "Interwał utrzymywania połączenia (sekundy)", "maxKeepaliveMisses": "Maks. pominiętych keepalive", "sameHost": "Ten host (tunel bezpośredni)", - "bindHost": "Host nasłuchu", "connectionToolbar": "Pasek narzędzi połączenia", "showConnectionToolbar": "Pokaż pasek narzędzi połączenia", "showConnectionToolbarDesc": "Pokaż pasek narzędzi w sesjach SSH, RDP, VNC i Telnet tego hosta. Możesz go również tymczasowo ukryć na samym pasku narzędzi.", "proxmoxLastSyncStatus": { "success": "Powodzenie" }, - "proxmoxGuestsSelected_one": "{{count}} gość, wybrano {{selected}}", - "proxmoxGuestsSelected_other": "{{count}} gości, wybrano {{selected}}", - "proxmoxImportButton_one": "Importuj {{count}} host", - "proxmoxImportButton_other": "Importuj {{count}} hostów", "proxmoxResultSkippedNoIp": "{{count}} pominięto (nie znaleziono adresu IP)", "proxmoxStatsUrlCopied": "Skopiowano adres URL statystyk Proxmox", "copyProxmoxStatsUrlAction": "Kopiuj adres URL statystyk Proxmox", @@ -896,13 +886,11 @@ "updatedCount": "Zaktualizowano {{count}} hostów", "friendlyNameLabel": "Przyjazna nazwa", "descriptionLabel": "Opis", - "loadingHost": "Ładowanie hosta...", "loadingHosts": "Ładowanie hostów...", "loadingCredentials": "Ładowanie poświadczeń...", "noHostsYet": "Brak hostów", "noHostsYetHint": "Dodaj serwer, aby otwierać terminale, przeglądać pliki i sprawdzać metryki.", "noHostsMatchSearch": "Brak hostów pasujących do wyszukiwania", - "hostNotFound": "Nie znaleziono hosta", "searchHosts": "Wyszukaj hosty...", "sortHosts": "Sortuj hosty", "sortDefault": "Domyślna kolejność", @@ -925,7 +913,6 @@ "filterAuthKey": "Klucz SSH", "filterAuthCredential": "Poświadczenie", "filterAuthNone": "Brak", - "filterAuthOpkssh": "OPKSSH", "filterAuthStepca": "Krok CA", "filterProtocolGroup": "Protokół", "filterProtocolSsh": "SSH", @@ -1114,13 +1101,7 @@ "connect": "Połącz z hostem", "clear": "Wyczyść", "paste": "Wklej", - "connected": "Połączono", - "clipboardWriteFailed": "Nie udało się skopiować do schowka. Upewnij się, że strona jest serwowana przez HTTPS lub localhost.", - "clipboardReadFailed": "Nie udało się odczytać danych ze schowka. Upewnij się, że uprawnienia do schowka zostały przyznane.", "tmuxDetach": "Odłącz od sesji tmux", - "terminalTitle": "Terminal - {{host}}", - "terminalWithPath": "Terminal - {{host}}:{{path}}", - "runTitle": "Wykonywanie {{command}} - {{host}}", "totpRequired": "Wymagane uwierzytelnianie dwuskładnikowe", "totpCodeLabel": "Kod weryfikacyjny", "totpVerify": "Zweryfikuj", @@ -1148,109 +1129,20 @@ } }, "transfer": { - "copyToHost": "Kopiuj do hosta…", - "moveToHost": "Przenieś do hosta…", - "copyItemsToHost": "Skopiuj {{count}} elementów do hosta…", - "moveItemsToHost": "Przenieś {{count}} elementów do hosta…", - "noHostsConnected": "Brak innych hostów z menedżerem plików.", - "noHostsConnectedHint": "Dodaj kolejny host SSH z włączonym Menedżerem plików w Menedżerze hostów.", - "selectDestinationHost": "Wybierz hosta docelowego", - "destinationPath": "Ścieżka docelowa", - "recentDestinations": "Ostatnie miejsca docelowe", "collapseRecentDestinations": "Zwiń ostatnie miejsca docelowe", "expandRecentDestinations": "Rozwiń ostatnie miejsca docelowe", - "browseFolders": "Przeglądaj foldery docelowe", "browseDestination": "Przeglądaj lub wprowadź ścieżkę", - "confirmCopy": "Kopiuj", - "confirmMove": "Przenieś", "transferring": "Przenoszenie…", - "progressVerifying": "Sprawdzanie integralności pliku…", - "progressBenchmarking": "Wybór najszybszej trasy transferu…", "compressing": "Kompresja…", "extracting": "Wyodrębnianie…", "transferringItems": "Przenoszenie {{current}} z {{total}} elementów…", - "transferSuccess": "Transfer zakończony", - "transferError": "Transfer nie powiódł się", "transferPartial": "Transfer zakończony z {{count}} błędami", - "transferPartialHint": "Nie można przesłać: {{paths}}", - "itemsSummary": "{{count}} elementów", - "destMustBeDirectory": "Miejsce docelowe musi być katalogiem przy transferze wielu elementów", "selectThisFolder": "Wybierz ten folder", - "browsePathWillBeCreated": "Ten folder jeszcze nie istnieje. Zostanie utworzony po rozpoczęciu transferu.", - "browsePathError": "Nie można otworzyć tej ścieżki na hoście docelowym.", - "goUp": "W górę", - "copyFolderToHost": "Kopiuj folder do hosta…", - "moveFolderToHost": "Przenieś folder do hosta…", - "hostReady": "Gotowy", - "hostConnecting": "Łączenie…", - "hostDisconnected": "Nie połączono", - "hostAuthRequired": "Wymagane uwierzytelnienie: najpierw otwórz menedżer plików na tym hoście", - "hostConnectionFailed": "Połączenie nieudane", "metricsTitle": "Czasy transferu", - "metricsPrepare": "Przygotowanie miejsca docelowego: {{duration}}", - "metricsCompress": "Kompresja w źródle: {{duration}}", "metricsHopSourceRead": "Źródło → serwer: {{throughput}}", "metricsHopDestSftpWrite": "Serwer → cel (SFTP): {{throughput}}", "metricsHopDestLocalWrite": "Serwer → cel (lokalny): {{throughput}}", - "metricsTransfer": "Całościowo: {{throughput}} ({{duration}})", - "metricsExtract": "Rozpakowanie w miejscu docelowym: {{duration}}", - "metricsVerify": "Zweryfikowano SHA-256: {{duration}}", - "metricsRouteBenchmark": "Sonda trasy. Bezpośrednia: {{direct}}, przez przekaźnik: {{relay}}", - "metricsSourceDelete": "Usunięcie ze źródła: {{duration}}", - "metricsTotal": "Razem: {{duration}}", - "progressCompressing": "Kompresja na hoście źródłowym…", - "progressExtracting": "Wyodrębnianie w miejscu docelowym…", - "progressTransferring": "Przesyłanie danych…", - "progressReconnecting": "Ponowne łączenie…", - "parallelSegmentsLabel": "Równoległe pasy transferowe", - "parallelSegmentsOption": "{{count}} pasów", - "parallelSegmentsHint": "Duże pliki są dzielone na fragmenty po 256 MB. Wiele pasów korzysta z osobnych połączeń (jak uruchomienie kilku transferów naraz), co daje większą łączną przepustowość.", - "progressTotalSpeed": "{{speed}} łącznie ({{lanes}} pasów)", - "progressTransferringItems": "Przesyłanie plików ({{current}} z {{total}})…", - "progressBytes": "{{transferred}} / {{total}}", - "progressItems": "{{current}} / {{total}} plików", - "sourceNotDeletedPartial": "Zachowano pliki źródłowe (częściowy transfer)", - "jumpHostLimitation": "Oba hosty muszą być osiągalne z serwera Termix. Bezpośrednie trasowanie między hostami nie jest obsługiwane.", - "cancel": "Anuluj", - "methodLabel": "Metoda transferu", - "methodAuto": "Auto", - "methodTar": "Archiwum tar", - "methodItemSftp": "SFTP dla każdego pliku", - "methodAutoHint": "Wybiera tar albo SFTP dla każdego pliku na podstawie liczby plików, ich rozmiaru i podatności na kompresję. Pojedyncze pliki zawsze używają strumieniowego SFTP.", - "methodTarHint": "Kompresja w źródle, transfer jednego archiwum, rozpakowanie w miejscu docelowym. Wymaga tar na obu hostach Unix.", - "methodItemSftpHint": "Przesyłaj każdy plik osobno przez SFTP. Działa na wszystkich hostach, w tym Windows.", - "methodPreviewLoading": "Obliczanie metody transferu…", - "methodPreviewError": "Nie można wyświetlić podglądu metody transferu. Serwer i tak wybierze metodę po uruchomieniu.", - "methodPreviewWillUseTar": "Zostanie użyte: archiwum tar", - "methodPreviewWillUseItemSftp": "Zostanie użyte: SFTP dla każdego pliku", - "methodPreviewScanSummary": "{{fileCount}} plików, łącznie {{totalSize}} (przeskanowano na hoście źródłowym).", - "methodItemSftpLimitation": "Każdy plik korzysta z tego samego strumienia SFTP co kopiowanie pojedynczego pliku, jeden po drugim. Postęp jest sumowany dla wszystkich plików, więc przy dużych plikach pasek przesuwa się powoli.", - "methodReason": { - "user_item_sftp": "Wybrano SFTP dla poszczególnych plików.", - "user_tar": "Wybrano archiwum tar.", - "tar_unavailable": "Tar nie jest dostępny na jednym lub obu hostach, zamiast niego zostanie użyty SFTP dla każdego pliku.", - "windows_host": "W transferze bierze udział host Windows, więc tar nie jest używany.", - "auto_multi_large": "Auto: wiele plików, w tym duży plik ({{largestSize}}) z kompresowalnymi danymi, tar pakuje je w jeden transfer.", - "auto_single_large_in_archive": "Auto: jeden duży plik ({{largestSize}}) w tym zestawie, SFTP dla każdego pliku.", - "auto_many_incompressible": "Auto: dane w większości niekompresowalne, SFTP dla każdego pliku.", - "auto_many_files": "Auto: wiele plików ({{fileCount}}), tar redukuje narzut na plik.", - "auto_default": "Auto: SFTP dla każdego pliku w tym zestawie." - }, - "progressCancel": "Anuluj", - "progressCancelling": "Anulowanie…", - "progressStalled": "Utknął", - "resumedHint": "Połączono ponownie z aktywnym transferem rozpoczętym w innym oknie.", - "transferCancelled": "Transfer anulowany", - "transferCancelledCopyHint": "W miejscu docelowym mogą pozostać częściowe pliki.", - "transferCancelledMoveHint": "W miejscu docelowym mogą pozostać częściowe pliki. Pliki źródłowe nie zostały usunięte.", - "cleanupDestFiles": "Wyczyść miejsce docelowe", - "cleanupDestFilesSuccess": "Usunięto częściowe pliki z miejsca docelowego", - "cleanupDestFilesPartial": "Niektórych częściowych plików nie można było usunąć", - "cleanupDestFilesNothing": "Nie ma czego czyścić w miejscu docelowym", - "cleanupDestFilesError": "Czyszczenie nie powiodło się", - "retryTransfer": "Ponów", - "retryTransferError": "Ponowna próba nie powiodła się", - "transferFailedRetryHint": "W miejscu docelowym zachowano częściowe dane. Ponowna próba zostanie wznowiona po przywróceniu połączenia." + "sourceNotDeletedPartial": "Zachowano pliki źródłowe (częściowy transfer)" }, "tunnels": { "connect": "Połącz", @@ -1261,8 +1153,6 @@ "clientTunnel": "Tunel klienta", "addClientTunnel": "Dodaj tunel klienta", "active": "Aktywny", - "start": "Start", - "stop": "Zatrzymaj", "typeServerLocalDesc": "Bieżący host do punktu końcowego.", "typeServerRemoteDesc": "Punkt końcowy z powrotem do bieżącego hosta.", "typeClientLocalDesc": "Komputer lokalny do punktu końcowego.", @@ -1374,8 +1264,7 @@ "resetCodeRateLimitedWithTime": "Przekroczono limit prób: zbyt wiele weryfikacji. Odczekaj {{time}} sekund przed kolejną próbą.", "authTokenSaveFailed": "Nie udało się zapisać tokenu uwierzytelniającego", "authTokenMissing": "Serwer nie zwrócił nowego tokenu uwierzytelniającego. Zaloguj się ponownie.", - "failedToLoadServer": "Nie udało się załadować serwera", - "remoteServerRequired": "Wymagany jest serwer zdalny. Połącz się z serwerem zdalnym w Ustawieniach, aby korzystać z tego typu połączenia." + "failedToLoadServer": "Nie udało się załadować serwera" }, "messages": { "registrationDisabled": "Rejestracja nowych kont jest obecnie wyłączona przez administratora. Zaloguj się lub skontaktuj się z administratorem.", @@ -1831,7 +1720,6 @@ "protocolLabel": "Protokół", "domainLabel": "Domena", "domainPlaceholder": "fakultatywny", - "connectToTerminal": "Połącz z terminalem", "connectToFiles": "Połącz z plikami" }, "splitScreen": { diff --git a/src/ui/locales/translated/pt_BR.json b/src/ui/locales/translated/pt_BR.json index 48fa74807..aec167013 100644 --- a/src/ui/locales/translated/pt_BR.json +++ b/src/ui/locales/translated/pt_BR.json @@ -324,10 +324,6 @@ "appearanceIntro": "Escolha um tema, uma cor de destaque e o seu idioma. Todos os três podem ser alterados posteriormente nas Configurações.", "featuresTitle": "O que mais a Termix faz?", "featuresIntro": "Cada servidor que você salva pode ser aberto em mais de um terminal. Veja o que está esperando por você por trás dos ícones à esquerda.", - "feature_files": "Gerenciador de arquivos", - "feature_files_desc": "Navegue, carregue, baixe e edite arquivos via SFTP sem sair do aplicativo.", - "feature_tunnels": "Túneis", - "feature_tunnels_desc": "Encaminhar portas através de um servidor para alcançar serviços que não estão expostos.", "feature_snippets": "Trechos", "feature_snippets_desc": "Salve os comandos que você executa com frequência e envie-os para um terminal com um único clique.", "featuresRailHint": "Não precisa de nenhum desses ícones? Oculte qualquer ícone da barra lateral em Configurações, na seção Navegação.", @@ -449,7 +445,6 @@ "passwordSaved": "Senha salva, digite para alterar", "key": "Chave", "credential": "Credencial", - "none": "Nenhum", "sshPrivateKey": "Chave privada SSH", "keyType": "Tipo de chave", "uploadFile": "Carregar arquivo", @@ -611,17 +606,12 @@ "keepaliveIntervalLabel": "Intervalo de Keepalive (segundos)", "maxKeepaliveMisses": "Max Keepalive falha", "sameHost": "Este host (túnel direto)", - "bindHost": "Vincular host", "connectionToolbar": "Barra de ferramentas de conexão", "showConnectionToolbar": "Mostrar barra de ferramentas de conexão", "showConnectionToolbarDesc": "Exiba a barra de ferramentas nas sessões SSH, RDP, VNC e Telnet deste host. Você também pode ocultá-la temporariamente na própria barra de ferramentas.", "proxmoxLastSyncStatus": { "success": "Sucesso" }, - "proxmoxGuestsSelected_one": "{{count}} convidado — {{selected}} selecionado", - "proxmoxGuestsSelected_other": "{{count}} convidados — {{selected}} selecionados", - "proxmoxImportButton_one": "Importar {{count}} host", - "proxmoxImportButton_other": "Importar {{count}} hosts", "proxmoxResultSkippedNoIp": "{{count}} ignorado (nenhum IP encontrado)", "proxmoxStatsUrlCopied": "URL das estatísticas do Proxmox copiada para a área de transferência", "copyProxmoxStatsUrlAction": "Copiar URL de estatísticas do Proxmox", @@ -896,13 +886,11 @@ "updatedCount": "Hosts atualizados {{count}}", "friendlyNameLabel": "Nome amigável", "descriptionLabel": "Descrição", - "loadingHost": "Carregando host...", "loadingHosts": "Carregando hosts...", "loadingCredentials": "Carregando credenciais...", "noHostsYet": "Ainda não há anfitriões.", "noHostsYetHint": "Adicione um servidor para abrir terminais, navegar por arquivos e visualizar métricas.", "noHostsMatchSearch": "Nenhum host corresponde à sua pesquisa.", - "hostNotFound": "Host não encontrado", "searchHosts": "Pesquisar hosts...", "sortHosts": "Classificar hosts", "sortDefault": "Ordem padrão", @@ -925,7 +913,6 @@ "filterAuthKey": "Chave SSH", "filterAuthCredential": "Credencial", "filterAuthNone": "Nenhum", - "filterAuthOpkssh": "OPKSSH", "filterAuthStepca": "Etapa CA", "filterProtocolGroup": "Protocolo", "filterProtocolSsh": "SSH", @@ -1114,13 +1101,7 @@ "connect": "Conectar ao host", "clear": "Claro", "paste": "Colar", - "connected": "Conectado", - "clipboardWriteFailed": "Falha ao copiar para a área de transferência. Certifique-se de que a página esteja sendo servida via HTTPS ou localhost.", - "clipboardReadFailed": "Não foi possível ler o conteúdo da área de transferência. Certifique-se de que as permissões de acesso à área de transferência estejam concedidas.", "tmuxDetach": "Desconectar da sessão tmux", - "terminalTitle": "Terminal - {{host}}", - "terminalWithPath": "Terminal - {{host}}:{{path}}", - "runTitle": "Executando {{command}} - {{host}}", "totpRequired": "Autenticação de dois fatores obrigatória", "totpCodeLabel": "Código de verificação", "totpVerify": "Verificar", @@ -1148,109 +1129,20 @@ } }, "transfer": { - "copyToHost": "Copiar para o host…", - "moveToHost": "Mover para o host…", - "copyItemsToHost": "Copiar {{count}} itens para o host…", - "moveItemsToHost": "Mova {{count}} itens para o host…", - "noHostsConnected": "Não há outros servidores de gerenciamento de arquivos disponíveis.", - "noHostsConnectedHint": "Adicione outro host SSH com o Gerenciador de Arquivos habilitado no Gerenciador de Hosts.", - "selectDestinationHost": "Selecione o host de destino", - "destinationPath": "Caminho de destino", - "recentDestinations": "Destinos recentes", "collapseRecentDestinations": "Recolher destinos recentes", "expandRecentDestinations": "Expandir destinos recentes", - "browseFolders": "Procurar pastas de destino", "browseDestination": "Navegue ou insira o caminho", - "confirmCopy": "Cópia", - "confirmMove": "Mover", "transferring": "Transferindo…", - "progressVerifying": "Verificando a integridade do arquivo…", - "progressBenchmarking": "Selecionando a rota de transferência mais rápida…", "compressing": "Comprimindo…", "extracting": "Extraindo…", "transferringItems": "Transferindo {{current}} de {{total}} itens…", - "transferSuccess": "Transferência concluída", - "transferError": "A transferência falhou", "transferPartial": "Transferência concluída com {{count}} erros", - "transferPartialHint": "Não foi possível transferir: {{paths}}", - "itemsSummary": "{{count}} itens", - "destMustBeDirectory": "O destino deve ser um diretório para transferências de múltiplos itens.", "selectThisFolder": "Selecione esta pasta", - "browsePathWillBeCreated": "Esta pasta ainda não existe. Ela será criada quando a transferência começar.", - "browsePathError": "Não foi possível abrir este caminho no host de destino.", - "goUp": "Subir", - "copyFolderToHost": "Copiar pasta para o host…", - "moveFolderToHost": "Mover pasta para o host…", - "hostReady": "Preparar", - "hostConnecting": "Conectando…", - "hostDisconnected": "Não conectado", - "hostAuthRequired": "Autenticação necessária — abra o Gerenciador de Arquivos neste host primeiro.", - "hostConnectionFailed": "Falha na conexão", "metricsTitle": "Horários de transferência", - "metricsPrepare": "Preparar destino: {{duration}}", - "metricsCompress": "Comprimir na origem: {{duration}}", "metricsHopSourceRead": "Origem → servidor: {{throughput}}", "metricsHopDestSftpWrite": "Servidor → destino (SFTP): {{throughput}}", "metricsHopDestLocalWrite": "Servidor → destino (local): {{throughput}}", - "metricsTransfer": "De ponta a ponta: {{throughput}} ({{duration}})", - "metricsExtract": "Extrair no destino: {{duration}}", - "metricsVerify": "Verificado por SHA-256: {{duration}}", - "metricsRouteBenchmark": "Sondagem de rota — direta: {{direct}}, retransmissão: {{relay}}", - "metricsSourceDelete": "Remover da fonte: {{duration}}", - "metricsTotal": "Total: {{duration}}", - "progressCompressing": "Comprimindo no host de origem…", - "progressExtracting": "Extraindo no destino…", - "progressTransferring": "Transferindo dados…", - "progressReconnecting": "Reconectando…", - "parallelSegmentsLabel": "Faixas de transferência paralelas", - "parallelSegmentsOption": "{{count}} faixas", - "parallelSegmentsHint": "Arquivos grandes são divididos em partes de 256 MB. Várias vias utilizam conexões separadas (como iniciar várias transferências) para obter uma taxa de transferência total maior.", - "progressTotalSpeed": "{{speed}} total ({{lanes}} faixas)", - "progressTransferringItems": "Transferindo arquivos ({{current}} de {{total}})…", - "progressBytes": "{{transferred}} / {{total}}", - "progressItems": "{{current}} / {{total}} arquivos", - "sourceNotDeletedPartial": "Arquivos de origem mantidos (transferência parcial)", - "jumpHostLimitation": "Ambos os hosts devem ser acessíveis a partir do servidor Termix. O roteamento direto de host para host não é suportado.", - "cancel": "Cancelar", - "methodLabel": "Método de transferência", - "methodAuto": "Auto", - "methodTar": "Arquivo Tar", - "methodItemSftp": "SFTP por arquivo", - "methodAutoHint": "Seleciona o método de compactação (tar) ou SFTP por arquivo com base na quantidade de arquivos, tamanho e compressibilidade. Arquivos individuais sempre utilizam SFTP de streaming.", - "methodTarHint": "Comprima na origem, transfira um único arquivo compactado e extraia no destino. Requer o uso do tar em ambos os hosts Unix.", - "methodItemSftpHint": "Transfira cada arquivo individualmente via SFTP. Funciona em todos os hosts, incluindo Windows.", - "methodPreviewLoading": "Calculando o método de transferência…", - "methodPreviewError": "Não foi possível visualizar o método de transferência. O servidor ainda escolherá um método quando você iniciar o servidor.", - "methodPreviewWillUseTar": "Será utilizado: Arquivo tar", - "methodPreviewWillUseItemSftp": "Será utilizado: SFTP por arquivo", - "methodPreviewScanSummary": "{{fileCount}} arquivos, {{totalSize}} total (verificado no host de origem).", - "methodItemSftpLimitation": "Cada arquivo utiliza o mesmo fluxo SFTP como uma cópia de arquivo único, um após o outro. O progresso é combinado em todos os arquivos, portanto a barra se move lentamente durante a transferência de arquivos grandes.", - "methodReason": { - "user_item_sftp": "Você escolheu SFTP por arquivo.", - "user_tar": "Você escolheu o arquivo tar.", - "tar_unavailable": "O arquivo tar não está disponível em um ou ambos os hosts — em vez disso, será usado o SFTP por arquivo.", - "windows_host": "O sistema operacional host é Windows — o arquivo tar não é utilizado.", - "auto_multi_large": "Automático: vários arquivos, incluindo um arquivo grande ({{largestSize}}) com dados compressíveis — pacotes tar em uma única transferência.", - "auto_single_large_in_archive": "Automático: um arquivo grande ({{largestSize}}) neste conjunto — SFTP por arquivo.", - "auto_many_incompressible": "Automático: dados em sua maioria não compressíveis — SFTP por arquivo.", - "auto_many_files": "Automático: muitos arquivos ({{fileCount}}) — tar reduz a sobrecarga por arquivo.", - "auto_default": "Automático: SFTP por arquivo para este conjunto." - }, - "progressCancel": "Cancelar", - "progressCancelling": "Cancelando…", - "progressStalled": "Paralisado", - "resumedHint": "Reconectado a uma transferência ativa iniciada em outra janela.", - "transferCancelled": "Transferência cancelada", - "transferCancelledCopyHint": "Alguns arquivos podem permanecer no destino.", - "transferCancelledMoveHint": "É possível que alguns arquivos permaneçam no destino. Os arquivos de origem não foram removidos.", - "cleanupDestFiles": "destino de limpeza", - "cleanupDestFilesSuccess": "Arquivos parciais removidos do destino.", - "cleanupDestFilesPartial": "Alguns arquivos parciais não puderam ser removidos.", - "cleanupDestFilesNothing": "Nada para limpar no destino.", - "cleanupDestFilesError": "A limpeza falhou", - "retryTransfer": "Tentar novamente", - "retryTransferError": "A nova tentativa falhou.", - "transferFailedRetryHint": "Dados parciais foram mantidos no destino. A tentativa será retomada quando a conexão for restabelecida." + "sourceNotDeletedPartial": "Arquivos de origem mantidos (transferência parcial)" }, "tunnels": { "connect": "Conectar", @@ -1261,8 +1153,6 @@ "clientTunnel": "Túnel do Cliente", "addClientTunnel": "Adicionar túnel de cliente", "active": "Ativo", - "start": "Começar", - "stop": "Parar", "typeServerLocalDesc": "Host atual para endpoint.", "typeServerRemoteDesc": "Retorno do ponto final para o host atual.", "typeClientLocalDesc": "Computador local para ponto final.", @@ -1374,8 +1264,7 @@ "resetCodeRateLimitedWithTime": "Taxa de tentativas limitada: Muitas tentativas de verificação. Aguarde {{time}} segundos antes de tentar novamente.", "authTokenSaveFailed": "Falha ao salvar o token de autenticação", "authTokenMissing": "O servidor não retornou um novo token de autenticação. Por favor, faça login novamente.", - "failedToLoadServer": "Falha ao carregar o servidor", - "remoteServerRequired": "É necessário um servidor remoto. Conecte um servidor remoto nas Configurações para usar este tipo de conexão." + "failedToLoadServer": "Falha ao carregar o servidor" }, "messages": { "registrationDisabled": "O cadastro de novas contas está temporariamente desativado por um administrador. Faça login ou entre em contato com um administrador.", @@ -1831,7 +1720,6 @@ "protocolLabel": "Protocolo", "domainLabel": "Domínio", "domainPlaceholder": "opcional", - "connectToTerminal": "Conectar ao terminal", "connectToFiles": "Conectar aos arquivos" }, "splitScreen": { diff --git a/src/ui/locales/translated/pt_PT.json b/src/ui/locales/translated/pt_PT.json index b4480ad98..1c3acce70 100644 --- a/src/ui/locales/translated/pt_PT.json +++ b/src/ui/locales/translated/pt_PT.json @@ -324,10 +324,6 @@ "appearanceIntro": "Escolha um tema, uma cor de destaque e o seu idioma. Todos os três podem ser alterados posteriormente nas Definições.", "featuresTitle": "O que mais faz a Termix?", "featuresIntro": "Cada servidor que guarda pode ser aberto em mais do que um terminal. Veja o que o espera por trás dos ícones à esquerda.", - "feature_files": "Gestor de arquivos", - "feature_files_desc": "Navegue, carregue, descarregue e edite ficheiros via SFTP sem sair da aplicação.", - "feature_tunnels": "Túneis", - "feature_tunnels_desc": "Encaminhar portas através de um servidor para chegar a serviços que não estão expostos.", "feature_snippets": "Trechos", "feature_snippets_desc": "Guarde os comandos que executa com frequência e envie-os para um terminal com um único clique.", "featuresRailHint": "Não precisa de nenhum destes ícones? Oculte qualquer ícone da barra lateral em Definições, na secção Navegação.", @@ -449,7 +445,6 @@ "passwordSaved": "Palavra-passe guardada, digite para alterar", "key": "Chave", "credential": "Credencial", - "none": "Nenhum", "sshPrivateKey": "Chave Privada SSH", "keyType": "Tipo de Chave", "uploadFile": "Carregar Ficheiro", @@ -611,17 +606,12 @@ "keepaliveIntervalLabel": "Intervalo de Keepalive (segundos)", "maxKeepaliveMisses": "Máximo de falhas de Keepalive", "sameHost": "Este host (túnel direto)", - "bindHost": "Host de Ligação", "connectionToolbar": "Barra de ferramentas de ligação", "showConnectionToolbar": "Mostrar barra de ferramentas de ligação", "showConnectionToolbarDesc": "Apresente a barra de ferramentas nas sessões SSH, RDP, VNC e Telnet deste host. Também pode ocultá-la temporariamente na própria barra de ferramentas.", "proxmoxLastSyncStatus": { "success": "Sucesso" }, - "proxmoxGuestsSelected_one": "{{count}} convidado — {{selected}} selecionado", - "proxmoxGuestsSelected_other": "{{count}} convidados — {{selected}} selecionados", - "proxmoxImportButton_one": "Importar {{count}} host", - "proxmoxImportButton_other": "Importar {{count}} hosts", "proxmoxResultSkippedNoIp": "{{count}} ignorado (nenhum IP encontrado)", "proxmoxStatsUrlCopied": "URL das estatísticas do Proxmox copiado para a área de transferência", "copyProxmoxStatsUrlAction": "Copiar URL das estatísticas do Proxmox", @@ -896,13 +886,11 @@ "updatedCount": "Atualizados {{count}} hosts", "friendlyNameLabel": "Nome Amigável", "descriptionLabel": "Descrição", - "loadingHost": "A carregar o host...", "loadingHosts": "A carregar hosts...", "loadingCredentials": "A carregar credenciais...", "noHostsYet": "Ainda sem hosts", "noHostsYetHint": "Adicione um servidor para abrir terminais, navegar por ficheiros e visualizar métricas.", "noHostsMatchSearch": "Nenhum host corresponde à sua pesquisa", - "hostNotFound": "Host não encontrado", "searchHosts": "Pesquisar hosts...", "sortHosts": "Ordenar Hosts", "sortDefault": "Ordem Padrão", @@ -925,7 +913,6 @@ "filterAuthKey": "Chave SSH", "filterAuthCredential": "Credencial", "filterAuthNone": "Nenhuma", - "filterAuthOpkssh": "OPKSSH", "filterAuthStepca": "Etapa CA", "filterProtocolGroup": "Protocolo", "filterProtocolSsh": "SSH", @@ -1114,13 +1101,7 @@ "connect": "Ligar ao Host", "clear": "Limpar", "paste": "Colar", - "connected": "Ligado", - "clipboardWriteFailed": "Erro ao copiar para a área de transferência. Certifique-se de que a página é servida via HTTPS ou localhost.", - "clipboardReadFailed": "Erro ao ler da área de transferência. Certifique-se de que as permissões da área de transferência foram concedidas.", "tmuxDetach": "Desanexar da sessão tmux", - "terminalTitle": "Terminal - {{host}}", - "terminalWithPath": "Terminal - {{host}}:{{path}}", - "runTitle": "A executar {{command}} - {{host}}", "totpRequired": "Autenticação de dois fatores necessária", "totpCodeLabel": "Código de verificação", "totpVerify": "Verificar", @@ -1148,109 +1129,20 @@ } }, "transfer": { - "copyToHost": "Copiar para o host…", - "moveToHost": "Mover para o host…", - "copyItemsToHost": "Copiar {{count}} itens para o host…", - "moveItemsToHost": "Mover {{count}} itens para o host…", - "noHostsConnected": "Não há outros hosts do gestor de ficheiros disponíveis.", - "noHostsConnectedHint": "Adicione outro host SSH com o Gestor de Ficheiros ativado no Gestor de Hosts.", - "selectDestinationHost": "Selecionar host de destino", - "destinationPath": "Caminho de destino", - "recentDestinations": "Destinos recentes", "collapseRecentDestinations": "Recolher destinos recentes", "expandRecentDestinations": "Expandir destinos recentes", - "browseFolders": "Navegar pelas pastas de destino", "browseDestination": "Navegar ou introduzir o caminho", - "confirmCopy": "Copiar", - "confirmMove": "Mover", "transferring": "A transferir…", - "progressVerifying": "Verificação da integridade do ficheiro…", - "progressBenchmarking": "Selecionando a rota de transferência mais rápida…", "compressing": "A comprimir…", "extracting": "A extrair…", "transferringItems": "A transferir {{current}} de {{total}} itens…", - "transferSuccess": "Transferência concluída", - "transferError": "Transferência falhou", "transferPartial": "Transferência concluída com {{count}} erros", - "transferPartialHint": "Não foi possível transferir: {{paths}}", - "itemsSummary": "{{count}} itens", - "destMustBeDirectory": "O destino deve ser uma pasta para transferências de vários itens.", "selectThisFolder": "Selecionar esta pasta", - "browsePathWillBeCreated": "Esta pasta ainda não existe. Será criada quando a transferência for iniciada.", - "browsePathError": "Não foi possível abrir este caminho no host de destino.", - "goUp": "Subir", - "copyFolderToHost": "Copiar pasta para o host…", - "moveFolderToHost": "Mover pasta para o host…", - "hostReady": "Pronto", - "hostConnecting": "A ligar…", - "hostDisconnected": "Desligado", - "hostAuthRequired": "Autenticação necessária — abra o Gestor de Ficheiros neste host primeiro", - "hostConnectionFailed": "Falha na ligação", "metricsTitle": "Tempos de transferência", - "metricsPrepare": "Preparar destino: {{duration}}", - "metricsCompress": "Compressão na origem: {{duration}}", "metricsHopSourceRead": "Origem → servidor: {{throughput}}", "metricsHopDestSftpWrite": "Servidor → destino (SFTP): {{throughput}}", "metricsHopDestLocalWrite": "Servidor → destino (local): {{throughput}}", - "metricsTransfer": "Ponta a ponta: {{throughput}} ({{duration}})", - "metricsExtract": "Extração no destino: {{duration}}", - "metricsVerify": "Verificado por SHA-256: {{duration}}", - "metricsRouteBenchmark": "Sondagem de percurso — direta: {{direct}}, retransmissão: {{relay}}", - "metricsSourceDelete": "Remoção da origem: {{duration}}", - "metricsTotal": "Total: {{duration}}", - "progressCompressing": "A comprimir no host de origem…", - "progressExtracting": "A extrair no destino…", - "progressTransferring": "A transferir dados…", - "progressReconnecting": "A reconectar…", - "parallelSegmentsLabel": "Vias de transferência paralelas", - "parallelSegmentsOption": "{{count}} vias", - "parallelSegmentsHint": "Os ficheiros grandes são divididos em partes de 256 MB. Múltiplas vias utilizam ligações separadas (como iniciar várias transferências) para um maior débito total.", - "progressTotalSpeed": "{{speed}} total ({{lanes}} vias)", - "progressTransferringItems": "A transferir ficheiros ({{current}} de {{total}})…", - "progressBytes": "{{transferred}} / {{total}}", - "progressItems": "{{current}} / {{total}} ficheiros", - "sourceNotDeletedPartial": "Ficheiros de origem mantidos (transferência parcial)", - "jumpHostLimitation": "Ambos os hosts têm de ser acessíveis a partir do servidor Termix. O encaminhamento direto entre hosts não é suportado.", - "cancel": "Cancelar", - "methodLabel": "Método de transferência", - "methodAuto": "Automático", - "methodTar": "Arquivo Tar", - "methodItemSftp": "SFTP por ficheiro", - "methodAutoHint": "Escolhe tar ou SFTP por ficheiro com base no número de ficheiros, tamanho e compressibilidade. Os ficheiros únicos usam sempre SFTP por streaming.", - "methodTarHint": "Comprime na origem, transfere um arquivo, extrai no destino. Requer tar em ambos os hosts Unix.", - "methodItemSftpHint": "Transfere cada ficheiro individualmente por SFTP. Funciona em todos os hosts, incluindo Windows.", - "methodPreviewLoading": "A calcular o método de transferência…", - "methodPreviewError": "Não foi possível pré-visualizar o método de transferência. O servidor ainda escolherá um método quando iniciar.", - "methodPreviewWillUseTar": "Utilizará: Arquivo Tar", - "methodPreviewWillUseItemSftp": "Utilizará: SFTP por ficheiro", - "methodPreviewScanSummary": "{{fileCount}} ficheiros, {{totalSize}} no total (analisados no host de origem).", - "methodItemSftpLimitation": "Cada ficheiro utiliza o mesmo stream SFTP como uma cópia de um único ficheiro, um após o outro. O progresso é combinado para todos os ficheiros, pelo que a barra se move lentamente durante ficheiros grandes.", - "methodReason": { - "user_item_sftp": "Optou por SFTP ficheiro a ficheiro.", - "user_tar": "Optou por ficheiro tar.", - "tar_unavailable": "O tar não está disponível num ou em ambos os anfitriões — será usado SFTP ficheiro a ficheiro.", - "windows_host": "Está envolvido um anfitrião Windows — o tar não é utilizado.", - "auto_multi_large": "Automático: vários ficheiros, incluindo um grande ({{largestSize}}) com dados compressíveis — o tar agrupa numa transferência única.", - "auto_single_large_in_archive": "Automático: um ficheiro grande ({{largestSize}}) neste conjunto — SFTP ficheiro a ficheiro.", - "auto_many_incompressible": "Automático: dados maioritariamente incompressíveis — SFTP ficheiro a ficheiro.", - "auto_many_files": "Automático: muitos ficheiros ({{fileCount}}) — o tar reduz a sobrecarga por ficheiro.", - "auto_default": "Automático: SFTP ficheiro a ficheiro para este conjunto." - }, - "progressCancel": "Cancelar", - "progressCancelling": "A cancelar…", - "progressStalled": "Parado", - "resumedHint": "Reconectado a uma transferência ativa iniciada noutra janela.", - "transferCancelled": "Transferência cancelada", - "transferCancelledCopyHint": "Poderão permanecer ficheiros parciais no destino.", - "transferCancelledMoveHint": "Poderão permanecer ficheiros parciais no destino. Os ficheiros de origem não foram removidos.", - "cleanupDestFiles": "Limpar destino", - "cleanupDestFilesSuccess": "Ficheiros parciais removidos do destino.", - "cleanupDestFilesPartial": "Não foi possível remover alguns ficheiros parciais.", - "cleanupDestFilesNothing": "Nada a limpar no destino.", - "cleanupDestFilesError": "A limpeza falhou.", - "retryTransfer": "Repetir", - "retryTransferError": "A repetição falhou.", - "transferFailedRetryHint": "Foram mantidos dados parciais no destino. A repetição será retomada quando a ligação for restabelecida." + "sourceNotDeletedPartial": "Ficheiros de origem mantidos (transferência parcial)" }, "tunnels": { "connect": "Ligar", @@ -1261,8 +1153,6 @@ "clientTunnel": "Túnel de cliente", "addClientTunnel": "Adicionar túnel de cliente", "active": "Ativo", - "start": "Iniciar", - "stop": "Parar", "typeServerLocalDesc": "Do host atual para o endpoint.", "typeServerRemoteDesc": "Do endpoint de volta para o host atual.", "typeClientLocalDesc": "Do computador local para o endpoint.", @@ -1374,8 +1264,7 @@ "resetCodeRateLimitedWithTime": "Limite de tentativas: demasiadas tentativas de verificação. Por favor, aguarde {{time}} segundos antes de tentar novamente.", "authTokenSaveFailed": "Falha ao guardar o token de autenticação", "authTokenMissing": "O servidor não devolveu um novo token de autenticação. Por favor, inicie sessão novamente.", - "failedToLoadServer": "Falha ao carregar o servidor", - "remoteServerRequired": "É necessário um servidor remoto. Ligue um servidor remoto nas Definições para utilizar este tipo de ligação." + "failedToLoadServer": "Falha ao carregar o servidor" }, "messages": { "registrationDisabled": "O registo de novas contas está atualmente desativado por um administrador. Por favor, inicie sessão ou contacte um administrador.", @@ -1831,7 +1720,6 @@ "protocolLabel": "Protocolo", "domainLabel": "Domínio", "domainPlaceholder": "opcional", - "connectToTerminal": "Ligar ao Terminal", "connectToFiles": "Ligar aos Ficheiros" }, "splitScreen": { diff --git a/src/ui/locales/translated/ro_RO.json b/src/ui/locales/translated/ro_RO.json index 5a58cba3c..f58f9465f 100644 --- a/src/ui/locales/translated/ro_RO.json +++ b/src/ui/locales/translated/ro_RO.json @@ -324,10 +324,6 @@ "appearanceIntro": "Alege o temă, o culoare de accent și limba. Toate trei pot fi modificate ulterior în Setări.", "featuresTitle": "Ce altceva face Termix", "featuresIntro": "Fiecare server pe care îl salvezi poate fi deschis în mai multe terminale. Iată ce se află în spatele pictogramelor din stânga.", - "feature_files": "Manager de fișiere", - "feature_files_desc": "Răsfoiți, încărcați, descărcați și editați fișiere prin SFTP fără a părăsi aplicația.", - "feature_tunnels": "Tuneluri", - "feature_tunnels_desc": "Redirecționează porturile printr-un server pentru a accesa servicii care nu sunt expuse.", "feature_snippets": "Fragmente", "feature_snippets_desc": "Salvează comenzile pe care le execuți des și trimite-le către un terminal cu un singur clic.", "featuresRailHint": "Nu ai nevoie de una dintre acestea? Ascunde orice pictogramă din bara laterală din Setări, la Navigare.", @@ -449,7 +445,6 @@ "passwordSaved": "Parolă salvată, tastați pentru a o modifica", "key": "Cheie", "credential": "Acreditare", - "none": "Nici unul", "sshPrivateKey": "Cheie privată SSH", "keyType": "Tipul cheii", "uploadFile": "Încărcați fișierul", @@ -611,17 +606,12 @@ "keepaliveIntervalLabel": "Interval Keepalive (secunde)", "maxKeepaliveMisses": "Ratări maxime de menținere în viață", "sameHost": "Această gazdă (tunel direct)", - "bindHost": "Legați gazda", "connectionToolbar": "Bara de instrumente Conexiune", "showConnectionToolbar": "Afișează bara de instrumente pentru conexiuni", "showConnectionToolbarDesc": "Afișează bara de instrumente în sesiunile SSH, RDP, VNC și Telnet ale acestei gazde. De asemenea, o poți ascunde temporar din bara de instrumente.", "proxmoxLastSyncStatus": { "success": "Succes" }, - "proxmoxGuestsSelected_one": "{{count}} invitat — {{selected}} selectat", - "proxmoxGuestsSelected_other": "{{count}} invitați — {{selected}} selectați", - "proxmoxImportButton_one": "Importați gazda {{count}}", - "proxmoxImportButton_other": "Importați gazde {{count}}", "proxmoxResultSkippedNoIp": "{{count}} omis (nu a fost găsită nicio adresă IP)", "proxmoxStatsUrlCopied": "URL-ul statisticilor Proxmox a fost copiat în clipboard", "copyProxmoxStatsUrlAction": "Copiați URL-ul statisticilor Proxmox", @@ -896,13 +886,11 @@ "updatedCount": "Gazdele {{count}} actualizate", "friendlyNameLabel": "Nume prietenos", "descriptionLabel": "Descriere", - "loadingHost": "Se încarcă gazda...", "loadingHosts": "Se încarcă gazdele...", "loadingCredentials": "Se încarcă acreditările...", "noHostsYet": "Nicio gazdă încă", "noHostsYetHint": "Adăugați un server pentru a deschide terminale, a răsfoi fișiere și a vedea valori.", "noHostsMatchSearch": "Nicio gazdă nu corespunde căutării dvs.", - "hostNotFound": "Gazdă negăsită", "searchHosts": "Căutați gazde...", "sortHosts": "Sortează gazdele", "sortDefault": "Ordine implicită", @@ -925,7 +913,6 @@ "filterAuthKey": "Cheie SSH", "filterAuthCredential": "Acreditare", "filterAuthNone": "Nici unul", - "filterAuthOpkssh": "OPKSSH", "filterAuthStepca": "Pasul CA", "filterProtocolGroup": "Protocol", "filterProtocolSsh": "SSH", @@ -1114,13 +1101,7 @@ "connect": "Conectare la gazdă", "clear": "Clar", "paste": "Pastă", - "connected": "Conectat", - "clipboardWriteFailed": "Copierea în clipboard nu a reușit. Asigurați-vă că pagina este servită prin HTTPS sau localhost.", - "clipboardReadFailed": "Citirea din clipboard nu a reușit. Asigurați-vă că permisiunile de acces la clipboard sunt acordate.", "tmuxDetach": "Detașare de la sesiunea tmux", - "terminalTitle": "Terminal - {{host}}", - "terminalWithPath": "Terminal - {{host}}:{{path}}", - "runTitle": "Rulează {{command}} - {{host}}", "totpRequired": "Autentificare cu doi factori necesară", "totpCodeLabel": "Cod de verificare", "totpVerify": "Verifica", @@ -1148,109 +1129,20 @@ } }, "transfer": { - "copyToHost": "Copiați către gazdă…", - "moveToHost": "Mutare la gazdă…", - "copyItemsToHost": "Copiați elementele {{count}} pe gazda…", - "moveItemsToHost": "Mută elementele {{count}} către gazda…", - "noHostsConnected": "Nu sunt disponibile alte gazde de gestionare a fișierelor.", - "noHostsConnectedHint": "Adăugați o altă gazdă SSH cu File Manager activat în Host Manager.", - "selectDestinationHost": "Selectați gazda de destinație", - "destinationPath": "Calea de destinație", - "recentDestinations": "Destinații recente", "collapseRecentDestinations": "Restrângeți destinațiile recente", "expandRecentDestinations": "Extindeți destinațiile recente", - "browseFolders": "Răsfoiți folderele de destinație", "browseDestination": "Răsfoiți sau introduceți calea", - "confirmCopy": "Copie", - "confirmMove": "Mişcare", "transferring": "Transferarea…", - "progressVerifying": "Verificarea integrității fișierului…", - "progressBenchmarking": "Selectarea celei mai rapide rute de transfer…", "compressing": "Comprimarea…", "extracting": "Extragerea…", "transferringItems": "Se transferă {{current}} din {{total}} articole…", - "transferSuccess": "Transfer finalizat", - "transferError": "Transferul a eșuat", "transferPartial": "Transfer finalizat cu erori {{count}}", - "transferPartialHint": "Nu s-a putut transfera: {{paths}}", - "itemsSummary": "{{count}} articole", - "destMustBeDirectory": "Destinația trebuie să fie un director pentru transferurile cu mai multe elemente", "selectThisFolder": "Selectați acest folder", - "browsePathWillBeCreated": "Acest folder nu există încă. Va fi creat când va începe transferul.", - "browsePathError": "Nu s-a putut deschide această cale pe gazda destinație.", - "goUp": "Mergi sus", - "copyFolderToHost": "Copiați folderul pe gazdă…", - "moveFolderToHost": "Mută folderul pe gazdă…", - "hostReady": "Gata", - "hostConnecting": "Conectare…", - "hostDisconnected": "Neconectat", - "hostAuthRequired": "Autentificare necesară — deschideți mai întâi File Manager pe această gazdă", - "hostConnectionFailed": "Conexiunea a eșuat", "metricsTitle": "Orele de transfer", - "metricsPrepare": "Pregătiți destinația: {{duration}}", - "metricsCompress": "Comprimare pe sursă: {{duration}}", "metricsHopSourceRead": "Sursă → server: {{throughput}}", "metricsHopDestSftpWrite": "Server → destinație (SFTP): {{throughput}}", "metricsHopDestLocalWrite": "Server → destinație (locală): {{throughput}}", - "metricsTransfer": "De la un capăt la altul: {{throughput}} ({{duration}})", - "metricsExtract": "Extras la destinație: {{duration}}", - "metricsVerify": "SHA-256 verificat: {{duration}}", - "metricsRouteBenchmark": "Sondă de rută — directă: {{direct}}, releu: {{relay}}", - "metricsSourceDelete": "Eliminare din sursă: {{duration}}", - "metricsTotal": "Total: {{duration}}", - "progressCompressing": "Comprimare pe gazda sursă…", - "progressExtracting": "Extragerea la destinație…", - "progressTransferring": "Transferul datelor…", - "progressReconnecting": "Reconectare…", - "parallelSegmentsLabel": "Benzi de transfer paralele", - "parallelSegmentsOption": "{{count}} benzi", - "parallelSegmentsHint": "Fișierele mari sunt împărțite în blocuri de 256 MB. Mai multe benzi utilizează conexiuni separate (cum ar fi pornirea mai multor transferuri) pentru un debit total mai mare.", - "progressTotalSpeed": "{{speed}} total ({{lanes}} benzi)", - "progressTransferringItems": "Transferarea fișierelor ({{current}} din {{total}})…", - "progressBytes": "{{transferred}} / {{total}}", - "progressItems": "{{current}} / {{total}} fișiere", - "sourceNotDeletedPartial": "Fișiere sursă păstrate (transfer parțial)", - "jumpHostLimitation": "Ambele gazde trebuie să fie accesibile de pe serverul Termix. Rutarea directă de la gazdă la gazdă nu este acceptată.", - "cancel": "Anula", - "methodLabel": "Metoda de transfer", - "methodAuto": "Auto", - "methodTar": "Arhivă Tar", - "methodItemSftp": "SFTP per fișier", - "methodAutoHint": "Alege SFTP tar sau per fișier în funcție de numărul de fișiere, dimensiune și compresibilitate. Fișierele individuale utilizează întotdeauna SFTP în flux continuu.", - "methodTarHint": "Comprimare la sursă, transfer o arhivă, extragere la destinație. Necesită tar pe ambele gazde Unix.", - "methodItemSftpHint": "Transferă fiecare fișier individual prin SFTP. Funcționează pe toate gazdele, inclusiv Windows.", - "methodPreviewLoading": "Metoda de calcul a transferului…", - "methodPreviewError": "Nu s-a putut previzualiza metoda de transfer. Serverul va alege în continuare o metodă când porniți.", - "methodPreviewWillUseTar": "Se va folosi: arhiva Tar", - "methodPreviewWillUseItemSftp": "Se va utiliza: SFTP per fișier", - "methodPreviewScanSummary": "{{fileCount}} fișiere, {{totalSize}} în total (scanate pe gazda sursă).", - "methodItemSftpLimitation": "Fiecare fișier folosește același flux SFTP ca o copie a unui singur fișier, una după alta. Progresul este combinat în toate fișierele, astfel încât bara se mișcă lent în timpul fișierelor mari.", - "methodReason": { - "user_item_sftp": "Ai ales SFTP per fișier.", - "user_tar": "Ai ales arhiva tar.", - "tar_unavailable": "Tar nu este disponibil pe una sau ambele gazde — se va folosi în schimb SFTP per fișier.", - "windows_host": "Este implicată o gazdă Windows — nu se folosește fișierul tar.", - "auto_multi_large": "Automat: fișiere multiple, inclusiv un fișier mare ({{largestSize}}) cu date compresibile — pachete tar într-un singur transfer.", - "auto_single_large_in_archive": "Automat: un fișier mare ({{largestSize}}) în acest set — SFTP per fișier.", - "auto_many_incompressible": "Automat: date în mare parte incompresibile — SFTP per fișier.", - "auto_many_files": "Auto: multe fișiere ({{fileCount}}) — tar reduce costul per fișier.", - "auto_default": "Automat: SFTP per fișier pentru acest set." - }, - "progressCancel": "Anula", - "progressCancelling": "Anulare…", - "progressStalled": "Blocat", - "resumedHint": "Reconectare la un transfer activ început într-o altă fereastră.", - "transferCancelled": "Transfer anulat", - "transferCancelledCopyHint": "Fișiere parțiale pot rămâne în destinație.", - "transferCancelledMoveHint": "Fișiere parțiale pot rămâne în destinație. Fișierele sursă nu au fost eliminate.", - "cleanupDestFiles": "Destinația de curățare", - "cleanupDestFilesSuccess": "Fișiere parțiale eliminate din destinație", - "cleanupDestFilesPartial": "Unele fișiere parțiale nu au putut fi eliminate", - "cleanupDestFilesNothing": "Nimic de curățat la destinație", - "cleanupDestFilesError": "Curățarea a eșuat", - "retryTransfer": "Reîncercați", - "retryTransferError": "Reîncercare eșuată", - "transferFailedRetryHint": "Date parțiale au fost păstrate la destinație. Reîncercarea va fi reluată după restabilirea conexiunii." + "sourceNotDeletedPartial": "Fișiere sursă păstrate (transfer parțial)" }, "tunnels": { "connect": "Conectează-te", @@ -1261,8 +1153,6 @@ "clientTunnel": "Tunelul clientului", "addClientTunnel": "Adăugați un tunel client", "active": "Activ", - "start": "Început", - "stop": "Stop", "typeServerLocalDesc": "Gazdă curentă către endpoint.", "typeServerRemoteDesc": "Revenire la gazda curentă în punctul final.", "typeClientLocalDesc": "Calculator local către endpoint.", @@ -1374,8 +1264,7 @@ "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", "authTokenMissing": "Serverul nu a returnat un nou token de autentificare. Vă rugăm să vă conectați din nou.", - "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." + "failedToLoadServer": "Nu s-a putut încărca serverul" }, "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.", @@ -1831,7 +1720,6 @@ "protocolLabel": "Protocol", "domainLabel": "Domeniu", "domainPlaceholder": "opțional", - "connectToTerminal": "Conectați-vă la terminal", "connectToFiles": "Conectare la fișiere" }, "splitScreen": { diff --git a/src/ui/locales/translated/ru_RU.json b/src/ui/locales/translated/ru_RU.json index 5d6abeda1..7c68e03ba 100644 --- a/src/ui/locales/translated/ru_RU.json +++ b/src/ui/locales/translated/ru_RU.json @@ -324,10 +324,6 @@ "appearanceIntro": "Выберите тему оформления, акцентный цвет и язык. Все три параметра можно изменить позже в настройках.", "featuresTitle": "Чем еще занимается Termix?", "featuresIntro": "Каждый сохраненный вами сервер можно открыть не только в терминале. Вот что скрывается за значками слева.", - "feature_files": "Файловый менеджер", - "feature_files_desc": "Просматривайте, загружайте, скачивайте и редактируйте файлы по протоколу SFTP, не выходя из приложения.", - "feature_tunnels": "Туннели", - "feature_tunnels_desc": "Перенаправляйте порты через сервер для доступа к службам, которые не доступны извне.", "feature_snippets": "Фрагменты", "feature_snippets_desc": "Сохраняйте часто выполняемые команды и отправляйте их на терминал одним щелчком мыши.", "featuresRailHint": "Не нуждаетесь ни в одном из этих значков? Скройте любой значок на боковой панели в настройках, в разделе «Навигация».", @@ -449,7 +445,6 @@ "passwordSaved": "Пароль сохранен, введите для изменения.", "key": "Ключ", "credential": "Учётные данные", - "none": "Нет", "sshPrivateKey": "Приватный ключ SSH", "keyType": "Тип ключа", "uploadFile": "Загрузить файл", @@ -611,17 +606,12 @@ "keepaliveIntervalLabel": "Интервал keepalive (секунд)", "maxKeepaliveMisses": "Макс. пропусков keepalive", "sameHost": "Этот хост (прямой туннель)", - "bindHost": "Хост для привязки", "connectionToolbar": "Панель инструментов подключения", "showConnectionToolbar": "Показать панель инструментов подключения", "showConnectionToolbarDesc": "Отображать панель инструментов в сеансах SSH, RDP, VNC и Telnet этого хоста. Также можно временно скрыть её с самой панели инструментов.", "proxmoxLastSyncStatus": { "success": "Успешно" }, - "proxmoxGuestsSelected_one": "{{count}} гость — {{selected}} выбрано", - "proxmoxGuestsSelected_other": "{{count}} гостей — {{selected}} выбрано", - "proxmoxImportButton_one": "Импортировать {{count}} хост", - "proxmoxImportButton_other": "Импортировать {{count}} хостов", "proxmoxResultSkippedNoIp": "{{count}} пропущено (IP-адрес не найден)", "proxmoxStatsUrlCopied": "URL-адрес статистики Proxmox скопирован в буфер обмена.", "copyProxmoxStatsUrlAction": "Скопируйте URL-адрес статистики Proxmox.", @@ -896,13 +886,11 @@ "updatedCount": "Обновлено хостов: {{count}}", "friendlyNameLabel": "Дружественное имя", "descriptionLabel": "Описание", - "loadingHost": "Загрузка хоста...", "loadingHosts": "Загрузка хостов...", "loadingCredentials": "Загрузка учётных данных...", "noHostsYet": "Пока нет хостов", "noHostsYetHint": "Добавьте сервер, чтобы открывать терминалы, просматривать файлы и отслеживать метрики.", "noHostsMatchSearch": "Нет хостов по вашему запросу", - "hostNotFound": "Хост не найден", "searchHosts": "Поиск хостов...", "sortHosts": "Сортировка хостов", "sortDefault": "По умолчанию", @@ -925,7 +913,6 @@ "filterAuthKey": "SSH-ключ", "filterAuthCredential": "Учётные данные", "filterAuthNone": "Нет", - "filterAuthOpkssh": "OPKSSH", "filterAuthStepca": "Шаг CA", "filterProtocolGroup": "Протокол", "filterProtocolSsh": "SSH", @@ -1114,13 +1101,7 @@ "connect": "Подключиться к хосту", "clear": "Очистить", "paste": "Вставить", - "connected": "Подключено", - "clipboardWriteFailed": "Не удалось скопировать в буфер обмена. Убедитесь, что страница загружена по HTTPS или с localhost.", - "clipboardReadFailed": "Не удалось прочитать из буфера обмена. Убедитесь, что предоставлены разрешения на доступ к буферу обмена.", "tmuxDetach": "Отключиться от сессии tmux", - "terminalTitle": "Терминал - {{host}}", - "terminalWithPath": "Терминал - {{host}}:{{path}}", - "runTitle": "Выполнение {{command}} - {{host}}", "totpRequired": "Требуется двухфакторная аутентификация", "totpCodeLabel": "Код подтверждения", "totpVerify": "Подтвердить", @@ -1148,109 +1129,20 @@ } }, "transfer": { - "copyToHost": "Копировать на хост…", - "moveToHost": "Переместить на хост…", - "copyItemsToHost": "Копировать {{count}} элементов на хост…", - "moveItemsToHost": "Переместить {{count}} элементов на хост…", - "noHostsConnected": "Нет других доступных хостов с файловым менеджером.", - "noHostsConnectedHint": "Добавьте другой SSH-хост с включенным Файловым Менеджером в Менеджере Хостов.", - "selectDestinationHost": "Выберите целевой хост", - "destinationPath": "Путь назначения", - "recentDestinations": "Недавние назначения", "collapseRecentDestinations": "Свернуть недавние назначения", "expandRecentDestinations": "Развернуть недавние назначения", - "browseFolders": "Обзор папок назначения", "browseDestination": "Обзор или ввод пути", - "confirmCopy": "Копировать", - "confirmMove": "Переместить", "transferring": "Передача…", - "progressVerifying": "Проверка целостности файла…", - "progressBenchmarking": "Выбор самого быстрого маршрута пересадки…", "compressing": "Сжатие…", "extracting": "Извлечение…", "transferringItems": "Передача {{current}} из {{total}} элементов…", - "transferSuccess": "Передача завершена", - "transferError": "Ошибка передачи", "transferPartial": "Передача завершена с {{count}} ошибками", - "transferPartialHint": "Не удалось передать: {{paths}}", - "itemsSummary": "{{count}} элементов", - "destMustBeDirectory": "Для передачи нескольких элементов путь назначения должен быть папкой", "selectThisFolder": "Выбрать эту папку", - "browsePathWillBeCreated": "Эта папка ещё не существует. Она будет создана при запуске передачи.", - "browsePathError": "Не удалось открыть этот путь на целевом хосте.", - "goUp": "Вверх", - "copyFolderToHost": "Копировать папку на хост…", - "moveFolderToHost": "Переместить папку на хост…", - "hostReady": "Готов", - "hostConnecting": "Подключение…", - "hostDisconnected": "Не подключен", - "hostAuthRequired": "Требуется аутентификация — сначала откройте Файловый Менеджер на этом хосте", - "hostConnectionFailed": "Ошибка подключения", "metricsTitle": "Время передачи", - "metricsPrepare": "Подготовка назначения: {{duration}}", - "metricsCompress": "Сжатие на источнике: {{duration}}", "metricsHopSourceRead": "Источник → сервер: {{throughput}}", "metricsHopDestSftpWrite": "Сервер → назначение (SFTP): {{throughput}}", "metricsHopDestLocalWrite": "Сервер → назначение (локально): {{throughput}}", - "metricsTransfer": "Сквозной: {{throughput}} ({{duration}})", - "metricsExtract": "Распаковка на назначении: {{duration}}", - "metricsVerify": "SHA-256 проверен: {{duration}}", - "metricsRouteBenchmark": "Маршрутный зонд — прямой: {{direct}}, ретранслятор: {{relay}}", - "metricsSourceDelete": "Удаление с источника: {{duration}}", - "metricsTotal": "Всего: {{duration}}", - "progressCompressing": "Сжатие на исходном хосте…", - "progressExtracting": "Распаковка на назначении…", - "progressTransferring": "Передача данных…", - "progressReconnecting": "Переподключение…", - "parallelSegmentsLabel": "Параллельные каналы передачи", - "parallelSegmentsOption": "{{count}} каналов", - "parallelSegmentsHint": "Большие файлы разбиваются на фрагменты по 256 МБ. Несколько каналов используют отдельные соединения (как при запуске нескольких передач) для повышения общей пропускной способности.", - "progressTotalSpeed": "{{speed}} всего ({{lanes}} каналов)", - "progressTransferringItems": "Передача файлов ({{current}} из {{total}})…", - "progressBytes": "{{transferred}} / {{total}}", - "progressItems": "{{current}} / {{total}} файлов", - "sourceNotDeletedPartial": "Файлы источника сохранены (частичная передача)", - "jumpHostLimitation": "Оба хоста должны быть доступны с сервера Termix. Прямая маршрутизация между хостами не поддерживается.", - "cancel": "Отмена", - "methodLabel": "Метод передачи", - "methodAuto": "Авто", - "methodTar": "Архив Tar", - "methodItemSftp": "Пофайловый SFTP", - "methodAutoHint": "Выбирает tar или пофайловый SFTP в зависимости от количества файлов, размера и сжимаемости. Одиночные файлы всегда передаются потоковым SFTP.", - "methodTarHint": "Сжатие на источнике, передача одного архива, распаковка на назначении. Требует tar на обоих Unix-хостах.", - "methodItemSftpHint": "Передача каждого файла отдельно по SFTP. Работает на всех хостах, включая Windows.", - "methodPreviewLoading": "Расчёт метода передачи…", - "methodPreviewError": "Не удалось предварительно определить метод передачи. Сервер выберет метод при запуске.", - "methodPreviewWillUseTar": "Будет использован: Архив Tar", - "methodPreviewWillUseItemSftp": "Будет использован: Пофайловый SFTP", - "methodPreviewScanSummary": "{{fileCount}} файлов, {{totalSize}} всего (просканировано на исходном хосте).", - "methodItemSftpLimitation": "Каждый файл использует один и тот же поток SFTP, как при копировании одного файла, один за другим. Прогресс объединяется по всем файлам, поэтому индикатор движется медленно при больших файлах.", - "methodReason": { - "user_item_sftp": "Вы выбрали пофайловый SFTP.", - "user_tar": "Вы выбрали tar-архив.", - "tar_unavailable": "Tar недоступен на одном или обоих хостах — вместо этого будет использоваться пофайловый SFTP.", - "windows_host": "Участвует хост под Windows — tar не используется.", - "auto_multi_large": "Авто: несколько файлов, включая большой файл ({{largestSize}}) со сжимаемыми данными — tar объединяет в одну передачу.", - "auto_single_large_in_archive": "Авто: один большой файл ({{largestSize}}) в этом наборе — пофайловый SFTP.", - "auto_many_incompressible": "Авто: в основном несжимаемые данные — пофайловый SFTP.", - "auto_many_files": "Авто: много файлов ({{fileCount}}) — tar сокращает накладные расходы на каждый файл.", - "auto_default": "Авто: пофайловый SFTP для этого набора." - }, - "progressCancel": "Отмена", - "progressCancelling": "Отмена…", - "progressStalled": "Зависло", - "resumedHint": "Переподключено к активной передаче, запущенной в другом окне.", - "transferCancelled": "Передача отменена", - "transferCancelledCopyHint": "Частично переданные файлы могут остаться в месте назначения.", - "transferCancelledMoveHint": "Частично переданные файлы могут остаться в месте назначения. Исходные файлы не были удалены.", - "cleanupDestFiles": "Очистить место назначения", - "cleanupDestFilesSuccess": "Частично переданные файлы удалены из места назначения", - "cleanupDestFilesPartial": "Некоторые частично переданные файлы не удалось удалить", - "cleanupDestFilesNothing": "В месте назначения нечего очищать", - "cleanupDestFilesError": "Очистка не удалась", - "retryTransfer": "Повторить", - "retryTransferError": "Повтор не удался", - "transferFailedRetryHint": "Частичные данные сохранены в месте назначения. Повтор возобновится, когда соединение восстановится." + "sourceNotDeletedPartial": "Файлы источника сохранены (частичная передача)" }, "tunnels": { "connect": "Подключить", @@ -1261,8 +1153,6 @@ "clientTunnel": "Клиентский туннель", "addClientTunnel": "Добавить клиентский туннель", "active": "Активные", - "start": "Запустить", - "stop": "Остановить", "typeServerLocalDesc": "С текущего хоста на конечную точку.", "typeServerRemoteDesc": "С конечной точки обратно на текущий хост.", "typeClientLocalDesc": "С локального компьютера на конечную точку.", @@ -1374,8 +1264,7 @@ "resetCodeRateLimitedWithTime": "Превышена частота запросов: слишком много попыток подтверждения. Подождите {{time}} секунд, прежде чем повторить попытку.", "authTokenSaveFailed": "Не удалось сохранить токен аутентификации", "authTokenMissing": "Сервер не вернул новый токен аутентификации. Пожалуйста, войдите в систему снова.", - "failedToLoadServer": "Не удалось загрузить сервер", - "remoteServerRequired": "Требуется удаленный сервер. Для использования этого типа подключения подключите удаленный сервер в настройках." + "failedToLoadServer": "Не удалось загрузить сервер" }, "messages": { "registrationDisabled": "Регистрация новых учетных записей отключена администратором. Войдите в систему или обратитесь к администратору.", @@ -1831,7 +1720,6 @@ "protocolLabel": "Протокол", "domainLabel": "Домен", "domainPlaceholder": "необязательный", - "connectToTerminal": "Подключиться к терминалу", "connectToFiles": "Подключиться к файлам" }, "splitScreen": { diff --git a/src/ui/locales/translated/sr_SP.json b/src/ui/locales/translated/sr_SP.json index b44cbc849..69f502e3c 100644 --- a/src/ui/locales/translated/sr_SP.json +++ b/src/ui/locales/translated/sr_SP.json @@ -324,10 +324,6 @@ "appearanceIntro": "Изаберите тему, боју акцента и језик. Сва три можете касније променити у Подешавањима.", "featuresTitle": "Шта још Термикс ради", "featuresIntro": "Сваки сервер који сачувате може се отворити у више од терминала. Ево шта вас чека иза икона са леве стране.", - "feature_files": "Менаџер датотека", - "feature_files_desc": "Прегледајте, отпремајте, преузимајте и уређујте датотеке преко SFTP-а без напуштања апликације.", - "feature_tunnels": "Тунели", - "feature_tunnels_desc": "Прослеђујте портове кроз сервер да бисте дошли до сервиса који нису изложени.", "feature_snippets": "Исечци", "feature_snippets_desc": "Сачувајте команде које често покрећете и пошаљите их у терминал једним кликом.", "featuresRailHint": "Не треба вам један од ових? Сакријте било коју икону са бочне траке у Подешавањима, под Навигацијом.", @@ -449,7 +445,6 @@ "passwordSaved": "Лозинка сачувана, унесите текст да бисте је променили", "key": "Кључ", "credential": "Акредитив", - "none": "Ниједан", "sshPrivateKey": "SSH приватни кључ", "keyType": "Тип кључа", "uploadFile": "Отпреми датотеку", @@ -611,17 +606,12 @@ "keepaliveIntervalLabel": "Интервал одржавања активности (секунде)", "maxKeepaliveMisses": "Максимални промашаји у Keepalive-у", "sameHost": "Овај хост (директни тунел)", - "bindHost": "Повежи хост", "connectionToolbar": "Трака са алаткама за повезивање", "showConnectionToolbar": "Прикажи траку са алаткама за повезивање", "showConnectionToolbarDesc": "Прикажи траку са алаткама у SSH, RDP, VNC и Telnet сесијама овог хоста. Такође је можете привремено сакрити са саме траке са алаткама.", "proxmoxLastSyncStatus": { "success": "Успех" }, - "proxmoxGuestsSelected_one": "{{count}} гост — {{selected}} изабрано", - "proxmoxGuestsSelected_other": "{{count}} гости — {{selected}} изабрано", - "proxmoxImportButton_one": "Увоз {{count}} хоста", - "proxmoxImportButton_other": "Увези {{count}} хостова", "proxmoxResultSkippedNoIp": "{{count}} прескочено (није пронађена IP адреса)", "proxmoxStatsUrlCopied": "URL Proxmox статистике је копиран у међуспремник", "copyProxmoxStatsUrlAction": "Копирај URL статистике Proxmox-а", @@ -896,13 +886,11 @@ "updatedCount": "Ажурирани {{count}} хостови", "friendlyNameLabel": "Пријатељско име", "descriptionLabel": "Опис", - "loadingHost": "Учитавање хоста...", "loadingHosts": "Учитавање хостова...", "loadingCredentials": "Учитавање акредитива...", "noHostsYet": "Још нема домаћина", "noHostsYetHint": "Додајте сервер да бисте отворили терминале, прегледали датотеке и видели метрике.", "noHostsMatchSearch": "Ниједан хост не одговара вашој претрази", - "hostNotFound": "Хост није пронађен", "searchHosts": "Претражи хостове...", "sortHosts": "Сортирај хостове", "sortDefault": "Подразумевани редослед", @@ -925,7 +913,6 @@ "filterAuthKey": "SSH кључ", "filterAuthCredential": "Акредитив", "filterAuthNone": "Ниједан", - "filterAuthOpkssh": "ОПКШ", "filterAuthStepca": "Корак CA", "filterProtocolGroup": "Протокол", "filterProtocolSsh": "SSH", @@ -1114,13 +1101,7 @@ "connect": "Повежи се са хостом", "clear": "Јасно", "paste": "Залепи", - "connected": "Повезано", - "clipboardWriteFailed": "Копирање у међуспремник није успело. Уверите се да се страница приказује преко HTTPS-а или localhost-а.", - "clipboardReadFailed": "Читање из међуспремника није успело. Уверите се да су дозволе за међуспремник одобрене.", "tmuxDetach": "Одвоји се од tmux сесије", - "terminalTitle": "Терминал - {{host}}", - "terminalWithPath": "Терминал - {{host}}:{{path}}", - "runTitle": "Покреће се {{command}} - {{host}}", "totpRequired": "Потребна је двофакторска аутентификација", "totpCodeLabel": "Верификациони код", "totpVerify": "Верификуј", @@ -1148,109 +1129,20 @@ } }, "transfer": { - "copyToHost": "Копирај на хост…", - "moveToHost": "Премести на хост…", - "copyItemsToHost": "Копирај {{count}} ставке за хостовање…", - "moveItemsToHost": "Премести {{count}} ставке на хост…", - "noHostsConnected": "Нема других доступних хостова за управљање датотекама.", - "noHostsConnectedHint": "Додајте још један SSH хост са омогућеним File Manager-ом у Host Manager-у.", - "selectDestinationHost": "Изаберите одредишни хост", - "destinationPath": "Путања одредишта", - "recentDestinations": "Недавне дестинације", "collapseRecentDestinations": "Скупи недавна одредишта", "expandRecentDestinations": "Прошири недавна одредишта", - "browseFolders": "Прегледајте одредишне фасцикле", "browseDestination": "Прегледајте или унесите путању", - "confirmCopy": "Копија", - "confirmMove": "Помери", "transferring": "Пренос…", - "progressVerifying": "Провера интегритета датотеке…", - "progressBenchmarking": "Избор најбрже руте за трансфер…", "compressing": "Компресија…", "extracting": "Издвајање…", "transferringItems": "Пренос {{current}} од {{total}} ставки…", - "transferSuccess": "Пренос завршен", - "transferError": "Пренос није успео", "transferPartial": "Пренос завршен са {{count}} грешака", - "transferPartialHint": "Није могуће пренети: {{paths}}", - "itemsSummary": "{{count}} ставке", - "destMustBeDirectory": "Одредиште мора бити директоријум за преносе више ставки", "selectThisFolder": "Изаберите ову фасциклу", - "browsePathWillBeCreated": "Ова фасцикла још увек не постоји. Биће креирана када пренос почне.", - "browsePathError": "Није могуће отворити ову путању на одредишном хосту.", - "goUp": "Иди горе", - "copyFolderToHost": "Копирај фасциклу на хост…", - "moveFolderToHost": "Премести фасциклу на хост…", - "hostReady": "Спреман", - "hostConnecting": "Повезивање…", - "hostDisconnected": "Није повезано", - "hostAuthRequired": "Потребна је аутентификација — прво отворите File Manager на овом хосту", - "hostConnectionFailed": "Повезивање није успело", "metricsTitle": "Времена трансфера", - "metricsPrepare": "Припреми одредиште: {{duration}}", - "metricsCompress": "Компресуј на изворном коду: {{duration}}", "metricsHopSourceRead": "Извор → сервер: {{throughput}}", "metricsHopDestSftpWrite": "Сервер → одредиште (SFTP): {{throughput}}", "metricsHopDestLocalWrite": "Сервер → одредиште (локално): {{throughput}}", - "metricsTransfer": "Од краја до краја: {{throughput}} ({{duration}})", - "metricsExtract": "Издвајање на одредишту: {{duration}}", - "metricsVerify": "SHA-256 верификован: {{duration}}", - "metricsRouteBenchmark": "Сонда руте — директна: {{direct}}, релеј: {{relay}}", - "metricsSourceDelete": "Уклони из извора: {{duration}}", - "metricsTotal": "Укупно: {{duration}}", - "progressCompressing": "Компресија на изворном хосту…", - "progressExtracting": "Распакује се на одредишту…", - "progressTransferring": "Пренос података…", - "progressReconnecting": "Поновно повезивање…", - "parallelSegmentsLabel": "Паралелне траке за прелазак", - "parallelSegmentsOption": "{{count}} траке", - "parallelSegmentsHint": "Велике датотеке су подељене на делове од 256 MB. Вишеструке траке користе одвојене везе (као што је покретање неколико преноса) за већи укупни проток.", - "progressTotalSpeed": "{{speed}} укупно ({{lanes}} трака)", - "progressTransferringItems": "Пренос датотека ({{current}} од {{total}})…", - "progressBytes": "{{transferred}} / {{total}}", - "progressItems": "{{current}} / {{total}} датотеке", - "sourceNotDeletedPartial": "Изворне датотеке сачуване (делимични пренос)", - "jumpHostLimitation": "Оба хоста морају бити доступна са Termix сервера. Директно рутирање од хоста до хоста није подржано.", - "cancel": "Откажи", - "methodLabel": "Метод преноса", - "methodAuto": "Аутоматски", - "methodTar": "Тар архива", - "methodItemSftp": "SFTP по датотеци", - "methodAutoHint": "Бира tar или SFTP за сваку датотеку на основу броја датотека, величине и компресибилности. Појединачне датотеке увек користе SFTP за стримовање.", - "methodTarHint": "Компресуј на изворном нивоу, пренеси једну архиву, распакуј на одредишту. Потребан је tar на оба Unix хоста.", - "methodItemSftpHint": "Пренесите сваку датотеку појединачно преко SFTP-а. Ради на свим хостовима, укључујући Windows.", - "methodPreviewLoading": "Израчунавање методе преноса…", - "methodPreviewError": "Није могуће прегледати метод преноса. Сервер ће ипак изабрати метод када покренете.", - "methodPreviewWillUseTar": "Користиће се: Тар архива", - "methodPreviewWillUseItemSftp": "Користиће се: SFTP за сваку датотеку", - "methodPreviewScanSummary": "{{fileCount}} датотека, {{totalSize}} укупно (скенирано на изворном хосту).", - "methodItemSftpLimitation": "Свака датотека користи исти SFTP ток као и копија појединачних датотека, једна за другом. Напредак се комбинује за све датотеке, тако да се трака помера споро током великих датотека.", - "methodReason": { - "user_item_sftp": "Изабрали сте SFTP за сваку датотеку.", - "user_tar": "Изабрали сте tar архиву.", - "tar_unavailable": "Тар није доступан на једном или оба хоста — уместо тога ће се користити SFTP протокол за сваку датотеку.", - "windows_host": "Укључен је Windows хост — tar се не користи.", - "auto_multi_large": "Аутоматски: више датотека укључујући велику датотеку ({{largestSize}}) са компресибилним подацима — tar пакети у један пренос.", - "auto_single_large_in_archive": "Аутоматски: једна велика датотека ({{largestSize}}) у овом скупу — SFTP за сваку датотеку.", - "auto_many_incompressible": "Аутоматски: углавном несемпљиви подаци — SFTP по датотеци.", - "auto_many_files": "Аутоматски: много датотека ({{fileCount}}) — tar смањује оптерећење по датотеци.", - "auto_default": "Аутоматски: SFTP за сваку датотеку за овај скуп." - }, - "progressCancel": "Откажи", - "progressCancelling": "Отказивање…", - "progressStalled": "Заустављено", - "resumedHint": "Поново повезано са активним преносом започетим у другом прозору.", - "transferCancelled": "Трансфер отказан", - "transferCancelledCopyHint": "Делимични фајлови могу остати на одредишту.", - "transferCancelledMoveHint": "Делимични фајлови могу остати на одредишту. Изворни фајлови нису уклоњени.", - "cleanupDestFiles": "Очистите одредиште", - "cleanupDestFilesSuccess": "Уклоњене су делимичне датотеке са одредишта", - "cleanupDestFilesPartial": "Неке делимичне датотеке нису могле бити уклоњене", - "cleanupDestFilesNothing": "Нема ништа за чишћење на одредишту", - "cleanupDestFilesError": "Чишћење није успело", - "retryTransfer": "Покушај поново", - "retryTransferError": "Поновни покушај није успео", - "transferFailedRetryHint": "Делимични подаци су сачувани на одредишту. Покушај ће бити настављен када се веза поново успостави." + "sourceNotDeletedPartial": "Изворне датотеке сачуване (делимични пренос)" }, "tunnels": { "connect": "Повежи се", @@ -1261,8 +1153,6 @@ "clientTunnel": "Тунел клијента", "addClientTunnel": "Додај клијентски тунел", "active": "Активно", - "start": "Почетак", - "stop": "Заустави", "typeServerLocalDesc": "Тренутни хост до крајње тачке.", "typeServerRemoteDesc": "Крајња тачка назад на тренутни хост.", "typeClientLocalDesc": "Локални рачунар до крајње тачке.", @@ -1374,8 +1264,7 @@ "resetCodeRateLimitedWithTime": "Ограничена брзина: Превише покушаја верификације. Молимо сачекајте {{time}} секунди пре него што покушате поново.", "authTokenSaveFailed": "Чување токена за аутентификацију није успело", "authTokenMissing": "Сервер није вратио нови токен за аутентификацију. Молимо вас да се поново пријавите.", - "failedToLoadServer": "Учитавање сервера није успело", - "remoteServerRequired": "Потребан је удаљени сервер. Повежите се са удаљеним сервером у Подешавањима да бисте користили овај тип везе." + "failedToLoadServer": "Учитавање сервера није успело" }, "messages": { "registrationDisabled": "Регистрација новог налога је тренутно онемогућена од стране администратора. Молимо вас да се пријавите или контактирате администратора.", @@ -1831,7 +1720,6 @@ "protocolLabel": "Протокол", "domainLabel": "Домен", "domainPlaceholder": "опционо", - "connectToTerminal": "Повежи се са терминалом", "connectToFiles": "Повежи се са датотекама" }, "splitScreen": { diff --git a/src/ui/locales/translated/sv_SE.json b/src/ui/locales/translated/sv_SE.json index ade4804af..417b5327a 100644 --- a/src/ui/locales/translated/sv_SE.json +++ b/src/ui/locales/translated/sv_SE.json @@ -324,10 +324,6 @@ "appearanceIntro": "Välj ett tema, en accentfärg och ditt språk. Alla tre kan ändras senare i Inställningar.", "featuresTitle": "Vad mer gör Termix", "featuresIntro": "Varje server du sparar kan öppnas i mer än en terminal. Här är vad som väntar bakom ikonerna till vänster.", - "feature_files": "Filhanteraren", - "feature_files_desc": "Bläddra, ladda upp, ladda ner och redigera filer via SFTP utan att lämna appen.", - "feature_tunnels": "Tunnlar", - "feature_tunnels_desc": "Vidarebefordra portar via en server för att nå tjänster som inte är exponerade.", "feature_snippets": "Snuttar", "feature_snippets_desc": "Spara kommandon du kör ofta och skicka dem till en terminal med ett enda klick.", "featuresRailHint": "Behöver du inte någon av dessa? Dölj valfri ikon från sidofältet i Inställningar, under Navigering.", @@ -449,7 +445,6 @@ "passwordSaved": "Lösenordet sparats, skriv för att ändra", "key": "Nyckel", "credential": "Referenser", - "none": "Ingen", "sshPrivateKey": "SSH privat nyckel", "keyType": "Nyckeltyp", "uploadFile": "Ladda upp fil", @@ -611,17 +606,12 @@ "keepaliveIntervalLabel": "Keepalive-intervall (sekunder)", "maxKeepaliveMisses": "Max Keepalive missar", "sameHost": "Denna värd (direkt tunnel)", - "bindHost": "Bind värd", "connectionToolbar": "Anslutningsverktygsfält", "showConnectionToolbar": "Visa anslutningsverktygsfältet", "showConnectionToolbarDesc": "Visa verktygsfältet i den här värdens SSH-, RDP-, VNC- och Telnet-sessioner. Du kan också dölja det tillfälligt från själva verktygsfältet.", "proxmoxLastSyncStatus": { "success": "Framgång" }, - "proxmoxGuestsSelected_one": "{{count}} gäst — {{selected}} vald", - "proxmoxGuestsSelected_other": "{{count}} gäster — {{selected}} vald", - "proxmoxImportButton_one": "Importera {{count}} värd", - "proxmoxImportButton_other": "Importera {{count}} värdar", "proxmoxResultSkippedNoIp": "{{count}} hoppades över (ingen IP-adress hittades)", "proxmoxStatsUrlCopied": "Proxmox Stats URL kopierad till urklipp", "copyProxmoxStatsUrlAction": "Kopiera Proxmox Stats-URL", @@ -896,13 +886,11 @@ "updatedCount": "Uppdaterade {{count}} värdar", "friendlyNameLabel": "Vänligt namn", "descriptionLabel": "Beskrivning", - "loadingHost": "Laddar värd...", "loadingHosts": "Laddar värdar...", "loadingCredentials": "Laddar inloggningsuppgifter...", "noHostsYet": "Inga värdar ännu", "noHostsYetHint": "Lägg till en server för att öppna terminaler, bläddra bland filer och se mätvärden.", "noHostsMatchSearch": "Inga värdar matchar din sökning", - "hostNotFound": "Värden hittades inte", "searchHosts": "Sök värdar...", "sortHosts": "Sortera värdar", "sortDefault": "Standardbeställning", @@ -925,7 +913,6 @@ "filterAuthKey": "SSH-nyckel", "filterAuthCredential": "Referenser", "filterAuthNone": "Ingen", - "filterAuthOpkssh": "OPKSSH", "filterAuthStepca": "Steg CA", "filterProtocolGroup": "Protokoll", "filterProtocolSsh": "SSH", @@ -1114,13 +1101,7 @@ "connect": "Anslut till värd", "clear": "Rensa", "paste": "Klistra", - "connected": "Ansluten", - "clipboardWriteFailed": "Kunde inte kopiera till urklipp. Kontrollera att sidan serveras via HTTPS eller localhost.", - "clipboardReadFailed": "Kunde inte läsa från urklipp. Kontrollera att behörigheter för urklipp är beviljade.", "tmuxDetach": "Koppla bort från tmux-sessionen", - "terminalTitle": "Terminal - {{host}}", - "terminalWithPath": "Terminal - {{host}}:{{path}}", - "runTitle": "Kör {{command}} - {{host}}", "totpRequired": "Tvåfaktorsautentisering krävs", "totpCodeLabel": "Verifieringskod", "totpVerify": "Kontrollera", @@ -1148,109 +1129,20 @@ } }, "transfer": { - "copyToHost": "Kopiera till värd…", - "moveToHost": "Flytta till värd…", - "copyItemsToHost": "Kopiera {{count}} objekt till…", - "moveItemsToHost": "Flytta {{count}} objekt till…", - "noHostsConnected": "Inga andra filhanterarvärdar tillgängliga.", - "noHostsConnectedHint": "Lägg till en annan SSH-värd med Filhanteraren aktiverad i Värdhanteraren.", - "selectDestinationHost": "Välj destinationsvärd", - "destinationPath": "Destinationsväg", - "recentDestinations": "Senaste destinationerna", "collapseRecentDestinations": "Komprimera senaste destinationer", "expandRecentDestinations": "Expandera senaste destinationer", - "browseFolders": "Bläddra bland målmappar", "browseDestination": "Bläddra eller ange sökväg", - "confirmCopy": "Kopiera", - "confirmMove": "Flytta", "transferring": "Överför…", - "progressVerifying": "Verifierar filintegritet…", - "progressBenchmarking": "Välja den snabbaste bytesvägen…", "compressing": "Komprimering…", "extracting": "Extraherar…", "transferringItems": "Överför {{current}} av {{total}} objekt…", - "transferSuccess": "Överföringen är klar", - "transferError": "Överföringen misslyckades", "transferPartial": "Överföringen slutförd med {{count}} fel", - "transferPartialHint": "Kunde inte överföra: {{paths}}", - "itemsSummary": "{{count}} objekt", - "destMustBeDirectory": "Destinationen måste vara en katalog för överföringar av flera objekt", "selectThisFolder": "Välj den här mappen", - "browsePathWillBeCreated": "Den här mappen finns inte ännu. Den kommer att skapas när överföringen startar.", - "browsePathError": "Kunde inte öppna den här sökvägen på målvärden.", - "goUp": "Gå upp", - "copyFolderToHost": "Kopiera mapp till värden…", - "moveFolderToHost": "Flytta mappen till värden…", - "hostReady": "Redo", - "hostConnecting": "Ansluter…", - "hostDisconnected": "Inte ansluten", - "hostAuthRequired": "Autentisering krävs — öppna filhanteraren på den här värden först", - "hostConnectionFailed": "Anslutningen misslyckades", "metricsTitle": "Överföringstider", - "metricsPrepare": "Förbered destination: {{duration}}", - "metricsCompress": "Komprimera på källan: {{duration}}", "metricsHopSourceRead": "Källa → server: {{throughput}}", "metricsHopDestSftpWrite": "Server → destination (SFTP): {{throughput}}", "metricsHopDestLocalWrite": "Server → destination (lokal): {{throughput}}", - "metricsTransfer": "Från slut till slut: {{throughput}} ({{duration}})", - "metricsExtract": "Extrahera på destination: {{duration}}", - "metricsVerify": "SHA-256 verifierad: {{duration}}", - "metricsRouteBenchmark": "Ruttsond — direkt: {{direct}}, relä: {{relay}}", - "metricsSourceDelete": "Ta bort från källan: {{duration}}", - "metricsTotal": "Totalt: {{duration}}", - "progressCompressing": "Komprimering på källvärd…", - "progressExtracting": "Extraherar på destination…", - "progressTransferring": "Överför data…", - "progressReconnecting": "Återansluter…", - "parallelSegmentsLabel": "Parallella överföringsfält", - "parallelSegmentsOption": "{{count}} körfält", - "parallelSegmentsHint": "Stora filer delas upp i bitar på 256 MB. Flera filer använder separata anslutningar (som att starta flera överföringar) för högre total dataflöde.", - "progressTotalSpeed": "{{speed}} totalt ({{lanes}} körfält)", - "progressTransferringItems": "Överföra filer ({{current}} av {{total}})…", - "progressBytes": "{{transferred}} / {{total}}", - "progressItems": "{{current}} / {{total}} filer", - "sourceNotDeletedPartial": "Källfiler behållna (delvis överföring)", - "jumpHostLimitation": "Båda värdarna måste vara nåbara från Termix-servern. Direkt routing mellan värdar stöds inte.", - "cancel": "Avboka", - "methodLabel": "Överföringsmetod", - "methodAuto": "Bil", - "methodTar": "Tar-arkiv", - "methodItemSftp": "SFTP per fil", - "methodAutoHint": "Väljer tar eller SFTP per fil baserat på filantal, storlek och komprimerbarhet. Enstaka filer använder alltid strömmande SFTP.", - "methodTarHint": "Komprimera vid källan, överför ett arkiv, extrahera vid destinationen. Kräver tar på båda Unix-värdarna.", - "methodItemSftpHint": "Överför varje fil individuellt via SFTP. Fungerar på alla värdar inklusive Windows.", - "methodPreviewLoading": "Beräkning av överföringsmetod…", - "methodPreviewError": "Kunde inte förhandsgranska överföringsmetoden. Servern kommer fortfarande att välja en metod när du startar.", - "methodPreviewWillUseTar": "Kommer att använda: Tar-arkiv", - "methodPreviewWillUseItemSftp": "Kommer att använda: SFTP per fil", - "methodPreviewScanSummary": "{{fileCount}} filer, {{totalSize}} totalt (skannat på källvärd).", - "methodItemSftpLimitation": "Varje fil använder samma SFTP-ström som en kopia av en enda fil, en efter en. Förloppet kombineras över alla filer, så stapeln rör sig långsamt vid stora filer.", - "methodReason": { - "user_item_sftp": "Du valde SFTP per fil.", - "user_tar": "Du valde tar-arkivet.", - "tar_unavailable": "Tar är inte tillgängligt på en eller båda värdarna — SFTP per fil kommer att användas istället.", - "windows_host": "En Windows-värd är inblandad — tar används inte.", - "auto_multi_large": "Auto: flera filer inklusive en stor fil ({{largestSize}}) med komprimerbar data — tar-paket samlas i en överföring.", - "auto_single_large_in_archive": "Auto: en stor fil ({{largestSize}}) i denna uppsättning — SFTP per fil.", - "auto_many_incompressible": "Auto: mestadels inkomprimerbar data — SFTP per fil.", - "auto_many_files": "Auto: många filer ({{fileCount}}) — tar minskar overhead per fil.", - "auto_default": "Auto: SFTP per fil för den här uppsättningen." - }, - "progressCancel": "Avboka", - "progressCancelling": "Avbryter…", - "progressStalled": "Stannade", - "resumedHint": "Återansluten till en aktiv överföring som startade i ett annat fönster.", - "transferCancelled": "Överföringen avbruten", - "transferCancelledCopyHint": "Delvisa filer kan finnas kvar på destinationen.", - "transferCancelledMoveHint": "Delvisa filer kan finnas kvar på destinationen. Källfilerna togs inte bort.", - "cleanupDestFiles": "Städa upp destinationen", - "cleanupDestFilesSuccess": "Tog bort delvisa filer från destinationen", - "cleanupDestFilesPartial": "Vissa delfiler kunde inte tas bort", - "cleanupDestFilesNothing": "Inget att städa upp på destinationen", - "cleanupDestFilesError": "Rensningen misslyckades", - "retryTransfer": "Försöka igen", - "retryTransferError": "Återförsök misslyckades", - "transferFailedRetryHint": "Delvis data sparades på destinationen. Försöket återupptas när anslutningen är tillbaka." + "sourceNotDeletedPartial": "Källfiler behållna (delvis överföring)" }, "tunnels": { "connect": "Ansluta", @@ -1261,8 +1153,6 @@ "clientTunnel": "Klienttunnel", "addClientTunnel": "Lägg till klienttunnel", "active": "Aktiv", - "start": "Start", - "stop": "Stopp", "typeServerLocalDesc": "Nuvarande värd till slutpunkt.", "typeServerRemoteDesc": "Slutpunkt tillbaka till nuvarande värd.", "typeClientLocalDesc": "Lokal dator till slutpunkt.", @@ -1374,8 +1264,7 @@ "resetCodeRateLimitedWithTime": "Begränsad hastighet: För många verifieringsförsök. Vänta {{time}} sekunder innan du försöker igen.", "authTokenSaveFailed": "Misslyckades med att spara autentiseringstoken", "authTokenMissing": "Servern returnerade inte en ny autentiseringstoken. Vänligen logga in igen.", - "failedToLoadServer": "Misslyckades med att ladda servern", - "remoteServerRequired": "Fjärrserver krävs. Anslut en fjärrserver i Inställningar för att använda den här anslutningstypen." + "failedToLoadServer": "Misslyckades med att ladda servern" }, "messages": { "registrationDisabled": "Registrering av nytt konto är för närvarande inaktiverat av en administratör. Vänligen logga in eller kontakta en administratör.", @@ -1831,7 +1720,6 @@ "protocolLabel": "Protokoll", "domainLabel": "Domän", "domainPlaceholder": "frivillig", - "connectToTerminal": "Anslut till terminalen", "connectToFiles": "Anslut till filer" }, "splitScreen": { diff --git a/src/ui/locales/translated/th_TH.json b/src/ui/locales/translated/th_TH.json index 659ef3d3c..c25bd75b3 100644 --- a/src/ui/locales/translated/th_TH.json +++ b/src/ui/locales/translated/th_TH.json @@ -324,10 +324,6 @@ "appearanceIntro": "เลือกธีม สีเน้น และภาษาของคุณ ทั้งสามอย่างนี้สามารถเปลี่ยนแปลงได้ในภายหลังในเมนูการตั้งค่า", "featuresTitle": "Termix ทำอะไรได้อีกบ้าง", "featuresIntro": "เซิร์ฟเวอร์ทุกเครื่องที่คุณบันทึกไว้สามารถเปิดได้ไม่เพียงแค่ในเทอร์มินัลเท่านั้น นี่คือสิ่งที่รออยู่เบื้องหลังไอคอนทางด้านซ้าย", - "feature_files": "ตัวจัดการไฟล์", - "feature_files_desc": "เรียกดู อัปโหลด ดาวน์โหลด และแก้ไขไฟล์ผ่าน SFTP โดยไม่ต้องออกจากแอปพลิเคชัน", - "feature_tunnels": "อุโมงค์", - "feature_tunnels_desc": "ส่งต่อพอร์ตผ่านเซิร์ฟเวอร์เพื่อเข้าถึงบริการที่ไม่เปิดเผยต่อสาธารณะ", "feature_snippets": "เศษเสี้ยว", "feature_snippets_desc": "บันทึกคำสั่งที่คุณใช้งานบ่อยและส่งไปยังเทอร์มินัลได้ด้วยการคลิกเพียงครั้งเดียว", "featuresRailHint": "ไม่ต้องการใช้ไอคอนเหล่านี้ใช่ไหม? ซ่อนไอคอนใดๆ ก็ได้จากแถบด้านข้างในเมนูการตั้งค่า ภายใต้การนำทาง", @@ -449,7 +445,6 @@ "passwordSaved": "บันทึกรหัสผ่านแล้ว กรุณาพิมพ์เพื่อเปลี่ยนรหัสผ่าน", "key": "สำคัญ", "credential": "ใบรับรอง", - "none": "ไม่มี", "sshPrivateKey": "คีย์ส่วนตัว SSH", "keyType": "ประเภทกุญแจ", "uploadFile": "อัปโหลดไฟล์", @@ -611,17 +606,12 @@ "keepaliveIntervalLabel": "ช่วงเวลาการเชื่อมต่อ (วินาที)", "maxKeepaliveMisses": "แม็กซ์ คีทอะไลฟ์ พลาด", "sameHost": "โฮสต์นี้ (อุโมงค์ตรง)", - "bindHost": "โฮสต์ผูก", "connectionToolbar": "แถบเครื่องมือการเชื่อมต่อ", "showConnectionToolbar": "แสดงแถบเครื่องมือการเชื่อมต่อ", "showConnectionToolbarDesc": "แสดงแถบเครื่องมือในเซสชัน SSH, RDP, VNC และ Telnet ของโฮสต์นี้ คุณยังสามารถซ่อนแถบเครื่องมือชั่วคราวได้จากแถบเครื่องมือโดยตรง", "proxmoxLastSyncStatus": { "success": "ความสำเร็จ" }, - "proxmoxGuestsSelected_one": "{{count}} แขก — {{selected}} เลือกแล้ว", - "proxmoxGuestsSelected_other": "แขก {{count}} คน — แขก {{selected}} คน ที่เลือก", - "proxmoxImportButton_one": "นำเข้าโฮสต์ {{count}}", - "proxmoxImportButton_other": "นำเข้าโฮสต์ {{count}}", "proxmoxResultSkippedNoIp": "{{count}} ข้ามไป (ไม่พบ IP)", "proxmoxStatsUrlCopied": "คัดลอก URL สถิติ Proxmox ไปยังคลิปบอร์ดแล้ว", "copyProxmoxStatsUrlAction": "คัดลอก URL สถิติของ Proxmox", @@ -896,13 +886,11 @@ "updatedCount": "อัปเดตโฮสต์ {{count}} แล้ว", "friendlyNameLabel": "ชื่อที่เป็นมิตร", "descriptionLabel": "คำอธิบาย", - "loadingHost": "กำลังโหลดโฮสต์...", "loadingHosts": "กำลังโหลดโฮสต์...", "loadingCredentials": "กำลังโหลดข้อมูลประจำตัว...", "noHostsYet": "ยังไม่มีโฮสต์", "noHostsYetHint": "เพิ่มเซิร์ฟเวอร์เพื่อเปิดเทอร์มินัล เรียกดูไฟล์ และดูข้อมูลสถิติ", "noHostsMatchSearch": "ไม่พบโฮสต์ใดตรงกับผลการค้นหาของคุณ", - "hostNotFound": "ไม่พบโฮสต์", "searchHosts": "ค้นหาโฮสต์...", "sortHosts": "เรียงลำดับโฮสต์", "sortDefault": "ลำดับเริ่มต้น", @@ -925,7 +913,6 @@ "filterAuthKey": "คีย์ SSH", "filterAuthCredential": "ใบรับรอง", "filterAuthNone": "ไม่มี", - "filterAuthOpkssh": "โอพีเคเอสเอช", "filterAuthStepca": "ขั้นตอน CA", "filterProtocolGroup": "โปรโตคอล", "filterProtocolSsh": "เอสเอช", @@ -1114,13 +1101,7 @@ "connect": "เชื่อมต่อกับโฮสต์", "clear": "ชัดเจน", "paste": "แปะ", - "connected": "เชื่อมต่อแล้ว", - "clipboardWriteFailed": "ไม่สามารถคัดลอกไปยังคลิปบอร์ดได้ โปรดตรวจสอบให้แน่ใจว่าหน้าเว็บนั้นให้บริการผ่าน HTTPS หรือ localhost", - "clipboardReadFailed": "ไม่สามารถอ่านข้อมูลจากคลิปบอร์ดได้ โปรดตรวจสอบให้แน่ใจว่าได้ให้สิทธิ์การเข้าถึงคลิปบอร์ดแล้ว", "tmuxDetach": "ยกเลิกการเชื่อมต่อจากเซสชัน tmux", - "terminalTitle": "เทอร์มินัล - {{host}}", - "terminalWithPath": "เทอร์มินัล - {{host}}:{{path}}", - "runTitle": "กำลังวิ่ง {{command}} - {{host}}", "totpRequired": "ต้องใช้การยืนยันตัวตนสองขั้นตอน", "totpCodeLabel": "รหัสยืนยัน", "totpVerify": "ตรวจสอบ", @@ -1148,109 +1129,20 @@ } }, "transfer": { - "copyToHost": "คัดลอกไปยังโฮสต์…", - "moveToHost": "ย้ายไปยังโฮสต์…", - "copyItemsToHost": "คัดลอกรายการ {{count}} รายการไปยังโฮสต์…", - "moveItemsToHost": "ย้ายรายการ {{count}} รายการไปยังโฮสต์…", - "noHostsConnected": "ไม่มีโฮสต์ตัวจัดการไฟล์อื่นให้บริการ", - "noHostsConnectedHint": "เพิ่มโฮสต์ SSH อีกตัวโดยเปิดใช้งานตัวจัดการไฟล์ในตัวจัดการโฮสต์", - "selectDestinationHost": "เลือกโฮสต์ปลายทาง", - "destinationPath": "เส้นทางปลายทาง", - "recentDestinations": "จุดหมายปลายทางล่าสุด", "collapseRecentDestinations": "ยุบจุดหมายปลายทางล่าสุด", "expandRecentDestinations": "ขยายข้อมูลจุดหมายปลายทางล่าสุด", - "browseFolders": "เรียกดูโฟลเดอร์ปลายทาง", "browseDestination": "เรียกดูหรือป้อนเส้นทาง", - "confirmCopy": "สำเนา", - "confirmMove": "เคลื่อนไหว", "transferring": "กำลังโอน…", - "progressVerifying": "กำลังตรวจสอบความสมบูรณ์ของไฟล์…", - "progressBenchmarking": "เลือกเส้นทางการโอนย้ายที่เร็วที่สุด…", "compressing": "กำลังบีบอัด…", "extracting": "กำลังแยก…", "transferringItems": "กำลังโอนย้ายรายการ {{current}} จำนวน {{total}} รายการ…", - "transferSuccess": "การโอนเสร็จสมบูรณ์", - "transferError": "การโอนล้มเหลว", "transferPartial": "การโอนเสร็จสมบูรณ์โดยมีข้อผิดพลาด {{count}}", - "transferPartialHint": "ไม่สามารถโอนเงินได้: {{paths}}", - "itemsSummary": "{{count}} รายการ", - "destMustBeDirectory": "สำหรับการโอนย้ายหลายรายการ ปลายทางต้องเป็นไดเร็กทอรี", "selectThisFolder": "เลือกโฟลเดอร์นี้", - "browsePathWillBeCreated": "โฟลเดอร์นี้ยังไม่มีอยู่ จะถูกสร้างขึ้นเมื่อการถ่ายโอนเริ่มต้นขึ้น", - "browsePathError": "ไม่สามารถเปิดเส้นทางนี้บนโฮสต์ปลายทางได้", - "goUp": "ขึ้นไป", - "copyFolderToHost": "คัดลอกโฟลเดอร์ไปยังโฮสต์…", - "moveFolderToHost": "ย้ายโฟลเดอร์ไปยังโฮสต์…", - "hostReady": "พร้อม", - "hostConnecting": "กำลังเชื่อมต่อ…", - "hostDisconnected": "ไม่ได้เชื่อมต่อ", - "hostAuthRequired": "ต้องมีการยืนยันตัวตน — โปรดเปิดตัวจัดการไฟล์บนโฮสต์นี้ก่อน", - "hostConnectionFailed": "การเชื่อมต่อล้มเหลว", "metricsTitle": "เวลาในการโอนย้าย", - "metricsPrepare": "เตรียมปลายทาง: {{duration}}", - "metricsCompress": "บีบอัดจากแหล่งที่มา: {{duration}}", "metricsHopSourceRead": "แหล่งที่มา → เซิร์ฟเวอร์: {{throughput}}", "metricsHopDestSftpWrite": "เซิร์ฟเวอร์ → ปลายทาง (SFTP): {{throughput}}", "metricsHopDestLocalWrite": "เซิร์ฟเวอร์ → ปลายทาง (ภายในเครื่อง): {{throughput}}", - "metricsTransfer": "จากต้นทางถึงปลายทาง: {{throughput}} ({{duration}})", - "metricsExtract": "แตกไฟล์ที่ปลายทาง: {{duration}}", - "metricsVerify": "ตรวจสอบด้วย SHA-256 แล้ว: {{duration}}", - "metricsRouteBenchmark": "การตรวจสอบเส้นทาง — โดยตรง: {{direct}}, ส่งต่อ: {{relay}}", - "metricsSourceDelete": "ลบออกจากแหล่งที่มา: {{duration}}", - "metricsTotal": "รวม: {{duration}}", - "progressCompressing": "กำลังบีบอัดบนโฮสต์ต้นทาง…", - "progressExtracting": "กำลังแตกไฟล์ที่ปลายทาง…", - "progressTransferring": "กำลังถ่ายโอนข้อมูล…", - "progressReconnecting": "กำลังเชื่อมต่อใหม่…", - "parallelSegmentsLabel": "ช่องทางเปลี่ยนถ่ายแบบขนาน", - "parallelSegmentsOption": "{{count}} เลน", - "parallelSegmentsHint": "ไฟล์ขนาดใหญ่จะถูกแบ่งออกเป็นส่วนย่อยขนาด 256 MB การใช้หลายเลนจะใช้การเชื่อมต่อแยกกัน (เช่น การเริ่มการถ่ายโอนหลายรายการพร้อมกัน) เพื่อให้ได้ปริมาณงานโดยรวมที่สูงขึ้น", - "progressTotalSpeed": "{{speed}} รวม ({{lanes}} เลน)", - "progressTransferringItems": "กำลังถ่ายโอนไฟล์ ({{current}} จาก {{total}})…", - "progressBytes": "{{transferred}} / {{total}}", - "progressItems": "ไฟล์ {{current}} / {{total}}", - "sourceNotDeletedPartial": "ไฟล์ต้นฉบับถูกเก็บไว้ (ถ่ายโอนบางส่วน)", - "jumpHostLimitation": "โฮสต์ทั้งสองต้องสามารถเข้าถึงได้จากเซิร์ฟเวอร์ Termix การกำหนดเส้นทางโดยตรงระหว่างโฮสต์ไม่ได้รับการสนับสนุน", - "cancel": "ยกเลิก", - "methodLabel": "วิธีการถ่ายโอน", - "methodAuto": "อัตโนมัติ", - "methodTar": "คลังข้อมูลทาร์", - "methodItemSftp": "SFTP ต่อไฟล์", - "methodAutoHint": "เลือกใช้ไฟล์บีบอัดแบบ tar หรือ SFTP แบบต่อไฟล์ โดยพิจารณาจากจำนวนไฟล์ ขนาดไฟล์ และความสามารถในการบีบอัด ไฟล์เดี่ยวจะใช้ SFTP แบบสตรีมมิ่งเสมอ", - "methodTarHint": "บีบอัดไฟล์ที่ต้นทาง ถ่ายโอนไฟล์เก็บถาวรหนึ่งไฟล์ และแตกไฟล์ที่ปลายทาง ต้องใช้ tar บนเครื่อง Unix ทั้งสองเครื่อง", - "methodItemSftpHint": "โอนไฟล์แต่ละไฟล์ทีละไฟล์ผ่าน SFTP ใช้งานได้กับทุกระบบปฏิบัติการ รวมถึง Windows", - "methodPreviewLoading": "กำลังคำนวณวิธีการโอน…", - "methodPreviewError": "ไม่สามารถดูตัวอย่างวิธีการถ่ายโอนได้ เซิร์ฟเวอร์จะเลือกวิธีการเมื่อคุณเริ่มต้นใช้งาน", - "methodPreviewWillUseTar": "จะใช้: ไฟล์เก็บถาวร Tar", - "methodPreviewWillUseItemSftp": "จะใช้: SFTP แบบแยกไฟล์", - "methodPreviewScanSummary": "ไฟล์ {{fileCount}} ไฟล์, รวม {{totalSize}} ไฟล์ (สแกนจากโฮสต์ต้นทาง)", - "methodItemSftpLimitation": "แต่ละไฟล์จะใช้สตรีม SFTP เดียวกันในการคัดลอกไฟล์ทีละไฟล์ ความคืบหน้าจะถูกรวมเข้าด้วยกัน ทำให้แถบแสดงความคืบหน้าเคลื่อนที่ช้าลงเมื่อคัดลอกไฟล์ขนาดใหญ่", - "methodReason": { - "user_item_sftp": "คุณเลือกใช้ SFTP แบบต่อไฟล์", - "user_tar": "คุณเลือกไฟล์เก็บถาวรแบบ tar", - "tar_unavailable": "Tar ไม่สามารถใช้งานได้บนโฮสต์หนึ่งหรือทั้งสองโฮสต์ จึงจะใช้ SFTP แบบแยกไฟล์แทน", - "windows_host": "ระบบปฏิบัติการที่ใช้คือ Windows — ไม่ได้ใช้โปรแกรม tar", - "auto_multi_large": "อัตโนมัติ: ไฟล์หลายไฟล์ รวมถึงไฟล์ขนาดใหญ่ ({{largestSize}}) ที่มีข้อมูลที่สามารถบีบอัดได้ — tar จะรวมไฟล์เหล่านั้นไว้ในการถ่ายโอนครั้งเดียว", - "auto_single_large_in_archive": "อัตโนมัติ: ไฟล์ขนาดใหญ่หนึ่งไฟล์ ({{largestSize}}) ในชุดนี้ — SFTP ต่อไฟล์", - "auto_many_incompressible": "อัตโนมัติ: ข้อมูลส่วนใหญ่ไม่สามารถบีบอัดได้ — SFTP แบบแยกไฟล์", - "auto_many_files": "อัตโนมัติ: หลายไฟล์ ({{fileCount}}) — tar ช่วยลดภาระต่อไฟล์", - "auto_default": "อัตโนมัติ: ตั้งค่า SFTP สำหรับแต่ละไฟล์ในชุดนี้" - }, - "progressCancel": "ยกเลิก", - "progressCancelling": "การยกเลิก…", - "progressStalled": "หยุดชะงัก", - "resumedHint": "เชื่อมต่อใหม่กับการถ่ายโอนที่เริ่มทำงานในหน้าต่างอื่นแล้ว", - "transferCancelled": "การโอนเงินถูกยกเลิก", - "transferCancelledCopyHint": "ไฟล์บางส่วนอาจยังคงอยู่ในปลายทาง", - "transferCancelledMoveHint": "ไฟล์บางส่วนอาจยังคงอยู่ในปลายทาง ไฟล์ต้นฉบับไม่ได้ถูกลบออก", - "cleanupDestFiles": "สถานที่ทำความสะอาด", - "cleanupDestFilesSuccess": "ลบไฟล์บางส่วนออกจากปลายทางแล้ว", - "cleanupDestFilesPartial": "ไม่สามารถลบไฟล์บางส่วนได้", - "cleanupDestFilesNothing": "ไม่มีอะไรต้องทำความสะอาดที่ปลายทาง", - "cleanupDestFilesError": "การทำความสะอาดล้มเหลว", - "retryTransfer": "ลองใหม่อีกครั้ง", - "retryTransferError": "การลองใหม่ล้มเหลว", - "transferFailedRetryHint": "ข้อมูลบางส่วนถูกเก็บไว้ในปลายทาง การลองใหม่จะดำเนินการต่อเมื่อการเชื่อมต่อกลับมาใช้งานได้" + "sourceNotDeletedPartial": "ไฟล์ต้นฉบับถูกเก็บไว้ (ถ่ายโอนบางส่วน)" }, "tunnels": { "connect": "เชื่อมต่อ", @@ -1261,8 +1153,6 @@ "clientTunnel": "อุโมงค์ลูกค้า", "addClientTunnel": "เพิ่มอุโมงค์ไคลเอ็นต์", "active": "คล่องแคล่ว", - "start": "เริ่ม", - "stop": "หยุด", "typeServerLocalDesc": "ปัจจุบันโฮสต์ไปยังเอนด์พอยต์", "typeServerRemoteDesc": "ปลายทางกลับไปยังโฮสต์ปัจจุบัน", "typeClientLocalDesc": "คอมพิวเตอร์ในพื้นที่เชื่อมต่อกับอุปกรณ์ปลายทาง", @@ -1374,8 +1264,7 @@ "resetCodeRateLimitedWithTime": "จำกัดจำนวนครั้ง: มีการพยายามยืนยันมากเกินไป โปรดรอ {{time}} วินาทีก่อนลองอีกครั้ง", "authTokenSaveFailed": "ไม่สามารถบันทึกโทเค็นการตรวจสอบสิทธิ์ได้", "authTokenMissing": "เซิร์ฟเวอร์ไม่ได้ส่งโทเค็นการตรวจสอบสิทธิ์ใหม่กลับมา โปรดเข้าสู่ระบบอีกครั้ง", - "failedToLoadServer": "ไม่สามารถโหลดเซิร์ฟเวอร์ได้", - "remoteServerRequired": "จำเป็นต้องใช้เซิร์ฟเวอร์ระยะไกล เชื่อมต่อเซิร์ฟเวอร์ระยะไกลในการตั้งค่าเพื่อใช้ประเภทการเชื่อมต่อนี้" + "failedToLoadServer": "ไม่สามารถโหลดเซิร์ฟเวอร์ได้" }, "messages": { "registrationDisabled": "ขณะนี้ผู้ดูแลระบบได้ปิดใช้งานการลงทะเบียนบัญชีใหม่แล้ว โปรดเข้าสู่ระบบหรือติดต่อผู้ดูแลระบบ", @@ -1831,7 +1720,6 @@ "protocolLabel": "โปรโตคอล", "domainLabel": "โดเมน", "domainPlaceholder": "ไม่จำเป็น", - "connectToTerminal": "เชื่อมต่อกับเทอร์มินัล", "connectToFiles": "เชื่อมต่อกับไฟล์" }, "splitScreen": { diff --git a/src/ui/locales/translated/tr_TR.json b/src/ui/locales/translated/tr_TR.json index b18943420..981f2e03e 100644 --- a/src/ui/locales/translated/tr_TR.json +++ b/src/ui/locales/translated/tr_TR.json @@ -324,10 +324,6 @@ "appearanceIntro": "Bir tema, bir vurgu rengi ve dil seçin. Bu üçü de daha sonra Ayarlar'dan değiştirilebilir.", "featuresTitle": "Termix başka neler yapıyor?", "featuresIntro": "Kaydettiğiniz her sunucu, terminalden daha fazlasında açılabilir. Soldaki simgelerin arkasında sizi bekleyenler şunlardır.", - "feature_files": "Dosya yöneticisi", - "feature_files_desc": "Uygulamadan çıkmadan SFTP üzerinden dosyalara göz atın, yükleyin, indirin ve düzenleyin.", - "feature_tunnels": "Tüneller", - "feature_tunnels_desc": "Sunucu üzerinden port yönlendirmesi yaparak, erişime açık olmayan hizmetlere ulaşabilirsiniz.", "feature_snippets": "Kısa bölümler", "feature_snippets_desc": "Sık kullandığınız komutları kaydedin ve tek tıklamayla terminale gönderin.", "featuresRailHint": "Bunlardan birine ihtiyacınız yok mu? Ayarlar'da, Gezinme altında bulunan kenar çubuğundaki herhangi bir simgeyi gizleyebilirsiniz.", @@ -449,7 +445,6 @@ "passwordSaved": "Parola kaydedildi, değiştirmek için tuşlayın.", "key": "Anahtar", "credential": "Kimlik Bilgisi", - "none": "Hiçbiri", "sshPrivateKey": "SSH Özel Anahtarı", "keyType": "Anahtar Türü", "uploadFile": "Dosya Yükle", @@ -611,17 +606,12 @@ "keepaliveIntervalLabel": "Canlı Tutma Aralığı (saniye)", "maxKeepaliveMisses": "Maksimum Keepalive Kaçırma", "sameHost": "Bu ana bilgisayar (doğrudan tünel)", - "bindHost": "Bağlanma Ana Bilgisayarı", "connectionToolbar": "Bağlantı Araç Çubuğu", "showConnectionToolbar": "Bağlantı araç çubuğunu göster", "showConnectionToolbarDesc": "Bu sunucunun SSH, RDP, VNC ve Telnet oturumlarında araç çubuğunu gösterin. Ayrıca, araç çubuğundan geçici olarak gizleyebilirsiniz.", "proxmoxLastSyncStatus": { "success": "Başarılı" }, - "proxmoxGuestsSelected_one": "{{count}} misafir — {{selected}} seçili", - "proxmoxGuestsSelected_other": "{{count}} misafir — {{selected}} seçili", - "proxmoxImportButton_one": "{{count}} ana makineyi içe aktar", - "proxmoxImportButton_other": "{{count}} sunucuyu içe aktar", "proxmoxResultSkippedNoIp": "{{count}} atlandı (IP adresi bulunamadı)", "proxmoxStatsUrlCopied": "Proxmox İstatistikleri URL'si panoya kopyalandı", "copyProxmoxStatsUrlAction": "Proxmox İstatistikleri URL'sini Kopyala", @@ -896,13 +886,11 @@ "updatedCount": "{{count}} host güncellendi", "friendlyNameLabel": "Gösterim Adı", "descriptionLabel": "Açıklama", - "loadingHost": "Host yükleniyor...", "loadingHosts": "Hostlar yükleniyor...", "loadingCredentials": "Kimlik bilgileri yükleniyor...", "noHostsYet": "Henüz host yok", "noHostsYetHint": "Terminalleri açmak, dosyalara göz atmak ve ölçümleri görmek için bir sunucu ekleyin.", "noHostsMatchSearch": "Aramanızla eşleşen host yok", - "hostNotFound": "Host bulunamadı", "searchHosts": "Host ara...", "sortHosts": "Hostları Sırala", "sortDefault": "Varsayılan Sıralama", @@ -925,7 +913,6 @@ "filterAuthKey": "SSH Anahtarı", "filterAuthCredential": "Kimlik Bilgisi", "filterAuthNone": "Yok", - "filterAuthOpkssh": "OPKSSH", "filterAuthStepca": "Adım CA", "filterProtocolGroup": "Protokol", "filterProtocolSsh": "SSH", @@ -1114,13 +1101,7 @@ "connect": "Sunucuya Bağlan", "clear": "Temizle", "paste": "Yapıştır", - "connected": "Bağlandı", - "clipboardWriteFailed": "Panoya kopyalama başarısız oldu. Sayfanın HTTPS veya localhost üzerinden sunulduğundan emin olun.", - "clipboardReadFailed": "Panodan okuma başarısız oldu. Pano izinlerinin verildiğinden emin olun.", "tmuxDetach": "tmux oturumundan ayrıl", - "terminalTitle": "Terminal - {{host}}", - "terminalWithPath": "Terminal - {{host}}:{{path}}", - "runTitle": "Çalıştırılıyor: {{command}} - {{host}}", "totpRequired": "İki Faktörlü Kimlik Doğrulama Gerekli", "totpCodeLabel": "Doğrulama Kodu", "totpVerify": "Doğrula", @@ -1148,109 +1129,20 @@ } }, "transfer": { - "copyToHost": "Sunucuya kopyala…", - "moveToHost": "Sunucuya taşı…", - "copyItemsToHost": "{{count}} öğeyi sunucuya kopyala…", - "moveItemsToHost": "{{count}} öğeyi ana bilgisayara taşı…", - "noHostsConnected": "Kullanılabilir başka dosya yöneticisi ana bilgisayarı yok.", - "noHostsConnectedHint": "Ana Bilgisayar Yöneticisi'nde Dosya Yöneticisi etkinleştirilmiş başka bir SSH ana bilgisayarı ekleyin.", - "selectDestinationHost": "Hedef ana bilgisayarı seçin", - "destinationPath": "Hedef yol", - "recentDestinations": "Son hedefler", "collapseRecentDestinations": "Son hedefleri daralt", "expandRecentDestinations": "Son hedefleri genişlet", - "browseFolders": "Hedef klasörlere göz at", "browseDestination": "Göz at veya yol gir", - "confirmCopy": "Kopyala", - "confirmMove": "Taşı", "transferring": "Aktarılıyor…", - "progressVerifying": "Dosya bütünlüğünün doğrulanması…", - "progressBenchmarking": "En hızlı aktarma rotasını seçme…", "compressing": "Sıkıştırılıyor…", "extracting": "Çıkartılıyor…", "transferringItems": "{{current}} / {{total}} öğe aktarılıyor…", - "transferSuccess": "Aktarım tamamlandı", - "transferError": "Aktarım başarısız", "transferPartial": "Aktarım {{count}} hatayla tamamlandı", - "transferPartialHint": "Aktarılamadı: {{paths}}", - "itemsSummary": "{{count}} öğe", - "destMustBeDirectory": "Çoklu öğe aktarımları için hedef bir dizin olmalıdır", "selectThisFolder": "Bu klasörü seç", - "browsePathWillBeCreated": "Bu klasör henüz mevcut değil. Aktarım başladığında oluşturulacak.", - "browsePathError": "Hedef ana bilgisayarda bu yol açılamadı.", - "goUp": "Yukarı", - "copyFolderToHost": "Klasörü ana bilgisayara kopyala…", - "moveFolderToHost": "Klasörü ana bilgisayara taşı…", - "hostReady": "Hazır", - "hostConnecting": "Bağlanıyor…", - "hostDisconnected": "Bağlı değil", - "hostAuthRequired": "Kimlik doğrulama gerekli — önce bu ana bilgisayarda Dosya Yöneticisi'ni açın", - "hostConnectionFailed": "Bağlantı başarısız", "metricsTitle": "Aktarım zamanlamaları", - "metricsPrepare": "Hedefi hazırla: {{duration}}", - "metricsCompress": "Kaynakta sıkıştırma: {{duration}}", "metricsHopSourceRead": "Kaynak → sunucu: {{throughput}}", "metricsHopDestSftpWrite": "Sunucu → hedef (SFTP): {{throughput}}", "metricsHopDestLocalWrite": "Sunucu → hedef (yerel): {{throughput}}", - "metricsTransfer": "Uçtan uca: {{throughput}} ({{duration}})", - "metricsExtract": "Hedefte çıkarma: {{duration}}", - "metricsVerify": "SHA-256 ile doğrulandı: {{duration}}", - "metricsRouteBenchmark": "Rota sondası — doğrudan: {{direct}}, röle: {{relay}}", - "metricsSourceDelete": "Kaynaktan silme: {{duration}}", - "metricsTotal": "Toplam: {{duration}}", - "progressCompressing": "Kaynak sunucuda sıkıştırılıyor…", - "progressExtracting": "Hedefte çıkarılıyor…", - "progressTransferring": "Veri aktarılıyor…", - "progressReconnecting": "Yeniden bağlanılıyor…", - "parallelSegmentsLabel": "Paralel aktarım yolları", - "parallelSegmentsOption": "{{count}} yol", - "parallelSegmentsHint": "Büyük dosyalar 256 MB'lık parçalara bölünür. Çoklu yollar, daha yüksek toplam aktarım hızı için ayrı bağlantılar kullanır (birden fazla aktarım başlatmak gibi).", - "progressTotalSpeed": "{{speed}} toplam ({{lanes}} yol)", - "progressTransferringItems": "Dosyalar aktarılıyor ({{current}} / {{total}})…", - "progressBytes": "{{transferred}} / {{total}}", - "progressItems": "{{current}} / {{total}} dosya", - "sourceNotDeletedPartial": "Kaynak dosyalar korundu (kısmi aktarım)", - "jumpHostLimitation": "Her iki sunucuya da Termix sunucusundan erişilebilir olmalıdır. Sunucular arası doğrudan yönlendirme desteklenmez.", - "cancel": "İptal", - "methodLabel": "Aktarım yöntemi", - "methodAuto": "Otomatik", - "methodTar": "Tar arşivi", - "methodItemSftp": "Dosya başına SFTP", - "methodAutoHint": "Dosya sayısı, boyutu ve sıkıştırılabilirliğe bağlı olarak tar veya dosya başına SFTP seçer. Tek dosyalar her zaman akış SFTP'si kullanır.", - "methodTarHint": "Kaynakta sıkıştır, tek arşiv aktar, hedefte çıkar. Her iki Unix sunucuda tar gerektirir.", - "methodItemSftpHint": "Her dosyayı SFTP üzerinden tek tek aktarır. Windows dahil tüm sunucularda çalışır.", - "methodPreviewLoading": "Aktarım yöntemi hesaplanıyor…", - "methodPreviewError": "Aktarım yöntemi önizlenemedi. Başlattığınızda sunucu yine de bir yöntem seçecektir.", - "methodPreviewWillUseTar": "Kullanılacak: Tar arşivi", - "methodPreviewWillUseItemSftp": "Kullanılacak: Dosya başına SFTP", - "methodPreviewScanSummary": "{{fileCount}} dosya, toplam {{totalSize}} (kaynak sunucuda tarandı).", - "methodItemSftpLimitation": "Her dosya, tek bir dosya kopyasıyla aynı SFTP akışını sırayla kullanır. İlerleme tüm dosyalar için birleştirilmiştir, bu nedenle büyük dosyalar sırasında çubuk yavaş hareket eder.", - "methodReason": { - "user_item_sftp": "Dosya bazında SFTP seçtiniz.", - "user_tar": "Tar arşivi seçtiniz.", - "tar_unavailable": "Bir veya her iki ana bilgisayarda Tar kullanılamıyor — bunun yerine dosya bazında SFTP kullanılacak.", - "windows_host": "Windows ana bilgisayarı söz konusu — tar kullanılmaz.", - "auto_multi_large": "Otomatik: sıkıştırılabilir veriye sahip büyük bir dosya ({{largestSize}}) dahil birden çok dosya — tar tek bir aktarımda birleştirir.", - "auto_single_large_in_archive": "Otomatik: bu kümede bir büyük dosya ({{largestSize}}) — dosya bazında SFTP.", - "auto_many_incompressible": "Otomatik: çoğunlukla sıkıştırılamayan veri — dosya bazında SFTP.", - "auto_many_files": "Otomatik: çok sayıda dosya ({{fileCount}}) — tar dosya başına ek yükü azaltır.", - "auto_default": "Otomatik: bu küme için dosya bazında SFTP." - }, - "progressCancel": "İptal", - "progressCancelling": "İptal ediliyor…", - "progressStalled": "Askıda", - "resumedHint": "Başka bir pencerede başlatılan aktif bir aktarıma yeniden bağlanıldı.", - "transferCancelled": "Aktarım iptal edildi", - "transferCancelledCopyHint": "Hedefte kısmi dosyalar kalabilir.", - "transferCancelledMoveHint": "Hedefte kısmi dosyalar kalabilir. Kaynak dosyalar silinmedi.", - "cleanupDestFiles": "Hedefi temizle", - "cleanupDestFilesSuccess": "Hedefteki kısmi dosyalar kaldırıldı", - "cleanupDestFilesPartial": "Bazı kısmi dosyalar kaldırılamadı", - "cleanupDestFilesNothing": "Hedefte temizlenecek bir şey yok", - "cleanupDestFilesError": "Temizleme başarısız oldu", - "retryTransfer": "Yeniden dene", - "retryTransferError": "Yeniden deneme başarısız oldu", - "transferFailedRetryHint": "Hedefte kısmi veri tutuldu. Bağlantı geri geldiğinde yeniden deneme devam edecek." + "sourceNotDeletedPartial": "Kaynak dosyalar korundu (kısmi aktarım)" }, "tunnels": { "connect": "Bağlan", @@ -1261,8 +1153,6 @@ "clientTunnel": "İstemci Tüneli", "addClientTunnel": "İstemci Tüneli Ekle", "active": "Aktif", - "start": "Başlat", - "stop": "Durdur", "typeServerLocalDesc": "Geçerli sunucudan uç noktaya.", "typeServerRemoteDesc": "Uç noktadan geçerli sunucuya.", "typeClientLocalDesc": "Yerel bilgisayardan uç noktaya.", @@ -1374,8 +1264,7 @@ "resetCodeRateLimitedWithTime": "Hız sınırlaması: Çok fazla doğrulama denemesi. Lütfen tekrar denemeden önce {{time}} saniye bekleyin.", "authTokenSaveFailed": "Kimlik doğrulama belirteci kaydedilemedi", "authTokenMissing": "Sunucu yeni bir kimlik doğrulama belirteci döndürmedi. Lütfen tekrar giriş yapın.", - "failedToLoadServer": "Sunucu yüklenemedi", - "remoteServerRequired": "Uzak sunucu gereklidir. Bu bağlantı türünü kullanmak için Ayarlar'dan bir uzak sunucu bağlayın." + "failedToLoadServer": "Sunucu yüklenemedi" }, "messages": { "registrationDisabled": "Yeni hesap kaydı şu anda bir yönetici tarafından devre dışı bırakıldı. Lütfen giriş yapın veya bir yöneticiyle iletişime geçin.", @@ -1831,7 +1720,6 @@ "protocolLabel": "Protokol", "domainLabel": "İhtisas", "domainPlaceholder": "isteğe bağlı", - "connectToTerminal": "Terminale Bağlan", "connectToFiles": "Dosyalara Bağlan" }, "splitScreen": { diff --git a/src/ui/locales/translated/uk_UA.json b/src/ui/locales/translated/uk_UA.json index 01cbefa30..3d4d7d3a8 100644 --- a/src/ui/locales/translated/uk_UA.json +++ b/src/ui/locales/translated/uk_UA.json @@ -324,10 +324,6 @@ "appearanceIntro": "Виберіть тему, акцентний колір і мову. Усі три параметри можна змінити пізніше в налаштуваннях.", "featuresTitle": "Що ще робить Termix", "featuresIntro": "Кожен збережений вами сервер можна відкрити не лише в терміналі. Ось що чекає за значками ліворуч.", - "feature_files": "Файловий менеджер", - "feature_files_desc": "Переглядайте, завантажуйте, вивантажуйте та редагуйте файли через SFTP, не виходячи з програми.", - "feature_tunnels": "Тунелі", - "feature_tunnels_desc": "Переадресовувати порти через сервер для доступу до служб, які не піддаються впливу.", "feature_snippets": "Фрагменти", "feature_snippets_desc": "Зберігайте команди, які ви часто виконуєте, та надсилайте їх у термінал одним клацанням миші.", "featuresRailHint": "Не потрібен один із них? Приховайте будь-який значок на бічній панелі в налаштуваннях, у розділі \"Навігація\".", @@ -449,7 +445,6 @@ "passwordSaved": "Пароль збережено, введіть, щоб змінити", "key": "Ключ", "credential": "Посвідчення", - "none": "Жоден", "sshPrivateKey": "Закритий ключ SSH", "keyType": "Тип ключа", "uploadFile": "Завантажити файл", @@ -611,17 +606,12 @@ "keepaliveIntervalLabel": "Інтервал підтримки активності (секунди)", "maxKeepaliveMisses": "Макс. промахи Keepalive", "sameHost": "Цей хост (прямий тунель)", - "bindHost": "Прив’язати хост", "connectionToolbar": "Панель інструментів з’єднання", "showConnectionToolbar": "Показати панель інструментів з’єднань", "showConnectionToolbarDesc": "Показувати панель інструментів у сеансах SSH, RDP, VNC та Telnet цього хоста. Ви також можете тимчасово приховати її з самої панелі інструментів.", "proxmoxLastSyncStatus": { "success": "Успіх" }, - "proxmoxGuestsSelected_one": "{{count}} гість — {{selected}} вибрано", - "proxmoxGuestsSelected_other": "{{count}} гостей — {{selected}} вибрано", - "proxmoxImportButton_one": "Імпортувати хост {{count}}", - "proxmoxImportButton_other": "Імпортувати {{count}} хостів", "proxmoxResultSkippedNoIp": "{{count}} пропущено (IP-адресу не знайдено)", "proxmoxStatsUrlCopied": "URL-адресу статистики Proxmox скопійовано в буфер обміну", "copyProxmoxStatsUrlAction": "Копіювати URL-адресу статистики Proxmox", @@ -896,13 +886,11 @@ "updatedCount": "Оновлено хостів {{count}}", "friendlyNameLabel": "Зрозуміле ім'я", "descriptionLabel": "Опис", - "loadingHost": "Завантаження хоста...", "loadingHosts": "Завантаження хостів...", "loadingCredentials": "Завантаження облікових даних...", "noHostsYet": "Поки що немає хостів", "noHostsYetHint": "Додайте сервер для відкриття терміналів, перегляду файлів та перегляду метрик.", "noHostsMatchSearch": "Немає хостів, що відповідають вашому пошуковому запиту", - "hostNotFound": "Хост не знайдено", "searchHosts": "Пошук хостів...", "sortHosts": "Сортувати хости", "sortDefault": "Порядок за замовчуванням", @@ -925,7 +913,6 @@ "filterAuthKey": "SSH-ключ", "filterAuthCredential": "Посвідчення", "filterAuthNone": "Жоден", - "filterAuthOpkssh": "ОПКШ", "filterAuthStepca": "Крок CA", "filterProtocolGroup": "Протокол", "filterProtocolSsh": "SSH", @@ -1114,13 +1101,7 @@ "connect": "Підключення до хоста", "clear": "Очистити", "paste": "Вставити", - "connected": "Підключено", - "clipboardWriteFailed": "Не вдалося скопіювати в буфер обміну. Переконайтеся, що сторінка обслуговується через HTTPS або localhost.", - "clipboardReadFailed": "Не вдалося прочитати з буфера обміну. Переконайтеся, що надано дозволи на доступ до буфера обміну.", "tmuxDetach": "Від’єднатися від сеансу tmux", - "terminalTitle": "Термінал - {{host}}", - "terminalWithPath": "Термінал - {{host}}:{{path}}", - "runTitle": "Запуск {{command}} - {{host}}", "totpRequired": "Потрібна двофакторна автентифікація", "totpCodeLabel": "Код підтвердження", "totpVerify": "Перевірити", @@ -1148,109 +1129,20 @@ } }, "transfer": { - "copyToHost": "Копіювати на хост…", - "moveToHost": "Перемістити на хост…", - "copyItemsToHost": "Копіювати елементи {{count}} для розміщення…", - "moveItemsToHost": "Перемістити {{count}} елементів на хост…", - "noHostsConnected": "Інших хостів файлових менеджерів немає.", - "noHostsConnectedHint": "Додайте ще один SSH-хост з увімкненим файловим менеджером у Host Manager.", - "selectDestinationHost": "Виберіть хост призначення", - "destinationPath": "Шлях призначення", - "recentDestinations": "Нещодавні напрямки", "collapseRecentDestinations": "Згорнути останні пункти призначення", "expandRecentDestinations": "Розгорнути нещодавні пункти призначення", - "browseFolders": "Перегляд папок призначення", "browseDestination": "Переглянути або ввести шлях", - "confirmCopy": "Копіювати", - "confirmMove": "Перемістити", "transferring": "Перенесення…", - "progressVerifying": "Перевірка цілісності файлу…", - "progressBenchmarking": "Вибір найшвидшого маршруту пересадки…", "compressing": "Стиснення…", "extracting": "Видобування…", "transferringItems": "Перенесення {{current}} з {{total}} елементів…", - "transferSuccess": "Перенесення завершено", - "transferError": "Передача не вдалася", "transferPartial": "Перенесення завершено з {{count}} помилками", - "transferPartialHint": "Не вдалося перенести: {{paths}}", - "itemsSummary": "{{count}} елементів", - "destMustBeDirectory": "Для перенесення кількох елементів місцем призначення має бути каталог", "selectThisFolder": "Виберіть цю папку", - "browsePathWillBeCreated": "Цієї папки ще не існує. Вона буде створена, коли розпочнеться передача.", - "browsePathError": "Не вдалося відкрити цей шлях на хості призначення.", - "goUp": "Піднімися", - "copyFolderToHost": "Копіювати папку на хост…", - "moveFolderToHost": "Перемістити папку на хост…", - "hostReady": "Готовий", - "hostConnecting": "Підключення…", - "hostDisconnected": "Не підключено", - "hostAuthRequired": "Потрібна автентифікація — спочатку відкрийте Файловий менеджер на цьому хості", - "hostConnectionFailed": "Помилка підключення", "metricsTitle": "Час пересадки", - "metricsPrepare": "Підготувати пункт призначення: {{duration}}", - "metricsCompress": "Стиснути у вихідному коді: {{duration}}", "metricsHopSourceRead": "Джерело → сервер: {{throughput}}", "metricsHopDestSftpWrite": "Сервер → призначення (SFTP): {{throughput}}", "metricsHopDestLocalWrite": "Сервер → призначення (локальний): {{throughput}}", - "metricsTransfer": "Від кінця до кінця: {{throughput}} ({{duration}})", - "metricsExtract": "Вилучити в місці призначення: {{duration}}", - "metricsVerify": "SHA-256 перевірено: {{duration}}", - "metricsRouteBenchmark": "Зонд маршруту — прямий: {{direct}}, ретрансляція: {{relay}}", - "metricsSourceDelete": "Видалити з джерела: {{duration}}", - "metricsTotal": "Всього: {{duration}}", - "progressCompressing": "Стиснення на вихідному хості…", - "progressExtracting": "Видобування в місці призначення…", - "progressTransferring": "Передача даних…", - "progressReconnecting": "Повторне підключення…", - "parallelSegmentsLabel": "Паралельні пересадочні смуги", - "parallelSegmentsOption": "{{count}} смуги", - "parallelSegmentsHint": "Великі файли розділяються на фрагменти по 256 МБ. Кілька ліній використовують окремі з’єднання (наприклад, запуск кількох передач) для підвищення загальної пропускної здатності.", - "progressTotalSpeed": "{{speed}} всього ({{lanes}} смуг)", - "progressTransferringItems": "Передача файлів ({{current}} з {{total}})…", - "progressBytes": "{{transferred}} / {{total}}", - "progressItems": "{{current}} / {{total}} файли", - "sourceNotDeletedPartial": "Вихідні файли збережено (часткове перенесення)", - "jumpHostLimitation": "Обидва хости мають бути доступні з сервера Termix. Пряма маршрутизація між хостами не підтримується.", - "cancel": "Скасувати", - "methodLabel": "Спосіб переказу", - "methodAuto": "Авто", - "methodTar": "Архів Tar", - "methodItemSftp": "SFTP для кожного файлу", - "methodAutoHint": "Вибирає tar-файл або SFTP для кожного файлу на основі кількості файлів, розміру та стискальності. Окремі файли завжди використовують потоковий SFTP.", - "methodTarHint": "Стиснення у вихідному коді, перенесення одного архіву, розпакування у кінцевому. Потрібен tar-архів на обох хостах Unix.", - "methodItemSftpHint": "Передавайте кожен файл окремо через SFTP. Працює на всіх хостах, включаючи Windows.", - "methodPreviewLoading": "Розрахунок методу переказу…", - "methodPreviewError": "Не вдалося переглянути метод передачі. Сервер все одно вибере метод під час запуску.", - "methodPreviewWillUseTar": "Буде використано: архів Tar", - "methodPreviewWillUseItemSftp": "Буде використовуватися: SFTP для кожного файлу", - "methodPreviewScanSummary": "{{fileCount}} файлів, {{totalSize}} всього (проскановано на вихідному хості).", - "methodItemSftpLimitation": "Кожен файл використовує той самий потік SFTP, що й копія окремого файлу, послідовно. Прогрес об'єднується для всіх файлів, тому шкала рухається повільно під час роботи з великими файлами.", - "methodReason": { - "user_item_sftp": "Ви обрали SFTP для кожного файлу.", - "user_tar": "Ви обрали tar-архів.", - "tar_unavailable": "Архів TAR недоступний на одному або обох хостах — замість нього використовуватиметься SFTP для кожного файлу.", - "windows_host": "Задіяний хост Windows — tar не використовується.", - "auto_multi_large": "Авто: кілька файлів, включаючи великий файл ({{largestSize}}) зі стисливими даними — tar-пакети об'єднуються в одну передачу.", - "auto_single_large_in_archive": "Авто: один великий файл ({{largestSize}}) у цьому наборі — SFTP для кожного файлу.", - "auto_many_incompressible": "Авто: переважно нестисливі дані — SFTP для кожного файлу.", - "auto_many_files": "Авто: багато файлів ({{fileCount}}) — tar зменшує навантаження на кожен файл.", - "auto_default": "Авто: SFTP для кожного файлу для цього набору." - }, - "progressCancel": "Скасувати", - "progressCancelling": "Скасування…", - "progressStalled": "Зупинився", - "resumedHint": "Повторне підключення до активної передачі, розпочатої в іншому вікні.", - "transferCancelled": "Переказ скасовано", - "transferCancelledCopyHint": "Часткові файли можуть залишатися на пристрої призначення.", - "transferCancelledMoveHint": "Часткові файли можуть залишатися в місці призначення. Вихідні файли не видалено.", - "cleanupDestFiles": "Прибирання місця призначення", - "cleanupDestFilesSuccess": "Видалено часткові файли з місця призначення", - "cleanupDestFilesPartial": "Не вдалося видалити деякі часткові файли", - "cleanupDestFilesNothing": "Нічого прибирати на місці призначення", - "cleanupDestFilesError": "Очищення не вдалося", - "retryTransfer": "Повторити спробу", - "retryTransferError": "Повторна спроба не вдалася", - "transferFailedRetryHint": "На місці призначення збережено частку даних. Повторна спроба відновиться після відновлення з’єднання." + "sourceNotDeletedPartial": "Вихідні файли збережено (часткове перенесення)" }, "tunnels": { "connect": "Підключитися", @@ -1261,8 +1153,6 @@ "clientTunnel": "Тунель клієнта", "addClientTunnel": "Додати клієнтський тунель", "active": "Активний", - "start": "Початок", - "stop": "СТІЙ", "typeServerLocalDesc": "Поточний хост до кінцевої точки.", "typeServerRemoteDesc": "Кінцева точка повертається до поточного хоста.", "typeClientLocalDesc": "Локальний комп'ютер до кінцевої точки.", @@ -1374,8 +1264,7 @@ "resetCodeRateLimitedWithTime": "Обмеження швидкості: Забагато спроб перевірки. Будь ласка, зачекайте {{time}} секунд, перш ніж повторити спробу.", "authTokenSaveFailed": "Не вдалося зберегти токен автентифікації", "authTokenMissing": "Сервер не повернув новий токен автентифікації. Будь ласка, увійдіть ще раз.", - "failedToLoadServer": "Не вдалося завантажити сервер", - "remoteServerRequired": "Потрібен віддалений сервер. Підключіться до віддаленого сервера в налаштуваннях, щоб використовувати цей тип підключення." + "failedToLoadServer": "Не вдалося завантажити сервер" }, "messages": { "registrationDisabled": "Реєстрацію нового облікового запису наразі вимкнено адміністратором. Будь ласка, увійдіть або зверніться до адміністратора.", @@ -1831,7 +1720,6 @@ "protocolLabel": "Протокол", "domainLabel": "Домен", "domainPlaceholder": "необов'язково", - "connectToTerminal": "Підключення до терміналу", "connectToFiles": "Підключення до файлів" }, "splitScreen": { diff --git a/src/ui/locales/translated/vi_VN.json b/src/ui/locales/translated/vi_VN.json index 65059cf74..541e4b726 100644 --- a/src/ui/locales/translated/vi_VN.json +++ b/src/ui/locales/translated/vi_VN.json @@ -324,10 +324,6 @@ "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_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_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.", "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.", @@ -449,7 +445,6 @@ "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", @@ -611,17 +606,12 @@ "keepaliveIntervalLabel": "Khoảng thời gian Keepalive (giây)", "maxKeepaliveMisses": "Số lần bỏ lỡ Keepalive tối đa", "sameHost": "Máy chủ này (đường hầm trực tiếp)", - "bindHost": "Máy chủ bind", "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ụ.", "proxmoxLastSyncStatus": { "success": "Thành công" }, - "proxmoxGuestsSelected_one": "{{count}} máy khách — đã chọn {{selected}}", - "proxmoxGuestsSelected_other": "{{count}} máy khách — đã chọn {{selected}}", - "proxmoxImportButton_one": "Nhập {{count}} máy chủ", - "proxmoxImportButton_other": "Nhập {{count}} máy chủ", "proxmoxResultSkippedNoIp": "{{count}} đã bỏ qua (không tìm thấy địa chỉ IP)", "proxmoxStatsUrlCopied": "URL Thống kê Proxmox đã được sao chép vào clipboard", "copyProxmoxStatsUrlAction": "Sao chép URL Thống kê Proxmox", @@ -896,13 +886,11 @@ "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", @@ -925,7 +913,6 @@ "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", @@ -1114,13 +1101,7 @@ "connect": "Kết nối đến máy chủ", "clear": "Xóa", "paste": "Dán", - "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.", "tmuxDetach": "Ngắt khỏi phiên tmux", - "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", @@ -1148,109 +1129,20 @@ } }, "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." + "sourceNotDeletedPartial": "Giữ tệp nguồn (truyền một phần)" }, "tunnels": { "connect": "Kết nối", @@ -1261,8 +1153,6 @@ "clientTunnel": "Đường hầm máy khách", "addClientTunnel": "Thêm đường hầm máy khách", "active": "Hoạt động", - "start": "Bắt đầu", - "stop": "Dừng", "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.", @@ -1374,8 +1264,7 @@ "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.", - "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." + "failedToLoadServer": "Tải máy chủ thất bại" }, "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.", @@ -1831,7 +1720,6 @@ "protocolLabel": "Giao thức", "domainLabel": "Lãnh địa", "domainPlaceholder": "không bắt buộc", - "connectToTerminal": "Kết nối đến Terminal", "connectToFiles": "Kết nối đến Files" }, "splitScreen": { diff --git a/src/ui/locales/translated/zh_CN.json b/src/ui/locales/translated/zh_CN.json index 33a51252d..e9a985dc4 100644 --- a/src/ui/locales/translated/zh_CN.json +++ b/src/ui/locales/translated/zh_CN.json @@ -324,10 +324,6 @@ "appearanceIntro": "选择主题、强调色和界面语言。后续均可在“设置”中随时更改。", "featuresTitle": "Termix 的其他功能", "featuresIntro": "保存的服务器不仅能在终端中打开。左侧图标还提供了以下强大功能。", - "feature_files": "文件管理器", - "feature_files_desc": "无需离开应用,即可通过 SFTP 浏览、上传、下载及编辑文件。", - "feature_tunnels": "隧道", - "feature_tunnels_desc": "通过服务器转发端口以访问未暴露的服务。", "feature_snippets": "代码片段", "feature_snippets_desc": "保存常用命令,一键发送至终端执行。", "featuresRailHint": "不需要某些功能?可在“设置” > “导航”中隐藏侧边栏的对应图标。", @@ -449,7 +445,6 @@ "passwordSaved": "密码已保存,输入即可更改", "key": "密钥", "credential": "凭据", - "none": "无", "sshPrivateKey": "SSH 私钥", "keyType": "密钥类型", "uploadFile": "上传文件", @@ -611,17 +606,12 @@ "keepaliveIntervalLabel": "保活间隔(秒)", "maxKeepaliveMisses": "最大保活失败次数", "sameHost": "此主机(直接隧道)", - "bindHost": "绑定主机", "connectionToolbar": "连接工具栏", "showConnectionToolbar": "显示连接工具栏", "showConnectionToolbarDesc": "在主机的 SSH、RDP、VNC 和 Telnet 会话中显示工具栏。您也可以暂时将其从工具栏本身隐藏。", "proxmoxLastSyncStatus": { "success": "成功" }, - "proxmoxGuestsSelected_one": "{{count}} 个客户主机 — 已选择 {{selected}} 个", - "proxmoxGuestsSelected_other": "{{count}} 个客户主机 — 已选择 {{selected}} 个", - "proxmoxImportButton_one": "导入 {{count}} 个主机", - "proxmoxImportButton_other": "导入 {{count}} 个主机", "proxmoxResultSkippedNoIp": "{{count}} 已跳过(未找到 IP )", "proxmoxStatsUrlCopied": "Proxmox 统计信息 URL 已复制到剪贴板", "copyProxmoxStatsUrlAction": "复制 Proxmox 统计信息 URL", @@ -896,13 +886,11 @@ "updatedCount": "已更新 {{count}} 台主机", "friendlyNameLabel": "友好名称", "descriptionLabel": "描述", - "loadingHost": "正在加载主机...", "loadingHosts": "正在加载主机...", "loadingCredentials": "正在加载凭据...", "noHostsYet": "暂无主机", "noHostsYetHint": "添加服务器以打开终端、浏览文件和查看指标。", "noHostsMatchSearch": "没有匹配搜索的主机", - "hostNotFound": "未找到主机", "searchHosts": "搜索主机...", "sortHosts": "排序主机", "sortDefault": "默认顺序", @@ -925,7 +913,6 @@ "filterAuthKey": "SSH 密钥", "filterAuthCredential": "凭据", "filterAuthNone": "无", - "filterAuthOpkssh": "OPKSSH", "filterAuthStepca": "步骤 CA", "filterProtocolGroup": "协议", "filterProtocolSsh": "SSH", @@ -1114,13 +1101,7 @@ "connect": "连接到主机", "clear": "清除", "paste": "粘贴", - "connected": "已连接", - "clipboardWriteFailed": "复制到剪贴板失败。请确保页面通过 HTTPS 或 localhost 提供服务。", - "clipboardReadFailed": "从剪贴板读取失败。请确保已授予剪贴板权限。", "tmuxDetach": "从 tmux 会话分离", - "terminalTitle": "终端 - {{host}}", - "terminalWithPath": "终端 - {{host}}:{{path}}", - "runTitle": "运行 {{command}} - {{host}}", "totpRequired": "需要双因素认证", "totpCodeLabel": "验证码", "totpVerify": "验证", @@ -1148,109 +1129,20 @@ } }, "transfer": { - "copyToHost": "复制到主机…", - "moveToHost": "移动到主机…", - "copyItemsToHost": "复制 {{count}} 个项目到主机…", - "moveItemsToHost": "移动 {{count}} 个项目到主机…", - "noHostsConnected": "没有其他可用的文件管理器主机。", - "noHostsConnectedHint": "在主机管理器中添加启用文件管理器的其他 SSH 主机。", - "selectDestinationHost": "选择目标主机", - "destinationPath": "目标路径", - "recentDestinations": "最近目标", "collapseRecentDestinations": "收起最近目标", "expandRecentDestinations": "展开最近目标", - "browseFolders": "浏览目标文件夹", "browseDestination": "浏览或输入路径", - "confirmCopy": "复制", - "confirmMove": "移动", "transferring": "传输中…", - "progressVerifying": "正在验证文件完整性…", - "progressBenchmarking": "选择最快的传输路线…", "compressing": "压缩中…", "extracting": "解压中…", "transferringItems": "正在传输 {{current}}/{{total}} 个项目…", - "transferSuccess": "传输完成", - "transferError": "传输失败", "transferPartial": "传输完成,但有 {{count}} 个错误", - "transferPartialHint": "无法传输:{{paths}}", - "itemsSummary": "{{count}} 个项目", - "destMustBeDirectory": "对于多项目传输,目标必须是一个目录", "selectThisFolder": "选择此文件夹", - "browsePathWillBeCreated": "此文件夹尚不存在,将在传输开始时创建。", - "browsePathError": "无法在目标主机上打开此路径。", - "goUp": "向上", - "copyFolderToHost": "复制文件夹到主机…", - "moveFolderToHost": "移动文件夹到主机…", - "hostReady": "就绪", - "hostConnecting": "连接中…", - "hostDisconnected": "未连接", - "hostAuthRequired": "需要身份验证 — 请先在此主机上打开文件管理器", - "hostConnectionFailed": "连接失败", "metricsTitle": "传输耗时", - "metricsPrepare": "准备目标:{{duration}}", - "metricsCompress": "源端压缩:{{duration}}", "metricsHopSourceRead": "源 → 服务器:{{throughput}}", "metricsHopDestSftpWrite": "服务器 → 目标 (SFTP):{{throughput}}", "metricsHopDestLocalWrite": "服务器 → 目标 (本地):{{throughput}}", - "metricsTransfer": "端到端:{{throughput}} ({{duration}})", - "metricsExtract": "目标端解压:{{duration}}", - "metricsVerify": "SHA-256 已验证: {{duration}}", - "metricsRouteBenchmark": "路由探测 — 直接: {{direct}},中继: {{relay}}", - "metricsSourceDelete": "从源端删除:{{duration}}", - "metricsTotal": "总计:{{duration}}", - "progressCompressing": "正在源主机上压缩…", - "progressExtracting": "正在目标端解压…", - "progressTransferring": "正在传输数据…", - "progressReconnecting": "重新连接中…", - "parallelSegmentsLabel": "并行传输通道", - "parallelSegmentsOption": "{{count}} 个通道", - "parallelSegmentsHint": "大文件会被拆分为 256 MB 的块。多个通道使用独立连接(如同同时进行多个传输),以获得更高的总吞吐量。", - "progressTotalSpeed": "{{speed}} 总计({{lanes}} 通道)", - "progressTransferringItems": "正在传输文件({{current}}/{{total}})…", - "progressBytes": "{{transferred}} / {{total}}", - "progressItems": "{{current}} / {{total}} 个文件", - "sourceNotDeletedPartial": "源文件已保留(部分传输)", - "jumpHostLimitation": "两个主机都必须能从 Termix 服务器访问。不支持直接的主机到主机路由。", - "cancel": "取消", - "methodLabel": "传输方式", - "methodAuto": "自动", - "methodTar": "Tar 归档", - "methodItemSftp": "逐文件 SFTP", - "methodAutoHint": "根据文件数量、大小和可压缩性选择 tar 或逐文件 SFTP。单个文件始终使用流式 SFTP。", - "methodTarHint": "在源端压缩,传输单个归档文件,在目标端解压。要求两个 Unix 主机都有 tar。", - "methodItemSftpHint": "通过 SFTP 逐个传输文件。适用于包括 Windows 在内的所有主机。", - "methodPreviewLoading": "正在计算传输方式…", - "methodPreviewError": "无法预览传输方式。启动时服务器仍会选择方式。", - "methodPreviewWillUseTar": "将使用:Tar 归档", - "methodPreviewWillUseItemSftp": "将使用:逐文件 SFTP", - "methodPreviewScanSummary": "{{fileCount}} 个文件,总计 {{totalSize}}(已在源主机上扫描)。", - "methodItemSftpLimitation": "每个文件使用相同的 SFTP 流(与单文件拷贝一样),一个接一个传输。所有文件的进度合并显示,因此大文件传输时进度条移动缓慢。", - "methodReason": { - "user_item_sftp": "您选择了逐文件 SFTP。", - "user_tar": "您选择了 Tar 归档。", - "tar_unavailable": "一个或多个主机上不可用 tar — 将转而使用逐文件 SFTP。", - "windows_host": "涉及 Windows 主机 — 不使用 tar。", - "auto_multi_large": "自动:多个文件,其中包括一个包含可压缩数据的大文件({{largestSize}})— tar 将其打包成一次传输。", - "auto_single_large_in_archive": "自动:此集合中有一个大文件({{largestSize}})— 使用逐文件 SFTP。", - "auto_many_incompressible": "自动:大部分为不可压缩数据 — 使用逐文件 SFTP。", - "auto_many_files": "自动:文件众多({{fileCount}})— tar 可减少逐文件开销。", - "auto_default": "自动:此集合使用逐文件 SFTP。" - }, - "progressCancel": "取消", - "progressCancelling": "正在取消…", - "progressStalled": "已停滞", - "resumedHint": "已重新连接到在另一个窗口中启动的进行中的传输。", - "transferCancelled": "传输已取消", - "transferCancelledCopyHint": "目标位置可能残留部分文件。", - "transferCancelledMoveHint": "目标位置可能残留部分文件。源文件未被删除。", - "cleanupDestFiles": "清理目标位置", - "cleanupDestFilesSuccess": "已从目标位置删除部分文件", - "cleanupDestFilesPartial": "部分文件无法删除", - "cleanupDestFilesNothing": "目标位置无需清理", - "cleanupDestFilesError": "清理失败", - "retryTransfer": "重试", - "retryTransferError": "重试失败", - "transferFailedRetryHint": "部分数据已保留在目标位置。连接恢复后重试将继续。" + "sourceNotDeletedPartial": "源文件已保留(部分传输)" }, "tunnels": { "connect": "连接", @@ -1261,8 +1153,6 @@ "clientTunnel": "客户端隧道", "addClientTunnel": "添加客户端隧道", "active": "活跃", - "start": "启动", - "stop": "停止", "typeServerLocalDesc": "当前主机至端点。", "typeServerRemoteDesc": "端点回连至当前主机。", "typeClientLocalDesc": "本地计算机至端点。", @@ -1374,8 +1264,7 @@ "resetCodeRateLimitedWithTime": "频率受限:验证尝试次数过多,请等待 {{time}} 秒后再试。", "authTokenSaveFailed": "保存认证令牌失败", "authTokenMissing": "服务器未返回新的身份验证令牌。请重新登录。", - "failedToLoadServer": "加载服务器失败", - "remoteServerRequired": "需要远程服务器。请在“设置”中连接远程服务器以使用此连接类型。" + "failedToLoadServer": "加载服务器失败" }, "messages": { "registrationDisabled": "新账户注册已被管理员禁用。请登录或联系管理员。", @@ -1831,7 +1720,6 @@ "protocolLabel": "协议", "domainLabel": "领域", "domainPlaceholder": "选修的", - "connectToTerminal": "连接到终端", "connectToFiles": "连接到文件管理器" }, "splitScreen": { diff --git a/src/ui/locales/translated/zh_TW.json b/src/ui/locales/translated/zh_TW.json index d5b28f942..82a27197f 100644 --- a/src/ui/locales/translated/zh_TW.json +++ b/src/ui/locales/translated/zh_TW.json @@ -324,10 +324,6 @@ "appearanceIntro": "選擇主題、強調色和語言。這三項都可以在「設定」中更改。", "featuresTitle": "Termix 還有哪些功能", "featuresIntro": "您保存的每個伺服器都可以在終端機以外的多個終端機中開啟。以下是左側圖示背後的功能。", - "feature_files": "文件管理器", - "feature_files_desc": "無需離開應用程序,即可透過 SFTP 瀏覽、上傳、下載和編輯檔案。", - "feature_tunnels": "隧道", - "feature_tunnels_desc": "透過伺服器轉送連接埠以存取未公開的服務。", "feature_snippets": "片段", "feature_snippets_desc": "儲存您經常執行的命令,並一鍵將其發送到終端。", "featuresRailHint": "不需要其中任何一個圖示?您可以在「設定」>「導覽」中隱藏側邊欄中的任何圖示。", @@ -449,7 +445,6 @@ "passwordSaved": "密碼已儲存,輸入即可更改", "key": "金鑰", "credential": "憑證", - "none": "無", "sshPrivateKey": "SSH 私密金鑰", "keyType": "金鑰類型", "uploadFile": "上傳檔案", @@ -611,17 +606,12 @@ "keepaliveIntervalLabel": "保持連線間隔(秒)", "maxKeepaliveMisses": "最大保持連線遺失次數", "sameHost": "此主機(直接通道)", - "bindHost": "綁定主機", "connectionToolbar": "連接工具列", "showConnectionToolbar": "顯示連接工具列", "showConnectionToolbarDesc": "在主機的 SSH、RDP、VNC 和 Telnet 會話中顯示工具列。您也可以暫時將其從工具列本身隱藏。", "proxmoxLastSyncStatus": { "success": "成功" }, - "proxmoxGuestsSelected_one": "{{count}} 個訪客主機 — 已選取 {{selected}}", - "proxmoxGuestsSelected_other": "{{count}} 個訪客主機 — 已選取 {{selected}}", - "proxmoxImportButton_one": "匯入 {{count}} 台主機", - "proxmoxImportButton_other": "匯入 {{count}} 台主機", "proxmoxResultSkippedNoIp": "{{count}} 已跳過(找不到 IP 位址)", "proxmoxStatsUrlCopied": "Proxmox 統計資料 URL 已複製到剪貼簿", "copyProxmoxStatsUrlAction": "複製 Proxmox 統計資料 URL", @@ -896,13 +886,11 @@ "updatedCount": "已更新 {{count}} 台主機", "friendlyNameLabel": "易記名稱", "descriptionLabel": "描述", - "loadingHost": "正在載入主機...", "loadingHosts": "正在載入主機...", "loadingCredentials": "正在載入憑證...", "noHostsYet": "尚無主機", "noHostsYetHint": "新增伺服器以開啟終端、瀏覽文件和查看指標。", "noHostsMatchSearch": "沒有符合搜尋的主機", - "hostNotFound": "找不到主機", "searchHosts": "搜尋主機...", "sortHosts": "排序主機", "sortDefault": "預設排序", @@ -925,7 +913,6 @@ "filterAuthKey": "SSH 金鑰", "filterAuthCredential": "憑證", "filterAuthNone": "無", - "filterAuthOpkssh": "OPKSSH", "filterAuthStepca": "步驟 CA", "filterProtocolGroup": "通訊協定", "filterProtocolSsh": "SSH", @@ -1114,13 +1101,7 @@ "connect": "連線至主機", "clear": "清除", "paste": "貼上", - "connected": "已連線", - "clipboardWriteFailed": "複製到剪貼簿失敗。請確認頁面是透過 HTTPS 或 localhost 提供。", - "clipboardReadFailed": "從剪貼簿讀取失敗。請確認已授予剪貼簿權限。", "tmuxDetach": "從 tmux 工作階段中斷連線", - "terminalTitle": "終端機 - {{host}}", - "terminalWithPath": "終端機 - {{host}}:{{path}}", - "runTitle": "正在執行 {{command}} - {{host}}", "totpRequired": "需要雙因素驗證", "totpCodeLabel": "驗證碼", "totpVerify": "驗證", @@ -1148,109 +1129,20 @@ } }, "transfer": { - "copyToHost": "複製到主機…", - "moveToHost": "移動到主機…", - "copyItemsToHost": "複製 {{count}} 個項目到主機…", - "moveItemsToHost": "將 {{count}} 個項目移至主機…", - "noHostsConnected": "無其他可用的檔案管理員主機。", - "noHostsConnectedHint": "在主機管理員中新增另一個已啟用檔案管理員的 SSH 主機。", - "selectDestinationHost": "選擇目標主機", - "destinationPath": "目標路徑", - "recentDestinations": "最近使用的目的地", "collapseRecentDestinations": "收起最近使用的目的地", "expandRecentDestinations": "展開最近使用的目的地", - "browseFolders": "瀏覽目標資料夾", "browseDestination": "瀏覽或輸入路徑", - "confirmCopy": "複製", - "confirmMove": "移動", "transferring": "傳送中…", - "progressVerifying": "正在驗證檔案完整性…", - "progressBenchmarking": "選擇最快的傳輸路線…", "compressing": "壓縮中…", "extracting": "解壓縮中…", "transferringItems": "正在傳送 {{total}} 個項目中的第 {{current}} 個…", - "transferSuccess": "傳送完成", - "transferError": "傳送失敗", "transferPartial": "傳送完成,有 {{count}} 個錯誤", - "transferPartialHint": "無法傳送:{{paths}}", - "itemsSummary": "{{count}} 個項目", - "destMustBeDirectory": "多項目傳送時,目標必須是資料夾", "selectThisFolder": "選擇此資料夾", - "browsePathWillBeCreated": "此資料夾尚不存在。傳送開始時將會建立。", - "browsePathError": "無法在目標主機上開啟此路徑。", - "goUp": "向上", - "copyFolderToHost": "複製資料夾至主機…", - "moveFolderToHost": "移動資料夾至主機…", - "hostReady": "就緒", - "hostConnecting": "連線中…", - "hostDisconnected": "未連線", - "hostAuthRequired": "需要驗證 — 請先在此主機上開啟檔案管理員", - "hostConnectionFailed": "連線失敗", "metricsTitle": "傳送時間計量", - "metricsPrepare": "準備目標:{{duration}}", - "metricsCompress": "在來源主機壓縮: {{duration}}", "metricsHopSourceRead": "來源主機 → 伺服器: {{throughput}}", "metricsHopDestSftpWrite": "伺服器 → 目標主機 (SFTP): {{throughput}}", "metricsHopDestLocalWrite": "伺服器 → 目標主機 (本機): {{throughput}}", - "metricsTransfer": "端對端: {{throughput}} ({{duration}})", - "metricsExtract": "在目標主機解壓縮: {{duration}}", - "metricsVerify": "SHA-256 已驗證: {{duration}}", - "metricsRouteBenchmark": "路由探測 — 直接: {{direct}},中繼: {{relay}}", - "metricsSourceDelete": "從來源主機刪除: {{duration}}", - "metricsTotal": "總計: {{duration}}", - "progressCompressing": "在來源主機壓縮中…", - "progressExtracting": "在目標主機解壓縮中…", - "progressTransferring": "傳輸資料中…", - "progressReconnecting": "重新連線中…", - "parallelSegmentsLabel": "平行傳輸通道", - "parallelSegmentsOption": "{{count}} 個通道", - "parallelSegmentsHint": "大型檔案會分割成 256 MB 區塊。多個通道會使用獨立的連線(如同啟動多個傳輸作業)以獲取更高的總傳輸速率。", - "progressTotalSpeed": "總計 {{speed}}({{lanes}} 個通道)", - "progressTransferringItems": "傳輸檔案中({{current}} / {{total}})…", - "progressBytes": "{{transferred}} / {{total}}", - "progressItems": "{{current}} / {{total}} 個檔案", - "sourceNotDeletedPartial": "保留來源檔案(部分傳輸)", - "jumpHostLimitation": "兩台主機都必須可從 Termix 伺服器連線。不支援主機對主機的直接路由。", - "cancel": "取消", - "methodLabel": "傳輸方法", - "methodAuto": "自動", - "methodTar": "Tar 封存", - "methodItemSftp": "逐檔 SFTP", - "methodAutoHint": "根據檔案數量、大小及可壓縮性選擇 tar 封存或逐檔 SFTP。單一檔案一律使用串流 SFTP。", - "methodTarHint": "在來源主機壓縮,傳輸一個封存檔,在目標主機解壓縮。需兩台 Unix 主機皆安裝 tar。", - "methodItemSftpHint": "透過 SFTP 逐一傳輸每個檔案。適用於所有主機,包括 Windows。", - "methodPreviewLoading": "正在計算傳輸方法…", - "methodPreviewError": "無法預覽傳輸方法。啟動時伺服器仍會選擇一個方法。", - "methodPreviewWillUseTar": "將使用:Tar 封存", - "methodPreviewWillUseItemSftp": "將使用:逐檔 SFTP", - "methodPreviewScanSummary": "{{fileCount}} 個檔案,總計 {{totalSize}}(已在來源主機掃描)。", - "methodItemSftpLimitation": "每個檔案依序使用相同的 SFTP 串流作為單一檔案複製。進度會合併所有檔案,因此處理大型檔案時進度條會緩慢移動。", - "methodReason": { - "user_item_sftp": "您選擇了逐檔 SFTP。", - "user_tar": "您選擇了 tar 封存。", - "tar_unavailable": "一或多部主機無法使用 tar,將改用逐檔 SFTP。", - "windows_host": "涉及 Windows 主機,因此不使用 tar。", - "auto_multi_large": "自動:多個檔案中包含一個具可壓縮資料的大型檔案 ({{largestSize}}),tar 會將所有檔案封裝成單一傳輸。", - "auto_single_large_in_archive": "自動:此集合中有一個大型檔案 ({{largestSize}}) — 逐檔 SFTP。", - "auto_many_incompressible": "自動:多為不可壓縮資料 — 逐檔 SFTP。", - "auto_many_files": "自動:多個檔案 ({{fileCount}}) — tar 可減少逐檔傳輸的額外負擔。", - "auto_default": "自動:此集合使用逐檔 SFTP。" - }, - "progressCancel": "取消", - "progressCancelling": "正在取消…", - "progressStalled": "停滯", - "resumedHint": "已重新連線至在另一個視窗中啟動的進行中傳輸。", - "transferCancelled": "傳輸已取消", - "transferCancelledCopyHint": "部分檔案可能仍留在目的地。", - "transferCancelledMoveHint": "部分檔案可能仍留在目的地,來源檔案未被移除。", - "cleanupDestFiles": "清理目的地", - "cleanupDestFilesSuccess": "已從目的地移除部分檔案", - "cleanupDestFilesPartial": "部分檔案無法移除", - "cleanupDestFilesNothing": "目的地無需清理", - "cleanupDestFilesError": "清理失敗", - "retryTransfer": "重試", - "retryTransferError": "重試失敗", - "transferFailedRetryHint": "部分資料已保留在目的地。重新連線後,重試將從斷點繼續。" + "sourceNotDeletedPartial": "保留來源檔案(部分傳輸)" }, "tunnels": { "connect": "連線", @@ -1261,8 +1153,6 @@ "clientTunnel": "用戶端通道", "addClientTunnel": "新增用戶端通道", "active": "作用中", - "start": "啟動", - "stop": "停止", "typeServerLocalDesc": "從目前主機到端點。", "typeServerRemoteDesc": "從端點返回目前主機。", "typeClientLocalDesc": "從本機電腦到端點。", @@ -1374,8 +1264,7 @@ "resetCodeRateLimitedWithTime": "速率限制:驗證嘗試次數過多。請等待 {{time}} 秒後再試。", "authTokenSaveFailed": "無法儲存驗證權杖", "authTokenMissing": "伺服器未傳回新的身份驗證令牌。請重新登入。", - "failedToLoadServer": "無法載入伺服器", - "remoteServerRequired": "需要遠端伺服器。請在「設定」中連接遠端伺服器以使用此連線類型。" + "failedToLoadServer": "無法載入伺服器" }, "messages": { "registrationDisabled": "管理員目前已停用新帳戶註冊。請登入或聯絡管理員。", @@ -1831,7 +1720,6 @@ "protocolLabel": "協定", "domainLabel": "領域", "domainPlaceholder": "選修的", - "connectToTerminal": "連線至終端機", "connectToFiles": "連線至檔案管理員" }, "splitScreen": { diff --git a/src/ui/plugin-host/bridge.ts b/src/ui/plugin-host/bridge.ts index 5bc60da7f..67b5a688b 100644 --- a/src/ui/plugin-host/bridge.ts +++ b/src/ui/plugin-host/bridge.ts @@ -143,8 +143,55 @@ const SETTINGS_WRITERS: Record< updatePluginHostSettings(pluginId, hostId!, values), }; -function toHostRecord(host: unknown): PluginHostRecord { - return host as PluginHostRecord; +/** Both host shapes the shell holds: its own list and the API's. */ +type ShellHost = Omit, "id" | "parentHostId"> & { + id: string | number; + parentHostId?: string | number | null; +}; + +/** + * The shell's host as the SDK types it. Copied field by field, so a core + * field reaches plugins only once it is part of PluginHostRecord. + */ +export function toHostRecord(host: ShellHost): PluginHostRecord { + return { + id: String(host.id), + name: host.name ?? "", + ip: host.ip ?? "", + port: host.port, + username: host.username, + folder: host.folder, + tags: host.tags, + pin: host.pin, + notes: host.notes, + syncId: host.syncId, + parentHostId: host.parentHostId == null ? null : String(host.parentHostId), + authType: host.authType, + credentialId: host.credentialId, + overrideCredentialUsername: host.overrideCredentialUsername, + connectionType: host.connectionType, + connectionOrigin: host.connectionOrigin, + enableSsh: host.enableSsh, + sshPort: host.sshPort, + jumpHosts: host.jumpHosts?.map((jump) => ({ hostId: jump.hostId })), + statusCheckEnabled: host.statusCheckEnabled, + statusCheckInterval: host.statusCheckInterval, + sshOptions: host.sshOptions, + pluginSettings: host.pluginSettings, + protocolAuth: host.protocolAuth, + quickConnectLogin: host.quickConnectLogin, + quickConnectSavable: host.quickConnectSavable, + instanceId: host.instanceId, + status: host.status, + online: host.online, + isShared: host.isShared, + permissionLevel: host.permissionLevel, + sharedExpiresAt: host.sharedExpiresAt, + ownerUsername: host.ownerUsername, + authOverrides: host.authOverrides, + sharedCopy: host.sharedCopy, + localOnly: host.localOnly, + }; } export const pluginHostBridge: PluginHostBridge = { diff --git a/src/ui/plugin-host/shell-bridge.ts b/src/ui/plugin-host/shell-bridge.ts index a90e9c4f9..3395b6d8a 100644 --- a/src/ui/plugin-host/shell-bridge.ts +++ b/src/ui/plugin-host/shell-bridge.ts @@ -79,9 +79,25 @@ function subscribe(set: Set<() => void>, listener: () => void): () => void { const noop = () => {}; +/** + * A plugin hands back the typed record it got from the SDK, which carries + * fewer fields than the shell's own host. A tab should get the shell's host, + * with whatever the plugin set on top. + */ +export function withShellHost(host: Host | null): Host | null { + if (!host) return host; + const own = hosts.find((entry) => String(entry.id) === String(host.id)); + if (!own || own === host) return host; + const merged: Record = { ...own }; + for (const [key, value] of Object.entries(host)) { + if (value !== undefined) merged[key] = value; + } + return merged as Host; +} + /** Forwards to the mounted shell; a no-op before it mounts or after logout. */ export const shell: TabShellCallbacks = { - openTab: (...args) => callbacks?.openTab(...args), + openTab: (host, ...rest) => callbacks?.openTab(withShellHost(host), ...rest), openSingletonTab: (...args) => callbacks?.openSingletonTab(...args), closeTab: (...args) => callbacks?.closeTab(...args), renameTab: (...args) => callbacks?.renameTab(...args), diff --git a/src/ui/tests/onboarding/onboarding-steps.test.ts b/src/ui/tests/onboarding/onboarding-steps.test.ts index ae738357e..c9bbad6ee 100644 --- a/src/ui/tests/onboarding/onboarding-steps.test.ts +++ b/src/ui/tests/onboarding/onboarding-steps.test.ts @@ -62,7 +62,6 @@ describe("ONBOARDING_STEPS", () => { describe("onboarding step body translations", () => { const KEYS: Record = { welcome: ["hosts", "terminal", "files"], - feature: ["files", "tunnels"], workflow: ["palette", "split", "dock"], security: ["credentials", "twofa", "identity", "sharing"], done: ["settings", "rerun", "docs"], diff --git a/src/ui/tests/plugin-host/bridge.test.ts b/src/ui/tests/plugin-host/bridge.test.ts new file mode 100644 index 000000000..d2dbf8b9d --- /dev/null +++ b/src/ui/tests/plugin-host/bridge.test.ts @@ -0,0 +1,34 @@ +import { describe, expect, it } from "vitest"; +import { toHostRecord } from "@/plugin-host/bridge"; + +describe("toHostRecord", () => { + it("copies only the fields the SDK types", () => { + const record = toHostRecord({ + id: 7, + name: "web", + ip: "10.0.0.7", + port: 22, + username: "root", + parentHostId: 3, + jumpHosts: [{ hostId: 2 }], + pluginSettings: { docker: { enableDocker: true } }, + authOverrides: { ssh: { required: true, ownerAuthShared: false } }, + password: "secret", + terminalConfig: { fontSize: 14 }, + enableDocker: true, + } as never); + + expect(record).toMatchObject({ + id: "7", + name: "web", + parentHostId: "3", + jumpHosts: [{ hostId: 2 }], + pluginSettings: { docker: { enableDocker: true } }, + authOverrides: { ssh: { required: true, ownerAuthShared: false } }, + }); + const loose = record as unknown as Record; + expect(loose).not.toHaveProperty("password"); + expect(loose).not.toHaveProperty("terminalConfig"); + expect(loose).not.toHaveProperty("enableDocker"); + }); +}); diff --git a/src/ui/tests/plugin-host/registries.test.tsx b/src/ui/tests/plugin-host/registries.test.tsx index c11a7131b..a8bed1dd3 100644 --- a/src/ui/tests/plugin-host/registries.test.tsx +++ b/src/ui/tests/plugin-host/registries.test.tsx @@ -110,13 +110,13 @@ function activate(app: TermixApp) { kind: "connect", priority: 500, tabType: "fixture-tab", - when: (host) => host.enableFixture === true, + when: (host) => host.pluginSettings?.fixture?.enableFixture === true, }); app.registerPaletteEntry({ id: "fixture-entry", titleKey: "title", scope: "host", - when: (host) => host?.enableFixture === true, + when: (host) => host?.pluginSettings?.fixture?.enableFixture === true, run: (shell, host) => shell.openTab(host ?? null, "fixture-tab"), }); app.registerDashboardCard({ @@ -262,7 +262,7 @@ describe("registries through the app object", () => { it("offers a host action only where it applies, and picks it as the default connect", async () => { await mount(); - const on = host({ enableFixture: true } as Partial); + const on = host({ pluginSettings: { fixture: { enableFixture: true } } }); const off = host(); expect(hostActionsFor(listHostActions(), on).map((a) => a.id)).toEqual([ "fixture-connect", @@ -307,7 +307,9 @@ describe("registries through the app object", () => { it("offers a per-host palette entry that runs against the shell", async () => { const app = await mount(); - const target = host({ enableFixture: true } as Partial); + const target = host({ + pluginSettings: { fixture: { enableFixture: true } }, + }); const entries = paletteEntriesFor(listPaletteEntries(), "host", target); expect(entries.map((entry) => entry.id)).toEqual(["fixture-entry"]); expect(paletteEntriesFor(listPaletteEntries(), "host", host())).toEqual([]); diff --git a/src/ui/tests/plugin-host/shell-bridge.test.ts b/src/ui/tests/plugin-host/shell-bridge.test.ts new file mode 100644 index 000000000..a55ac4b16 --- /dev/null +++ b/src/ui/tests/plugin-host/shell-bridge.test.ts @@ -0,0 +1,52 @@ +import { afterEach, describe, expect, it, vi } from "vitest"; +import { + resetShellBridge, + setShellCallbacks, + setShellHosts, + shell, + withShellHost, +} from "@/plugin-host/shell-bridge"; +import type { Host } from "@/types/ui-types"; + +const saved = { + id: "5", + name: "db", + ip: "10.0.0.5", + port: 22, + username: "root", + useSocks5: true, + socks5Host: "proxy", +} as unknown as Host; + +afterEach(() => resetShellBridge()); + +describe("withShellHost", () => { + it("fills a typed record back in from the shell's own host", () => { + setShellHosts([saved]); + const merged = withShellHost({ + id: "5", + name: "db (renamed)", + notes: undefined, + } as unknown as Host); + expect(merged).toMatchObject({ + name: "db (renamed)", + useSocks5: true, + socks5Host: "proxy", + }); + }); + + it("keeps a host the shell does not list as it is", () => { + setShellHosts([saved]); + const quick = { id: "quick-connect-1", ip: "1.2.3.4" } as unknown as Host; + expect(withShellHost(quick)).toBe(quick); + expect(withShellHost(null)).toBeNull(); + }); + + it("is what shell.openTab hands the mounted shell", () => { + setShellHosts([saved]); + const openTab = vi.fn(); + setShellCallbacks({ openTab } as never); + shell.openTab({ id: "5", name: "db" } as unknown as Host, "terminal"); + expect(openTab.mock.calls[0][0]).toMatchObject({ socks5Host: "proxy" }); + }); +});