From e88d5a52e313c7c8b50f9fb8945815f2ae264cfa Mon Sep 17 00:00:00 2001 From: LukeGus Date: Tue, 22 Sep 2026 20:15:52 -0500 Subject: [PATCH] feat: load plugin frontends at runtime and remove plugin ids from the shell --- docker/nginx-https.conf | 13 +- docker/nginx.conf | 13 +- eslint.config.mjs | 16 +- package.json | 2 +- packages/plugin-sdk/ARCHITECTURE.md | 200 ++- packages/plugin-sdk/cli/commands/build.mjs | 19 +- packages/plugin-sdk/cli/lib/externals.mjs | 21 +- .../cli/lib/legacy-core-imports.mjs | 40 +- .../cli/lib/legacy-core-specifier.mjs | 62 + .../plugin-sdk/schema/manifest.schema.json | 31 +- packages/plugin-sdk/src/frontend.ts | 625 ++++++++- packages/plugin-sdk/src/manifest.ts | 55 +- packages/plugin-sdk/src/testing.ts | 113 +- packages/plugin-sdk/src/testing/setup.ts | 40 + packages/plugin-sdk/src/vitest-preset.ts | 24 + plugins/ai/locales/en.json | 108 +- plugins/ai/locales/translated/af_ZA.json | 78 ++ plugins/ai/locales/translated/ar_SA.json | 78 ++ plugins/ai/locales/translated/bg_BG.json | 78 ++ plugins/ai/locales/translated/bn_BD.json | 78 ++ plugins/ai/locales/translated/ca_ES.json | 78 ++ plugins/ai/locales/translated/cs_CZ.json | 78 ++ plugins/ai/locales/translated/da_DK.json | 78 ++ plugins/ai/locales/translated/de_DE.json | 78 ++ plugins/ai/locales/translated/el_GR.json | 78 ++ plugins/ai/locales/translated/es_ES.json | 78 ++ plugins/ai/locales/translated/fi_FI.json | 78 ++ plugins/ai/locales/translated/fr_FR.json | 78 ++ plugins/ai/locales/translated/he_IL.json | 78 ++ plugins/ai/locales/translated/hi_IN.json | 78 ++ plugins/ai/locales/translated/hu_HU.json | 78 ++ plugins/ai/locales/translated/id_ID.json | 78 ++ plugins/ai/locales/translated/it_IT.json | 78 ++ plugins/ai/locales/translated/ja_JP.json | 78 ++ plugins/ai/locales/translated/ko_KR.json | 78 ++ plugins/ai/locales/translated/nl_NL.json | 78 ++ plugins/ai/locales/translated/no_NO.json | 78 ++ plugins/ai/locales/translated/pl_PL.json | 78 ++ plugins/ai/locales/translated/pt_BR.json | 78 ++ plugins/ai/locales/translated/pt_PT.json | 78 ++ plugins/ai/locales/translated/ro_RO.json | 78 ++ plugins/ai/locales/translated/ru_RU.json | 78 ++ plugins/ai/locales/translated/sr_SP.json | 78 ++ plugins/ai/locales/translated/sv_SE.json | 78 ++ plugins/ai/locales/translated/th_TH.json | 78 ++ plugins/ai/locales/translated/tr_TR.json | 78 ++ plugins/ai/locales/translated/uk_UA.json | 78 ++ plugins/ai/locales/translated/vi_VN.json | 78 ++ plugins/ai/locales/translated/zh_CN.json | 78 ++ plugins/ai/locales/translated/zh_TW.json | 78 ++ plugins/ai/manifest.json | 18 +- .../ai/src/frontend}/AiAssistantStep.tsx | 21 +- .../ai/src/frontend}/AiMessage.tsx | 0 .../ai/src/frontend}/AiPanel.tsx | 4 +- .../ai/src/frontend}/AiProviderSettings.tsx | 6 +- .../ai/src/frontend}/AiToolCall.tsx | 2 +- .../ai/src/frontend}/ProposalCard.tsx | 10 +- .../api => plugins/ai/src/frontend}/ai-api.ts | 61 - plugins/ai/src/frontend/index.mjs | 68 - plugins/ai/src/frontend/index.tsx | 183 +++ .../ai => plugins/ai/src/frontend}/labels.ts | 0 .../frontend/settings/AiAccessSettings.tsx | 95 ++ .../src/frontend/settings/AiUserSettings.tsx | 112 ++ .../frontend}/terminal/TerminalAiPanel.tsx | 14 +- .../terminal/TerminalProposalCard.tsx | 8 +- .../ai/src/frontend}/use-ai-availability.ts | 2 +- .../ai/src/frontend}/use-ai-stream.ts | 4 +- .../ai/src/frontend}/useMentions.ts | 16 +- .../frontend/AiProviderSettings.test.tsx | 6 +- plugins/ai/tests/frontend/activate.test.tsx | 53 + plugins/ai/tests/frontend/labels.test.ts | 2 +- .../frontend}/use-ai-availability.test.ts | 4 +- plugins/automations/locales/en.json | 172 ++- .../automations/locales/translated/af_ZA.json | 149 ++ .../automations/locales/translated/ar_SA.json | 149 ++ .../automations/locales/translated/bg_BG.json | 149 ++ .../automations/locales/translated/bn_BD.json | 149 ++ .../automations/locales/translated/ca_ES.json | 149 ++ .../automations/locales/translated/cs_CZ.json | 149 ++ .../automations/locales/translated/da_DK.json | 149 ++ .../automations/locales/translated/de_DE.json | 149 ++ .../automations/locales/translated/el_GR.json | 149 ++ .../automations/locales/translated/es_ES.json | 149 ++ .../automations/locales/translated/fi_FI.json | 149 ++ .../automations/locales/translated/fr_FR.json | 149 ++ .../automations/locales/translated/he_IL.json | 149 ++ .../automations/locales/translated/hi_IN.json | 149 ++ .../automations/locales/translated/hu_HU.json | 149 ++ .../automations/locales/translated/id_ID.json | 149 ++ .../automations/locales/translated/it_IT.json | 149 ++ .../automations/locales/translated/ja_JP.json | 149 ++ .../automations/locales/translated/ko_KR.json | 149 ++ .../automations/locales/translated/nl_NL.json | 149 ++ .../automations/locales/translated/no_NO.json | 149 ++ .../automations/locales/translated/pl_PL.json | 149 ++ .../automations/locales/translated/pt_BR.json | 149 ++ .../automations/locales/translated/pt_PT.json | 149 ++ .../automations/locales/translated/ro_RO.json | 149 ++ .../automations/locales/translated/ru_RU.json | 149 ++ .../automations/locales/translated/sr_SP.json | 149 ++ .../automations/locales/translated/sv_SE.json | 149 ++ .../automations/locales/translated/th_TH.json | 149 ++ .../automations/locales/translated/tr_TR.json | 149 ++ .../automations/locales/translated/uk_UA.json | 149 ++ .../automations/locales/translated/vi_VN.json | 149 ++ .../automations/locales/translated/zh_CN.json | 149 ++ .../automations/locales/translated/zh_TW.json | 149 ++ plugins/automations/manifest.json | 8 + .../src/frontend/AutomationsPanel.tsx | 13 +- .../frontend/automations/AutomationEditor.tsx | 2 +- .../automations/HostSelectorField.tsx | 2 +- .../src/frontend/automations/StepBlock.tsx | 2 +- .../src/frontend/automations/TriggerCard.tsx | 2 +- plugins/automations/src/frontend/index.mjs | 36 - plugins/automations/src/frontend/index.tsx | 51 + .../tests/frontend/activate.test.tsx | 53 + plugins/docker/locales/en.json | 126 +- plugins/docker/locales/translated/af_ZA.json | 116 ++ plugins/docker/locales/translated/ar_SA.json | 116 ++ plugins/docker/locales/translated/bg_BG.json | 116 ++ plugins/docker/locales/translated/bn_BD.json | 116 ++ plugins/docker/locales/translated/ca_ES.json | 116 ++ plugins/docker/locales/translated/cs_CZ.json | 116 ++ plugins/docker/locales/translated/da_DK.json | 116 ++ plugins/docker/locales/translated/de_DE.json | 116 ++ plugins/docker/locales/translated/el_GR.json | 116 ++ plugins/docker/locales/translated/es_ES.json | 116 ++ plugins/docker/locales/translated/fi_FI.json | 116 ++ plugins/docker/locales/translated/fr_FR.json | 116 ++ plugins/docker/locales/translated/he_IL.json | 116 ++ plugins/docker/locales/translated/hi_IN.json | 116 ++ plugins/docker/locales/translated/hu_HU.json | 116 ++ plugins/docker/locales/translated/id_ID.json | 116 ++ plugins/docker/locales/translated/it_IT.json | 116 ++ plugins/docker/locales/translated/ja_JP.json | 116 ++ plugins/docker/locales/translated/ko_KR.json | 116 ++ plugins/docker/locales/translated/nl_NL.json | 116 ++ plugins/docker/locales/translated/no_NO.json | 116 ++ plugins/docker/locales/translated/pl_PL.json | 116 ++ plugins/docker/locales/translated/pt_BR.json | 116 ++ plugins/docker/locales/translated/pt_PT.json | 116 ++ plugins/docker/locales/translated/ro_RO.json | 116 ++ plugins/docker/locales/translated/ru_RU.json | 116 ++ plugins/docker/locales/translated/sr_SP.json | 116 ++ plugins/docker/locales/translated/sv_SE.json | 116 ++ plugins/docker/locales/translated/th_TH.json | 116 ++ plugins/docker/locales/translated/tr_TR.json | 116 ++ plugins/docker/locales/translated/uk_UA.json | 116 ++ plugins/docker/locales/translated/vi_VN.json | 116 ++ plugins/docker/locales/translated/zh_CN.json | 116 ++ plugins/docker/locales/translated/zh_TW.json | 116 ++ plugins/docker/src/frontend/DockerApp.tsx | 2 +- plugins/docker/src/frontend/DockerManager.tsx | 7 +- .../docker/src/frontend}/DockerWidget.tsx | 15 +- .../src/frontend}/DockerWidgetEditForm.tsx | 2 +- plugins/docker/src/frontend/HostDockerTab.tsx | 68 + .../frontend/components/ConsoleTerminal.tsx | 2 +- .../src/frontend/components/ContainerCard.tsx | 4 +- .../frontend/components/ContainerDetail.tsx | 2 +- .../src/frontend/components/ContainerList.tsx | 2 +- .../frontend/components/ContainerStats.tsx | 4 +- .../frontend/components/ContainerTable.tsx | 4 +- .../src/frontend/components/LogViewer.tsx | 4 +- .../docker/src/frontend}/docker-api.ts | 0 plugins/docker/src/frontend/index.mjs | 67 - plugins/docker/src/frontend/index.tsx | 83 ++ .../docker/tests/frontend/activate.test.tsx | 53 + plugins/fleets/locales/en.json | 97 +- plugins/fleets/locales/translated/af_ZA.json | 89 ++ plugins/fleets/locales/translated/ar_SA.json | 89 ++ plugins/fleets/locales/translated/bg_BG.json | 89 ++ plugins/fleets/locales/translated/bn_BD.json | 89 ++ plugins/fleets/locales/translated/ca_ES.json | 89 ++ plugins/fleets/locales/translated/cs_CZ.json | 89 ++ plugins/fleets/locales/translated/da_DK.json | 89 ++ plugins/fleets/locales/translated/de_DE.json | 89 ++ plugins/fleets/locales/translated/el_GR.json | 89 ++ plugins/fleets/locales/translated/es_ES.json | 89 ++ plugins/fleets/locales/translated/fi_FI.json | 89 ++ plugins/fleets/locales/translated/fr_FR.json | 89 ++ plugins/fleets/locales/translated/he_IL.json | 89 ++ plugins/fleets/locales/translated/hi_IN.json | 89 ++ plugins/fleets/locales/translated/hu_HU.json | 89 ++ plugins/fleets/locales/translated/id_ID.json | 89 ++ plugins/fleets/locales/translated/it_IT.json | 89 ++ plugins/fleets/locales/translated/ja_JP.json | 89 ++ plugins/fleets/locales/translated/ko_KR.json | 89 ++ plugins/fleets/locales/translated/nl_NL.json | 89 ++ plugins/fleets/locales/translated/no_NO.json | 89 ++ plugins/fleets/locales/translated/pl_PL.json | 89 ++ plugins/fleets/locales/translated/pt_BR.json | 89 ++ plugins/fleets/locales/translated/pt_PT.json | 89 ++ plugins/fleets/locales/translated/ro_RO.json | 89 ++ plugins/fleets/locales/translated/ru_RU.json | 89 ++ plugins/fleets/locales/translated/sr_SP.json | 89 ++ plugins/fleets/locales/translated/sv_SE.json | 89 ++ plugins/fleets/locales/translated/th_TH.json | 89 ++ plugins/fleets/locales/translated/tr_TR.json | 89 ++ plugins/fleets/locales/translated/uk_UA.json | 89 ++ plugins/fleets/locales/translated/vi_VN.json | 89 ++ plugins/fleets/locales/translated/zh_CN.json | 89 ++ plugins/fleets/locales/translated/zh_TW.json | 89 ++ plugins/fleets/manifest.json | 19 +- .../fleets/src/frontend/FleetInventoryTab.tsx | 4 +- plugins/fleets/src/frontend/FleetsPanel.tsx | 4 +- .../fleets/src/frontend}/fleets-api.ts | 0 plugins/fleets/src/frontend/index.mjs | 40 - plugins/fleets/src/frontend/index.tsx | 55 + .../fleets/tests/frontend/activate.test.tsx | 53 + plugins/host-metrics/locales/en.json | 315 ++++- .../locales/translated/af_ZA.json | 313 +++++ .../locales/translated/ar_SA.json | 313 +++++ .../locales/translated/bg_BG.json | 313 +++++ .../locales/translated/bn_BD.json | 313 +++++ .../locales/translated/ca_ES.json | 313 +++++ .../locales/translated/cs_CZ.json | 313 +++++ .../locales/translated/da_DK.json | 313 +++++ .../locales/translated/de_DE.json | 313 +++++ .../locales/translated/el_GR.json | 313 +++++ .../locales/translated/es_ES.json | 313 +++++ .../locales/translated/fi_FI.json | 313 +++++ .../locales/translated/fr_FR.json | 313 +++++ .../locales/translated/he_IL.json | 313 +++++ .../locales/translated/hi_IN.json | 313 +++++ .../locales/translated/hu_HU.json | 313 +++++ .../locales/translated/id_ID.json | 313 +++++ .../locales/translated/it_IT.json | 313 +++++ .../locales/translated/ja_JP.json | 313 +++++ .../locales/translated/ko_KR.json | 313 +++++ .../locales/translated/nl_NL.json | 313 +++++ .../locales/translated/no_NO.json | 313 +++++ .../locales/translated/pl_PL.json | 313 +++++ .../locales/translated/pt_BR.json | 313 +++++ .../locales/translated/pt_PT.json | 313 +++++ .../locales/translated/ro_RO.json | 313 +++++ .../locales/translated/ru_RU.json | 313 +++++ .../locales/translated/sr_SP.json | 313 +++++ .../locales/translated/sv_SE.json | 313 +++++ .../locales/translated/th_TH.json | 313 +++++ .../locales/translated/tr_TR.json | 313 +++++ .../locales/translated/uk_UA.json | 313 +++++ .../locales/translated/vi_VN.json | 313 +++++ .../locales/translated/zh_CN.json | 313 +++++ .../locales/translated/zh_TW.json | 313 +++++ plugins/host-metrics/manifest.json | 17 +- .../src/frontend}/HostEditorStatsTab.tsx | 4 +- .../src/frontend/HostMetricsApp.tsx | 2 +- .../src/frontend/HostMetricsTab.tsx | 2 +- .../src/frontend}/MetricsChartEditForm.tsx | 2 +- .../src/frontend}/MetricsChartWidget.tsx | 20 +- .../src/frontend/MetricsRetentionSetting.tsx | 73 + .../src/frontend/cards/CardTimeTabs.tsx | 2 +- .../src/frontend/cards/CpuCard.tsx | 7 +- .../src/frontend/cards/DiskCard.tsx | 7 +- .../src/frontend/cards/FilesystemPicker.tsx | 2 +- .../src/frontend/cards/FirewallCard.tsx | 2 +- .../src/frontend/cards/GpuCard.tsx | 2 +- .../src/frontend/cards/LoginStatsCard.tsx | 2 +- .../src/frontend/cards/MemoryCard.tsx | 7 +- .../src/frontend/cards/NetworkCard.tsx | 7 +- .../src/frontend/cards/PortsCard.tsx | 2 +- .../src/frontend/cards/ProcessesCard.tsx | 2 +- .../src/frontend/cards/SystemCard.tsx | 2 +- .../src/frontend/cards/TemperatureCard.tsx | 2 +- .../src/frontend/cards/UptimeCard.tsx | 2 +- .../cards/managers/CronManagerCard.tsx | 4 +- .../cards/managers/FirewallManagerCard.tsx | 5 +- .../cards/managers/HealthCheckCard.tsx | 4 +- .../frontend/cards/managers/LogViewerCard.tsx | 4 +- .../cards/managers/ManagerCardShell.tsx | 2 +- .../cards/managers/ManagerToolbar.tsx | 2 +- .../cards/managers/PackageManagerCard.tsx | 4 +- .../cards/managers/ProcessInspectorCard.tsx | 4 +- .../cards/managers/ServiceManagerCard.tsx | 4 +- .../cards/managers/SimpleManagerCards.tsx | 2 +- .../cards/managers/SslManagerCard.tsx | 4 +- .../cards/managers/TailscaleManagerCard.tsx | 2 +- .../cards/managers/UserManagerCard.tsx | 4 +- .../cards/managers/WireGuardManagerCard.tsx | 2 +- .../frontend/cards/managers/useManagerData.ts | 2 +- .../hooks/useHostMetricsPreferences.ts | 5 +- .../src/frontend}/host-metrics-api.ts | 0 plugins/host-metrics/src/frontend/index.mjs | 49 - plugins/host-metrics/src/frontend/index.tsx | 161 +++ .../frontend}/proxmox-stats/GuestTable.tsx | 2 +- .../proxmox-stats/HostProxmoxStatsTab.tsx | 79 ++ .../proxmox-stats/NodeSummaryStrip.tsx | 2 +- .../proxmox-stats/ProxmoxStatsApp.tsx | 4 +- .../proxmox-stats/ProxmoxStatsTab.tsx | 6 +- .../proxmox-stats/cards/ClusterHealthCard.tsx | 2 +- .../proxmox-stats/cards/NodeNetworkCard.tsx | 2 +- .../proxmox-stats/cards/StoragePoolsCard.tsx | 2 +- .../proxmox-stats}/proxmox-stats-api.ts | 0 .../tests/frontend/activate.test.tsx | 53 + plugins/network-topology/locales/en.json | 61 +- .../locales/translated/af_ZA.json | 60 + .../locales/translated/ar_SA.json | 60 + .../locales/translated/bg_BG.json | 60 + .../locales/translated/bn_BD.json | 60 + .../locales/translated/ca_ES.json | 60 + .../locales/translated/cs_CZ.json | 60 + .../locales/translated/da_DK.json | 60 + .../locales/translated/de_DE.json | 60 + .../locales/translated/el_GR.json | 60 + .../locales/translated/es_ES.json | 60 + .../locales/translated/fi_FI.json | 60 + .../locales/translated/fr_FR.json | 60 + .../locales/translated/he_IL.json | 60 + .../locales/translated/hi_IN.json | 60 + .../locales/translated/hu_HU.json | 60 + .../locales/translated/id_ID.json | 60 + .../locales/translated/it_IT.json | 60 + .../locales/translated/ja_JP.json | 60 + .../locales/translated/ko_KR.json | 60 + .../locales/translated/nl_NL.json | 60 + .../locales/translated/no_NO.json | 60 + .../locales/translated/pl_PL.json | 60 + .../locales/translated/pt_BR.json | 60 + .../locales/translated/pt_PT.json | 60 + .../locales/translated/ro_RO.json | 60 + .../locales/translated/ru_RU.json | 60 + .../locales/translated/sr_SP.json | 60 + .../locales/translated/sv_SE.json | 60 + .../locales/translated/th_TH.json | 60 + .../locales/translated/tr_TR.json | 60 + .../locales/translated/uk_UA.json | 60 + .../locales/translated/vi_VN.json | 60 + .../locales/translated/zh_CN.json | 60 + .../locales/translated/zh_TW.json | 60 + plugins/network-topology/manifest.json | 7 + .../src/frontend/NetworkGraphCard.tsx | 2 +- .../network-topology/src/frontend/index.mjs | 44 - .../network-topology/src/frontend/index.tsx | 47 + .../tests/frontend/activate.test.tsx | 53 + plugins/proxmox/locales/en.json | 54 +- plugins/proxmox/locales/translated/af_ZA.json | 53 + plugins/proxmox/locales/translated/ar_SA.json | 53 + plugins/proxmox/locales/translated/bg_BG.json | 53 + plugins/proxmox/locales/translated/bn_BD.json | 53 + plugins/proxmox/locales/translated/ca_ES.json | 53 + plugins/proxmox/locales/translated/cs_CZ.json | 53 + plugins/proxmox/locales/translated/da_DK.json | 53 + plugins/proxmox/locales/translated/de_DE.json | 53 + plugins/proxmox/locales/translated/el_GR.json | 53 + plugins/proxmox/locales/translated/es_ES.json | 53 + plugins/proxmox/locales/translated/fi_FI.json | 53 + plugins/proxmox/locales/translated/fr_FR.json | 53 + plugins/proxmox/locales/translated/he_IL.json | 53 + plugins/proxmox/locales/translated/hi_IN.json | 53 + plugins/proxmox/locales/translated/hu_HU.json | 53 + plugins/proxmox/locales/translated/id_ID.json | 53 + plugins/proxmox/locales/translated/it_IT.json | 53 + plugins/proxmox/locales/translated/ja_JP.json | 53 + plugins/proxmox/locales/translated/ko_KR.json | 53 + plugins/proxmox/locales/translated/nl_NL.json | 53 + plugins/proxmox/locales/translated/no_NO.json | 53 + plugins/proxmox/locales/translated/pl_PL.json | 53 + plugins/proxmox/locales/translated/pt_BR.json | 53 + plugins/proxmox/locales/translated/pt_PT.json | 53 + plugins/proxmox/locales/translated/ro_RO.json | 53 + plugins/proxmox/locales/translated/ru_RU.json | 53 + plugins/proxmox/locales/translated/sr_SP.json | 53 + plugins/proxmox/locales/translated/sv_SE.json | 53 + plugins/proxmox/locales/translated/th_TH.json | 53 + plugins/proxmox/locales/translated/tr_TR.json | 53 + plugins/proxmox/locales/translated/uk_UA.json | 53 + plugins/proxmox/locales/translated/vi_VN.json | 53 + plugins/proxmox/locales/translated/zh_CN.json | 53 + plugins/proxmox/locales/translated/zh_TW.json | 53 + .../proxmox/src/frontend/HostProxmoxTab.tsx | 244 +--- .../src/frontend/ProxmoxDiscoverDialog.tsx | 2 +- plugins/proxmox/src/frontend/index.mjs | 44 - plugins/proxmox/src/frontend/index.tsx | 128 ++ .../proxmox/tests/frontend/activate.test.tsx | 53 + plugins/remote-desktop/locales/en.json | 215 ++- .../locales/translated/af_ZA.json | 214 +++ .../locales/translated/ar_SA.json | 214 +++ .../locales/translated/bg_BG.json | 214 +++ .../locales/translated/bn_BD.json | 214 +++ .../locales/translated/ca_ES.json | 214 +++ .../locales/translated/cs_CZ.json | 214 +++ .../locales/translated/da_DK.json | 214 +++ .../locales/translated/de_DE.json | 214 +++ .../locales/translated/el_GR.json | 214 +++ .../locales/translated/es_ES.json | 214 +++ .../locales/translated/fi_FI.json | 214 +++ .../locales/translated/fr_FR.json | 214 +++ .../locales/translated/he_IL.json | 214 +++ .../locales/translated/hi_IN.json | 214 +++ .../locales/translated/hu_HU.json | 214 +++ .../locales/translated/id_ID.json | 214 +++ .../locales/translated/it_IT.json | 214 +++ .../locales/translated/ja_JP.json | 214 +++ .../locales/translated/ko_KR.json | 214 +++ .../locales/translated/nl_NL.json | 214 +++ .../locales/translated/no_NO.json | 214 +++ .../locales/translated/pl_PL.json | 214 +++ .../locales/translated/pt_BR.json | 214 +++ .../locales/translated/pt_PT.json | 214 +++ .../locales/translated/ro_RO.json | 214 +++ .../locales/translated/ru_RU.json | 214 +++ .../locales/translated/sr_SP.json | 214 +++ .../locales/translated/sv_SE.json | 214 +++ .../locales/translated/th_TH.json | 214 +++ .../locales/translated/tr_TR.json | 214 +++ .../locales/translated/uk_UA.json | 214 +++ .../locales/translated/vi_VN.json | 214 +++ .../locales/translated/zh_CN.json | 214 +++ .../locales/translated/zh_TW.json | 214 +++ plugins/remote-desktop/manifest.json | 3 +- .../src/frontend/GuacamoleApp.tsx | 28 +- .../src/frontend/GuacamoleDisplay.tsx | 5 +- .../src/frontend/GuacamoleFileBrowser.tsx | 2 +- .../src/frontend/GuacamoleToolbar.tsx | 2 +- .../src/frontend}/HostEditorGuacamoleTabs.tsx | 4 +- plugins/remote-desktop/src/frontend/index.mjs | 28 - plugins/remote-desktop/src/frontend/index.tsx | 307 ++++ .../src/frontend/quick-connect-guac-host.ts | 19 + .../tests/frontend/activate.test.tsx | 53 + .../frontend/quick-connect-guac-host.test.ts | 41 + plugins/ssh-terminal/manifest.json | 10 +- plugins/ssh-terminal/src/frontend/index.mjs | 49 - plugins/ssh-terminal/src/frontend/index.tsx | 66 + .../tests/frontend/activate.test.tsx | 53 + plugins/tailscale/locales/en.json | 55 +- .../tailscale/locales/translated/af_ZA.json | 20 + .../tailscale/locales/translated/ar_SA.json | 20 + .../tailscale/locales/translated/bg_BG.json | 20 + .../tailscale/locales/translated/bn_BD.json | 20 + .../tailscale/locales/translated/ca_ES.json | 20 + .../tailscale/locales/translated/cs_CZ.json | 20 + .../tailscale/locales/translated/da_DK.json | 20 + .../tailscale/locales/translated/de_DE.json | 20 + .../tailscale/locales/translated/el_GR.json | 20 + .../tailscale/locales/translated/es_ES.json | 20 + .../tailscale/locales/translated/fi_FI.json | 20 + .../tailscale/locales/translated/fr_FR.json | 20 + .../tailscale/locales/translated/he_IL.json | 20 + .../tailscale/locales/translated/hi_IN.json | 20 + .../tailscale/locales/translated/hu_HU.json | 20 + .../tailscale/locales/translated/id_ID.json | 20 + .../tailscale/locales/translated/it_IT.json | 20 + .../tailscale/locales/translated/ja_JP.json | 20 + .../tailscale/locales/translated/ko_KR.json | 20 + .../tailscale/locales/translated/nl_NL.json | 20 + .../tailscale/locales/translated/no_NO.json | 20 + .../tailscale/locales/translated/pl_PL.json | 20 + .../tailscale/locales/translated/pt_BR.json | 20 + .../tailscale/locales/translated/pt_PT.json | 20 + .../tailscale/locales/translated/ro_RO.json | 20 + .../tailscale/locales/translated/ru_RU.json | 20 + .../tailscale/locales/translated/sr_SP.json | 20 + .../tailscale/locales/translated/sv_SE.json | 20 + .../tailscale/locales/translated/th_TH.json | 20 + .../tailscale/locales/translated/tr_TR.json | 20 + .../tailscale/locales/translated/uk_UA.json | 20 + .../tailscale/locales/translated/vi_VN.json | 20 + .../tailscale/locales/translated/zh_CN.json | 20 + .../tailscale/locales/translated/zh_TW.json | 20 + plugins/tailscale/manifest.json | 7 + .../src/frontend/TailscaleAuthEditor.tsx | 122 ++ .../src/frontend/TailscaleCheckDialog.tsx | 2 +- .../src/frontend/TailscaleCheckOverlay.tsx | 101 ++ .../src/frontend/TailscaleDevicesPanel.tsx | 4 +- .../src/frontend}/TailscaleDevicesStatus.tsx | 11 +- plugins/tailscale/src/frontend/index.mjs | 40 - plugins/tailscale/src/frontend/index.tsx | 52 + .../tests/frontend/activate.test.tsx | 53 + plugins/web-endpoint/locales/en.json | 53 +- .../locales/translated/af_ZA.json | 52 + .../locales/translated/ar_SA.json | 52 + .../locales/translated/bg_BG.json | 52 + .../locales/translated/bn_BD.json | 52 + .../locales/translated/ca_ES.json | 52 + .../locales/translated/cs_CZ.json | 52 + .../locales/translated/da_DK.json | 52 + .../locales/translated/de_DE.json | 52 + .../locales/translated/el_GR.json | 52 + .../locales/translated/es_ES.json | 52 + .../locales/translated/fi_FI.json | 52 + .../locales/translated/fr_FR.json | 52 + .../locales/translated/he_IL.json | 52 + .../locales/translated/hi_IN.json | 52 + .../locales/translated/hu_HU.json | 52 + .../locales/translated/id_ID.json | 52 + .../locales/translated/it_IT.json | 52 + .../locales/translated/ja_JP.json | 52 + .../locales/translated/ko_KR.json | 52 + .../locales/translated/nl_NL.json | 52 + .../locales/translated/no_NO.json | 52 + .../locales/translated/pl_PL.json | 52 + .../locales/translated/pt_BR.json | 52 + .../locales/translated/pt_PT.json | 52 + .../locales/translated/ro_RO.json | 52 + .../locales/translated/ru_RU.json | 52 + .../locales/translated/sr_SP.json | 52 + .../locales/translated/sv_SE.json | 52 + .../locales/translated/th_TH.json | 52 + .../locales/translated/tr_TR.json | 52 + .../locales/translated/uk_UA.json | 52 + .../locales/translated/vi_VN.json | 52 + .../locales/translated/zh_CN.json | 52 + .../locales/translated/zh_TW.json | 52 + .../src/frontend}/HostEditorWebUiSection.tsx | 6 +- .../src/frontend/HostWebUiTab.tsx | 66 + .../src/frontend/WebEndpointTab.tsx | 2 +- plugins/web-endpoint/src/frontend/index.mjs | 39 - plugins/web-endpoint/src/frontend/index.tsx | 117 ++ .../host-web-endpoint-enumeration.test.ts | 2 +- .../frontend}/HostEditorWebUiSection.test.tsx | 2 +- .../tests/frontend/activate.test.tsx | 126 ++ plugins/workspaces/locales/en.json | 56 +- .../workspaces/locales/translated/af_ZA.json | 55 + .../workspaces/locales/translated/ar_SA.json | 55 + .../workspaces/locales/translated/bg_BG.json | 55 + .../workspaces/locales/translated/bn_BD.json | 55 + .../workspaces/locales/translated/ca_ES.json | 55 + .../workspaces/locales/translated/cs_CZ.json | 55 + .../workspaces/locales/translated/da_DK.json | 55 + .../workspaces/locales/translated/de_DE.json | 55 + .../workspaces/locales/translated/el_GR.json | 55 + .../workspaces/locales/translated/es_ES.json | 55 + .../workspaces/locales/translated/fi_FI.json | 55 + .../workspaces/locales/translated/fr_FR.json | 55 + .../workspaces/locales/translated/he_IL.json | 55 + .../workspaces/locales/translated/hi_IN.json | 55 + .../workspaces/locales/translated/hu_HU.json | 55 + .../workspaces/locales/translated/id_ID.json | 55 + .../workspaces/locales/translated/it_IT.json | 55 + .../workspaces/locales/translated/ja_JP.json | 55 + .../workspaces/locales/translated/ko_KR.json | 55 + .../workspaces/locales/translated/nl_NL.json | 55 + .../workspaces/locales/translated/no_NO.json | 55 + .../workspaces/locales/translated/pl_PL.json | 55 + .../workspaces/locales/translated/pt_BR.json | 55 + .../workspaces/locales/translated/pt_PT.json | 55 + .../workspaces/locales/translated/ro_RO.json | 55 + .../workspaces/locales/translated/ru_RU.json | 55 + .../workspaces/locales/translated/sr_SP.json | 55 + .../workspaces/locales/translated/sv_SE.json | 55 + .../workspaces/locales/translated/th_TH.json | 55 + .../workspaces/locales/translated/tr_TR.json | 55 + .../workspaces/locales/translated/uk_UA.json | 55 + .../workspaces/locales/translated/vi_VN.json | 55 + .../workspaces/locales/translated/zh_CN.json | 55 + .../workspaces/locales/translated/zh_TW.json | 55 + plugins/workspaces/manifest.json | 11 +- .../src/frontend/WorkspacesPanel.tsx | 2 +- plugins/workspaces/src/frontend/index.mjs | 34 - plugins/workspaces/src/frontend/index.tsx | 95 ++ .../workspaces/src/frontend/workspaceUtils.ts | 163 --- .../tests/frontend/activate.test.tsx | 53 + scripts/check-importmap-csp.cjs | 67 + scripts/check-plugin-boundaries.cjs | 28 +- scripts/check-shell-plugin-ids.cjs | 120 ++ scripts/lib/plugin-import-map.mjs | 141 ++ scripts/plugin-boundary-allowlist.json | 128 +- scripts/shell-plugin-id-allowlist.json | 121 ++ scripts/vite-plugin-termix-plugins.mjs | 204 +++ src/backend/database/database.ts | 6 + src/backend/database/routes/plugins.ts | 76 + src/backend/plugins/assets.ts | 218 +++ .../tests/database/routes/plugins.test.ts | 54 +- src/backend/tests/plugins/assets.test.ts | 132 ++ src/backend/tests/plugins/manifest.test.ts | 53 +- src/main.tsx | 96 +- src/types/homepage-types.ts | 18 +- src/types/ui-types.ts | 14 +- src/ui/AppShell.tsx | 547 +++----- src/ui/api/dashboard-api.ts | 21 +- src/ui/api/plugins-api.ts | 22 + src/ui/api/private-endpoints-api.ts | 67 + src/ui/dashboard/DashboardTab.tsx | 192 +-- src/ui/dashboard/dashboard-cards-registry.ts | 47 +- src/ui/features/collab/CollabGuestView.tsx | 11 +- src/ui/features/collab/CollabRoomTab.tsx | 30 +- src/ui/features/homepage/HomepageCanvas.tsx | 2 - .../homepage/dialogs/AddWidgetMenu.tsx | 4 +- .../homepage/dialogs/QuickConnectEditForm.tsx | 18 +- .../dialogs/RecentActivityEditForm.tsx | 13 +- .../homepage/dialogs/WidgetEditDialog.tsx | 28 +- .../homepage/quick-connect-targets.ts | 64 + .../homepage/widgets/QuickConnectWidget.tsx | 56 +- .../homepage/widgets/RecentActivityWidget.tsx | 29 +- .../homepage/widgets/WidgetRegistry.ts | 12 +- .../features/homepage/widgets/WidgetShell.tsx | 9 +- .../features/remote-display/RemoteDisplay.tsx | 59 + .../session-sharing/SharedSessionView.tsx | 11 +- src/ui/features/terminal/Terminal.tsx | 278 ++-- .../features/terminal/TerminalTabContent.tsx | 116 ++ src/ui/features/terminal/TerminalToolbar.tsx | 28 +- src/ui/features/terminal/terminal-slots.ts | 60 + src/ui/features/tmux-monitor/PanePreview.tsx | 38 +- src/ui/hooks/use-action-slot.ts | 26 +- src/ui/hooks/use-permissions.ts | 10 + src/ui/i18n/i18n.ts | 129 +- src/ui/lib/activity-types.ts | 37 + src/ui/lib/host-connection-tabs.ts | 56 +- src/ui/lib/host-to-ssh-host.ts | 51 + src/ui/lib/plugin-i18n.ts | 22 +- src/ui/lib/registry.ts | 81 ++ src/ui/lib/theme.ts | 6 - src/ui/locales/en.json | 1240 +---------------- src/ui/locales/translated/af_ZA.json | 1129 +-------------- src/ui/locales/translated/ar_SA.json | 1129 +-------------- src/ui/locales/translated/bg_BG.json | 1129 +-------------- src/ui/locales/translated/bn_BD.json | 1129 +-------------- src/ui/locales/translated/ca_ES.json | 1129 +-------------- src/ui/locales/translated/cs_CZ.json | 1129 +-------------- src/ui/locales/translated/da_DK.json | 1129 +-------------- src/ui/locales/translated/de_DE.json | 1129 +-------------- src/ui/locales/translated/el_GR.json | 1129 +-------------- src/ui/locales/translated/es_ES.json | 1129 +-------------- src/ui/locales/translated/fi_FI.json | 1129 +-------------- src/ui/locales/translated/fr_FR.json | 1129 +-------------- src/ui/locales/translated/he_IL.json | 1129 +-------------- src/ui/locales/translated/hi_IN.json | 1129 +-------------- src/ui/locales/translated/hu_HU.json | 1129 +-------------- src/ui/locales/translated/id_ID.json | 1129 +-------------- src/ui/locales/translated/it_IT.json | 1129 +-------------- src/ui/locales/translated/ja_JP.json | 1129 +-------------- src/ui/locales/translated/ko_KR.json | 1129 +-------------- src/ui/locales/translated/nl_NL.json | 1129 +-------------- src/ui/locales/translated/no_NO.json | 1129 +-------------- src/ui/locales/translated/pl_PL.json | 1129 +-------------- src/ui/locales/translated/pt_BR.json | 1129 +-------------- src/ui/locales/translated/pt_PT.json | 1129 +-------------- src/ui/locales/translated/ro_RO.json | 1129 +-------------- src/ui/locales/translated/ru_RU.json | 1129 +-------------- src/ui/locales/translated/sr_SP.json | 1129 +-------------- src/ui/locales/translated/sv_SE.json | 1129 +-------------- src/ui/locales/translated/th_TH.json | 1129 +-------------- src/ui/locales/translated/tr_TR.json | 1129 +-------------- src/ui/locales/translated/uk_UA.json | 1129 +-------------- src/ui/locales/translated/vi_VN.json | 1129 +-------------- src/ui/locales/translated/zh_CN.json | 1129 +-------------- src/ui/locales/translated/zh_TW.json | 1129 +-------------- src/ui/main-axios.ts | 61 +- src/ui/onboarding/OnboardingDialog.tsx | 27 +- src/ui/onboarding/onboarding-steps.ts | 18 +- src/ui/onboarding/steps/FeaturesStep.tsx | 48 +- src/ui/onboarding/steps/WorkflowStep.tsx | 39 +- src/ui/plugin-host/PluginViewPlaceholder.tsx | 65 + src/ui/plugin-host/app.ts | 377 +++++ src/ui/plugin-host/auth-registry.ts | 59 + src/ui/plugin-host/bridge.ts | 251 ++++ src/ui/plugin-host/loader.ts | 404 ++++++ src/ui/plugin-host/plugin-store.ts | 115 ++ src/ui/plugin-host/scope.tsx | 112 ++ src/ui/plugin-host/sdk-ui.ts | 65 + src/ui/plugin-host/shell-bridge.ts | 126 ++ src/ui/plugin-host/testing-host.tsx | 266 ++++ src/ui/plugin-host/view-ownership.ts | 89 ++ src/ui/plugin-host/workspace-plugins.ts | 17 + src/ui/settings/SettingsFields.tsx | 7 +- src/ui/settings/SettingsScreen.tsx | 7 - src/ui/settings/host-plugins-tab.tsx | 19 +- src/ui/settings/legacy-settings-components.ts | 27 - src/ui/settings/settings-components.ts | 38 +- src/ui/shell/ActionSlot.tsx | 36 +- src/ui/shell/CommandPalette.tsx | 206 ++- src/ui/shell/MobileBottomBar.tsx | 14 +- src/ui/shell/TabBar.tsx | 23 +- src/ui/shell/TabContext.tsx | 18 +- src/ui/shell/action-registry.ts | 59 +- src/ui/shell/palette-registry.ts | 40 + src/ui/shell/panel-registry.ts | 29 + src/ui/shell/pluginLoader.ts | 159 --- src/ui/shell/shell-layout.ts | 175 +++ src/ui/shell/tab-registry.ts | 149 ++ src/ui/shell/tabUtils.tsx | 518 +------ src/ui/sidebar/AdminPluginsSection.tsx | 4 +- src/ui/sidebar/AdminSettingsPanel.tsx | 76 +- src/ui/sidebar/AdminSettingsSections.tsx | 75 - src/ui/sidebar/AdminUserManagePanel.tsx | 12 +- src/ui/sidebar/AppRail.tsx | 25 +- src/ui/sidebar/ConnectionsPanel.tsx | 38 +- src/ui/sidebar/HostEditor.tsx | 312 ++--- src/ui/sidebar/HostEditorFilesTab.tsx | 61 + src/ui/sidebar/HostManager.tsx | 29 +- src/ui/sidebar/HostManagerTabs.tsx | 278 ++-- src/ui/sidebar/HostsPanel.tsx | 53 +- .../sidebar/NavigationVisibilityToggles.tsx | 49 + src/ui/sidebar/QuickConnectPanel.tsx | 10 +- src/ui/sidebar/UserProfilePanel.tsx | 122 +- src/ui/sidebar/host-contributions.ts | 122 ++ src/ui/sidebar/quick-connect-host.ts | 18 - src/ui/sidebar/rail-items.ts | 179 ++- src/ui/sidebar/tree/FolderItem/FolderItem.tsx | 8 +- src/ui/sidebar/tree/HostItem/HostItem.tsx | 573 +++----- src/ui/sidebar/tree/SidebarTree.tsx | 15 +- .../tests/dashboard/HostStatusCard.test.tsx | 53 +- .../dashboard-cards-registry.test.ts | 2 +- .../SharedSessionView.test.tsx | 25 +- .../terminal/TerminalToolbar.test.tsx | 12 +- .../tests/onboarding/onboarding-steps.test.ts | 31 +- src/ui/tests/plugin-host/cli-bundle.test.tsx | 70 + .../fixtures/hook-plugin/manifest.json | 14 + .../fixtures/hook-plugin/src/backend/index.ts | 1 + .../hook-plugin/src/frontend/index.tsx | 16 + src/ui/tests/plugin-host/loader.test.tsx | 263 ++++ src/ui/tests/plugin-host/registries.test.tsx | 298 ++++ .../tests/plugin-host/slots-and-i18n.test.tsx | 156 +++ .../tests/plugin-host/view-ownership.test.tsx | 160 +++ .../tests/settings/host-plugins-tab.test.tsx | 22 +- src/ui/tests/shell/persistentTabTypes.test.ts | 24 - src/ui/tests/shell/pluginLoader.test.ts | 256 ---- .../ui/tests/shell/shell-layout.test.ts | 66 +- .../sidebar/HostManagerTabs.webUi.test.ts | 18 - .../sidebar/host-editor-tab-seam.test.tsx | 83 +- .../sidebar/plugin-extension-seam.test.tsx | 127 -- .../tests/sidebar/quick-connect-host.test.ts | 14 - src/ui/tests/sidebar/rail-items.test.ts | 96 +- .../sidebar/role-permission-groups.test.tsx | 4 +- .../sidebar/tree/HostItem/HostItem.test.tsx | 25 +- .../tree/HostItem/getSshActions.webUi.test.ts | 98 -- tsconfig.app.json | 2 + tsconfig.json | 3 + tsconfig.plugins.frontend.json | 16 + vite.config.ts | 18 +- vitest.config.ts | 12 + 721 files changed, 54265 insertions(+), 44416 deletions(-) create mode 100644 packages/plugin-sdk/cli/lib/legacy-core-specifier.mjs create mode 100644 plugins/ai/locales/translated/af_ZA.json create mode 100644 plugins/ai/locales/translated/ar_SA.json create mode 100644 plugins/ai/locales/translated/bg_BG.json create mode 100644 plugins/ai/locales/translated/bn_BD.json create mode 100644 plugins/ai/locales/translated/ca_ES.json create mode 100644 plugins/ai/locales/translated/cs_CZ.json create mode 100644 plugins/ai/locales/translated/da_DK.json create mode 100644 plugins/ai/locales/translated/de_DE.json create mode 100644 plugins/ai/locales/translated/el_GR.json create mode 100644 plugins/ai/locales/translated/es_ES.json create mode 100644 plugins/ai/locales/translated/fi_FI.json create mode 100644 plugins/ai/locales/translated/fr_FR.json create mode 100644 plugins/ai/locales/translated/he_IL.json create mode 100644 plugins/ai/locales/translated/hi_IN.json create mode 100644 plugins/ai/locales/translated/hu_HU.json create mode 100644 plugins/ai/locales/translated/id_ID.json create mode 100644 plugins/ai/locales/translated/it_IT.json create mode 100644 plugins/ai/locales/translated/ja_JP.json create mode 100644 plugins/ai/locales/translated/ko_KR.json create mode 100644 plugins/ai/locales/translated/nl_NL.json create mode 100644 plugins/ai/locales/translated/no_NO.json create mode 100644 plugins/ai/locales/translated/pl_PL.json create mode 100644 plugins/ai/locales/translated/pt_BR.json create mode 100644 plugins/ai/locales/translated/pt_PT.json create mode 100644 plugins/ai/locales/translated/ro_RO.json create mode 100644 plugins/ai/locales/translated/ru_RU.json create mode 100644 plugins/ai/locales/translated/sr_SP.json create mode 100644 plugins/ai/locales/translated/sv_SE.json create mode 100644 plugins/ai/locales/translated/th_TH.json create mode 100644 plugins/ai/locales/translated/tr_TR.json create mode 100644 plugins/ai/locales/translated/uk_UA.json create mode 100644 plugins/ai/locales/translated/vi_VN.json create mode 100644 plugins/ai/locales/translated/zh_CN.json create mode 100644 plugins/ai/locales/translated/zh_TW.json rename {src/ui/onboarding/steps => plugins/ai/src/frontend}/AiAssistantStep.tsx (79%) rename {src/ui/features/ai => plugins/ai/src/frontend}/AiMessage.tsx (100%) rename {src/ui/features/ai => plugins/ai/src/frontend}/AiPanel.tsx (99%) rename {src/ui/features/ai => plugins/ai/src/frontend}/AiProviderSettings.tsx (99%) rename {src/ui/features/ai => plugins/ai/src/frontend}/AiToolCall.tsx (97%) rename {src/ui/features/ai => plugins/ai/src/frontend}/ProposalCard.tsx (97%) rename {src/ui/api => plugins/ai/src/frontend}/ai-api.ts (78%) delete mode 100644 plugins/ai/src/frontend/index.mjs create mode 100644 plugins/ai/src/frontend/index.tsx rename {src/ui/features/ai => plugins/ai/src/frontend}/labels.ts (100%) create mode 100644 plugins/ai/src/frontend/settings/AiAccessSettings.tsx create mode 100644 plugins/ai/src/frontend/settings/AiUserSettings.tsx rename {src/ui/features => plugins/ai/src/frontend}/terminal/TerminalAiPanel.tsx (97%) rename {src/ui/features => plugins/ai/src/frontend}/terminal/TerminalProposalCard.tsx (95%) rename {src/ui/hooks => plugins/ai/src/frontend}/use-ai-availability.ts (98%) rename {src/ui/features/ai => plugins/ai/src/frontend}/use-ai-stream.ts (98%) rename {src/ui/features/ai => plugins/ai/src/frontend}/useMentions.ts (84%) create mode 100644 plugins/ai/tests/frontend/activate.test.tsx rename {src/ui/tests/hooks => plugins/ai/tests/frontend}/use-ai-availability.test.ts (96%) create mode 100644 plugins/automations/locales/translated/af_ZA.json create mode 100644 plugins/automations/locales/translated/ar_SA.json create mode 100644 plugins/automations/locales/translated/bg_BG.json create mode 100644 plugins/automations/locales/translated/bn_BD.json create mode 100644 plugins/automations/locales/translated/ca_ES.json create mode 100644 plugins/automations/locales/translated/cs_CZ.json create mode 100644 plugins/automations/locales/translated/da_DK.json create mode 100644 plugins/automations/locales/translated/de_DE.json create mode 100644 plugins/automations/locales/translated/el_GR.json create mode 100644 plugins/automations/locales/translated/es_ES.json create mode 100644 plugins/automations/locales/translated/fi_FI.json create mode 100644 plugins/automations/locales/translated/fr_FR.json create mode 100644 plugins/automations/locales/translated/he_IL.json create mode 100644 plugins/automations/locales/translated/hi_IN.json create mode 100644 plugins/automations/locales/translated/hu_HU.json create mode 100644 plugins/automations/locales/translated/id_ID.json create mode 100644 plugins/automations/locales/translated/it_IT.json create mode 100644 plugins/automations/locales/translated/ja_JP.json create mode 100644 plugins/automations/locales/translated/ko_KR.json create mode 100644 plugins/automations/locales/translated/nl_NL.json create mode 100644 plugins/automations/locales/translated/no_NO.json create mode 100644 plugins/automations/locales/translated/pl_PL.json create mode 100644 plugins/automations/locales/translated/pt_BR.json create mode 100644 plugins/automations/locales/translated/pt_PT.json create mode 100644 plugins/automations/locales/translated/ro_RO.json create mode 100644 plugins/automations/locales/translated/ru_RU.json create mode 100644 plugins/automations/locales/translated/sr_SP.json create mode 100644 plugins/automations/locales/translated/sv_SE.json create mode 100644 plugins/automations/locales/translated/th_TH.json create mode 100644 plugins/automations/locales/translated/tr_TR.json create mode 100644 plugins/automations/locales/translated/uk_UA.json create mode 100644 plugins/automations/locales/translated/vi_VN.json create mode 100644 plugins/automations/locales/translated/zh_CN.json create mode 100644 plugins/automations/locales/translated/zh_TW.json delete mode 100644 plugins/automations/src/frontend/index.mjs create mode 100644 plugins/automations/src/frontend/index.tsx create mode 100644 plugins/automations/tests/frontend/activate.test.tsx create mode 100644 plugins/docker/locales/translated/af_ZA.json create mode 100644 plugins/docker/locales/translated/ar_SA.json create mode 100644 plugins/docker/locales/translated/bg_BG.json create mode 100644 plugins/docker/locales/translated/bn_BD.json create mode 100644 plugins/docker/locales/translated/ca_ES.json create mode 100644 plugins/docker/locales/translated/cs_CZ.json create mode 100644 plugins/docker/locales/translated/da_DK.json create mode 100644 plugins/docker/locales/translated/de_DE.json create mode 100644 plugins/docker/locales/translated/el_GR.json create mode 100644 plugins/docker/locales/translated/es_ES.json create mode 100644 plugins/docker/locales/translated/fi_FI.json create mode 100644 plugins/docker/locales/translated/fr_FR.json create mode 100644 plugins/docker/locales/translated/he_IL.json create mode 100644 plugins/docker/locales/translated/hi_IN.json create mode 100644 plugins/docker/locales/translated/hu_HU.json create mode 100644 plugins/docker/locales/translated/id_ID.json create mode 100644 plugins/docker/locales/translated/it_IT.json create mode 100644 plugins/docker/locales/translated/ja_JP.json create mode 100644 plugins/docker/locales/translated/ko_KR.json create mode 100644 plugins/docker/locales/translated/nl_NL.json create mode 100644 plugins/docker/locales/translated/no_NO.json create mode 100644 plugins/docker/locales/translated/pl_PL.json create mode 100644 plugins/docker/locales/translated/pt_BR.json create mode 100644 plugins/docker/locales/translated/pt_PT.json create mode 100644 plugins/docker/locales/translated/ro_RO.json create mode 100644 plugins/docker/locales/translated/ru_RU.json create mode 100644 plugins/docker/locales/translated/sr_SP.json create mode 100644 plugins/docker/locales/translated/sv_SE.json create mode 100644 plugins/docker/locales/translated/th_TH.json create mode 100644 plugins/docker/locales/translated/tr_TR.json create mode 100644 plugins/docker/locales/translated/uk_UA.json create mode 100644 plugins/docker/locales/translated/vi_VN.json create mode 100644 plugins/docker/locales/translated/zh_CN.json create mode 100644 plugins/docker/locales/translated/zh_TW.json rename {src/ui/features/homepage/widgets => plugins/docker/src/frontend}/DockerWidget.tsx (85%) rename {src/ui/features/homepage/dialogs => plugins/docker/src/frontend}/DockerWidgetEditForm.tsx (82%) create mode 100644 plugins/docker/src/frontend/HostDockerTab.tsx rename {src/ui/api => plugins/docker/src/frontend}/docker-api.ts (100%) delete mode 100644 plugins/docker/src/frontend/index.mjs create mode 100644 plugins/docker/src/frontend/index.tsx create mode 100644 plugins/docker/tests/frontend/activate.test.tsx create mode 100644 plugins/fleets/locales/translated/af_ZA.json create mode 100644 plugins/fleets/locales/translated/ar_SA.json create mode 100644 plugins/fleets/locales/translated/bg_BG.json create mode 100644 plugins/fleets/locales/translated/bn_BD.json create mode 100644 plugins/fleets/locales/translated/ca_ES.json create mode 100644 plugins/fleets/locales/translated/cs_CZ.json create mode 100644 plugins/fleets/locales/translated/da_DK.json create mode 100644 plugins/fleets/locales/translated/de_DE.json create mode 100644 plugins/fleets/locales/translated/el_GR.json create mode 100644 plugins/fleets/locales/translated/es_ES.json create mode 100644 plugins/fleets/locales/translated/fi_FI.json create mode 100644 plugins/fleets/locales/translated/fr_FR.json create mode 100644 plugins/fleets/locales/translated/he_IL.json create mode 100644 plugins/fleets/locales/translated/hi_IN.json create mode 100644 plugins/fleets/locales/translated/hu_HU.json create mode 100644 plugins/fleets/locales/translated/id_ID.json create mode 100644 plugins/fleets/locales/translated/it_IT.json create mode 100644 plugins/fleets/locales/translated/ja_JP.json create mode 100644 plugins/fleets/locales/translated/ko_KR.json create mode 100644 plugins/fleets/locales/translated/nl_NL.json create mode 100644 plugins/fleets/locales/translated/no_NO.json create mode 100644 plugins/fleets/locales/translated/pl_PL.json create mode 100644 plugins/fleets/locales/translated/pt_BR.json create mode 100644 plugins/fleets/locales/translated/pt_PT.json create mode 100644 plugins/fleets/locales/translated/ro_RO.json create mode 100644 plugins/fleets/locales/translated/ru_RU.json create mode 100644 plugins/fleets/locales/translated/sr_SP.json create mode 100644 plugins/fleets/locales/translated/sv_SE.json create mode 100644 plugins/fleets/locales/translated/th_TH.json create mode 100644 plugins/fleets/locales/translated/tr_TR.json create mode 100644 plugins/fleets/locales/translated/uk_UA.json create mode 100644 plugins/fleets/locales/translated/vi_VN.json create mode 100644 plugins/fleets/locales/translated/zh_CN.json create mode 100644 plugins/fleets/locales/translated/zh_TW.json rename {src/ui/api => plugins/fleets/src/frontend}/fleets-api.ts (100%) delete mode 100644 plugins/fleets/src/frontend/index.mjs create mode 100644 plugins/fleets/src/frontend/index.tsx create mode 100644 plugins/fleets/tests/frontend/activate.test.tsx create mode 100644 plugins/host-metrics/locales/translated/af_ZA.json create mode 100644 plugins/host-metrics/locales/translated/ar_SA.json create mode 100644 plugins/host-metrics/locales/translated/bg_BG.json create mode 100644 plugins/host-metrics/locales/translated/bn_BD.json create mode 100644 plugins/host-metrics/locales/translated/ca_ES.json create mode 100644 plugins/host-metrics/locales/translated/cs_CZ.json create mode 100644 plugins/host-metrics/locales/translated/da_DK.json create mode 100644 plugins/host-metrics/locales/translated/de_DE.json create mode 100644 plugins/host-metrics/locales/translated/el_GR.json create mode 100644 plugins/host-metrics/locales/translated/es_ES.json create mode 100644 plugins/host-metrics/locales/translated/fi_FI.json create mode 100644 plugins/host-metrics/locales/translated/fr_FR.json create mode 100644 plugins/host-metrics/locales/translated/he_IL.json create mode 100644 plugins/host-metrics/locales/translated/hi_IN.json create mode 100644 plugins/host-metrics/locales/translated/hu_HU.json create mode 100644 plugins/host-metrics/locales/translated/id_ID.json create mode 100644 plugins/host-metrics/locales/translated/it_IT.json create mode 100644 plugins/host-metrics/locales/translated/ja_JP.json create mode 100644 plugins/host-metrics/locales/translated/ko_KR.json create mode 100644 plugins/host-metrics/locales/translated/nl_NL.json create mode 100644 plugins/host-metrics/locales/translated/no_NO.json create mode 100644 plugins/host-metrics/locales/translated/pl_PL.json create mode 100644 plugins/host-metrics/locales/translated/pt_BR.json create mode 100644 plugins/host-metrics/locales/translated/pt_PT.json create mode 100644 plugins/host-metrics/locales/translated/ro_RO.json create mode 100644 plugins/host-metrics/locales/translated/ru_RU.json create mode 100644 plugins/host-metrics/locales/translated/sr_SP.json create mode 100644 plugins/host-metrics/locales/translated/sv_SE.json create mode 100644 plugins/host-metrics/locales/translated/th_TH.json create mode 100644 plugins/host-metrics/locales/translated/tr_TR.json create mode 100644 plugins/host-metrics/locales/translated/uk_UA.json create mode 100644 plugins/host-metrics/locales/translated/vi_VN.json create mode 100644 plugins/host-metrics/locales/translated/zh_CN.json create mode 100644 plugins/host-metrics/locales/translated/zh_TW.json rename {src/ui/sidebar => plugins/host-metrics/src/frontend}/HostEditorStatsTab.tsx (99%) rename {src/ui/features/homepage/dialogs => plugins/host-metrics/src/frontend}/MetricsChartEditForm.tsx (98%) rename {src/ui/features/homepage/widgets => plugins/host-metrics/src/frontend}/MetricsChartWidget.tsx (92%) create mode 100644 plugins/host-metrics/src/frontend/MetricsRetentionSetting.tsx rename {src/ui/api => plugins/host-metrics/src/frontend}/host-metrics-api.ts (100%) delete mode 100644 plugins/host-metrics/src/frontend/index.mjs create mode 100644 plugins/host-metrics/src/frontend/index.tsx rename {src/ui/features => plugins/host-metrics/src/frontend}/proxmox-stats/GuestTable.tsx (99%) create mode 100644 plugins/host-metrics/src/frontend/proxmox-stats/HostProxmoxStatsTab.tsx rename {src/ui/features => plugins/host-metrics/src/frontend}/proxmox-stats/NodeSummaryStrip.tsx (98%) rename {src/ui/features => plugins/host-metrics/src/frontend}/proxmox-stats/ProxmoxStatsApp.tsx (91%) rename {src/ui/features => plugins/host-metrics/src/frontend}/proxmox-stats/ProxmoxStatsTab.tsx (98%) rename {src/ui/features => plugins/host-metrics/src/frontend}/proxmox-stats/cards/ClusterHealthCard.tsx (97%) rename {src/ui/features => plugins/host-metrics/src/frontend}/proxmox-stats/cards/NodeNetworkCard.tsx (94%) rename {src/ui/features => plugins/host-metrics/src/frontend}/proxmox-stats/cards/StoragePoolsCard.tsx (97%) rename {src/ui/api => plugins/host-metrics/src/frontend/proxmox-stats}/proxmox-stats-api.ts (100%) create mode 100644 plugins/host-metrics/tests/frontend/activate.test.tsx create mode 100644 plugins/network-topology/locales/translated/af_ZA.json create mode 100644 plugins/network-topology/locales/translated/ar_SA.json create mode 100644 plugins/network-topology/locales/translated/bg_BG.json create mode 100644 plugins/network-topology/locales/translated/bn_BD.json create mode 100644 plugins/network-topology/locales/translated/ca_ES.json create mode 100644 plugins/network-topology/locales/translated/cs_CZ.json create mode 100644 plugins/network-topology/locales/translated/da_DK.json create mode 100644 plugins/network-topology/locales/translated/de_DE.json create mode 100644 plugins/network-topology/locales/translated/el_GR.json create mode 100644 plugins/network-topology/locales/translated/es_ES.json create mode 100644 plugins/network-topology/locales/translated/fi_FI.json create mode 100644 plugins/network-topology/locales/translated/fr_FR.json create mode 100644 plugins/network-topology/locales/translated/he_IL.json create mode 100644 plugins/network-topology/locales/translated/hi_IN.json create mode 100644 plugins/network-topology/locales/translated/hu_HU.json create mode 100644 plugins/network-topology/locales/translated/id_ID.json create mode 100644 plugins/network-topology/locales/translated/it_IT.json create mode 100644 plugins/network-topology/locales/translated/ja_JP.json create mode 100644 plugins/network-topology/locales/translated/ko_KR.json create mode 100644 plugins/network-topology/locales/translated/nl_NL.json create mode 100644 plugins/network-topology/locales/translated/no_NO.json create mode 100644 plugins/network-topology/locales/translated/pl_PL.json create mode 100644 plugins/network-topology/locales/translated/pt_BR.json create mode 100644 plugins/network-topology/locales/translated/pt_PT.json create mode 100644 plugins/network-topology/locales/translated/ro_RO.json create mode 100644 plugins/network-topology/locales/translated/ru_RU.json create mode 100644 plugins/network-topology/locales/translated/sr_SP.json create mode 100644 plugins/network-topology/locales/translated/sv_SE.json create mode 100644 plugins/network-topology/locales/translated/th_TH.json create mode 100644 plugins/network-topology/locales/translated/tr_TR.json create mode 100644 plugins/network-topology/locales/translated/uk_UA.json create mode 100644 plugins/network-topology/locales/translated/vi_VN.json create mode 100644 plugins/network-topology/locales/translated/zh_CN.json create mode 100644 plugins/network-topology/locales/translated/zh_TW.json delete mode 100644 plugins/network-topology/src/frontend/index.mjs create mode 100644 plugins/network-topology/src/frontend/index.tsx create mode 100644 plugins/network-topology/tests/frontend/activate.test.tsx create mode 100644 plugins/proxmox/locales/translated/af_ZA.json create mode 100644 plugins/proxmox/locales/translated/ar_SA.json create mode 100644 plugins/proxmox/locales/translated/bg_BG.json create mode 100644 plugins/proxmox/locales/translated/bn_BD.json create mode 100644 plugins/proxmox/locales/translated/ca_ES.json create mode 100644 plugins/proxmox/locales/translated/cs_CZ.json create mode 100644 plugins/proxmox/locales/translated/da_DK.json create mode 100644 plugins/proxmox/locales/translated/de_DE.json create mode 100644 plugins/proxmox/locales/translated/el_GR.json create mode 100644 plugins/proxmox/locales/translated/es_ES.json create mode 100644 plugins/proxmox/locales/translated/fi_FI.json create mode 100644 plugins/proxmox/locales/translated/fr_FR.json create mode 100644 plugins/proxmox/locales/translated/he_IL.json create mode 100644 plugins/proxmox/locales/translated/hi_IN.json create mode 100644 plugins/proxmox/locales/translated/hu_HU.json create mode 100644 plugins/proxmox/locales/translated/id_ID.json create mode 100644 plugins/proxmox/locales/translated/it_IT.json create mode 100644 plugins/proxmox/locales/translated/ja_JP.json create mode 100644 plugins/proxmox/locales/translated/ko_KR.json create mode 100644 plugins/proxmox/locales/translated/nl_NL.json create mode 100644 plugins/proxmox/locales/translated/no_NO.json create mode 100644 plugins/proxmox/locales/translated/pl_PL.json create mode 100644 plugins/proxmox/locales/translated/pt_BR.json create mode 100644 plugins/proxmox/locales/translated/pt_PT.json create mode 100644 plugins/proxmox/locales/translated/ro_RO.json create mode 100644 plugins/proxmox/locales/translated/ru_RU.json create mode 100644 plugins/proxmox/locales/translated/sr_SP.json create mode 100644 plugins/proxmox/locales/translated/sv_SE.json create mode 100644 plugins/proxmox/locales/translated/th_TH.json create mode 100644 plugins/proxmox/locales/translated/tr_TR.json create mode 100644 plugins/proxmox/locales/translated/uk_UA.json create mode 100644 plugins/proxmox/locales/translated/vi_VN.json create mode 100644 plugins/proxmox/locales/translated/zh_CN.json create mode 100644 plugins/proxmox/locales/translated/zh_TW.json rename src/ui/sidebar/HostEditorFeatureTabs.tsx => plugins/proxmox/src/frontend/HostProxmoxTab.tsx (53%) delete mode 100644 plugins/proxmox/src/frontend/index.mjs create mode 100644 plugins/proxmox/src/frontend/index.tsx create mode 100644 plugins/proxmox/tests/frontend/activate.test.tsx create mode 100644 plugins/remote-desktop/locales/translated/af_ZA.json create mode 100644 plugins/remote-desktop/locales/translated/ar_SA.json create mode 100644 plugins/remote-desktop/locales/translated/bg_BG.json create mode 100644 plugins/remote-desktop/locales/translated/bn_BD.json create mode 100644 plugins/remote-desktop/locales/translated/ca_ES.json create mode 100644 plugins/remote-desktop/locales/translated/cs_CZ.json create mode 100644 plugins/remote-desktop/locales/translated/da_DK.json create mode 100644 plugins/remote-desktop/locales/translated/de_DE.json create mode 100644 plugins/remote-desktop/locales/translated/el_GR.json create mode 100644 plugins/remote-desktop/locales/translated/es_ES.json create mode 100644 plugins/remote-desktop/locales/translated/fi_FI.json create mode 100644 plugins/remote-desktop/locales/translated/fr_FR.json create mode 100644 plugins/remote-desktop/locales/translated/he_IL.json create mode 100644 plugins/remote-desktop/locales/translated/hi_IN.json create mode 100644 plugins/remote-desktop/locales/translated/hu_HU.json create mode 100644 plugins/remote-desktop/locales/translated/id_ID.json create mode 100644 plugins/remote-desktop/locales/translated/it_IT.json create mode 100644 plugins/remote-desktop/locales/translated/ja_JP.json create mode 100644 plugins/remote-desktop/locales/translated/ko_KR.json create mode 100644 plugins/remote-desktop/locales/translated/nl_NL.json create mode 100644 plugins/remote-desktop/locales/translated/no_NO.json create mode 100644 plugins/remote-desktop/locales/translated/pl_PL.json create mode 100644 plugins/remote-desktop/locales/translated/pt_BR.json create mode 100644 plugins/remote-desktop/locales/translated/pt_PT.json create mode 100644 plugins/remote-desktop/locales/translated/ro_RO.json create mode 100644 plugins/remote-desktop/locales/translated/ru_RU.json create mode 100644 plugins/remote-desktop/locales/translated/sr_SP.json create mode 100644 plugins/remote-desktop/locales/translated/sv_SE.json create mode 100644 plugins/remote-desktop/locales/translated/th_TH.json create mode 100644 plugins/remote-desktop/locales/translated/tr_TR.json create mode 100644 plugins/remote-desktop/locales/translated/uk_UA.json create mode 100644 plugins/remote-desktop/locales/translated/vi_VN.json create mode 100644 plugins/remote-desktop/locales/translated/zh_CN.json create mode 100644 plugins/remote-desktop/locales/translated/zh_TW.json rename {src/ui/sidebar => plugins/remote-desktop/src/frontend}/HostEditorGuacamoleTabs.tsx (99%) delete mode 100644 plugins/remote-desktop/src/frontend/index.mjs create mode 100644 plugins/remote-desktop/src/frontend/index.tsx create mode 100644 plugins/remote-desktop/src/frontend/quick-connect-guac-host.ts create mode 100644 plugins/remote-desktop/tests/frontend/activate.test.tsx create mode 100644 plugins/remote-desktop/tests/frontend/quick-connect-guac-host.test.ts delete mode 100644 plugins/ssh-terminal/src/frontend/index.mjs create mode 100644 plugins/ssh-terminal/src/frontend/index.tsx create mode 100644 plugins/ssh-terminal/tests/frontend/activate.test.tsx create mode 100644 plugins/tailscale/locales/translated/af_ZA.json create mode 100644 plugins/tailscale/locales/translated/ar_SA.json create mode 100644 plugins/tailscale/locales/translated/bg_BG.json create mode 100644 plugins/tailscale/locales/translated/bn_BD.json create mode 100644 plugins/tailscale/locales/translated/ca_ES.json create mode 100644 plugins/tailscale/locales/translated/cs_CZ.json create mode 100644 plugins/tailscale/locales/translated/da_DK.json create mode 100644 plugins/tailscale/locales/translated/de_DE.json create mode 100644 plugins/tailscale/locales/translated/el_GR.json create mode 100644 plugins/tailscale/locales/translated/es_ES.json create mode 100644 plugins/tailscale/locales/translated/fi_FI.json create mode 100644 plugins/tailscale/locales/translated/fr_FR.json create mode 100644 plugins/tailscale/locales/translated/he_IL.json create mode 100644 plugins/tailscale/locales/translated/hi_IN.json create mode 100644 plugins/tailscale/locales/translated/hu_HU.json create mode 100644 plugins/tailscale/locales/translated/id_ID.json create mode 100644 plugins/tailscale/locales/translated/it_IT.json create mode 100644 plugins/tailscale/locales/translated/ja_JP.json create mode 100644 plugins/tailscale/locales/translated/ko_KR.json create mode 100644 plugins/tailscale/locales/translated/nl_NL.json create mode 100644 plugins/tailscale/locales/translated/no_NO.json create mode 100644 plugins/tailscale/locales/translated/pl_PL.json create mode 100644 plugins/tailscale/locales/translated/pt_BR.json create mode 100644 plugins/tailscale/locales/translated/pt_PT.json create mode 100644 plugins/tailscale/locales/translated/ro_RO.json create mode 100644 plugins/tailscale/locales/translated/ru_RU.json create mode 100644 plugins/tailscale/locales/translated/sr_SP.json create mode 100644 plugins/tailscale/locales/translated/sv_SE.json create mode 100644 plugins/tailscale/locales/translated/th_TH.json create mode 100644 plugins/tailscale/locales/translated/tr_TR.json create mode 100644 plugins/tailscale/locales/translated/uk_UA.json create mode 100644 plugins/tailscale/locales/translated/vi_VN.json create mode 100644 plugins/tailscale/locales/translated/zh_CN.json create mode 100644 plugins/tailscale/locales/translated/zh_TW.json create mode 100644 plugins/tailscale/src/frontend/TailscaleAuthEditor.tsx create mode 100644 plugins/tailscale/src/frontend/TailscaleCheckOverlay.tsx rename {src/ui/settings/components => plugins/tailscale/src/frontend}/TailscaleDevicesStatus.tsx (86%) delete mode 100644 plugins/tailscale/src/frontend/index.mjs create mode 100644 plugins/tailscale/src/frontend/index.tsx create mode 100644 plugins/tailscale/tests/frontend/activate.test.tsx create mode 100644 plugins/web-endpoint/locales/translated/af_ZA.json create mode 100644 plugins/web-endpoint/locales/translated/ar_SA.json create mode 100644 plugins/web-endpoint/locales/translated/bg_BG.json create mode 100644 plugins/web-endpoint/locales/translated/bn_BD.json create mode 100644 plugins/web-endpoint/locales/translated/ca_ES.json create mode 100644 plugins/web-endpoint/locales/translated/cs_CZ.json create mode 100644 plugins/web-endpoint/locales/translated/da_DK.json create mode 100644 plugins/web-endpoint/locales/translated/de_DE.json create mode 100644 plugins/web-endpoint/locales/translated/el_GR.json create mode 100644 plugins/web-endpoint/locales/translated/es_ES.json create mode 100644 plugins/web-endpoint/locales/translated/fi_FI.json create mode 100644 plugins/web-endpoint/locales/translated/fr_FR.json create mode 100644 plugins/web-endpoint/locales/translated/he_IL.json create mode 100644 plugins/web-endpoint/locales/translated/hi_IN.json create mode 100644 plugins/web-endpoint/locales/translated/hu_HU.json create mode 100644 plugins/web-endpoint/locales/translated/id_ID.json create mode 100644 plugins/web-endpoint/locales/translated/it_IT.json create mode 100644 plugins/web-endpoint/locales/translated/ja_JP.json create mode 100644 plugins/web-endpoint/locales/translated/ko_KR.json create mode 100644 plugins/web-endpoint/locales/translated/nl_NL.json create mode 100644 plugins/web-endpoint/locales/translated/no_NO.json create mode 100644 plugins/web-endpoint/locales/translated/pl_PL.json create mode 100644 plugins/web-endpoint/locales/translated/pt_BR.json create mode 100644 plugins/web-endpoint/locales/translated/pt_PT.json create mode 100644 plugins/web-endpoint/locales/translated/ro_RO.json create mode 100644 plugins/web-endpoint/locales/translated/ru_RU.json create mode 100644 plugins/web-endpoint/locales/translated/sr_SP.json create mode 100644 plugins/web-endpoint/locales/translated/sv_SE.json create mode 100644 plugins/web-endpoint/locales/translated/th_TH.json create mode 100644 plugins/web-endpoint/locales/translated/tr_TR.json create mode 100644 plugins/web-endpoint/locales/translated/uk_UA.json create mode 100644 plugins/web-endpoint/locales/translated/vi_VN.json create mode 100644 plugins/web-endpoint/locales/translated/zh_CN.json create mode 100644 plugins/web-endpoint/locales/translated/zh_TW.json rename {src/ui/sidebar => plugins/web-endpoint/src/frontend}/HostEditorWebUiSection.tsx (98%) create mode 100644 plugins/web-endpoint/src/frontend/HostWebUiTab.tsx delete mode 100644 plugins/web-endpoint/src/frontend/index.mjs create mode 100644 plugins/web-endpoint/src/frontend/index.tsx rename {src/ui/tests/sidebar => plugins/web-endpoint/tests/frontend}/HostEditorWebUiSection.test.tsx (98%) create mode 100644 plugins/web-endpoint/tests/frontend/activate.test.tsx create mode 100644 plugins/workspaces/locales/translated/af_ZA.json create mode 100644 plugins/workspaces/locales/translated/ar_SA.json create mode 100644 plugins/workspaces/locales/translated/bg_BG.json create mode 100644 plugins/workspaces/locales/translated/bn_BD.json create mode 100644 plugins/workspaces/locales/translated/ca_ES.json create mode 100644 plugins/workspaces/locales/translated/cs_CZ.json create mode 100644 plugins/workspaces/locales/translated/da_DK.json create mode 100644 plugins/workspaces/locales/translated/de_DE.json create mode 100644 plugins/workspaces/locales/translated/el_GR.json create mode 100644 plugins/workspaces/locales/translated/es_ES.json create mode 100644 plugins/workspaces/locales/translated/fi_FI.json create mode 100644 plugins/workspaces/locales/translated/fr_FR.json create mode 100644 plugins/workspaces/locales/translated/he_IL.json create mode 100644 plugins/workspaces/locales/translated/hi_IN.json create mode 100644 plugins/workspaces/locales/translated/hu_HU.json create mode 100644 plugins/workspaces/locales/translated/id_ID.json create mode 100644 plugins/workspaces/locales/translated/it_IT.json create mode 100644 plugins/workspaces/locales/translated/ja_JP.json create mode 100644 plugins/workspaces/locales/translated/ko_KR.json create mode 100644 plugins/workspaces/locales/translated/nl_NL.json create mode 100644 plugins/workspaces/locales/translated/no_NO.json create mode 100644 plugins/workspaces/locales/translated/pl_PL.json create mode 100644 plugins/workspaces/locales/translated/pt_BR.json create mode 100644 plugins/workspaces/locales/translated/pt_PT.json create mode 100644 plugins/workspaces/locales/translated/ro_RO.json create mode 100644 plugins/workspaces/locales/translated/ru_RU.json create mode 100644 plugins/workspaces/locales/translated/sr_SP.json create mode 100644 plugins/workspaces/locales/translated/sv_SE.json create mode 100644 plugins/workspaces/locales/translated/th_TH.json create mode 100644 plugins/workspaces/locales/translated/tr_TR.json create mode 100644 plugins/workspaces/locales/translated/uk_UA.json create mode 100644 plugins/workspaces/locales/translated/vi_VN.json create mode 100644 plugins/workspaces/locales/translated/zh_CN.json create mode 100644 plugins/workspaces/locales/translated/zh_TW.json delete mode 100644 plugins/workspaces/src/frontend/index.mjs create mode 100644 plugins/workspaces/src/frontend/index.tsx delete mode 100644 plugins/workspaces/src/frontend/workspaceUtils.ts create mode 100644 plugins/workspaces/tests/frontend/activate.test.tsx create mode 100644 scripts/check-importmap-csp.cjs create mode 100644 scripts/check-shell-plugin-ids.cjs create mode 100644 scripts/lib/plugin-import-map.mjs create mode 100644 scripts/shell-plugin-id-allowlist.json create mode 100644 scripts/vite-plugin-termix-plugins.mjs create mode 100644 src/backend/plugins/assets.ts create mode 100644 src/backend/tests/plugins/assets.test.ts create mode 100644 src/ui/api/private-endpoints-api.ts create mode 100644 src/ui/features/homepage/quick-connect-targets.ts create mode 100644 src/ui/features/remote-display/RemoteDisplay.tsx create mode 100644 src/ui/features/terminal/TerminalTabContent.tsx create mode 100644 src/ui/features/terminal/terminal-slots.ts create mode 100644 src/ui/lib/activity-types.ts create mode 100644 src/ui/lib/host-to-ssh-host.ts create mode 100644 src/ui/lib/registry.ts create mode 100644 src/ui/plugin-host/PluginViewPlaceholder.tsx create mode 100644 src/ui/plugin-host/app.ts create mode 100644 src/ui/plugin-host/auth-registry.ts create mode 100644 src/ui/plugin-host/bridge.ts create mode 100644 src/ui/plugin-host/loader.ts create mode 100644 src/ui/plugin-host/plugin-store.ts create mode 100644 src/ui/plugin-host/scope.tsx create mode 100644 src/ui/plugin-host/sdk-ui.ts create mode 100644 src/ui/plugin-host/shell-bridge.ts create mode 100644 src/ui/plugin-host/testing-host.tsx create mode 100644 src/ui/plugin-host/view-ownership.ts create mode 100644 src/ui/plugin-host/workspace-plugins.ts delete mode 100644 src/ui/settings/legacy-settings-components.ts create mode 100644 src/ui/shell/palette-registry.ts create mode 100644 src/ui/shell/panel-registry.ts delete mode 100644 src/ui/shell/pluginLoader.ts create mode 100644 src/ui/shell/shell-layout.ts create mode 100644 src/ui/shell/tab-registry.ts create mode 100644 src/ui/sidebar/HostEditorFilesTab.tsx create mode 100644 src/ui/sidebar/NavigationVisibilityToggles.tsx create mode 100644 src/ui/sidebar/host-contributions.ts create mode 100644 src/ui/tests/plugin-host/cli-bundle.test.tsx create mode 100644 src/ui/tests/plugin-host/fixtures/hook-plugin/manifest.json create mode 100644 src/ui/tests/plugin-host/fixtures/hook-plugin/src/backend/index.ts create mode 100644 src/ui/tests/plugin-host/fixtures/hook-plugin/src/frontend/index.tsx create mode 100644 src/ui/tests/plugin-host/loader.test.tsx create mode 100644 src/ui/tests/plugin-host/registries.test.tsx create mode 100644 src/ui/tests/plugin-host/slots-and-i18n.test.tsx create mode 100644 src/ui/tests/plugin-host/view-ownership.test.tsx delete mode 100644 src/ui/tests/shell/persistentTabTypes.test.ts delete mode 100644 src/ui/tests/shell/pluginLoader.test.ts rename plugins/workspaces/tests/frontend/workspaceUtils.test.ts => src/ui/tests/shell/shell-layout.test.ts (82%) delete mode 100644 src/ui/tests/sidebar/HostManagerTabs.webUi.test.ts delete mode 100644 src/ui/tests/sidebar/plugin-extension-seam.test.tsx delete mode 100644 src/ui/tests/sidebar/tree/HostItem/getSshActions.webUi.test.ts create mode 100644 tsconfig.plugins.frontend.json diff --git a/docker/nginx-https.conf b/docker/nginx-https.conf index 6b4254c36..9b02c2ecd 100644 --- a/docker/nginx-https.conf +++ b/docker/nginx-https.conf @@ -161,7 +161,7 @@ http { root /app/html; index index.html index.htm; expires off; - add_header Content-Security-Policy "default-src 'self'; script-src 'self' 'wasm-unsafe-eval'; style-src 'self' 'unsafe-inline'; img-src 'self' data: blob: http: https:; font-src 'self' data:; connect-src 'self' http: https: ws: wss:; media-src 'self' data: blob: http: https:; worker-src 'self' blob:; frame-src http: https:; object-src 'none'; base-uri 'self'; form-action 'self'; frame-ancestors 'none'" always; + add_header Content-Security-Policy "default-src 'self'; script-src 'self' 'wasm-unsafe-eval' 'sha256-AOzhY2+y5QtkFA+y4ASX7ouU+zPyffKUNFrJiRrW6nw='; style-src 'self' 'unsafe-inline'; img-src 'self' data: blob: http: https:; font-src 'self' data:; connect-src 'self' http: https: ws: wss:; media-src 'self' data: blob: http: https:; worker-src 'self' blob:; frame-src http: https:; object-src 'none'; base-uri 'self'; form-action 'self'; frame-ancestors 'none'" always; add_header X-Frame-Options "DENY" always; add_header Referrer-Policy "strict-origin-when-cross-origin" always; add_header Permissions-Policy "camera=(), microphone=(), geolocation=()" always; @@ -321,6 +321,17 @@ http { proxy_set_header X-Forwarded-Proto $proxy_x_forwarded_proto; } + # Plugin frontend bundles, stylesheets and locales. Public like + # /assets; the backend picks the cache policy from the ?v= query. + location ^~ /plugin-assets/ { + proxy_pass http://127.0.0.1:30001; + proxy_http_version 1.1; + proxy_set_header Host $http_host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $proxy_x_forwarded_proto; + } + # Every plugin's HTTP routes. One block, no per-plugin entries: a # plugin serves at /plugin-api// on the main backend and never # gets a port or a block of its own. Buffering is off so SSE streams diff --git a/docker/nginx.conf b/docker/nginx.conf index 4fcadf574..f12cd8176 100644 --- a/docker/nginx.conf +++ b/docker/nginx.conf @@ -142,7 +142,7 @@ http { root /app/html; index index.html index.htm; expires off; - add_header Content-Security-Policy "default-src 'self'; script-src 'self' 'wasm-unsafe-eval'; style-src 'self' 'unsafe-inline'; img-src 'self' data: blob: http: https:; font-src 'self' data:; connect-src 'self' http: https: ws: wss:; media-src 'self' data: blob: http: https:; worker-src 'self' blob:; frame-src http: https:; object-src 'none'; base-uri 'self'; form-action 'self'; frame-ancestors 'none'" always; + add_header Content-Security-Policy "default-src 'self'; script-src 'self' 'wasm-unsafe-eval' 'sha256-AOzhY2+y5QtkFA+y4ASX7ouU+zPyffKUNFrJiRrW6nw='; style-src 'self' 'unsafe-inline'; img-src 'self' data: blob: http: https:; font-src 'self' data:; connect-src 'self' http: https: ws: wss:; media-src 'self' data: blob: http: https:; worker-src 'self' blob:; frame-src http: https:; object-src 'none'; base-uri 'self'; form-action 'self'; frame-ancestors 'none'" always; add_header X-Frame-Options "DENY" always; add_header Referrer-Policy "strict-origin-when-cross-origin" always; add_header Permissions-Policy "camera=(), microphone=(), geolocation=()" always; @@ -301,6 +301,17 @@ http { proxy_set_header X-Forwarded-Proto $proxy_x_forwarded_proto; } + # Plugin frontend bundles, stylesheets and locales. Public like + # /assets; the backend picks the cache policy from the ?v= query. + location ^~ /plugin-assets/ { + proxy_pass http://127.0.0.1:30001; + proxy_http_version 1.1; + proxy_set_header Host $http_host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $proxy_x_forwarded_proto; + } + # Every plugin's HTTP routes. One block, no per-plugin entries: a # plugin serves at /plugin-api// on the main backend and never # gets a port or a block of its own. Buffering is off so SSE streams diff --git a/eslint.config.mjs b/eslint.config.mjs index a21c9c646..816e3c82e 100644 --- a/eslint.config.mjs +++ b/eslint.config.mjs @@ -129,21 +129,21 @@ export default tseslint.config([ }, }, { - // The shell still imports plugin components directly (the terminal tab, - // the Guacamole app, the Proxmox dialog). There is no frontend plugin - // loader yet, so there is nothing to move them to: A7 builds the app - // object that registers these surfaces and this becomes an error. - files: ["src/ui/**/*.{ts,tsx}"], + // The shell never imports a plugin. It reaches plugins only through the + // registries their frontends fill via the app object (A7). This block + // also carries the backend rule for src/ui files, because flat config + // replaces a rule's options rather than merging them. + files: ["src/ui/**/*.{ts,tsx}", "src/main.tsx"], ignores: ["src/ui/tests/**"], rules: { "no-restricted-imports": [ - "warn", + "error", { patterns: [ { - group: ["**/plugins/*/src/frontend/**"], + group: ["**/plugins/*/src/**", "**/plugins/*/dist/**"], message: - "The shell should not import plugin components directly. A7 replaces these with registrations through the app object.", + "The shell does not import plugins. Register the surface through the app object and read it from a registry.", }, ], }, diff --git a/package.json b/package.json index cd3b8baee..b7906c889 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-plugin-boundaries.cjs", + "lint": "node scripts/generate-dialect-schema.cjs --check && npm run plugin:validate-manifest && eslint . && node scripts/check-plugin-boundaries.cjs && node scripts/check-importmap-csp.cjs && node scripts/check-shell-plugin-ids.cjs", "lint:fix": "eslint --fix .", "type-check": "tsc -b --force", "test": "vitest run", diff --git a/packages/plugin-sdk/ARCHITECTURE.md b/packages/plugin-sdk/ARCHITECTURE.md index 23bbf88d1..1295bf529 100644 --- a/packages/plugin-sdk/ARCHITECTURE.md +++ b/packages/plugin-sdk/ARCHITECTURE.md @@ -29,7 +29,8 @@ dependencies. Entry points: | `@termix/plugin-sdk/backend` | `PluginContext`, `definePlugin()`, `PluginCapabilityError` | | `@termix/plugin-sdk/db` | `defineTable()`, the column builders, the legacy-table map | | `@termix/plugin-sdk/ddl` | The per-dialect DDL emitter, shared with the CLI | -| `@termix/plugin-sdk/frontend` | The `app` object types (stubs until A7) | +| `@termix/plugin-sdk/frontend` | The `app` object types, the hooks, `invokeAction()` | +| `@termix/plugin-sdk/ui` | Core's shared components, a fixed public list (see UI) | | `@termix/plugin-sdk/manifest` | Manifest types, validation, the JSON schema | | `@termix/plugin-sdk/capabilities` | The capability catalog | | `@termix/plugin-sdk/settings` | Settings field types and the shared value validator | @@ -271,11 +272,145 @@ allowlist (`CORE_SETTINGS_ALLOWLIST`) rather than the whole settings table. ### 8. UI -A plugin frontend is a built ESM bundle loaded at runtime by the core loader. -It registers everything through the `app` object: rail items, panels, tabs, -host editor sections, host actions and badges, context menu items, palette -entries, dashboard cards, homepage widgets, settings components, action slots, -login/2FA UI, SSH auth editors. The shell contains no plugin ids. **A7.** +A plugin frontend is a built ESM bundle, `dist/frontend.js`, exporting +`activate(app)` and optionally `deactivate()`. The shell has no plugin ids and +no imports from `plugins/`; everything a plugin shows goes through the `app` +object. `scripts/check-shell-plugin-ids.cjs` (run by lint) fails on a quoted +plugin id in `src/ui` outside tests, apart from the entries in +`scripts/shell-plugin-id-allowlist.json`, each with a reason (host protocol +data like `rdp`, which Phase B moves). + +#### The loader + +`src/ui/plugin-host/loader.ts` runs after login and again whenever plugin +state may have changed: the `termix:plugins-changed` window event (the admin +toggle fires it) and window focus, throttled to 30 seconds. There is no push +channel yet. Each pass: + +1. Fetches `GET /plugins` (`frontend`, `css`, `assetVersion`, `locales`, + `dependencies` and `contributes` per plugin). +2. Loads every plugin's locales into the i18next namespace ``, enabled or + not, because the role editor and the plugin list need disabled plugins' + titles. +3. Orders enabled plugins by dependencies. A plugin whose hard dependency is + missing or off is skipped. +4. For each plugin with a frontend: injects `frontend.css`, imports + `/plugin-assets//frontend.js?v=` and calls `activate(app)`. + In dev the workspace plugins are imported from + `plugins//src/frontend/index.tsx` through Vite, so HMR works. +5. Deactivates plugins that went away: runs `deactivate()` then every + disposer. No reload. + +A plugin that throws while importing or activating is marked failed, its +partial registrations are disposed, and the rest of the app carries on. The +same `assetVersion` is not retried until it changes. + +Anonymous shared-session and collab pages have no session. They load only +plugins whose manifest sets `contributes.guest: true`, from the public +`GET /plugins/public`, and `app.guest` is true there. + +#### Shared modules and the import map + +A bundle keeps `react`, `react-dom`, `react-dom/client`, `react/jsx-runtime`, +`i18next`, `react-i18next`, `sonner`, `@termix/plugin-sdk/frontend`, +`@termix/plugin-sdk/ui` and `@termix/legacy-core/*` as bare imports. Core's +Vite build (`scripts/vite-plugin-termix-plugins.mjs`) emits one entry per +shared module, writes a stable unhashed shim for each at +`dist/shared/.js`, and injects an import map into `index.html` mapping +the bare names to those shims. In dev the map points at Vite's virtual +modules instead. The map is inline, so both nginx configs allow it by hash in +`script-src`; `scripts/check-importmap-csp.cjs` (run by lint) fails when the +hash is out of date and `--write` updates it. The map changes only when the +list of shared modules does, which includes the legacy-core modules plugins +import. + +Electron loads `index.html` from `file://`. The map uses relative URLs, and +plugin bundles come from the embedded backend +(`http://localhost:30001/plugin-assets/...`), which is why `/plugin-assets` +sends `Access-Control-Allow-Origin: *`. + +#### Serving bundles + +`GET /plugin-assets//` serves the directory holding a plugin's +frontend bundle and its `locales/` directory, nothing else: never +`backend.js`, never a path outside those two, only `.js`, `.css`, `.json` and +`.map`. It is unauthenticated like `/assets`, since `import()` cannot send the +bearer header and bundles are not secret. With `?v=` the response is cached +as immutable; without it, `no-cache`. nginx has a `^~ /plugin-assets/` block. + +#### The app object + +Every `register*` call returns a disposer and is also disposed automatically +when the plugin deactivates. Every registered component is wrapped in the +plugin's scope (so the hooks know which plugin they belong to), an error +boundary and Suspense. + +| Member | What it does | +| --------------------------------------------------- | -------------------------------------------------------------------------------------------------------- | +| `registerRailItem` | A rail button. Hideable items show in Appearance > Sidebar > Navigation. The id must be a declared view | +| `registerPanel` | A rail panel, id in `contributes.panels` or `contributes.tabs` | +| `registerTab` | A tab type, id in `contributes.tabs`. Options cover persistence, layouts, singletons and host needs | +| `registerHostEditorSection` | A host editor tab in the top strip or the SSH group, with `form`, `setField` and `updateForm` | +| `registerHostAction` | A connect or open action on a host: sidebar row, palette, dashboard, default connect | +| `registerHostBadge`, `registerHostContextMenuItem` | Host row badges and context menu entries | +| `registerPaletteEntry` | A global or per-host command palette entry | +| `registerDashboardCard` | A dashboard card, id in `contributes.dashboardCards` | +| `registerHomepageWidget` | A homepage widget, with an optional edit form | +| `registerSettingsComponent` | A component a `type: "custom"` settings field names | +| `registerAction`, `declareActionSlot` | Frontend actions and the slots a plugin owns | +| `registerSlotContribution`, `invokeAction` | Fill a slot with a `button` or a `component`, with an optional `when`; call an action and get its result | +| `registerSshAuthEditor` | An SSH auth method's editor in the host editor | +| `registerLoginMethod`, `registerSecondFactorUI` | Typed now, wired by A8 | +| `api`, `wsUrl(path)` | axios on `/plugin-api//` and the plugin's WebSocket URL | +| `tabs.open`, `getLayout`, `applyLayout`, `onChange` | Tab control, used by workspaces | +| `guest`, `info`, `onDispose` | Guest mode flag, plugin info, extra cleanup | + +Hooks: `useTranslation` (the plugin's namespace), `usePermission` (a short +name resolves to `.`), `useSettings`, `useHost`, `useHosts`, +`useCurrentUser`, `useTheme`, `useToast`, `usePluginApi`, `useTabs`. The SDK +has no runtime dependencies: the hooks delegate to a host bridge core installs. + +Slots core owns: `terminal.toolbar`, `terminal.dock`, `terminal.overlay` +(declared by ssh-terminal), `onboarding.steps`, `onboarding.features`, +`onboarding.workflow`, `hosts.importMenu`, `hosts.panel`, `proxmox.hostEditor` +and `session.remoteDisplay`. Cross-plugin frontend calls go through actions: +`automations.list`, `fleets.list`, `session.remoteDisplay.token`. + +#### View ownership + +Who owns a tab, panel or card comes from manifests, so it is known even for a +disabled plugin whose code never loaded. A saved tab or dashboard card whose +plugin is disabled, failed, still loading or not installed renders "This +needs the plugin" (`PluginViewPlaceholder`) and is never dropped from +the saved layout. Tab restore waits for the first plugin pass, so a restored +tab does not race its plugin. + +#### The `ui` entry + +`@termix/plugin-sdk/ui` is public API, implemented by +`src/ui/plugin-host/sdk-ui.ts`. Adding to it is a contract change; removing +from it is a breaking one. Today it exports: alert, alert-dialog, badge, +button, card, checkbox, dialog, dropdown-menu, input, label, password-input, +select, select2, separator, switch, textarea, tooltip, section-card, +metric-card, charts, the card grid, `ConnectionScreen` and the connection +status helpers, `SnippetVariablesDialog`, `FullScreenAppWrapper`, the +connection log context, `TOTPDialog`, `SSHAuthDialog`, `WarpgateDialog`, +`useTabs`/`useTabsSafe`, `ActionSlot` and `ComponentSlot`. Publishing its +`.d.ts` for plugins outside this repo is a follow-up for the repo split. + +#### Strings + +A plugin's strings live in `plugins//locales/en.json` and load into the +`` namespace, with core's `translation` as the fallback, so a plugin can +still use `common.*`. Manifest keys (`titleKey`, `labelKey`) resolve in the +plugin namespace; `pluginKey(id, key)` in core returns `:`. +Translations go to `plugins//locales/translated/.json`, which is +where Crowdin writes them. Only `en.json` is edited by hand. + +#### Type checking + +`tsconfig.plugins.frontend.json` checks every plugin frontend and its tests +with bundler resolution, and is part of `npm run type-check`. ### 9. Cross-plugin use @@ -314,8 +449,12 @@ capability, registry, service, secret and shutdown suites. `@termix/plugin-sdk/testing` provides `createMockCtx()`, which enforces capabilities the way the runtime does, `createFakeContext()` for tests that do -not care about the gates, and `renderWithApp()` for frontend tests (**A7** -finishes it). +not care about the gates, and `renderWithApp(plugin, options)` for frontend +tests. `renderWithApp` activates the plugin against core's real registries, +records what it registered and the shell calls it made, renders any tab, +panel, card, host editor section, settings component or slot, and +`deactivate()` disposes it all. Every bundled plugin has a +`tests/frontend/activate.test.tsx` built on it. ### 12. Auth @@ -339,8 +478,8 @@ plugins// tsconfig.json extends @termix/plugin-sdk/tsconfig.plugin.json vitest.config.ts one line, the SDK preset src/backend/index.ts exports activate(ctx) and deactivate() - src/frontend/index.tsx exports activate(app) and deactivate() (A7) - locales/en.json English strings; Crowdin translates the rest + src/frontend/index.tsx exports activate(app) and deactivate() + locales/en.json English strings; Crowdin writes locales/translated/ migrations/{sqlite,postgres,mysql}/ owned tables, one .sql per dialect migrations/snapshot.json diff basis for the generator src/backend/tables.ts defineTable() definitions @@ -545,17 +684,23 @@ Cross-field rules the JSON schema cannot express, checked by `parseManifest`: appear in the plugin's own `contributes.permissions`. A dotted id is taken as given, because the validator cannot know which other plugins exist. +`contributes.panels` and `contributes.dashboardCards` (each `{ id, titleKey, +icon? }`) declare the views a plugin owns besides its tabs; the app object +refuses to register a view the manifest does not declare. `contributes.guest` +opts a plugin into anonymous guest pages. Action contributions and slots +accept the kinds `button` and `component`. + `contributes.hostCapability`, `provides`, `requires`, `providesSecret` and `requiresSecret` are carried forward from v1 unchanged because the service and -secret registries read them at activation. A6 and A7 reshape them. +secret registries read them at activation. Phase B reshapes them. Removed in A5: `contributes.permissionGroup` and its `defaultForRole`, replaced by `contributes.permissions`. A plugin no longer picks its own group name. Removed in v2: `permissions` (replaced by `capabilities`), `sidecars`, the `capabilities.{backend,frontend,electron,platforms}` object (replaced by the -`backend`/`frontend`/`platforms` fields), `contributes.dashboardCards`, -`contributes.settingsPanel`, `contributes.apiPrefix`, and +`backend`/`frontend`/`platforms` fields), the v1 shape of +`contributes.dashboardCards`, `contributes.settingsPanel`, `contributes.apiPrefix`, and `process:transport-owner` (the marker for the tier that no longer exists). --- @@ -767,11 +912,12 @@ and that is bundled into its output. `ws`, `multer`, `cookie-parser`, `axios`, `jszip`, `guacamole-lite`, `@anthropic-ai/sdk`, `drizzle-orm`. -**Frontend**: `react`, `react-dom`, `react/jsx-runtime`, `@termix/plugin-sdk`, -`i18next`, `react-i18next`, and the UI libraries core provides today -(`lucide-react`, `sonner`, `axios`, `cytoscape`, `react-cytoscapejs`, -`guacamole-common-js`, `react-xtermjs`, `@xterm/*`). **A7** serves these -through the SDK `ui` entry. +**Frontend**: `react`, `react-dom`, `react-dom/client`, `react/jsx-runtime`, +`i18next`, `react-i18next`, `sonner`, `@termix/plugin-sdk/frontend`, +`@termix/plugin-sdk/ui` and `@termix/legacy-core/*`, all resolved through the +import map (see UI). Everything else, including `lucide-react`, `axios`, +`cytoscape` and `guacamole-common-js`, is bundled into the plugin that uses +it. The lists live in `packages/plugin-sdk/cli/lib/externals.mjs`. @@ -787,6 +933,13 @@ and rewrites to the compiled output path (`../../../backend/backend/...`, or so a source file at any nesting collapses to the same prefix. D1 deletes that file. +Frontends do the same with `@/`: in the browser build, `@/x` and +`../src/ui/x` become the bare `@termix/legacy-core/ui/x` (or +`@termix/legacy-core/types/x`), which core's Vite build exposes as a shared +module so plugin and shell use one instance of each core module. The CLI +refuses the rewrite outside a Termix checkout. Every such import is counted +in the `plugin-frontend-to-core` direction below. + This is expected and temporary. The SDK does not yet expose what they need: the SSH connection pool, host resolution, the repository layer, the shared component library. D1 removes the debt once A3 through A8 have given them @@ -798,7 +951,8 @@ What the lint fence enforces today, in `eslint.config.mjs`: | ------------------------------------------------ | --------- | --------- | ---------- | | Core importing a plugin backend | **Error** | 0 | - | | A plugin backend importing frontend code or `@/` | **Error** | 0 | - | -| The shell importing plugin components | Warning | 16 files | A7 | +| The shell importing plugin code | **Error** | 0 | - | +| A plugin frontend importing core through `@/` | Warning | 109 files | D1 | | A plugin importing core by relative path | Warning | 70 files | D1 | | A plugin importing another plugin's source | Warning | 3 files | B18 | @@ -831,5 +985,9 @@ Known specifics: - Core feature servers that are not plugins yet still own ports: tunnel 30003, file-manager 30004, dashboard 30006, tmux 30010, serial 30011 and homepage 30012. Each keeps its nginx block until its own Phase B step. No plugin owns a port any more (A4). -- `src/ui/shell/pluginLoader.ts` still hardcodes plugin ids in - `BUILT_IN_TABS_BY_PLUGIN` and `applyFirstPartyActions`. A7 removes both. +- The terminal component and `TerminalTabContent` stay in core until the + terminal's Phase B step (session manager, split view and file-manager + callbacks). ssh-terminal registers them through the legacy alias. +- Host data columns (`enableDocker`, `enableRdp`, `guacamoleConfig` and so on) + stay in core types until Phase B moves them. Only UI branches on them left + the shell. diff --git a/packages/plugin-sdk/cli/commands/build.mjs b/packages/plugin-sdk/cli/commands/build.mjs index 9a29c7f8e..85ceae4b8 100644 --- a/packages/plugin-sdk/cli/commands/build.mjs +++ b/packages/plugin-sdk/cli/commands/build.mjs @@ -17,6 +17,17 @@ const FRONTEND_ENTRIES = [ "src/frontend/index.js", ]; +/** Whether the plugin sits in a Termix checkout, i.e. is a bundled plugin. */ +function insideTermixCheckout(cwd) { + let dir = path.resolve(cwd); + for (;;) { + if (fs.existsSync(path.join(dir, "src", "ui", "plugin-host"))) return true; + const parent = path.dirname(dir); + if (parent === dir) return false; + dir = parent; + } +} + export async function build({ cwd }) { const manifest = readManifest(cwd); const pluginId = manifest.id ?? path.basename(cwd); @@ -58,7 +69,13 @@ export async function build({ cwd }) { sourcemap: true, logLevel: "warning", external: FRONTEND_EXTERNALS, - plugins: [legacyCoreImports({ pluginId, platform: "browser" })], + plugins: [ + legacyCoreImports({ + pluginId, + platform: "browser", + insideTermix: insideTermixCheckout(cwd), + }), + ], }); } diff --git a/packages/plugin-sdk/cli/lib/externals.mjs b/packages/plugin-sdk/cli/lib/externals.mjs index 563ac2aaa..2c11a5e27 100644 --- a/packages/plugin-sdk/cli/lib/externals.mjs +++ b/packages/plugin-sdk/cli/lib/externals.mjs @@ -25,24 +25,21 @@ export const BACKEND_EXTERNALS = [ "drizzle-orm/*", ]; +/** + * Resolved by the page's import map to the shell's own copies, because these + * must be one instance: React, i18next, the toast store, and the SDK entries + * that share state with core. Anything else a plugin imports is bundled. + */ export const FRONTEND_EXTERNALS = [ "react", "react-dom", "react/jsx-runtime", "react-dom/client", - "@termix/plugin-sdk", - "@termix/plugin-sdk/*", "i18next", "react-i18next", - // Core-provided UI libraries. A7 serves these through the SDK ui entry. - "lucide-react", "sonner", - "axios", - "cytoscape", - "react-cytoscapejs", - "guacamole-common-js", - "react-xtermjs", - "@xterm/*", - // Legacy: the shell's own modules, still reached by alias. A7 removes. - "@/*", + "@termix/plugin-sdk/frontend", + "@termix/plugin-sdk/ui", + // Legacy: the shell's own modules, see legacy-core-imports.mjs. D1 removes. + "@termix/legacy-core/*", ]; diff --git a/packages/plugin-sdk/cli/lib/legacy-core-imports.mjs b/packages/plugin-sdk/cli/lib/legacy-core-imports.mjs index 802d9b490..9a35094ca 100644 --- a/packages/plugin-sdk/cli/lib/legacy-core-imports.mjs +++ b/packages/plugin-sdk/cli/lib/legacy-core-imports.mjs @@ -12,6 +12,8 @@ * Delete this file in D1, once every plugin reaches core through the SDK. */ +import { legacyCoreSpecifier } from "./legacy-core-specifier.mjs"; + // "../../../src/backend/" or "../../../../src/backend/", any depth. const CORE_BACKEND = /^(?:\.\.\/)+src\/backend\//; // Shared types. Mostly erased at compile, but automations imports a real @@ -27,10 +29,36 @@ const CROSS_PLUGIN = /^(?:\.\.\/)+([a-z0-9-]+)\/(?:src\/)?backend\//; const COMPILED_CORE = "../../../backend/backend/"; const COMPILED_TYPES = "../../../backend/types/"; -export function legacyCoreImports({ pluginId, platform }) { +const CORE_ALIAS = /^@\//; + +export function legacyCoreImports({ pluginId, platform, insideTermix = true }) { return { name: "legacy-core-imports", setup(build) { + // The shell's own modules, reached as "@/..." or by relative path. + // Bundling them would give the plugin a second copy of the shell's + // contexts and API client, so each becomes a bare specifier the page's + // import map resolves to the shell's own module. + if (platform === "browser") { + const toLegacy = (args) => { + const specifier = legacyCoreSpecifier(args.path); + if (!specifier) return null; + if (!insideTermix) { + return { + errors: [ + { + text: `${pluginId}: "${args.path}" reaches Termix core. Only plugins built inside a Termix checkout may; use @termix/plugin-sdk instead.`, + }, + ], + }; + } + return { path: specifier, external: true }; + }; + build.onResolve({ filter: CORE_ALIAS }, toLegacy); + build.onResolve({ filter: CORE_UI }, toLegacy); + build.onResolve({ filter: CORE_TYPES }, toLegacy); + } + build.onResolve({ filter: CORE_BACKEND }, (args) => ({ path: args.path.replace(CORE_BACKEND, COMPILED_CORE), external: true, @@ -41,16 +69,6 @@ export function legacyCoreImports({ pluginId, platform }) { external: true, })); - // The shell's own modules. Only plugins/docker's frontend entry reaches - // core this way; every other frontend uses the "@/" alias, which is - // externalized by name. A7 removes both. - if (platform === "browser") { - build.onResolve({ filter: CORE_UI }, (args) => ({ - path: args.path, - external: true, - })); - } - build.onResolve({ filter: CROSS_PLUGIN }, (args) => { const [, other] = CROSS_PLUGIN.exec(args.path); if (other === "src" || other === pluginId) return null; diff --git a/packages/plugin-sdk/cli/lib/legacy-core-specifier.mjs b/packages/plugin-sdk/cli/lib/legacy-core-specifier.mjs new file mode 100644 index 000000000..051274c29 --- /dev/null +++ b/packages/plugin-sdk/cli/lib/legacy-core-specifier.mjs @@ -0,0 +1,62 @@ +/** + * Legacy core modules a bundled plugin frontend still imports. + * + * Bundled plugin frontends predate the SDK and import the shell's own modules + * as "@/..." (or, in a couple of places, by relative path into src/). Bundling + * those would give the plugin a second copy of the shell's contexts and API + * client, so the CLI rewrites each one to a bare specifier under + * "@termix/legacy-core/" and core's build exposes exactly that module through + * the import map. Both sides use this one normalizer so they cannot disagree. + * + * Only plugins built inside a Termix checkout may do this. D1 deletes it. + */ + +export const LEGACY_CORE_PREFIX = "@termix/legacy-core/"; + +const EXTENSION = /\.(tsx|ts|jsx|js|mjs)$/; + +function clean(rest) { + return rest.replace(EXTENSION, "").replace(/\/+$/, ""); +} + +/** + * "@/components/button.tsx" -> "@termix/legacy-core/ui/components/button" + * "@/types" -> "@termix/legacy-core/types" + * "@/types/connection-log" -> "@termix/legacy-core/types/connection-log" + * "../../../src/ui/x.tsx" -> "@termix/legacy-core/ui/x" + * Anything else -> null + */ +export function legacyCoreSpecifier(specifier) { + if (specifier.startsWith("@/")) { + const rest = clean(specifier.slice(2)); + if (rest === "types" || rest.startsWith("types/")) { + return LEGACY_CORE_PREFIX + rest; + } + return `${LEGACY_CORE_PREFIX}ui/${rest}`; + } + const relative = /^(?:\.\.\/)+src\/(ui|types)(\/.*)?$/.exec(specifier); + if (relative) { + return LEGACY_CORE_PREFIX + clean(`${relative[1]}${relative[2] ?? ""}`); + } + return null; +} + +/** + * Every value import in a source file that names a legacy core module. + * Type-only imports are skipped: they are erased and never reach the map. + */ +export function findLegacyCoreImports(source) { + const found = new Set(); + const patterns = [ + /^\s*(?:import|export)\s+(?!type\s)[^'";]*?\sfrom\s+["']([^"']+)["']/gm, + /^\s*import\s+["']([^"']+)["']/gm, + /import\(\s*["']([^"']+)["']\s*\)/g, + ]; + for (const pattern of patterns) { + for (const match of source.matchAll(pattern)) { + const normalized = legacyCoreSpecifier(match[1]); + if (normalized) found.add(normalized); + } + } + return found; +} diff --git a/packages/plugin-sdk/schema/manifest.schema.json b/packages/plugin-sdk/schema/manifest.schema.json index 23e7bd69b..65ab009e1 100644 --- a/packages/plugin-sdk/schema/manifest.schema.json +++ b/packages/plugin-sdk/schema/manifest.schema.json @@ -263,6 +263,33 @@ } } }, + "guest": { "type": "boolean" }, + "panels": { + "type": "array", + "items": { + "type": "object", + "additionalProperties": false, + "required": ["id", "titleKey"], + "properties": { + "id": { "type": "string", "minLength": 1 }, + "titleKey": { "type": "string", "minLength": 1 }, + "icon": { "type": "string", "minLength": 1 } + } + } + }, + "dashboardCards": { + "type": "array", + "items": { + "type": "object", + "additionalProperties": false, + "required": ["id", "titleKey"], + "properties": { + "id": { "type": "string", "minLength": 1 }, + "titleKey": { "type": "string", "minLength": 1 }, + "icon": { "type": "string", "minLength": 1 } + } + } + }, "actions": { "type": "array", "items": { @@ -296,7 +323,7 @@ }, "kind": { "type": "string", - "enum": ["button"] + "enum": ["button", "component"] } } } @@ -317,7 +344,7 @@ "minItems": 1, "items": { "type": "string", - "enum": ["button"] + "enum": ["button", "component"] } }, "descriptionKey": { diff --git a/packages/plugin-sdk/src/frontend.ts b/packages/plugin-sdk/src/frontend.ts index 8b283e444..2928b0d72 100644 --- a/packages/plugin-sdk/src/frontend.ts +++ b/packages/plugin-sdk/src/frontend.ts @@ -1,29 +1,478 @@ /** - * The frontend contract: what a plugin's frontend entry receives. + * The frontend contract: what a plugin's frontend entry receives, and the + * hooks its components use. * - * Stubs only. A7 builds the real loader and fills these in, at which point a - * plugin registers every surface it contributes through this object and the - * shell stops carrying plugin ids of its own. + * A plugin frontend is `src/frontend/index.tsx` exporting `activate(app)` and + * optionally `deactivate()`. Everything it contributes goes through `app`, and + * everything registered there is removed when the plugin is disabled, without + * a page reload. + * + * This module has no runtime dependencies. The hooks delegate to a host that + * core installs at startup (`__setPluginHost`), because React, i18next and the + * shell's state all live in core and must be one instance across the shell + * and every plugin bundle. */ +import type { ComponentType, ReactNode, Ref } from "react"; import type { PluginManifest } from "./manifest.js"; +export type Disposer = () => void; + +/** A Lucide icon or anything with the same props. */ +export type IconComponent = ComponentType<{ + className?: string; + size?: number | string; + strokeWidth?: number | string; +}>; + +/** + * 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. + */ +export interface PluginHostRecord { + id: string; + name: string; + ip: string; + port: number; + username?: string; + folder?: string; + tags?: string[]; + [key: string]: unknown; +} + +/** An open tab as the shell holds it. `data` is the plugin's own payload. */ +export interface PluginTabRecord { + id: string; + type: string; + label: string; + host?: PluginHostRecord; + data?: Record; + [key: string]: unknown; +} + +export interface OpenTabOptions { + label?: string; + /** Open a second tab even when one for this host and type exists. */ + forceNewTab?: boolean; + /** Plugin payload, stored on the tab and restored with it. */ + data?: Record; +} + +/** A saved arrangement of tabs, used by workspaces. Opaque to plugins. */ +export interface ShellLayout { + version: number; + [key: string]: unknown; +} + +/** What a plugin may ask of the shell. */ +export interface ShellApi { + openTab: ( + host: PluginHostRecord | null, + type: string, + options?: OpenTabOptions, + ) => void; + openSingletonTab: (type: string, options?: OpenTabOptions) => void; + closeTab: (tabId: string) => void; + renameTab: (tabId: string, label: string) => void; + openFileInEditor: (host: PluginHostRecord, path: string) => void; + openFileManager: (host: PluginHostRecord, path?: string) => void; + openTerminalTab: (host: PluginHostRecord, path?: string) => void; + /** Opens a rail view in the left sidebar. */ + openRailView: (id: string) => void; + /** Closes a rail view wherever it is shown. */ + closeRailView: (id: string) => void; +} + +export interface TabsApi extends Pick< + ShellApi, + "openTab" | "openSingletonTab" | "closeTab" +> { + /** The current tabs and split layout, or null before the shell mounts. */ + getLayout: () => ShellLayout | null; + /** + * Replaces the open tabs with a saved layout. `name` labels a restored + * split. Resolves with the tabs that could not be reopened, e.g. because + * their host was deleted. + */ + applyLayout: ( + layout: ShellLayout, + options?: { name?: string }, + ) => Promise<{ skipped: string[] }>; + /** Called whenever tabs open, close or move. */ + onChange: (listener: () => void) => Disposer; + /** Called once the shell has restored its tabs after login. */ + onReady: (listener: () => void) => Disposer; +} + +// --------------------------------------------------------------------------- +// Registrations +// --------------------------------------------------------------------------- + +export interface RailItemContribution { + /** Must be declared in manifest contributes.tabs or contributes.panels. */ + id: string; + icon: IconComponent; + titleKey: string; + /** "panel" opens the left sidebar, "tab" opens a tab. Default "panel". */ + kind?: "panel" | "tab"; + /** Users may hide it from Appearance > Sidebar > Navigation. Default true. */ + hideable?: boolean; + /** Can also open as a full-width tab. */ + promotable?: boolean; + /** Can open in the right dock. */ + rightDockable?: boolean; + /** Shown on the mobile bar's primary row. */ + mobilePrimary?: boolean; + /** Desktop app only. */ + electronOnly?: boolean; + separatorAfter?: boolean; + /** Hidden without being unregistered, e.g. while a feature is switched off. */ + hidden?: boolean; + /** Place it after this rail id rather than at the end. */ + after?: string; + /** Lower sorts first among plugin items. */ + order?: number; +} + +export interface PanelProps { + /** Whether the panel is the one currently shown. */ + active: boolean; + shell: ShellApi; + /** Tells the shell the panel is editing, which widens the sidebar. */ + setEditing: (editing: boolean) => void; + /** Type of the focused tab, if any. */ + activeTabType?: string; + /** Where the panel is rendered. */ + placement: "left" | "right" | "tab"; +} + +export interface PanelOptions { + /** Keep the panel mounted after the user switches away. */ + keepMounted?: boolean; +} + +export interface TabProps { + tab: PluginTabRecord; + host?: PluginHostRecord; + /** The host in the shape the connection APIs take. */ + sshHost?: Record; + label: string; + isVisible: boolean; + isFocusedPane: boolean; + /** Forward to a component exposing `refresh()` or `disconnect()`. */ + handleRef: Ref; + shell: ShellApi; +} + +export interface StandaloneViewProps { + hostId?: string; + view: string; + params: URLSearchParams; +} + +export interface TabOptions { + icon?: IconComponent; + /** Label for singleton tabs and anywhere the type is named. */ + titleKey?: string; + /** Needs a host; renders `noHostMessageKey` without one. */ + requiresHost?: boolean; + noHostMessageKey?: string; + /** Reopened after login. */ + persistent?: boolean; + /** One tab of this type at a time, keyed by type. */ + singleton?: boolean; + /** A live session: asks before closing and can be refreshed. */ + session?: boolean; + /** Restorable without a host. */ + hostless?: boolean; + /** Decides whether a saved tab for this host may be restored. */ + restore?: (host: PluginHostRecord) => boolean; + /** Recent-activity types that open this tab. */ + activityTypes?: string[]; + /** Rendered for `?view=` full-screen links. */ + standalone?: ComponentType; + /** Extra `?view=` names that also open `standalone`. */ + standaloneViews?: string[]; + /** Wrap in the readable-width frame used by panels opened as tabs. */ + panelFrame?: boolean; + /** False keeps the tab out of saved layouts and workspaces. Default true. */ + inLayouts?: boolean; + /** Warms the tab's code before it is opened. */ + preload?: () => Promise; +} + +export interface HostEditorSectionProps { + // The editor form is a plain object; a section reads the fields it owns. + // eslint-disable-next-line @typescript-eslint/no-explicit-any + form: any; + setField: (key: string, value: unknown) => void; + /** Sets several fields at once, computed from the latest form. */ + updateForm: ( + patch: (form: Record) => Record, + ) => void; + host?: PluginHostRecord; + credentials?: unknown[]; + snippets?: unknown[]; + /** Which connection protocols are switched on for this host. */ + protocols: Record; +} + +export interface HostEditorSectionContribution { + id: string; + /** "top" sits in the main tab strip, "ssh" under the SSH group. */ + group: "top" | "ssh"; + titleKey: string; + icon?: IconComponent; + /** + * Position among the group's tabs, core ones included. Top: General 0, + * SSH 10. SSH group: General 0, Terminal 10, Tunnels 20, Files 60. + */ + order?: number; + /** Whether to offer the tab, from the host's enabled protocols. */ + visible?: (protocols: Record) => boolean; + component: ComponentType; +} + +export interface HostActionContribution { + id: string; + titleKey: string; + icon: IconComponent; + /** + * "connect" is a way to open a session (terminal, RDP) and is offered as a + * host's default action by priority. "open" opens a tool for the host. + */ + kind: "connect" | "open"; + /** Higher wins when choosing a host's default connect action. */ + priority?: number; + /** Opened with shell.openTab when `run` is absent. */ + tabType?: string; + when: (host: PluginHostRecord) => boolean; + run?: (host: PluginHostRecord, shell: ShellApi) => void; + /** Shows a quick button on the host row. Default true. */ + tray?: boolean; + /** `?view=` name for "Copy link". */ + copyUrlView?: string; + /** Where a host overview (the dashboard's host status list) sends a click. */ + overview?: boolean; + /** + * Position in the host row. Core: Files 20, Tunnel 40, Tmux 70. Connect + * actions default to 100 and sit after a separator. + */ + order?: number; + /** A label worked out per host, e.g. a single endpoint's name. */ + label?: (host: PluginHostRecord) => string | undefined; + /** Several targets: two or more become a picker, one runs directly. */ + items?: (host: PluginHostRecord) => { + id: string; + label: string; + run: (host: PluginHostRecord, shell: ShellApi) => void; + }[]; +} + +export interface HostBadgeContribution { + id: string; + when: (host: PluginHostRecord) => boolean; + component: ComponentType<{ host: PluginHostRecord }>; +} + +export interface HostContextMenuItemContribution { + id: string; + titleKey: string; + icon?: IconComponent; + when: (host: PluginHostRecord) => boolean; + run: (host: PluginHostRecord, shell: ShellApi) => void; +} + +export interface PaletteEntryContribution { + id: string; + titleKey: string; + icon?: IconComponent; + keywords?: string[]; + /** "global" entries stand alone, "host" entries appear under a host. */ + scope: "global" | "host"; + when?: (host?: PluginHostRecord) => boolean; + run: (shell: ShellApi, host?: PluginHostRecord) => void; +} + +export interface DashboardCardProps { + isVisible: boolean; + shell: ShellApi; +} + +export interface DashboardCardContribution { + /** Must be declared in manifest contributes.dashboardCards. */ + id: string; + titleKey: string; + defaultHeight?: number; + component: ComponentType; +} + +export interface HomepageWidgetContribution> { + id: string; + name: string; + description: string; + category: "links" | "info" | "system" | "monitoring"; + icon: ReactNode; + defaultConfig: C; + defaultSize: { w: number; h: number }; + minSize: { w: number; h: number }; + // eslint-disable-next-line @typescript-eslint/no-explicit-any + component: ComponentType; + // eslint-disable-next-line @typescript-eslint/no-explicit-any + editFormComponent?: ComponentType; +} + +export interface SettingsComponentProps { + pluginId: string; + values: Record; + setValue: (key: string, value: unknown) => void; + running: boolean; +} + +export type ActionHandler = (...args: never[]) => unknown; + +export interface ActionSlotDefinition { + id: string; + /** Contribution kinds the slot renders: "button", "component". */ + accepts: string[]; +} + +export interface SlotContribution { + actionId: string; + titleKey: string; + /** Secondary text, for slots that show one (onboarding cards). */ + descriptionKey?: string; + icon?: IconComponent; + kind?: "button" | "component" | string; + /** For kind "component". Receives the slot owner's props. */ + component?: ComponentType>; + /** Extra condition on top of the action's permission. */ + when?: (context: Record) => boolean; + order?: number; +} + +export interface SshAuthEditorProps { + form: Record; + setField: (key: string, value: unknown) => void; +} + +export interface SshAuthEditorContribution { + /** The value stored in the host's authType. */ + authType: string; + titleKey: string; + hintKey?: string; + component?: ComponentType; +} + +/** A7 declares these; A8 wires them into the login screen. */ +export interface LoginMethodContribution { + id: string; + titleKey: string; + icon?: IconComponent; + component: ComponentType>; +} + +export interface SecondFactorContribution { + id: string; + titleKey: string; + component: ComponentType>; +} + +/** The subset of axios a plugin uses, rooted at /plugin-api//. */ +export interface PluginApiClient { + get(url: string, config?: unknown): Promise<{ data: T }>; + delete(url: string, config?: unknown): Promise<{ data: T }>; + post( + url: string, + body?: unknown, + config?: unknown, + ): Promise<{ data: T }>; + put( + url: string, + body?: unknown, + config?: unknown, + ): Promise<{ data: T }>; + patch( + url: string, + body?: unknown, + config?: unknown, + ): Promise<{ data: T }>; +} + +export interface PluginWsTarget { + url: string; + protocols?: string[]; +} + export interface TermixAppInfo { readonly pluginId: string; readonly manifest: PluginManifest; } /** - * Registration surface for a plugin frontend. - * - * A7 adds: rail items, panels, tabs, host editor sections, host actions and - * badges, context menu items, palette entries, dashboard cards, homepage - * widgets, settings components, action slots, login/2FA UI and SSH auth - * editors. Everything registered here is removed when the plugin is disabled. + * Registration surface for a plugin frontend. Every `register*` returns a + * disposer, and anything not disposed by hand is disposed when the plugin is + * disabled. */ export interface TermixApp extends TermixAppInfo { + /** + * True on anonymous guest pages (a shared-session link). Only plugins with + * contributes.guest run there, and they should register just what a guest + * sees: there is no user, so API calls needing a login will fail. + */ + readonly guest: boolean; + registerRailItem: (item: RailItemContribution) => Disposer; + registerPanel: ( + id: string, + component: ComponentType, + options?: PanelOptions, + ) => Disposer; + registerTab: ( + type: string, + component: ComponentType, + options?: TabOptions, + ) => Disposer; + registerHostEditorSection: ( + section: HostEditorSectionContribution, + ) => Disposer; + registerHostAction: (action: HostActionContribution) => Disposer; + registerHostBadge: (badge: HostBadgeContribution) => Disposer; + registerHostContextMenuItem: ( + item: HostContextMenuItemContribution, + ) => Disposer; + registerPaletteEntry: (entry: PaletteEntryContribution) => Disposer; + registerDashboardCard: (card: DashboardCardContribution) => Disposer; + registerHomepageWidget: (widget: HomepageWidgetContribution) => Disposer; + registerSettingsComponent: ( + componentId: string, + component: ComponentType, + ) => Disposer; + registerAction: ( + id: string, + handler: ActionHandler, + options?: { permission?: string }, + ) => Disposer; + declareActionSlot: (slot: ActionSlotDefinition) => Disposer; + registerSlotContribution: ( + slotId: string, + contribution: SlotContribution, + ) => Disposer; + invokeAction: (id: string, ...args: unknown[]) => Promise; + registerSshAuthEditor: (editor: SshAuthEditorContribution) => Disposer; + registerLoginMethod: (method: LoginMethodContribution) => Disposer; + registerSecondFactorUI: (factor: SecondFactorContribution) => Disposer; + + /** HTTP client for this plugin's /plugin-api// routes. */ + api: PluginApiClient; + /** WebSocket URL and auth subprotocols for /plugin-ws//. */ + wsUrl: ( + path: string, + options?: { origin?: unknown }, + ) => Promise; + tabs: TabsApi; /** Registered cleanup, run when the plugin is disabled. */ - onDispose: (dispose: () => void) => void; + onDispose: (dispose: Disposer) => void; } export type FrontendActivate = (app: TermixApp) => void | Promise; @@ -37,4 +486,158 @@ export function definePluginFrontend(plugin: FrontendModule): FrontendModule { return plugin; } +// --------------------------------------------------------------------------- +// Hooks +// --------------------------------------------------------------------------- + +export type TranslateFn = ( + key: string, + options?: Record | string, +) => string; + +export interface CurrentUser { + userId: string; + username: string; + isAdmin: boolean; +} + +export interface ToastApi { + success: (message: string) => void; + error: (message: string) => void; + info: (message: string) => void; + warning: (message: string) => void; +} + +export type SettingsScope = "admin" | "user" | "host"; + +export interface SettingsState { + values: Record; + loaded: boolean; + save: (values: Record) => Promise; +} + +/** + * What core implements behind the hooks. Internal: a plugin never calls this. + */ +export interface PluginHostBridge { + usePluginId: () => string; + useTranslation: (pluginId: string) => { + t: TranslateFn; + language: string; + }; + usePermission: (pluginId: string, permission: string) => boolean; + useSettings: ( + pluginId: string, + scope: SettingsScope, + hostId?: number | string, + ) => SettingsState; + useHost: (hostId: string | number | undefined) => PluginHostRecord | null; + useHosts: () => { hosts: PluginHostRecord[]; loaded: boolean }; + useCurrentUser: () => CurrentUser | null; + useTheme: () => { theme: "light" | "dark" }; + toast: ToastApi; + getApi: (pluginId: string) => PluginApiClient; + useTabs: () => TabsApi; + invokeAction: (id: string, ...args: unknown[]) => Promise; +} + +let host: PluginHostBridge | null = null; + +/** Called once by core. Not part of the plugin API. */ +export function __setPluginHost(bridge: PluginHostBridge | null): void { + host = bridge; +} + +/** + * Set by the shared test setup, so a plugin component rendered on its own in a + * unit test still has hooks. A global rather than an import, because the test + * setup and the component can load different copies of this module. + */ +const TEST_HOST_KEY = "__termixTestPluginHost"; + +function requireHost(): PluginHostBridge { + const fallback = (globalThis as Record)[TEST_HOST_KEY] as + PluginHostBridge | undefined; + if (!host && fallback) return fallback; + if (!host) { + throw new Error( + "@termix/plugin-sdk/frontend: no plugin host. Hooks only work inside Termix or renderWithApp().", + ); + } + return host; +} + +/** The id of the plugin that registered the component being rendered. */ +export function usePluginId(): string { + return requireHost().usePluginId(); +} + +/** + * Translation bound to this plugin's namespace. Keys the plugin does not + * define fall back to core's shared strings (common.*, hosts.*). + */ +export function useTranslation(): { t: TranslateFn; language: string } { + const bridge = requireHost(); + return bridge.useTranslation(bridge.usePluginId()); +} + +/** + * Whether the current user holds a permission. A short name resolves to this + * plugin's own namespace, a dotted id is taken as given. UI only: the backend + * route checks again. + */ +export function usePermission(permission: string): boolean { + const bridge = requireHost(); + return bridge.usePermission(bridge.usePluginId(), permission); +} + +export function useSettings( + scope: SettingsScope, + hostId?: number | string, +): SettingsState { + const bridge = requireHost(); + return bridge.useSettings(bridge.usePluginId(), scope, hostId); +} + +export function useHost( + hostId: string | number | undefined, +): PluginHostRecord | null { + return requireHost().useHost(hostId); +} + +export function useHosts(): { hosts: PluginHostRecord[]; loaded: boolean } { + return requireHost().useHosts(); +} + +export function useCurrentUser(): CurrentUser | null { + return requireHost().useCurrentUser(); +} + +export function useTheme(): { theme: "light" | "dark" } { + return requireHost().useTheme(); +} + +export function useToast(): ToastApi { + return requireHost().toast; +} + +export function usePluginApi(): PluginApiClient { + const bridge = requireHost(); + return bridge.getApi(bridge.usePluginId()); +} + +export function useTabs(): TabsApi { + return requireHost().useTabs(); +} + +/** + * Runs an action another plugin registered, from anywhere in a plugin's code. + * Resolves undefined when nobody registered it, so an optional dependency + * that is switched off reads as "nothing there". + */ +export function invokeAction(id: string, ...args: unknown[]): Promise { + return requireHost().invokeAction(id, ...args); +} + export type { PluginManifest } from "./manifest.js"; +export type { ReactNode }; diff --git a/packages/plugin-sdk/src/manifest.ts b/packages/plugin-sdk/src/manifest.ts index 727603721..f0874d6f7 100644 --- a/packages/plugin-sdk/src/manifest.ts +++ b/packages/plugin-sdk/src/manifest.ts @@ -31,7 +31,7 @@ export const PLUGIN_CATEGORIES = [ export const PLUGIN_PLATFORMS = ["linux", "win32", "darwin"] as const; -export const ACTION_CONTRIBUTION_KINDS = ["button"] as const; +export const ACTION_CONTRIBUTION_KINDS = ["button", "component"] as const; export type ActionContributionKind = (typeof ACTION_CONTRIBUTION_KINDS)[number]; const OPEN_FROM_VALUES = ["rail", "host-context-menu", "palette"] as const; @@ -97,6 +97,17 @@ export interface PluginTabContribution { openFrom: string[]; } +/** + * A sidebar panel or dashboard card the plugin's frontend registers. Declared + * here so core knows who owns a saved view even while the plugin is off and + * its code never loaded. + */ +export interface PluginViewContribution { + id: string; + titleKey: string; + icon?: string; +} + /** * One role permission a plugin contributes. * @@ -224,6 +235,13 @@ export interface PluginSettingsContribution { export interface PluginContributions { tabs?: PluginTabContribution[]; + panels?: PluginViewContribution[]; + dashboardCards?: PluginViewContribution[]; + /** + * The frontend also runs on anonymous guest pages (shared-session and + * collab links), where it is activated with app.guest set. + */ + guest?: boolean; actions?: PluginActionContribution[]; actionSlots?: PluginActionSlot[]; permissions?: PluginPermissionContribution[]; @@ -302,6 +320,9 @@ const ALLOWED_TOP_LEVEL = new Set([ const ALLOWED_CONTRIBUTES = new Set([ "tabs", + "panels", + "dashboardCards", + "guest", "actions", "actionSlots", "permissions", @@ -650,6 +671,14 @@ function validateContributes( rejectUnknown(contributes, ALLOWED_CONTRIBUTES, '"contributes"', errors); validateTabs(contributes.tabs, errors); + validateViews(contributes.panels, "panels", errors); + validateViews(contributes.dashboardCards, "dashboardCards", errors); + if ( + contributes.guest !== undefined && + typeof contributes.guest !== "boolean" + ) { + errors.push('Field "contributes.guest" must be a boolean'); + } validatePermissions(contributes.permissions, pluginId, errors); validateActions(contributes.actions, errors); validateActionSlots(contributes.actionSlots, errors); @@ -884,6 +913,30 @@ function validateTabs(tabs: unknown, errors: string[]): void { }); } +function validateViews(views: unknown, field: string, errors: string[]): void { + if (views === undefined) return; + if (!Array.isArray(views)) { + errors.push(`Field "contributes.${field}" must be an array`); + return; + } + const seen = new Set(); + views.forEach((raw, index) => { + const where = `contributes.${field}[${index}]`; + if (!isPlainObject(raw)) { + errors.push(`${where} must be an object`); + return; + } + rejectUnknown(raw, ["id", "titleKey", "icon"], where, errors); + if (requireString(raw.id, `${where}.id`, errors)) { + if (seen.has(raw.id)) errors.push(`${where}.id duplicates "${raw.id}"`); + seen.add(raw.id); + } + requireString(raw.titleKey, `${where}.titleKey`, errors); + if (raw.icon !== undefined) + requireString(raw.icon, `${where}.icon`, errors); + }); +} + function validatePermissions( permissions: unknown, pluginId: string | undefined, diff --git a/packages/plugin-sdk/src/testing.ts b/packages/plugin-sdk/src/testing.ts index 93065ae3d..b1818d3ad 100644 --- a/packages/plugin-sdk/src/testing.ts +++ b/packages/plugin-sdk/src/testing.ts @@ -443,43 +443,88 @@ export function createMockCtx( } /** - * A TermixApp double for frontend tests. + * Rendering a plugin frontend in a test. * - * A7 builds the real registration surface; until then this records what a - * plugin's frontend entry registered, which is all a test can assert about a - * loader that does not exist yet. Deliberately free of any render library so - * a plugin only needs testing-library if its own tests render something. + * renderWithApp activates the plugin against the real registration surface, + * so a test sees exactly what the shell would: which rail items, tabs, host + * actions and cards it registered, and each of those rendered with the SDK + * hooks working. It is implemented by the Termix host, which is where the + * registries live; the vitest preset points "@termix/plugin-host/testing" at + * core's implementation. */ -export interface FakeTermixApp { +export interface RenderWithAppOptions { + pluginId?: string; + manifest?: Partial; + /** Role permissions the current user holds. */ + permissions?: string[]; + isAdmin?: boolean; + /** Hosts useHosts() returns. */ + hosts?: Array>; + /** The plugin's locales/en.json, loaded into its namespace. */ + locales?: Record; + /** Render as an anonymous guest page. */ + guest?: boolean; +} + +/** A call a plugin made on the shell, recorded instead of performed. */ +export interface ShellCall { + method: string; + args: unknown[]; +} + +export interface RenderedPluginApp { app: TermixApp; - /** Cleanups the plugin handed to app.onDispose. */ - disposals: Array<() => void>; -} - -export function renderWithApp( - options: { pluginId?: string; manifest?: Partial } = {}, -): FakeTermixApp { - const pluginId = options.pluginId ?? "test-plugin"; - const disposals: Array<() => void> = []; - - const manifest = { - id: pluginId, - name: pluginId, - version: "1.0.0", - description: "", - author: { name: "test" }, - license: "MIT", - category: "Productivity", - engine: { termix: ">=2.9.0", api: "1" }, - capabilities: [], - ...options.manifest, - } as PluginManifest; - - const app: TermixApp = { - pluginId, - manifest, - onDispose: (dispose) => disposals.push(dispose), + /** Everything this plugin registered, by kind. */ + registered: { + railItems: () => Array<{ id: string; hidden?: boolean }>; + tabs: () => string[]; + panels: () => string[]; + hostActions: () => Array<{ id: string; tabType?: string }>; + hostEditorSections: () => string[]; + dashboardCards: () => string[]; + settingsComponents: () => string[]; + slot: (slotId: string) => string[]; + actions: () => string[]; }; + /** Shell calls made by the plugin's code. */ + shellCalls: ShellCall[]; + renderTab: (type: string, props?: Record) => HTMLElement; + renderPanel: (id: string, props?: Record) => HTMLElement; + renderDashboardCard: (id: string) => HTMLElement; + renderHostEditorSection: ( + id: string, + props?: Record, + ) => HTMLElement; + renderSettingsComponent: ( + componentId: string, + props?: Record, + ) => HTMLElement; + /** Renders a slot the way its owner would. */ + renderSlot: (slotId: string, props?: Record) => HTMLElement; + /** Runs deactivate and every disposer, as disabling the plugin does. */ + deactivate: () => Promise; +} - return { app, disposals }; +export type FrontendPluginModule = { + activate: (app: TermixApp) => void | Promise; + deactivate?: () => void | Promise; +}; + +interface PluginTestHost { + renderPlugin: ( + plugin: FrontendPluginModule, + options: RenderWithAppOptions, + ) => Promise; +} + +const TEST_HOST = "@termix/plugin-host/testing"; + +export async function renderWithApp( + plugin: FrontendPluginModule, + options: RenderWithAppOptions = {}, +): Promise { + // A variable specifier keeps bundlers from resolving it at build time; the + // test runner resolves it through its alias. + const host = (await import(/* @vite-ignore */ TEST_HOST)) as PluginTestHost; + return host.renderPlugin(plugin, options); } diff --git a/packages/plugin-sdk/src/testing/setup.ts b/packages/plugin-sdk/src/testing/setup.ts index 5570255aa..366468fd5 100644 --- a/packages/plugin-sdk/src/testing/setup.ts +++ b/packages/plugin-sdk/src/testing/setup.ts @@ -63,6 +63,46 @@ if (typeof globalThis.localStorage === "undefined") { }); } +/** + * A plain plugin host for components a test renders on its own: keys come + * back as text, every permission is held, and nothing reaches a server. + * renderWithApp installs Termix's real host instead, which takes precedence. + */ +const noop = () => {}; +const offline = () => + Promise.reject(new Error("No plugin API in a unit test; mock it")); +(globalThis as Record).__termixTestPluginHost = { + usePluginId: () => "test-plugin", + useTranslation: () => ({ + t: (key: string) => key, + language: "en", + }), + usePermission: () => true, + useSettings: () => ({ values: {}, loaded: true, save: async () => {} }), + useHost: () => null, + useHosts: () => ({ hosts: [], loaded: true }), + useCurrentUser: () => null, + useTheme: () => ({ theme: "dark" }), + toast: { success: noop, error: noop, info: noop, warning: noop }, + getApi: () => ({ + get: offline, + delete: offline, + post: offline, + put: offline, + patch: offline, + }), + useTabs: () => ({ + openTab: noop, + openSingletonTab: noop, + closeTab: noop, + getLayout: () => null, + applyLayout: async () => ({ skipped: [] }), + onChange: () => noop, + onReady: () => noop, + }), + invokeAction: async () => undefined, +}; + afterEach(() => { vi.restoreAllMocks(); }); diff --git a/packages/plugin-sdk/src/vitest-preset.ts b/packages/plugin-sdk/src/vitest-preset.ts index b9e0aee70..7c535d67c 100644 --- a/packages/plugin-sdk/src/vitest-preset.ts +++ b/packages/plugin-sdk/src/vitest-preset.ts @@ -48,9 +48,33 @@ export function pluginVitestConfig( ); const repoRoot = findRepoRoot(pluginDir); + // Inside a Termix checkout the SDK's browser entries resolve to source and + // the test host is core's, so renderWithApp exercises the real registries + // and the plugin shares one SDK instance with them. const alias: Record = { ...(repoRoot ? { + "@termix/plugin-sdk/frontend": path.join( + repoRoot, + "packages", + "plugin-sdk", + "src", + "frontend.ts", + ), + "@termix/plugin-sdk/ui": path.join( + repoRoot, + "src", + "ui", + "plugin-host", + "sdk-ui.ts", + ), + "@termix/plugin-host/testing": path.join( + repoRoot, + "src", + "ui", + "plugin-host", + "testing-host.tsx", + ), "@/types": path.join(repoRoot, "src", "types"), "@": path.join(repoRoot, "src", "ui"), } diff --git a/plugins/ai/locales/en.json b/plugins/ai/locales/en.json index 0967ef424..1b4bc3d1a 100644 --- a/plugins/ai/locales/en.json +++ b/plugins/ai/locales/en.json @@ -1 +1,107 @@ -{} +{ + "permissions": { + "use": { + "title": "Use the assistant", + "description": "Open the assistant and ask it things." + }, + "manage_providers": { + "title": "Manage providers", + "description": "Add, edit and remove the AI providers and their API keys." + }, + "apply_proposals": { + "title": "Apply proposals", + "description": "Let the assistant carry out the changes it suggests." + }, + "services.use": { + "title": "Use AI from other plugins", + "description": "Other plugins may call the assistant on your behalf." + }, + "secrets.share": { + "title": "Share the API key", + "description": "Other plugins may use the stored AI API key without seeing it." + } + }, + "settings": { + "assistantUnavailable": "The AI assistant is turned off on this server." + }, + "ai": { + "title": "Assistant", + "send": "Send", + "stop": "Stop", + "save": "Save", + "cancel": "Cancel", + "running": "running", + "approve": "Approve", + "reject": "Reject", + "inputPlaceholder": "Ask about your servers, or describe a change to propose", + "selectProvider": "Select a provider", + "providerSettings": "Provider settings", + "addProvider": "Add provider", + "editProvider": "Edit provider", + "removeProvider": "Remove provider", + "providerType": "Provider", + "providerLabel": "Name", + "providerLabelPlaceholder": "For example: Local Ollama", + "baseUrl": "Server address", + "apiKey": "API key", + "defaultModel": "Default model", + "defaultModelPlaceholder": "For example: llama3.1 or claude-opus-5", + "labelRequired": "Give this provider a name", + "providerSaveFailed": "Could not save the provider", + "providerUpdated": "Provider updated", + "providerDeleteFailed": "Could not remove the provider", + "privateEndpointHint": "Addresses on your private network need an administrator to allow the host first.", + "providerOllama": "Ollama", + "providerAnthropic": "Anthropic", + "providerOpenai": "OpenAI", + "providerGemini": "Google Gemini", + "providerOpenaiCompatible": "OpenAI compatible", + "toolArguments": "Input", + "toolResult": "Result", + "statusApplied": "Applied", + "statusRejected": "Rejected", + "proposalApplied": "Change applied", + "proposalApplyFailed": "Could not apply the change", + "proposalRejectFailed": "Could not reject the change", + "enableTitle": "Enable the AI assistant", + "enableDescription": "Let the assistant read your setup and suggest changes for you to approve.", + "readOnlyCommands": "Allow read-only diagnostic commands", + "readOnlyCommandsDescription": "The assistant may run a short list of safe commands like df and uptime without asking each time. Anything that changes a server is always proposed first.", + "modelDetectFailed": "Could not reach the provider, so this is a general list. You can type any model name.", + "modelCustom": "Enter a model name", + "modelRefresh": "Refresh list", + "modelPlaceholder": "Choose or type a model", + "attachHint": "Type @ to reference a host, snippet or automation. Changes are proposed for you to approve.", + "runCommandTitle": "Run command", + "assistant": "AI Assistant", + "terminalPanelEmpty": "Ask the assistant about this host. Anything that changes state needs your approval first.", + "terminalPanelPlaceholder": "Ask about this host...", + "noProvidersConfigured": "No AI provider is configured yet. Add one in the AI assistant tab.", + "runsInOpenTerminal": "Runs in your open terminal session.", + "runInTerminal": "Run", + "terminalContextPrefill": "Here is my terminal output:\n\n{{output}}\n\n", + "secrets": { + "shareApiKey": "Let other plugins use your AI provider API key for their own requests. The key is never copied, and you can revoke this at any time." + } + }, + "nav": { + "ai": "AI" + }, + "onboarding": { + "aiTitle": "AI assistant", + "aiIntro": "Termix can include an optional AI assistant. You can change this later in your settings.", + "aiSkipTitle": "Leave it off", + "aiSkipDesc": "Termix works as it does now. The assistant stays hidden.", + "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." + }, + "admin": { + "aiGloballyEnabled": "AI assistant", + "aiGloballyEnabledDesc": "Let users turn on the AI assistant. While this is off, the assistant is hidden and blocked for everyone.", + "aiPrivateEndpoints": "Allowed private AI hosts", + "aiPrivateEndpointsDesc": "Hosts on your private network that users may point a provider at, such as a self-hosted Ollama. Separate them with commas.", + "updateAiEnabledFailed": "Could not update the AI setting", + "updateAiEndpointsFailed": "Could not update the allowed hosts" + } +} diff --git a/plugins/ai/locales/translated/af_ZA.json b/plugins/ai/locales/translated/af_ZA.json new file mode 100644 index 000000000..763374548 --- /dev/null +++ b/plugins/ai/locales/translated/af_ZA.json @@ -0,0 +1,78 @@ +{ + "ai": { + "title": "Assistent", + "send": "Stuur", + "stop": "Stop", + "save": "Stoor", + "cancel": "Kanselleer", + "running": "hardloop", + "approve": "Goedkeur", + "reject": "Verwerp", + "inputPlaceholder": "Vra oor jou bedieners, of beskryf 'n verandering om voor te stel", + "selectProvider": "Kies 'n verskaffer", + "providerSettings": "Verskafferinstellings", + "addProvider": "Voeg verskaffer by", + "editProvider": "Wysig verskaffer", + "removeProvider": "Verwyder verskaffer", + "providerType": "Verskaffer", + "providerLabel": "Naam", + "providerLabelPlaceholder": "Byvoorbeeld: Plaaslike Ollama", + "baseUrl": "Bedieneradres", + "apiKey": "API-sleutel", + "defaultModel": "Standaardmodel", + "defaultModelPlaceholder": "Byvoorbeeld: llama3.1 of claude-opus-5", + "labelRequired": "Gee hierdie verskaffer 'n naam", + "providerSaveFailed": "Kon nie die verskaffer stoor nie", + "providerUpdated": "Verskaffer opgedateer", + "providerDeleteFailed": "Kon nie die verskaffer verwyder nie", + "privateEndpointHint": "Adresse op jou private netwerk benodig eers 'n administrateur om die gasheer toe te laat.", + "providerOllama": "Ollama", + "providerAnthropic": "Antropiese", + "providerOpenai": "OpenAI", + "providerGemini": "Google Tweeling", + "providerOpenaiCompatible": "OpenAI-versoenbaar", + "toolArguments": "Invoer", + "toolResult": "Resultaat", + "statusApplied": "Toegepas", + "statusRejected": "Verwerp", + "proposalApplied": "Verandering toegepas", + "proposalApplyFailed": "Kon nie die verandering toepas nie", + "proposalRejectFailed": "Kon nie die verandering verwerp nie", + "enableTitle": "Aktiveer die KI-assistent", + "enableDescription": "Laat die assistent jou opstelling lees en veranderinge voorstel wat jy kan goedkeur.", + "readOnlyCommands": "Laat leesalleen-diagnostiese bevele toe", + "readOnlyCommandsDescription": "Die assistent kan 'n kort lys veilige opdragte soos df en uptime uitvoer sonder om elke keer te vra. Enigiets wat 'n bediener verander, word altyd eerste voorgestel.", + "modelDetectFailed": "Kon nie die verskaffer bereik nie, so dit is 'n algemene lys. Jy kan enige modelnaam tik.", + "modelCustom": "Voer 'n modelnaam in", + "modelRefresh": "Verfris lys", + "modelPlaceholder": "Kies of tik 'n model", + "attachHint": "Tik @ om na 'n gasheer, brokkie of outomatisering te verwys. Veranderinge word voorgestel vir jou om goed te keur.", + "runCommandTitle": "Voer opdrag uit", + "assistant": "KI-assistent", + "terminalPanelEmpty": "Vra die assistent oor hierdie gasheer. Enigiets wat van status verander, benodig eers jou goedkeuring.", + "terminalPanelPlaceholder": "Vra oor hierdie gasheer...", + "noProvidersConfigured": "Geen KI-verskaffer is nog gekonfigureer nie. Voeg een by in die KI-assistent-oortjie.", + "runsInOpenTerminal": "Loop in jou oop terminaalsessie.", + "runInTerminal": "Hardloop" + }, + "nav": { + "ai": "KI" + }, + "onboarding": { + "aiTitle": "KI-assistent", + "aiIntro": "Termix kan 'n opsionele KI-assistent insluit. Jy kan dit later in jou instellings verander.", + "aiSkipTitle": "Los dit af", + "aiSkipDesc": "Termix werk soos dit nou doen. Die assistent bly versteek.", + "aiEnableTitle": "Skakel dit aan", + "aiEnableDesc": "Voeg 'n assistent by wat jou opstelling lees en veranderinge voorstel wat jy goedkeur. Benodig 'n verskaffer wat jy verskaf, soos 'n plaaslike Ollama.", + "aiNote": "Niks word êrens heen gestuur totdat jy 'n verskaffer byvoeg en 'n boodskap stuur nie." + }, + "admin": { + "aiGloballyEnabled": "KI-assistent", + "aiGloballyEnabledDesc": "Laat gebruikers die KI-assistent aanskakel. Terwyl dit af is, is die assistent vir almal versteek en geblokkeer.", + "aiPrivateEndpoints": "Toegelate private KI-gashere", + "aiPrivateEndpointsDesc": "Gashere op jou privaat netwerk waarna gebruikers 'n verskaffer kan verwys, soos 'n self-gehoste Ollama. Skei hulle met kommas.", + "updateAiEnabledFailed": "Kon nie die KI-instelling opdateer nie", + "updateAiEndpointsFailed": "Kon nie die toegelate gashere opdateer nie" + } +} diff --git a/plugins/ai/locales/translated/ar_SA.json b/plugins/ai/locales/translated/ar_SA.json new file mode 100644 index 000000000..9c1fd3f99 --- /dev/null +++ b/plugins/ai/locales/translated/ar_SA.json @@ -0,0 +1,78 @@ +{ + "ai": { + "title": "مساعد", + "send": "يرسل", + "stop": "قف", + "save": "يحفظ", + "cancel": "يلغي", + "running": "جري", + "approve": "يعتمد", + "reject": "يرفض", + "inputPlaceholder": "استفسر عن خوادمك، أو صف تغييرًا ترغب في اقتراحه.", + "selectProvider": "اختر مزود الخدمة", + "providerSettings": "إعدادات المزوّد", + "addProvider": "إضافة موفر", + "editProvider": "موفر التحرير", + "removeProvider": "إزالة الموفر", + "providerType": "مزود", + "providerLabel": "اسم", + "providerLabelPlaceholder": "على سبيل المثال: أولاما المحلي", + "baseUrl": "عنوان الخادم", + "apiKey": "مفتاح API", + "defaultModel": "النموذج الافتراضي", + "defaultModelPlaceholder": "على سبيل المثال: llama3.1 أو claude-opus-5", + "labelRequired": "أعطِ هذا المزوّد اسمًا", + "providerSaveFailed": "تعذر حفظ بيانات المزوّد", + "providerUpdated": "تم تحديث المزوّد", + "providerDeleteFailed": "تعذر إزالة الموفر", + "privateEndpointHint": "تحتاج العناوين الموجودة على شبكتك الخاصة إلى موافقة المسؤول أولاً للسماح للمضيف بالوصول إليها.", + "providerOllama": "أولاما", + "providerAnthropic": "الأنثروبيك", + "providerOpenai": "أوبن إيه آي", + "providerGemini": "جوجل جيميني", + "providerOpenaiCompatible": "متوافق مع OpenAI", + "toolArguments": "مدخل", + "toolResult": "نتيجة", + "statusApplied": "مُطبَّق", + "statusRejected": "مرفوض", + "proposalApplied": "تم تطبيق التغيير", + "proposalApplyFailed": "تعذر تطبيق التغيير", + "proposalRejectFailed": "لم يكن بالإمكان رفض التغيير", + "enableTitle": "قم بتفعيل مساعد الذكاء الاصطناعي", + "enableDescription": "دع المساعد يقرأ إعداداتك ويقترح تغييرات لتوافق عليها.", + "readOnlyCommands": "السماح بأوامر التشخيص للقراءة فقط", + "readOnlyCommandsDescription": "قد يقوم المساعد بتشغيل قائمة مختصرة من الأوامر الآمنة مثل df و uptime دون الحاجة إلى طلب ذلك في كل مرة. ويتم اقتراح أي أمر يُغيّر حالة الخادم أولاً.", + "modelDetectFailed": "تعذر الوصول إلى المورّد، لذا فهذه قائمة عامة. يمكنك كتابة أي اسم طراز.", + "modelCustom": "أدخل اسم النموذج", + "modelRefresh": "تحديث القائمة", + "modelPlaceholder": "اختر أو اكتب طرازًا", + "attachHint": "اكتب @ للإشارة إلى مضيف أو مقتطف أو عملية آلية. سيتم اقتراح تغييرات عليك الموافقة عليها.", + "runCommandTitle": "تشغيل الأمر", + "assistant": "مساعد الذكاء الاصطناعي", + "terminalPanelEmpty": "استفسر من المساعد عن هذا المضيف. أي تغيير في حالته يتطلب موافقتك أولاً.", + "terminalPanelPlaceholder": "اسأل عن هذا المضيف...", + "noProvidersConfigured": "لم يتم إعداد أي موفر للذكاء الاصطناعي حتى الآن. أضف واحداً في علامة تبويب مساعد الذكاء الاصطناعي.", + "runsInOpenTerminal": "يتم تشغيله في جلسة الطرفية المفتوحة لديك.", + "runInTerminal": "يجري" + }, + "nav": { + "ai": "الذكاء الاصطناعي" + }, + "onboarding": { + "aiTitle": "مساعد الذكاء الاصطناعي", + "aiIntro": "يمكن أن يتضمن تطبيق Termix مساعدًا ذكيًا اختياريًا. يمكنك تغيير هذا الخيار لاحقًا من الإعدادات.", + "aiSkipTitle": "اتركه مغلقًا", + "aiSkipDesc": "يعمل برنامج Termix كما هو الآن. ويبقى المساعد مخفياً.", + "aiEnableTitle": "قم بتشغيله", + "aiEnableDesc": "يُضيف هذا البرنامج مساعدًا يقرأ إعداداتك ويقترح تغييرات توافق عليها. يتطلب ذلك مزود خدمة تُحدده بنفسك، مثل مزود خدمة Ollama محلي.", + "aiNote": "لن يتم إرسال أي شيء إلى أي مكان حتى تقوم بإضافة مزود خدمة وإرسال رسالة." + }, + "admin": { + "aiGloballyEnabled": "مساعد الذكاء الاصطناعي", + "aiGloballyEnabledDesc": "اسمح للمستخدمين بتفعيل مساعد الذكاء الاصطناعي. عند إيقاف تشغيله، يكون المساعد مخفيًا ومحظورًا عن الجميع.", + "aiPrivateEndpoints": "المضيفون الخاصون المسموح بهم للذكاء الاصطناعي", + "aiPrivateEndpointsDesc": "المضيفون على شبكتك الخاصة الذين يمكن للمستخدمين توجيه مزود الخدمة إليهم، مثل Ollama المستضاف ذاتيًا. افصل بينهم بفواصل.", + "updateAiEnabledFailed": "تعذر تحديث إعدادات الذكاء الاصطناعي", + "updateAiEndpointsFailed": "تعذر تحديث المضيفين المسموح بهم" + } +} diff --git a/plugins/ai/locales/translated/bg_BG.json b/plugins/ai/locales/translated/bg_BG.json new file mode 100644 index 000000000..63fbc29fb --- /dev/null +++ b/plugins/ai/locales/translated/bg_BG.json @@ -0,0 +1,78 @@ +{ + "ai": { + "title": "Асистент", + "send": "Изпрати", + "stop": "Спри", + "save": "Запазване", + "cancel": "Отказ", + "running": "бягане", + "approve": "Одобряване", + "reject": "Отхвърляне", + "inputPlaceholder": "Попитайте за вашите сървъри или опишете промяна, която да предложите", + "selectProvider": "Изберете доставчик", + "providerSettings": "Настройки на доставчика", + "addProvider": "Добавяне на доставчик", + "editProvider": "Редактиране на доставчика", + "removeProvider": "Премахване на доставчика", + "providerType": "Доставчик", + "providerLabel": "Име", + "providerLabelPlaceholder": "Например: Местна Олама", + "baseUrl": "Адрес на сървъра", + "apiKey": "API ключ", + "defaultModel": "Модел по подразбиране", + "defaultModelPlaceholder": "Например: llama3.1 или claude-opus-5", + "labelRequired": "Дайте име на този доставчик", + "providerSaveFailed": "Доставчикът не можа да бъде запазен", + "providerUpdated": "Доставчикът е актуализиран", + "providerDeleteFailed": "Доставчикът не можа да бъде премахнат", + "privateEndpointHint": "Адресите във вашата частна мрежа се нуждаят първо от администратор, който да разреши хоста.", + "providerOllama": "Олама", + "providerAnthropic": "Антропен", + "providerOpenai": "OpenAI", + "providerGemini": "Google Джемини", + "providerOpenaiCompatible": "Съвместим с OpenAI", + "toolArguments": "Вход", + "toolResult": "Резултат", + "statusApplied": "Приложено", + "statusRejected": "Отхвърлено", + "proposalApplied": "Промяната е приложена", + "proposalApplyFailed": "Промяната не можа да се приложи", + "proposalRejectFailed": "Промяната не можа да бъде отхвърлена", + "enableTitle": "Активирайте AI асистента", + "enableDescription": "Нека асистентът прочете настройката ви и предложи промени, които да одобрите.", + "readOnlyCommands": "Разрешаване на диагностични команди само за четене", + "readOnlyCommandsDescription": "Асистентът може да изпълни кратък списък с безопасни команди като df и uptime, без да пита всеки път. Всичко, което променя сървър, винаги се предлага първо.", + "modelDetectFailed": "Не можахме да се свържем с доставчика, така че това е общ списък. Можете да въведете име на произволен модел.", + "modelCustom": "Въведете име на модел", + "modelRefresh": "Обновяване на списъка", + "modelPlaceholder": "Изберете или въведете модел", + "attachHint": "Въведете @, за да се обърнете към хост, фрагмент или автоматизация. Предлагат се промени за одобрение.", + "runCommandTitle": "Изпълнете командата", + "assistant": "Асистент с изкуствен интелект", + "terminalPanelEmpty": "Попитайте асистента за този хост. Всичко, което променя състоянието, първо изисква вашето одобрение.", + "terminalPanelPlaceholder": "Попитайте за този домакин...", + "noProvidersConfigured": "Все още не е конфигуриран доставчик на ИИ. Добавете такъв в раздела „Асистент за ИИ“.", + "runsInOpenTerminal": "Изпълнява се във вашата отворена терминална сесия.", + "runInTerminal": "Бягане" + }, + "nav": { + "ai": "Изкуствен интелект" + }, + "onboarding": { + "aiTitle": "Асистент с изкуствен интелект", + "aiIntro": "Termix може да включва опционален AI асистент. Можете да промените това по-късно в настройките си.", + "aiSkipTitle": "Остави го изключено", + "aiSkipDesc": "Termix работи както сега. Асистентът остава скрит.", + "aiEnableTitle": "Включете го", + "aiEnableDesc": "Добавя асистент, който чете настройките ви и предлага промени, които одобрявате. Необходим е доставчик, когото вие предоставяте, например местен Ollama.", + "aiNote": "Нищо не се изпраща никъде, докато не добавите доставчик и не изпратите съобщение." + }, + "admin": { + "aiGloballyEnabled": "Асистент с изкуствен интелект", + "aiGloballyEnabledDesc": "Позволете на потребителите да включат асистента с изкуствен интелект. Докато това е изключено, асистентът е скрит и блокиран за всички.", + "aiPrivateEndpoints": "Разрешени частни хостове с изкуствен интелект", + "aiPrivateEndpointsDesc": "Хостове във вашата частна мрежа, към които потребителите могат да насочат доставчик, като например самостоятелно хостван Ollama. Разделете ги със запетаи.", + "updateAiEnabledFailed": "Не можа да се актуализира настройката за изкуствен интелект", + "updateAiEndpointsFailed": "Не можаха да се актуализират разрешените хостове" + } +} diff --git a/plugins/ai/locales/translated/bn_BD.json b/plugins/ai/locales/translated/bn_BD.json new file mode 100644 index 000000000..5022e0c27 --- /dev/null +++ b/plugins/ai/locales/translated/bn_BD.json @@ -0,0 +1,78 @@ +{ + "ai": { + "title": "সহকারী", + "send": "পাঠান", + "stop": "থামুন", + "save": "সংরক্ষণ করুন", + "cancel": "বাতিল করুন", + "running": "দৌড়ানো", + "approve": "অনুমোদন করুন", + "reject": "প্রত্যাখ্যান করুন", + "inputPlaceholder": "আপনার সার্ভারগুলো সম্পর্কে জিজ্ঞাসা করুন, অথবা কোনো পরিবর্তনের প্রস্তাব বর্ণনা করুন।", + "selectProvider": "একজন সরবরাহকারী নির্বাচন করুন", + "providerSettings": "প্রদানকারীর সেটিংস", + "addProvider": "প্রদানকারী যোগ করুন", + "editProvider": "সম্পাদনা প্রদানকারী", + "removeProvider": "প্রদানকারীকে অপসারণ করুন", + "providerType": "সরবরাহকারী", + "providerLabel": "নাম", + "providerLabelPlaceholder": "উদাহরণস্বরূপ: স্থানীয় ওলামা", + "baseUrl": "সার্ভারের ঠিকানা", + "apiKey": "এপিআই কী", + "defaultModel": "ডিফল্ট মডেল", + "defaultModelPlaceholder": "উদাহরণস্বরূপ: llama3.1 অথবা claude-opus-5", + "labelRequired": "এই সরবরাহকারীকে একটি নাম দিন", + "providerSaveFailed": "প্রদানকারীকে সংরক্ষণ করা যায়নি", + "providerUpdated": "প্রদানকারী আপডেট করেছেন", + "providerDeleteFailed": "প্রদানকারীকে সরানো যায়নি", + "privateEndpointHint": "আপনার ব্যক্তিগত নেটওয়ার্কের অ্যাড্রেসগুলো ব্যবহার করার জন্য প্রথমে একজন অ্যাডমিনিস্ট্রেটরের কাছ থেকে হোস্টটিকে অনুমতি নিতে হয়।", + "providerOllama": "ওল্লামা", + "providerAnthropic": "অ্যানথ্রোপিক", + "providerOpenai": "ওপেনএআই", + "providerGemini": "গুগল জেমিনি", + "providerOpenaiCompatible": "ওপেনএআই সামঞ্জস্যপূর্ণ", + "toolArguments": "ইনপুট", + "toolResult": "ফলাফল", + "statusApplied": "প্রয়োগ করা হয়েছে", + "statusRejected": "প্রত্যাখ্যাত", + "proposalApplied": "পরিবর্তন প্রয়োগ করা হয়েছে", + "proposalApplyFailed": "পরিবর্তনটি প্রয়োগ করা যায়নি।", + "proposalRejectFailed": "পরিবর্তনটি প্রত্যাখ্যান করা যায়নি", + "enableTitle": "এআই অ্যাসিস্ট্যান্ট সক্রিয় করুন", + "enableDescription": "সহকারীকে আপনার সেটআপটি পড়তে দিন এবং আপনার অনুমোদনের জন্য পরিবর্তনের পরামর্শ দিতে দিন।", + "readOnlyCommands": "শুধুমাত্র পঠনযোগ্য ডায়াগনস্টিক কমান্ডের অনুমতি দিন", + "readOnlyCommandsDescription": "সহকারী প্রতিবার অনুমতি না নিয়েই df এবং uptime-এর মতো কয়েকটি নিরাপদ কমান্ড চালাতে পারে। সার্ভার পরিবর্তন করে এমন যেকোনো কিছু সর্বদা প্রথমে প্রস্তাব করা হয়।", + "modelDetectFailed": "সরবরাহকারীর সাথে যোগাযোগ করা সম্ভব হয়নি, তাই এটি একটি সাধারণ তালিকা। আপনি যেকোনো মডেলের নাম টাইপ করতে পারেন।", + "modelCustom": "একটি মডেলের নাম লিখুন", + "modelRefresh": "তালিকা রিফ্রেশ করুন", + "modelPlaceholder": "একটি মডেল বেছে নিন বা টাইপ করুন", + "attachHint": "কোনো হোস্ট, স্নিপেট বা অটোমেশন উল্লেখ করতে @ টাইপ করুন। আপনার অনুমোদনের জন্য পরিবর্তনগুলো প্রস্তাব করা হবে।", + "runCommandTitle": "রান কমান্ড", + "assistant": "এআই সহকারী", + "terminalPanelEmpty": "এই হোস্ট সম্পর্কে অ্যাসিস্ট্যান্টকে জিজ্ঞাসা করুন। অবস্থা পরিবর্তনের জন্য প্রথমে আপনার অনুমোদন প্রয়োজন।", + "terminalPanelPlaceholder": "এই হোস্ট সম্পর্কে জিজ্ঞাসা করুন...", + "noProvidersConfigured": "এখনো কোনো এআই প্রোভাইডার কনফিগার করা হয়নি। এআই অ্যাসিস্ট্যান্ট ট্যাবে একটি যোগ করুন।", + "runsInOpenTerminal": "আপনার খোলা টার্মিনাল সেশনে চলে।", + "runInTerminal": "দৌড়" + }, + "nav": { + "ai": "এআই" + }, + "onboarding": { + "aiTitle": "এআই সহকারী", + "aiIntro": "টারমিক্সে একটি ঐচ্ছিক এআই অ্যাসিস্ট্যান্ট অন্তর্ভুক্ত থাকতে পারে। আপনি পরবর্তীতে আপনার সেটিংসে এটি পরিবর্তন করতে পারবেন।", + "aiSkipTitle": "এটা ছেড়ে দাও", + "aiSkipDesc": "টারমিক্স এখন যেমন কাজ করে, তেমনই কাজ করে। অ্যাসিস্ট্যান্টটি লুকানো থাকে।", + "aiEnableTitle": "এটা চালু করুন", + "aiEnableDesc": "একজন সহকারী যোগ করে যে আপনার সেটআপ পড়ে এবং আপনার অনুমোদিত পরিবর্তনের পরামর্শ দেয়। এর জন্য আপনার সরবরাহ করা একজন প্রদানকারীর প্রয়োজন, যেমন একজন স্থানীয় ওলামা।", + "aiNote": "আপনি একজন প্রোভাইডার যোগ করে মেসেজ না পাঠানো পর্যন্ত কোথাও কিছু পাঠানো হয় না।" + }, + "admin": { + "aiGloballyEnabled": "এআই সহকারী", + "aiGloballyEnabledDesc": "ব্যবহারকারীদের এআই অ্যাসিস্ট্যান্ট চালু করার সুযোগ দিন। এটি বন্ধ থাকা অবস্থায়, অ্যাসিস্ট্যান্টটি সকলের জন্য লুকানো এবং ব্লক করা থাকবে।", + "aiPrivateEndpoints": "ব্যক্তিগত এআই হোস্ট অনুমোদিত", + "aiPrivateEndpointsDesc": "আপনার প্রাইভেট নেটওয়ার্কের হোস্টগুলো, যেগুলোকে ব্যবহারকারীরা কোনো প্রোভাইডারের দিকে নির্দেশ করতে পারে, যেমন একটি সেলফ-হোস্টেড ওলামা। এগুলোকে কমা দিয়ে আলাদা করুন।", + "updateAiEnabledFailed": "এআই সেটিং আপডেট করা যায়নি", + "updateAiEndpointsFailed": "অনুমোদিত হোস্টগুলি আপডেট করা যায়নি" + } +} diff --git a/plugins/ai/locales/translated/ca_ES.json b/plugins/ai/locales/translated/ca_ES.json new file mode 100644 index 000000000..38c87313f --- /dev/null +++ b/plugins/ai/locales/translated/ca_ES.json @@ -0,0 +1,78 @@ +{ + "ai": { + "title": "Assistent", + "send": "Enviar", + "stop": "Atura", + "save": "Desa", + "cancel": "Cancel·la", + "running": "corrent", + "approve": "Aprova", + "reject": "Rebutja", + "inputPlaceholder": "Pregunteu pels vostres cambrers o descriviu un canvi que vulgueu proposar", + "selectProvider": "Seleccioneu un proveïdor", + "providerSettings": "Configuració del proveïdor", + "addProvider": "Afegeix un proveïdor", + "editProvider": "Edita el proveïdor", + "removeProvider": "Elimina el proveïdor", + "providerType": "Proveïdor", + "providerLabel": "Nom", + "providerLabelPlaceholder": "Per exemple: Ollama local", + "baseUrl": "Adreça del servidor", + "apiKey": "Clau API", + "defaultModel": "Model per defecte", + "defaultModelPlaceholder": "Per exemple: llama3.1 o claude-opus-5", + "labelRequired": "Doneu un nom a aquest proveïdor", + "providerSaveFailed": "No s'ha pogut desar el proveïdor", + "providerUpdated": "Proveïdor actualitzat", + "providerDeleteFailed": "No s'ha pogut eliminar el proveïdor", + "privateEndpointHint": "Les adreces de la vostra xarxa privada necessiten primer que un administrador permeti l'accés a l'amfitrió.", + "providerOllama": "Ollama", + "providerAnthropic": "Antròpic", + "providerOpenai": "OpenAI", + "providerGemini": "Google Bessons", + "providerOpenaiCompatible": "Compatible amb OpenAI", + "toolArguments": "Entrada", + "toolResult": "Resultat", + "statusApplied": "Aplicat", + "statusRejected": "Rebutjat", + "proposalApplied": "Canvi aplicat", + "proposalApplyFailed": "No s'ha pogut aplicar el canvi", + "proposalRejectFailed": "No s'ha pogut rebutjar el canvi", + "enableTitle": "Activa l'assistent d'IA", + "enableDescription": "Deixa que l'assistent llegeixi la teva configuració i et suggereixi canvis perquè els aprovis.", + "readOnlyCommands": "Permetre ordres de diagnòstic de només lectura", + "readOnlyCommandsDescription": "L'assistent pot executar una llista curta d'ordres segures com ara df i uptime sense preguntar cada vegada. Qualsevol cosa que canviï un servidor sempre es proposa primer.", + "modelDetectFailed": "No s'ha pogut contactar amb el proveïdor, per tant, aquesta és una llista general. Podeu escriure qualsevol nom de model.", + "modelCustom": "Introduïu un nom de model", + "modelRefresh": "Actualitza la llista", + "modelPlaceholder": "Trieu o escriviu un model", + "attachHint": "Escriviu @ per fer referència a un host, fragment o automatització. Es proposen canvis perquè els aprovi.", + "runCommandTitle": "Executa l'ordre", + "assistant": "Assistent d'IA", + "terminalPanelEmpty": "Pregunta a l'assistent sobre aquest amfitrió. Qualsevol cosa que canviï d'estat necessita primer la teva aprovació.", + "terminalPanelPlaceholder": "Pregunta per aquest amfitrió...", + "noProvidersConfigured": "Encara no hi ha cap proveïdor d'IA configurat. Afegeix-ne un a la pestanya Assistent d'IA.", + "runsInOpenTerminal": "S'executa a la sessió de terminal oberta.", + "runInTerminal": "Corre" + }, + "nav": { + "ai": "IA" + }, + "onboarding": { + "aiTitle": "Assistent d'IA", + "aiIntro": "Termix pot incloure un assistent d'IA opcional. Pots canviar-ho més tard a la configuració.", + "aiSkipTitle": "Deixa-ho fora", + "aiSkipDesc": "Termix funciona com ho fa ara. L'assistent roman ocult.", + "aiEnableTitle": "Engega-ho", + "aiEnableDesc": "Afegeix un assistent que llegeix la configuració i suggereix els canvis que aproveu. Necessita un proveïdor que subministreu, com ara un Ollama local.", + "aiNote": "No s'envia res enlloc fins que no afegiu un proveïdor i envieu un missatge." + }, + "admin": { + "aiGloballyEnabled": "Assistent d'IA", + "aiGloballyEnabledDesc": "Permet que els usuaris activin l'assistent d'IA. Mentre estigui desactivat, l'assistent està ocult i bloquejat per a tothom.", + "aiPrivateEndpoints": "Amfitrions d'IA privats permesos", + "aiPrivateEndpointsDesc": "Amfitrions de la vostra xarxa privada als quals els usuaris poden dirigir un proveïdor, com ara un Ollama autoallotjat. Separeu-los amb comes.", + "updateAiEnabledFailed": "No s'ha pogut actualitzar la configuració de la IA", + "updateAiEndpointsFailed": "No s'han pogut actualitzar els amfitrions permesos" + } +} diff --git a/plugins/ai/locales/translated/cs_CZ.json b/plugins/ai/locales/translated/cs_CZ.json new file mode 100644 index 000000000..43e5ba12a --- /dev/null +++ b/plugins/ai/locales/translated/cs_CZ.json @@ -0,0 +1,78 @@ +{ + "ai": { + "title": "Asistent", + "send": "Poslat", + "stop": "Zastávka", + "save": "Uložit", + "cancel": "Zrušit", + "running": "běh", + "approve": "Schvalovat", + "reject": "Odmítnout", + "inputPlaceholder": "Zeptejte se na své servery nebo popište změnu, kterou chcete navrhnout", + "selectProvider": "Vyberte poskytovatele", + "providerSettings": "Nastavení poskytovatele", + "addProvider": "Přidat poskytovatele", + "editProvider": "Upravit poskytovatele", + "removeProvider": "Odebrat poskytovatele", + "providerType": "Poskytovatel", + "providerLabel": "Jméno", + "providerLabelPlaceholder": "Například: Místní Ollama", + "baseUrl": "Adresa serveru", + "apiKey": "Klíč API", + "defaultModel": "Výchozí model", + "defaultModelPlaceholder": "Například: llama3.1 nebo claude-opus-5", + "labelRequired": "Zadejte tomuto poskytovateli název", + "providerSaveFailed": "Nepodařilo se uložit poskytovatele", + "providerUpdated": "Poskytovatel aktualizován", + "providerDeleteFailed": "Nepodařilo se odebrat poskytovatele", + "privateEndpointHint": "Adresy ve vaší privátní síti vyžadují, aby je správce nejprve povolil hostiteli.", + "providerOllama": "Ollama", + "providerAnthropic": "Antropický", + "providerOpenai": "OpenAI", + "providerGemini": "Google Gemini", + "providerOpenaiCompatible": "Kompatibilní s OpenAI", + "toolArguments": "Vstup", + "toolResult": "Výsledek", + "statusApplied": "Aplikovaný", + "statusRejected": "Zamítnuto", + "proposalApplied": "Změna použita", + "proposalApplyFailed": "Změnu se nepodařilo použít", + "proposalRejectFailed": "Změnu se nepodařilo odmítnout", + "enableTitle": "Povolte asistenta s umělou inteligencí", + "enableDescription": "Nechte asistenta přečíst si vaše nastavení a navrhnout změny ke schválení.", + "readOnlyCommands": "Povolit diagnostické příkazy pouze pro čtení", + "readOnlyCommandsDescription": "Asistent může spustit krátký seznam bezpečných příkazů, jako například df a uptime, aniž by se pokaždé ptal. Vše, co mění server, je vždy navrženo jako první.", + "modelDetectFailed": "Nepodařilo se mi spojit s poskytovatelem, toto je obecný seznam. Můžete zadat libovolný název modelu.", + "modelCustom": "Zadejte název modelu", + "modelRefresh": "Obnovit seznam", + "modelPlaceholder": "Vyberte nebo zadejte model", + "attachHint": "Zadejte @ pro odkaz na hostitele, úryvek kódu nebo automatizaci. Změny jsou navrženy ke schválení.", + "runCommandTitle": "Spustit příkaz", + "assistant": "Asistent umělé inteligence", + "terminalPanelEmpty": "Zeptejte se asistenta na tohoto hostitele. Jakákoli změna stavu vyžaduje váš první souhlas.", + "terminalPanelPlaceholder": "Zeptejte se na tohoto hostitele...", + "noProvidersConfigured": "Zatím není nakonfigurován žádný poskytovatel AI. Přidejte ho na kartě Asistent AI.", + "runsInOpenTerminal": "Spustí se ve vaší otevřené terminálové relaci.", + "runInTerminal": "Běh" + }, + "nav": { + "ai": "Umělá inteligence" + }, + "onboarding": { + "aiTitle": "Asistent s umělou inteligencí", + "aiIntro": "Termix může obsahovat volitelného asistenta s umělou inteligencí. Toto můžete později změnit v nastavení.", + "aiSkipTitle": "Nech to být", + "aiSkipDesc": "Termix funguje stejně jako teď. Asistent zůstává skrytý.", + "aiEnableTitle": "Zapněte to", + "aiEnableDesc": "Přidá asistenta, který si přečte vaše nastavení a navrhne změny, které schválíte. Vyžaduje poskytovatele, kterého dodáte, například místní Ollamu.", + "aiNote": "Nic se nikam neodesílá, dokud nepřidáte poskytovatele a neodešlete zprávu." + }, + "admin": { + "aiGloballyEnabled": "Asistent s umělou inteligencí", + "aiGloballyEnabledDesc": "Umožněte uživatelům zapnout asistenta s umělou inteligencí. Pokud je tato funkce vypnutá, asistent je skrytý a blokovaný pro všechny.", + "aiPrivateEndpoints": "Povolení soukromí hostitelé s umělou inteligencí", + "aiPrivateEndpointsDesc": "Hostitelé ve vaší privátní síti, na které mohou uživatelé odkazovat poskytovatele, například samostatně hostovaný Ollama. Oddělte je čárkami.", + "updateAiEnabledFailed": "Nepodařilo se aktualizovat nastavení umělé inteligence", + "updateAiEndpointsFailed": "Nepodařilo se aktualizovat povolené hostitele" + } +} diff --git a/plugins/ai/locales/translated/da_DK.json b/plugins/ai/locales/translated/da_DK.json new file mode 100644 index 000000000..8a0697998 --- /dev/null +++ b/plugins/ai/locales/translated/da_DK.json @@ -0,0 +1,78 @@ +{ + "ai": { + "title": "Assistent", + "send": "Sende", + "stop": "Stop", + "save": "Spare", + "cancel": "Ophæve", + "running": "løb", + "approve": "Godkende", + "reject": "Afvise", + "inputPlaceholder": "Spørg om dine servere, eller beskriv en ændring, du vil foreslå", + "selectProvider": "Vælg en udbyder", + "providerSettings": "Udbyderindstillinger", + "addProvider": "Tilføj udbyder", + "editProvider": "Rediger udbyder", + "removeProvider": "Fjern udbyder", + "providerType": "Udbyder", + "providerLabel": "Navn", + "providerLabelPlaceholder": "For eksempel: Lokal Ollama", + "baseUrl": "Serveradresse", + "apiKey": "API-nøgle", + "defaultModel": "Standardmodel", + "defaultModelPlaceholder": "For eksempel: llama3.1 eller claude-opus-5", + "labelRequired": "Giv denne udbyder et navn", + "providerSaveFailed": "Udbyderen kunne ikke gemmes", + "providerUpdated": "Udbyder opdateret", + "providerDeleteFailed": "Udbyderen kunne ikke fjernes", + "privateEndpointHint": "Adresser på dit private netværk kræver først tilladelse fra en administrator til værten.", + "providerOllama": "Ollama", + "providerAnthropic": "Antropisk", + "providerOpenai": "OpenAI", + "providerGemini": "Google Gemini", + "providerOpenaiCompatible": "OpenAI-kompatibel", + "toolArguments": "Input", + "toolResult": "Resultat", + "statusApplied": "Anvendt", + "statusRejected": "Afvist", + "proposalApplied": "Ændring anvendt", + "proposalApplyFailed": "Ændringen kunne ikke anvendes", + "proposalRejectFailed": "Kunne ikke afvise ændringen", + "enableTitle": "Aktivér AI-assistenten", + "enableDescription": "Lad assistenten læse din opsætning og foreslå ændringer, som du kan godkende.", + "readOnlyCommands": "Tillad skrivebeskyttede diagnosticeringskommandoer", + "readOnlyCommandsDescription": "Assistenten kan køre en kort liste med sikre kommandoer som f.eks. df og uptime uden at spørge hver gang. Alt, der ændrer en server, foreslås altid først.", + "modelDetectFailed": "Kunne ikke få kontakt med udbyderen, så dette er en generel liste. Du kan skrive et hvilket som helst modelnavn.", + "modelCustom": "Indtast et modelnavn", + "modelRefresh": "Opdater listen", + "modelPlaceholder": "Vælg eller skriv en model", + "attachHint": "Skriv @ for at referere til en vært, et kodestykke eller en automatisering. Ændringer foreslås, som du skal godkende.", + "runCommandTitle": "Kør kommando", + "assistant": "AI-assistent", + "terminalPanelEmpty": "Spørg assistenten om denne vært. Alt, der ændrer status, kræver din godkendelse først.", + "terminalPanelPlaceholder": "Spørg om denne vært...", + "noProvidersConfigured": "Der er endnu ikke konfigureret nogen AI-udbyder. Tilføj en i fanen AI-assistent.", + "runsInOpenTerminal": "Kører i din åbne terminalsession.", + "runInTerminal": "Løbe" + }, + "nav": { + "ai": "AI" + }, + "onboarding": { + "aiTitle": "AI-assistent", + "aiIntro": "Termix kan inkludere en valgfri AI-assistent. Du kan ændre dette senere i dine indstillinger.", + "aiSkipTitle": "Lad det være slukket", + "aiSkipDesc": "Termix fungerer som den gør nu. Assistenten forbliver skjult.", + "aiEnableTitle": "Tænd den", + "aiEnableDesc": "Tilføjer en assistent, der læser din opsætning og foreslår ændringer, du godkender. Kræver en udbyder, du angiver, f.eks. en lokal Ollama.", + "aiNote": "Intet sendes nogen steder, før du tilføjer en udbyder og sender en besked." + }, + "admin": { + "aiGloballyEnabled": "AI-assistent", + "aiGloballyEnabledDesc": "Lad brugerne aktivere AI-assistenten. Når dette er slået fra, er assistenten skjult og blokeret for alle.", + "aiPrivateEndpoints": "Tilladte private AI-værter", + "aiPrivateEndpointsDesc": "Værter på dit private netværk, som brugerne kan henvise til en udbyder, f.eks. en selvhostet Ollama. Adskil dem med kommaer.", + "updateAiEnabledFailed": "Kunne ikke opdatere AI-indstillingen", + "updateAiEndpointsFailed": "Kunne ikke opdatere de tilladte værter" + } +} diff --git a/plugins/ai/locales/translated/de_DE.json b/plugins/ai/locales/translated/de_DE.json new file mode 100644 index 000000000..62468dfe5 --- /dev/null +++ b/plugins/ai/locales/translated/de_DE.json @@ -0,0 +1,78 @@ +{ + "ai": { + "title": "Assistent", + "send": "Schicken", + "stop": "Stoppen", + "save": "Speichern", + "cancel": "Stornieren", + "running": "läuft", + "approve": "Genehmigen", + "reject": "Ablehnen", + "inputPlaceholder": "Erkundigen Sie sich nach Ihren Servern oder beschreiben Sie einen Änderungsvorschlag.", + "selectProvider": "Wählen Sie einen Anbieter aus", + "providerSettings": "Anbietereinstellungen", + "addProvider": "Anbieter hinzufügen", + "editProvider": "Anbieter bearbeiten", + "removeProvider": "Anbieter entfernen", + "providerType": "Anbieter", + "providerLabel": "Name", + "providerLabelPlaceholder": "Zum Beispiel: Lokaler Ollama", + "baseUrl": "Serveradresse", + "apiKey": "API-Schlüssel", + "defaultModel": "Standardmodell", + "defaultModelPlaceholder": "Zum Beispiel: llama3.1 oder claude-opus-5", + "labelRequired": "Geben Sie diesem Anbieter einen Namen", + "providerSaveFailed": "Der Anbieter konnte nicht gespeichert werden.", + "providerUpdated": "Anbieter aktualisiert", + "providerDeleteFailed": "Der Anbieter konnte nicht entfernt werden.", + "privateEndpointHint": "Adressen in Ihrem privaten Netzwerk benötigen eine vorherige Genehmigung durch einen Administrator.", + "providerOllama": "Ollama", + "providerAnthropic": "Anthropisch", + "providerOpenai": "OpenAI", + "providerGemini": "Google Gemini", + "providerOpenaiCompatible": "OpenAI-kompatibel", + "toolArguments": "Eingang", + "toolResult": "Ergebnis", + "statusApplied": "Angewandt", + "statusRejected": "Abgelehnt", + "proposalApplied": "Änderung angewendet", + "proposalApplyFailed": "Die Änderung konnte nicht angewendet werden.", + "proposalRejectFailed": "Die Änderung konnte nicht abgelehnt werden.", + "enableTitle": "Aktivieren Sie den KI-Assistenten", + "enableDescription": "Lassen Sie den Assistenten Ihre Einstellungen lesen und Ihnen Änderungen zur Genehmigung vorschlagen.", + "readOnlyCommands": "Zulassen von schreibgeschützten Diagnosebefehlen", + "readOnlyCommandsDescription": "Der Assistent kann eine kurze Liste sicherer Befehle wie df und uptime ausführen, ohne jedes Mal nachzufragen. Alle Änderungen, die einen Server betreffen, werden immer zuerst vorgeschlagen.", + "modelDetectFailed": "Der Anbieter konnte nicht erreicht werden, daher handelt es sich um eine allgemeine Liste. Sie können einen beliebigen Modellnamen eingeben.", + "modelCustom": "Geben Sie einen Modellnamen ein", + "modelRefresh": "Liste aktualisieren", + "modelPlaceholder": "Wählen Sie ein Modell aus oder geben Sie es ein.", + "attachHint": "Geben Sie @ ein, um auf einen Host, ein Code-Snippet oder eine Automatisierung zu verweisen. Die Änderungen werden Ihnen zur Genehmigung vorgeschlagen.", + "runCommandTitle": "Befehl ausführen", + "assistant": "KI-Assistent", + "terminalPanelEmpty": "Fragen Sie den Assistenten nach diesem Gastgeber. Jede Statusänderung bedarf Ihrer vorherigen Zustimmung.", + "terminalPanelPlaceholder": "Erkundigen Sie sich nach diesem Gastgeber...", + "noProvidersConfigured": "Es ist noch kein KI-Anbieter konfiguriert. Fügen Sie einen im Tab „KI-Assistent“ hinzu.", + "runsInOpenTerminal": "Wird in Ihrer geöffneten Terminal-Sitzung ausgeführt.", + "runInTerminal": "Laufen" + }, + "nav": { + "ai": "KI" + }, + "onboarding": { + "aiTitle": "KI-Assistent", + "aiIntro": "Termix kann optional einen KI-Assistenten beinhalten. Sie können dies später in Ihren Einstellungen ändern.", + "aiSkipTitle": "Lass es weg", + "aiSkipDesc": "Termix funktioniert wie bisher. Der Assistent bleibt verborgen.", + "aiEnableTitle": "Schalte es ein", + "aiEnableDesc": "Fügt einen Assistenten hinzu, der Ihre Einstellungen analysiert und Ihnen von Ihnen genehmigte Änderungen vorschlägt. Benötigt einen von Ihnen angegebenen Anbieter, z. B. einen lokalen Ollama-Händler.", + "aiNote": "Es wird nichts gesendet, bis Sie einen Anbieter hinzufügen und eine Nachricht senden." + }, + "admin": { + "aiGloballyEnabled": "KI-Assistent", + "aiGloballyEnabledDesc": "Ermöglichen Sie den Nutzern, den KI-Assistenten zu aktivieren. Solange diese Option deaktiviert ist, ist der Assistent für alle ausgeblendet und gesperrt.", + "aiPrivateEndpoints": "Zulässige private KI-Hosts", + "aiPrivateEndpointsDesc": "Hosts in Ihrem privaten Netzwerk, auf die Benutzer einen Provider verweisen können, wie z. B. ein selbst gehostetes Ollama. Trennen Sie diese durch Kommas.", + "updateAiEnabledFailed": "Die KI-Einstellungen konnten nicht aktualisiert werden.", + "updateAiEndpointsFailed": "Die Liste der zulässigen Hosts konnte nicht aktualisiert werden." + } +} diff --git a/plugins/ai/locales/translated/el_GR.json b/plugins/ai/locales/translated/el_GR.json new file mode 100644 index 000000000..beba7d035 --- /dev/null +++ b/plugins/ai/locales/translated/el_GR.json @@ -0,0 +1,78 @@ +{ + "ai": { + "title": "Βοηθός", + "send": "Στέλνω", + "stop": "Στάση", + "save": "Εκτός", + "cancel": "Ματαίωση", + "running": "τρέξιμο", + "approve": "Εγκρίνω", + "reject": "Απορρίπτω", + "inputPlaceholder": "Ρωτήστε για τους διακομιστές σας ή περιγράψτε μια αλλαγή που προτείνετε", + "selectProvider": "Επιλέξτε έναν πάροχο", + "providerSettings": "Ρυθμίσεις παρόχου", + "addProvider": "Προσθήκη παρόχου", + "editProvider": "Επεξεργασία παρόχου", + "removeProvider": "Κατάργηση παρόχου", + "providerType": "Προμηθευτής", + "providerLabel": "Ονομα", + "providerLabelPlaceholder": "Για παράδειγμα: Τοπικό Ollama", + "baseUrl": "Διεύθυνση διακομιστή", + "apiKey": "Κλειδί API", + "defaultModel": "Προεπιλεγμένο μοντέλο", + "defaultModelPlaceholder": "Για παράδειγμα: llama3.1 ή claude-opus-5", + "labelRequired": "Δώστε σε αυτόν τον πάροχο ένα όνομα", + "providerSaveFailed": "Δεν ήταν δυνατή η αποθήκευση του παρόχου", + "providerUpdated": "Ο πάροχος ενημερώθηκε", + "providerDeleteFailed": "Δεν ήταν δυνατή η κατάργηση του παρόχου", + "privateEndpointHint": "Οι διευθύνσεις στο ιδιωτικό σας δίκτυο χρειάζονται πρώτα έναν διαχειριστή για να επιτρέψει στον κεντρικό υπολογιστή.", + "providerOllama": "Ολάμα", + "providerAnthropic": "Ανθρώπινο", + "providerOpenai": "Ανοιχτή Τεχνητή Νοημοσύνη", + "providerGemini": "Google Gemini", + "providerOpenaiCompatible": "Συμβατό με OpenAI", + "toolArguments": "Εισαγωγή", + "toolResult": "Αποτέλεσμα", + "statusApplied": "Εφαρμοσμένος", + "statusRejected": "Απορρίφθηκε", + "proposalApplied": "Η αλλαγή εφαρμόστηκε", + "proposalApplyFailed": "Δεν ήταν δυνατή η εφαρμογή της αλλαγής", + "proposalRejectFailed": "Δεν ήταν δυνατή η απόρριψη της αλλαγής", + "enableTitle": "Ενεργοποίηση του βοηθού τεχνητής νοημοσύνης", + "enableDescription": "Αφήστε τον βοηθό να διαβάσει τη ρύθμισή σας και να σας προτείνει αλλαγές για έγκριση.", + "readOnlyCommands": "Να επιτρέπονται διαγνωστικές εντολές μόνο για ανάγνωση", + "readOnlyCommandsDescription": "Ο βοηθός μπορεί να εκτελέσει μια σύντομη λίστα ασφαλών εντολών όπως df και uptime χωρίς να ρωτάει κάθε φορά. Οτιδήποτε αλλάζει έναν διακομιστή προτείνεται πάντα πρώτο.", + "modelDetectFailed": "Δεν ήταν δυνατή η επικοινωνία με τον πάροχο, επομένως αυτή είναι μια γενική λίστα. Μπορείτε να πληκτρολογήσετε οποιοδήποτε όνομα μοντέλου.", + "modelCustom": "Εισαγάγετε ένα όνομα μοντέλου", + "modelRefresh": "Ανανέωση λίστας", + "modelPlaceholder": "Επιλέξτε ή πληκτρολογήστε ένα μοντέλο", + "attachHint": "Πληκτρολογήστε @ για να αναφέρετε έναν κεντρικό υπολογιστή, ένα απόσπασμα κώδικα ή έναν αυτοματισμό. Προτείνονται αλλαγές για έγκριση.", + "runCommandTitle": "Εκτέλεση εντολής", + "assistant": "Βοηθός Τεχνητής Νοημοσύνης", + "terminalPanelEmpty": "Ρωτήστε τον βοηθό σχετικά με αυτόν τον οικοδεσπότη. Οτιδήποτε αλλάζει κατάσταση χρειάζεται πρώτα την έγκρισή σας.", + "terminalPanelPlaceholder": "Ρωτήστε για αυτόν τον οικοδεσπότη...", + "noProvidersConfigured": "Δεν έχει διαμορφωθεί ακόμη πάροχος τεχνητής νοημοσύνης. Προσθέστε έναν στην καρτέλα βοηθού τεχνητής νοημοσύνης.", + "runsInOpenTerminal": "Εκτελείται στην ανοιχτή συνεδρία τερματικού σας.", + "runInTerminal": "Τρέξιμο" + }, + "nav": { + "ai": "Όλα συμπεριλαμβάνονται" + }, + "onboarding": { + "aiTitle": "Βοηθός Τεχνητής Νοημοσύνης", + "aiIntro": "Το Termix μπορεί να περιλαμβάνει έναν προαιρετικό βοηθό τεχνητής νοημοσύνης. Μπορείτε να το αλλάξετε αυτό αργότερα στις ρυθμίσεις σας.", + "aiSkipTitle": "Αφήστε το μακριά", + "aiSkipDesc": "Το Termix λειτουργεί όπως τώρα. Ο βοηθός παραμένει κρυφός.", + "aiEnableTitle": "Ενεργοποίησέ το", + "aiEnableDesc": "Προσθέτει έναν βοηθό που διαβάζει τη ρύθμισή σας και προτείνει αλλαγές που εγκρίνετε. Χρειάζεται έναν πάροχο που παρέχετε, όπως ένα τοπικό Ollama.", + "aiNote": "Τίποτα δεν αποστέλλεται πουθενά μέχρι να προσθέσετε έναν πάροχο και να στείλετε ένα μήνυμα." + }, + "admin": { + "aiGloballyEnabled": "Βοηθός Τεχνητής Νοημοσύνης", + "aiGloballyEnabledDesc": "Επιτρέψτε στους χρήστες να ενεργοποιήσουν τον βοηθό τεχνητής νοημοσύνης. Όσο είναι απενεργοποιημένος, ο βοηθός είναι κρυφός και αποκλεισμένος για όλους.", + "aiPrivateEndpoints": "Επιτρεπόμενοι ιδιωτικοί κεντρικοί υπολογιστές τεχνητής νοημοσύνης", + "aiPrivateEndpointsDesc": "Κεντρικοί υπολογιστές στο ιδιωτικό σας δίκτυο στους οποίους οι χρήστες μπορούν να υποδείξουν έναν πάροχο, όπως ένα αυτοφιλοξενούμενο Ollama. Διαχωρίστε τους με κόμματα.", + "updateAiEnabledFailed": "Δεν ήταν δυνατή η ενημέρωση της ρύθμισης AI", + "updateAiEndpointsFailed": "Δεν ήταν δυνατή η ενημέρωση των επιτρεπόμενων κεντρικών υπολογιστών" + } +} diff --git a/plugins/ai/locales/translated/es_ES.json b/plugins/ai/locales/translated/es_ES.json new file mode 100644 index 000000000..3e64afa90 --- /dev/null +++ b/plugins/ai/locales/translated/es_ES.json @@ -0,0 +1,78 @@ +{ + "ai": { + "title": "Asistente", + "send": "Enviar", + "stop": "Detener", + "save": "Ahorrar", + "cancel": "Cancelar", + "running": "correr", + "approve": "Aprobar", + "reject": "Rechazar", + "inputPlaceholder": "Pregunte sobre sus servidores o describa un cambio para proponer.", + "selectProvider": "Seleccione un proveedor", + "providerSettings": "Configuración del proveedor", + "addProvider": "Agregar proveedor", + "editProvider": "Editar proveedor", + "removeProvider": "Eliminar proveedor", + "providerType": "Proveedor", + "providerLabel": "Nombre", + "providerLabelPlaceholder": "Por ejemplo: Ollama local", + "baseUrl": "Dirección del servidor", + "apiKey": "clave API", + "defaultModel": "Modelo predeterminado", + "defaultModelPlaceholder": "Por ejemplo: llama3.1 o claude-opus-5", + "labelRequired": "Dale un nombre a este proveedor.", + "providerSaveFailed": "No se pudo guardar el proveedor", + "providerUpdated": "Proveedor actualizado", + "providerDeleteFailed": "No se pudo eliminar al proveedor.", + "privateEndpointHint": "Las direcciones de su red privada necesitan que un administrador autorice el acceso al host previamente.", + "providerOllama": "Ollama", + "providerAnthropic": "Antrópico", + "providerOpenai": "OpenAI", + "providerGemini": "Google Gemini", + "providerOpenaiCompatible": "Compatible con OpenAI", + "toolArguments": "Aporte", + "toolResult": "Resultado", + "statusApplied": "Aplicado", + "statusRejected": "Rechazado", + "proposalApplied": "Cambio aplicado", + "proposalApplyFailed": "No se pudo aplicar el cambio.", + "proposalRejectFailed": "No se pudo rechazar el cambio", + "enableTitle": "Habilitar el asistente de IA", + "enableDescription": "Deja que el asistente lea tu configuración y te sugiera cambios para que los apruebes.", + "readOnlyCommands": "Permitir comandos de diagnóstico de solo lectura", + "readOnlyCommandsDescription": "El asistente puede ejecutar una breve lista de comandos seguros, como df y uptime, sin preguntar cada vez. Cualquier cambio que afecte al servidor siempre se propone primero.", + "modelDetectFailed": "No se pudo contactar con el proveedor, por lo que esta es una lista general. Puede escribir cualquier nombre de modelo.", + "modelCustom": "Introduzca un nombre de modelo", + "modelRefresh": "Actualizar lista", + "modelPlaceholder": "Seleccione o escriba un modelo.", + "attachHint": "Escribe @ para hacer referencia a un host, fragmento de código o automatización. Se proponen cambios para su aprobación.", + "runCommandTitle": "Ejecutar comando", + "assistant": "Asistente de IA", + "terminalPanelEmpty": "Consulta con el asistente sobre este anfitrión. Cualquier cambio de estado requiere tu aprobación previa.", + "terminalPanelPlaceholder": "Pregunta por este anfitrión...", + "noProvidersConfigured": "Aún no hay ningún proveedor de IA configurado. Añada uno en la pestaña del asistente de IA.", + "runsInOpenTerminal": "Se ejecuta en tu sesión de terminal abierta.", + "runInTerminal": "Correr" + }, + "nav": { + "ai": "AI" + }, + "onboarding": { + "aiTitle": "Asistente de IA", + "aiIntro": "Termix puede incluir un asistente de IA opcional. Puedes cambiar esto más adelante en la configuración.", + "aiSkipTitle": "Déjalo apagado", + "aiSkipDesc": "Termix funciona como hasta ahora. El asistente permanece oculto.", + "aiEnableTitle": "Enciéndelo", + "aiEnableDesc": "Agrega un asistente que lee tu configuración y sugiere cambios que apruebas. Requiere un proveedor que tú proporciones, como un Ollama local.", + "aiNote": "No se envía nada a ningún sitio hasta que añadas un proveedor y envíes un mensaje." + }, + "admin": { + "aiGloballyEnabled": "Asistente de IA", + "aiGloballyEnabledDesc": "Permita que los usuarios activen el asistente de IA. Mientras esté desactivado, el asistente permanecerá oculto y bloqueado para todos.", + "aiPrivateEndpoints": "Hosts de IA privados permitidos", + "aiPrivateEndpointsDesc": "Hosts en tu red privada a los que los usuarios pueden dirigir un proveedor, como un servidor Ollama autogestionado. Sepáralos con comas.", + "updateAiEnabledFailed": "No se pudo actualizar la configuración de la IA.", + "updateAiEndpointsFailed": "No se pudieron actualizar los hosts permitidos." + } +} diff --git a/plugins/ai/locales/translated/fi_FI.json b/plugins/ai/locales/translated/fi_FI.json new file mode 100644 index 000000000..c385b8e5b --- /dev/null +++ b/plugins/ai/locales/translated/fi_FI.json @@ -0,0 +1,78 @@ +{ + "ai": { + "title": "Assistentti", + "send": "Lähetä", + "stop": "Stop", + "save": "Tallentaa", + "cancel": "Peruuttaa", + "running": "juokseminen", + "approve": "Hyväksyä", + "reject": "Hylätä", + "inputPlaceholder": "Kysy tarjoilijoistasi tai kuvaile ehdottamaasi muutosta", + "selectProvider": "Valitse palveluntarjoaja", + "providerSettings": "Palveluntarjoajan asetukset", + "addProvider": "Lisää palveluntarjoaja", + "editProvider": "Muokkaa palveluntarjoajaa", + "removeProvider": "Poista palveluntarjoaja", + "providerType": "Palveluntarjoaja", + "providerLabel": "Nimi", + "providerLabelPlaceholder": "Esimerkiksi: Paikallinen Ollama", + "baseUrl": "Palvelimen osoite", + "apiKey": "API-avain", + "defaultModel": "Oletusmalli", + "defaultModelPlaceholder": "Esimerkiksi: llama3.1 tai claude-opus-5", + "labelRequired": "Anna tälle palveluntarjoajalle nimi", + "providerSaveFailed": "Palveluntarjoajaa ei voitu tallentaa", + "providerUpdated": "Palveluntarjoaja päivitetty", + "providerDeleteFailed": "Palveluntarjoajaa ei voitu poistaa", + "privateEndpointHint": "Yksityisen verkon osoitteiden ylläpitäjän on ensin sallittava isäntä.", + "providerOllama": "Ollama", + "providerAnthropic": "Antrooppinen", + "providerOpenai": "OpenAI", + "providerGemini": "Google Gemini", + "providerOpenaiCompatible": "OpenAI-yhteensopiva", + "toolArguments": "Syöttö", + "toolResult": "Tulos", + "statusApplied": "Käytetty", + "statusRejected": "Hylätty", + "proposalApplied": "Muutos otettu käyttöön", + "proposalApplyFailed": "Muutosta ei voitu ottaa käyttöön", + "proposalRejectFailed": "Muutosta ei voitu hylätä", + "enableTitle": "Ota tekoälyavustaja käyttöön", + "enableDescription": "Anna avustajan lukea asetuksesi ja ehdottaa muutoksia hyväksyttäväksi.", + "readOnlyCommands": "Salli vain luettavat diagnostiikkakomennot", + "readOnlyCommandsDescription": "Assistantti voi suorittaa lyhyen listan turvallisia komentoja, kuten df ja uptime, kysymättä joka kerta. Kaikki palvelinta muuttavat ehdotukset esitetään aina ensin.", + "modelDetectFailed": "Palveluntarjoajaan ei saatu yhteyttä, joten tämä on yleisluettelo. Voit kirjoittaa minkä tahansa mallin nimen.", + "modelCustom": "Anna mallin nimi", + "modelRefresh": "Päivitä lista", + "modelPlaceholder": "Valitse tai kirjoita malli", + "attachHint": "Kirjoita @ viitataksesi isäntään, koodinpätkään tai automaatioon. Muutoksia ehdotetaan hyväksyttäväksi.", + "runCommandTitle": "Suorita komento", + "assistant": "Tekoälyavustaja", + "terminalPanelEmpty": "Kysy avustajalta tästä majoittajasta. Kaikki osavaltion muutokset vaativat ensin hyväksyntäsi.", + "terminalPanelPlaceholder": "Kysy tästä isännöitsijästä...", + "noProvidersConfigured": "Tekoälypalveluntarjoajaa ei ole vielä määritetty. Lisää sellainen tekoälyavustaja-välilehdellä.", + "runsInOpenTerminal": "Suoritetaan avoimessa pääteistunnossa.", + "runInTerminal": "Juokse" + }, + "nav": { + "ai": "Tekoäly" + }, + "onboarding": { + "aiTitle": "Tekoälyavustaja", + "aiIntro": "Termix voi sisältää valinnaisen tekoälyavustaja. Voit muuttaa tätä myöhemmin asetuksissasi.", + "aiSkipTitle": "Jätä se pois", + "aiSkipDesc": "Termix toimii kuten nytkin. Avustaja pysyy piilossa.", + "aiEnableTitle": "Käynnistä se", + "aiEnableDesc": "Lisää avustajan, joka lukee asetuksesi ja ehdottaa hyväksymiäsi muutoksia. Edellyttää toimittamaasi palveluntarjoajaa, kuten paikallisen Ollaman.", + "aiNote": "Mitään ei lähetetä mihinkään ennen kuin lisäät palveluntarjoajan ja lähetät viestin." + }, + "admin": { + "aiGloballyEnabled": "Tekoälyavustaja", + "aiGloballyEnabledDesc": "Salli käyttäjien ottaa tekoälyavustaja käyttöön. Kun tämä on pois päältä, avustaja on piilotettu ja estetty kaikilta.", + "aiPrivateEndpoints": "Sallitut yksityiset tekoälyisännät", + "aiPrivateEndpointsDesc": "Yksityisen verkon isännät, joihin käyttäjät voivat ohjata palveluntarjoajan, kuten itse isännöity Ollama. Erota ne pilkuilla.", + "updateAiEnabledFailed": "Tekoälyasetuksen päivittäminen epäonnistui", + "updateAiEndpointsFailed": "Sallittujen isäntien päivittäminen epäonnistui" + } +} diff --git a/plugins/ai/locales/translated/fr_FR.json b/plugins/ai/locales/translated/fr_FR.json new file mode 100644 index 000000000..ae54cb28b --- /dev/null +++ b/plugins/ai/locales/translated/fr_FR.json @@ -0,0 +1,78 @@ +{ + "ai": { + "title": "Assistant", + "send": "Envoyer", + "stop": "Arrêt", + "save": "Sauvegarder", + "cancel": "Annuler", + "running": "en cours d'exécution", + "approve": "Approuver", + "reject": "Rejeter", + "inputPlaceholder": "Renseignez-vous sur vos serveurs ou décrivez un changement à proposer.", + "selectProvider": "Sélectionnez un fournisseur", + "providerSettings": "Paramètres du fournisseur", + "addProvider": "Ajouter un fournisseur", + "editProvider": "Modifier le fournisseur", + "removeProvider": "Supprimer le fournisseur", + "providerType": "Fournisseur", + "providerLabel": "Nom", + "providerLabelPlaceholder": "Par exemple : Ollama local", + "baseUrl": "Adresse du serveur", + "apiKey": "Clé API", + "defaultModel": "Modèle par défaut", + "defaultModelPlaceholder": "Par exemple : llama3.1 ou claude-opus-5", + "labelRequired": "Donnez un nom à ce fournisseur", + "providerSaveFailed": "Impossible de sauver le fournisseur", + "providerUpdated": "Mise à jour du fournisseur", + "providerDeleteFailed": "Impossible de supprimer le fournisseur", + "privateEndpointHint": "Les adresses de votre réseau privé nécessitent l'autorisation préalable d'un administrateur pour accéder à l'hôte.", + "providerOllama": "Ollama", + "providerAnthropic": "Anthropique", + "providerOpenai": "OpenAI", + "providerGemini": "Google Gemini", + "providerOpenaiCompatible": "Compatible avec OpenAI", + "toolArguments": "Saisir", + "toolResult": "Résultat", + "statusApplied": "Appliqué", + "statusRejected": "Rejeté", + "proposalApplied": "Changement appliqué", + "proposalApplyFailed": "Impossible d'appliquer la modification", + "proposalRejectFailed": "Impossible de refuser la modification", + "enableTitle": "Activer l'assistant IA", + "enableDescription": "Laissez l'assistant analyser votre configuration et vous suggérer des modifications à approuver.", + "readOnlyCommands": "Autoriser les commandes de diagnostic en lecture seule", + "readOnlyCommandsDescription": "L'assistant peut exécuter une courte liste de commandes sûres, comme `df` et `uptime`, sans demander l'autorisation à chaque fois. Toute modification apportée au serveur est toujours proposée au préalable.", + "modelDetectFailed": "Impossible de joindre le fournisseur ; voici donc une liste générale. Vous pouvez saisir n’importe quel nom de modèle.", + "modelCustom": "Saisissez le nom du modèle", + "modelRefresh": "Actualiser la liste", + "modelPlaceholder": "Choisissez ou saisissez un modèle", + "attachHint": "Saisissez @ pour faire référence à un hôte, un extrait de code ou une automatisation. Les modifications proposées doivent être approuvées.", + "runCommandTitle": "Exécuter la commande", + "assistant": "Assistant IA", + "terminalPanelEmpty": "Renseignez-vous auprès de l'assistant concernant cet hôte. Tout changement d'état nécessite votre approbation préalable.", + "terminalPanelPlaceholder": "Renseignez-vous sur cet hôte...", + "noProvidersConfigured": "Aucun fournisseur d'IA n'est encore configuré. Ajoutez-en un dans l'onglet Assistant IA.", + "runsInOpenTerminal": "S'exécute dans votre session de terminal ouverte.", + "runInTerminal": "Courir" + }, + "nav": { + "ai": "IA" + }, + "onboarding": { + "aiTitle": "Assistant IA", + "aiIntro": "Termix peut inclure un assistant IA optionnel. Vous pouvez modifier ce paramètre ultérieurement.", + "aiSkipTitle": "Laissez-le de côté", + "aiSkipDesc": "Termix fonctionne comme actuellement. L'assistant reste caché.", + "aiEnableTitle": "Allumez-le", + "aiEnableDesc": "Ajoute un assistant qui analyse votre configuration et suggère des modifications que vous approuvez. Nécessite un fournisseur que vous désignez, comme un Ollama local.", + "aiNote": "Aucun message n'est envoyé tant que vous n'avez pas ajouté de fournisseur et envoyé un message." + }, + "admin": { + "aiGloballyEnabled": "Assistant IA", + "aiGloballyEnabledDesc": "Autoriser les utilisateurs à activer l'assistant IA. Lorsqu'il est désactivé, l'assistant est masqué et inaccessible à tous.", + "aiPrivateEndpoints": "Hôtes d'IA privés autorisés", + "aiPrivateEndpointsDesc": "Les hôtes de votre réseau privé vers lesquels les utilisateurs peuvent orienter un fournisseur, comme un serveur Ollama auto-hébergé. Séparez-les par des virgules.", + "updateAiEnabledFailed": "Impossible de mettre à jour les paramètres d'IA", + "updateAiEndpointsFailed": "Impossible de mettre à jour les hôtes autorisés." + } +} diff --git a/plugins/ai/locales/translated/he_IL.json b/plugins/ai/locales/translated/he_IL.json new file mode 100644 index 000000000..f50cebbbf --- /dev/null +++ b/plugins/ai/locales/translated/he_IL.json @@ -0,0 +1,78 @@ +{ + "ai": { + "title": "עוֹזֵר", + "send": "לִשְׁלוֹחַ", + "stop": "לְהַפְסִיק", + "save": "לְהַצִיל", + "cancel": "לְבַטֵל", + "running": "רִיצָה", + "approve": "לְאַשֵׁר", + "reject": "לִדחוֹת", + "inputPlaceholder": "שאל לגבי המלצרים שלך, או תאר שינוי להציע", + "selectProvider": "בחר ספק", + "providerSettings": "הגדרות ספק", + "addProvider": "הוסף ספק", + "editProvider": "עריכת ספק", + "removeProvider": "הסר ספק", + "providerType": "ספק", + "providerLabel": "שֵׁם", + "providerLabelPlaceholder": "לדוגמה: אולמה מקומית", + "baseUrl": "כתובת השרת", + "apiKey": "מפתח API", + "defaultModel": "מודל ברירת מחדל", + "defaultModelPlaceholder": "לדוגמה: llama3.1 או claude-opus-5", + "labelRequired": "תן שם לספק הזה", + "providerSaveFailed": "לא ניתן היה לשמור את הספק", + "providerUpdated": "הספק עודכן", + "providerDeleteFailed": "לא ניתן היה להסיר את הספק", + "privateEndpointHint": "כתובות ברשת הפרטית שלך דורשות תחילה אישור ממנהל מערכת למארח.", + "providerOllama": "אולמה", + "providerAnthropic": "אנתרופי", + "providerOpenai": "בינה מלאכותית פתוחה", + "providerGemini": "גוגל ג'מיני", + "providerOpenaiCompatible": "תואם ל-OpenAI", + "toolArguments": "קֶלֶט", + "toolResult": "תוֹצָאָה", + "statusApplied": "יישומי", + "statusRejected": "נִדחֶה", + "proposalApplied": "השינוי הוחל", + "proposalApplyFailed": "לא ניתן היה להחיל את השינוי", + "proposalRejectFailed": "לא ניתן היה לדחות את השינוי", + "enableTitle": "הפעל את עוזר הבינה המלאכותית", + "enableDescription": "תן לעוזר לקרוא את ההגדרות שלך ולהציע שינויים לאישור.", + "readOnlyCommands": "אפשר פקודות אבחון לקריאה בלבד", + "readOnlyCommandsDescription": "העוזר יכול להריץ רשימה קצרה של פקודות בטוחות כמו df ו-uptime מבלי לשאול בכל פעם. כל דבר שמשנה שרת תמיד מוצע ראשון.", + "modelDetectFailed": "לא ניתן היה להגיע לספק, לכן זוהי רשימה כללית. ניתן להקליד כל שם דגם.", + "modelCustom": "הזן שם דגם", + "modelRefresh": "רענון הרשימה", + "modelPlaceholder": "בחר או הקלד מודל", + "attachHint": "הקלד @ כדי להפנות למארח, קטע טקסט או אוטומציה. שינויים מוצעים לאישורך.", + "runCommandTitle": "הפעלה של הפקודה", + "assistant": "עוזר בינה מלאכותית", + "terminalPanelEmpty": "שאל את העוזר לגבי המארח הזה. כל שינוי במצב דורש תחילה את אישורך.", + "terminalPanelPlaceholder": "שאל על המארח הזה...", + "noProvidersConfigured": "עדיין לא הוגדר ספק בינה מלאכותית. הוסף אחד בכרטיסייה עוזר בינה מלאכותית.", + "runsInOpenTerminal": "פועל בסשן הטרמינל הפתוח שלך.", + "runInTerminal": "לָרוּץ" + }, + "nav": { + "ai": "בינה מלאכותית" + }, + "onboarding": { + "aiTitle": "עוזר בינה מלאכותית", + "aiIntro": "טרמיקס יכול לכלול עוזר בינה מלאכותית אופציונלי. ניתן לשנות זאת מאוחר יותר בהגדרות.", + "aiSkipTitle": "תעזוב את זה", + "aiSkipDesc": "טרמיקס עובד כמו שהוא עובד עכשיו. העוזר נשאר מוסתר.", + "aiEnableTitle": "הפעל אותו", + "aiEnableDesc": "מוסיף עוזר שקורא את ההגדרות שלך ומציע שינויים שאתה מאשר. נדרש ספק שאתה מספק, כגון אולמה מקומי.", + "aiNote": "שום דבר לא נשלח לשום מקום עד שתוסיף ספק ותשלח הודעה." + }, + "admin": { + "aiGloballyEnabled": "עוזר בינה מלאכותית", + "aiGloballyEnabledDesc": "אפשר למשתמשים להפעיל את עוזר הבינה המלאכותית. כאשר זה כבוי, העוזר מוסתר וחסום עבור כולם.", + "aiPrivateEndpoints": "מארחים פרטיים של בינה מלאכותית מורשים", + "aiPrivateEndpointsDesc": "מארחים ברשת הפרטית שלך שמשתמשים עשויים להפנות אליהם ספק, כגון Ollama המאוחסן בעצמו. הפרד ביניהם באמצעות פסיקים.", + "updateAiEnabledFailed": "לא ניתן היה לעדכן את הגדרת הבינה המלאכותית", + "updateAiEndpointsFailed": "לא ניתן היה לעדכן את המארחים המותרים" + } +} diff --git a/plugins/ai/locales/translated/hi_IN.json b/plugins/ai/locales/translated/hi_IN.json new file mode 100644 index 000000000..8b0e7b585 --- /dev/null +++ b/plugins/ai/locales/translated/hi_IN.json @@ -0,0 +1,78 @@ +{ + "ai": { + "title": "सहायक", + "send": "भेजना", + "stop": "रुकना", + "save": "बचाना", + "cancel": "रद्द करना", + "running": "दौड़ना", + "approve": "मंज़ूरी देना", + "reject": "अस्वीकार करना", + "inputPlaceholder": "अपने सर्वरों के बारे में पूछें, या प्रस्तावित परिवर्तन का वर्णन करें।", + "selectProvider": "एक प्रदाता का चयन करें", + "providerSettings": "प्रदाता सेटिंग्स", + "addProvider": "प्रदाता जोड़ें", + "editProvider": "प्रदाता संपादित करें", + "removeProvider": "प्रदाता को हटाएँ", + "providerType": "प्रदाता", + "providerLabel": "नाम", + "providerLabelPlaceholder": "उदाहरण के लिए: स्थानीय ओलामा", + "baseUrl": "सर्वर पता", + "apiKey": "एपीआई कुंजी", + "defaultModel": "डिफ़ॉल्ट मॉडल", + "defaultModelPlaceholder": "उदाहरण के लिए: llama3.1 या claude-opus-5", + "labelRequired": "इस प्रदाता को एक नाम दें", + "providerSaveFailed": "प्रदाता को बचाया नहीं जा सका", + "providerUpdated": "प्रदाता ने अपडेट किया", + "providerDeleteFailed": "प्रदाता को हटाया नहीं जा सका", + "privateEndpointHint": "आपके निजी नेटवर्क पर मौजूद पतों के लिए पहले एक प्रशासक द्वारा होस्ट को अनुमति देना आवश्यक है।", + "providerOllama": "ओलामा", + "providerAnthropic": "anthropic", + "providerOpenai": "ओपनएआई", + "providerGemini": "गूगल जेमिनी", + "providerOpenaiCompatible": "OpenAI संगत", + "toolArguments": "इनपुट", + "toolResult": "परिणाम", + "statusApplied": "लागू किया गया", + "statusRejected": "अस्वीकार कर दिया", + "proposalApplied": "परिवर्तन लागू हो गया", + "proposalApplyFailed": "परिवर्तन लागू नहीं हो सका", + "proposalRejectFailed": "परिवर्तन को अस्वीकार नहीं किया जा सका", + "enableTitle": "एआई सहायक को सक्रिय करें", + "enableDescription": "सहायक को आपकी सेटअप प्रक्रिया पढ़ने दें और वह आपके अनुमोदन के लिए परिवर्तन सुझाएगा।", + "readOnlyCommands": "केवल पढ़ने योग्य डायग्नोस्टिक कमांड की अनुमति दें", + "readOnlyCommandsDescription": "सहायक बिना पूछे ही df और uptime जैसे कुछ सुरक्षित कमांड चला सकता है। सर्वर में कोई भी बदलाव करने का प्रस्ताव हमेशा पहले दिया जाता है।", + "modelDetectFailed": "प्रदाता से संपर्क नहीं हो सका, इसलिए यह एक सामान्य सूची है। आप किसी भी मॉडल का नाम टाइप कर सकते हैं।", + "modelCustom": "मॉडल का नाम दर्ज करें", + "modelRefresh": "सूची रीफ़्रेश करें", + "modelPlaceholder": "कोई मॉडल चुनें या टाइप करें", + "attachHint": "किसी होस्ट, स्निपेट या ऑटोमेशन को संदर्भित करने के लिए @ टाइप करें। आपके अनुमोदन के लिए परिवर्तन प्रस्तावित किए जा रहे हैं।", + "runCommandTitle": "कमांड चलाएँ", + "assistant": "एआई सहायक", + "terminalPanelEmpty": "इस होस्ट के बारे में असिस्टेंट से पूछें। किसी भी स्थिति में बदलाव के लिए पहले आपकी स्वीकृति आवश्यक है।", + "terminalPanelPlaceholder": "इस होस्ट के बारे में पूछें...", + "noProvidersConfigured": "अभी तक कोई एआई प्रदाता कॉन्फ़िगर नहीं किया गया है। एआई सहायक टैब में एक जोड़ें।", + "runsInOpenTerminal": "यह आपके खुले टर्मिनल सत्र में चलता है।", + "runInTerminal": "दौड़ना" + }, + "nav": { + "ai": "ऐ" + }, + "onboarding": { + "aiTitle": "एआई सहायक", + "aiIntro": "टर्मिक्स में एक वैकल्पिक एआई सहायक शामिल हो सकता है। आप इसे बाद में अपनी सेटिंग्स में बदल सकते हैं।", + "aiSkipTitle": "इसे बंद कर दो", + "aiSkipDesc": "टर्मिक्स अभी की तरह ही काम करता है। असिस्टेंट छिपा रहता है।", + "aiEnableTitle": "इसे चालू करें", + "aiEnableDesc": "यह एक सहायक सुविधा जोड़ता है जो आपके सेटअप को पढ़ता है और आपके द्वारा स्वीकृत किए जाने वाले परिवर्तनों का सुझाव देता है। इसके लिए आपको एक प्रदाता उपलब्ध कराना होगा, जैसे कि स्थानीय ओलामा।", + "aiNote": "जब तक आप कोई प्रदाता नहीं जोड़ते और संदेश नहीं भेजते, तब तक कुछ भी कहीं नहीं भेजा जाता।" + }, + "admin": { + "aiGloballyEnabled": "एआई सहायक", + "aiGloballyEnabledDesc": "उपयोगकर्ताओं को एआई सहायक चालू करने की अनुमति दें। जब यह बंद होगा, तो सहायक सभी के लिए छिपा हुआ और अवरुद्ध रहेगा।", + "aiPrivateEndpoints": "निजी एआई होस्ट की अनुमति दी गई", + "aiPrivateEndpointsDesc": "आपके निजी नेटवर्क पर मौजूद होस्ट, जिन्हें उपयोगकर्ता किसी प्रदाता से जोड़ सकते हैं, जैसे कि स्व-होस्टेड ओलामा। इन्हें अल्पविराम से अलग करें।", + "updateAiEnabledFailed": "एआई सेटिंग अपडेट नहीं हो सकी", + "updateAiEndpointsFailed": "अनुमत होस्टों को अपडेट नहीं किया जा सका" + } +} diff --git a/plugins/ai/locales/translated/hu_HU.json b/plugins/ai/locales/translated/hu_HU.json new file mode 100644 index 000000000..d2ba82771 --- /dev/null +++ b/plugins/ai/locales/translated/hu_HU.json @@ -0,0 +1,78 @@ +{ + "ai": { + "title": "Helyettes", + "send": "Elküld", + "stop": "Stop", + "save": "Megtakarítás", + "cancel": "Mégsem", + "running": "futás", + "approve": "Jóváhagyás", + "reject": "Elutasít", + "inputPlaceholder": "Kérdezzen a felszolgálókról, vagy írjon le egy javasolt változtatást", + "selectProvider": "Válasszon szolgáltatót", + "providerSettings": "Szolgáltatói beállítások", + "addProvider": "Szolgáltató hozzáadása", + "editProvider": "Szolgáltató szerkesztése", + "removeProvider": "Szolgáltató eltávolítása", + "providerType": "Szolgáltató", + "providerLabel": "Név", + "providerLabelPlaceholder": "Például: Helyi Ollama", + "baseUrl": "Szerver címe", + "apiKey": "API-kulcs", + "defaultModel": "Alapértelmezett modell", + "defaultModelPlaceholder": "Például: llama3.1 vagy claude-opus-5", + "labelRequired": "Adjon nevet ennek a szolgáltatónak", + "providerSaveFailed": "Nem sikerült menteni a szolgáltatót", + "providerUpdated": "Szolgáltató frissítve", + "providerDeleteFailed": "Nem sikerült eltávolítani a szolgáltatót", + "privateEndpointHint": "A privát hálózaton lévő címekhez először egy rendszergazdának kell engedélyeznie a gazdagépet.", + "providerOllama": "Ollama", + "providerAnthropic": "Antropikus", + "providerOpenai": "Nyílt mesterséges intelligencia", + "providerGemini": "Google Gemini", + "providerOpenaiCompatible": "OpenAI-kompatibilis", + "toolArguments": "Bemenet", + "toolResult": "Eredmény", + "statusApplied": "Alkalmazott", + "statusRejected": "Elutasítva", + "proposalApplied": "Módosítás alkalmazva", + "proposalApplyFailed": "Nem sikerült alkalmazni a módosítást", + "proposalRejectFailed": "Nem sikerült elutasítani a módosítást", + "enableTitle": "Engedélyezze a mesterséges intelligencia asszisztenst", + "enableDescription": "Hagyd, hogy az asszisztens felolvassa a beállításokat, és javasoljon módosításokat jóváhagyásra.", + "readOnlyCommands": "Csak olvasható diagnosztikai parancsok engedélyezése", + "readOnlyCommandsDescription": "Az asszisztens lefuttathat egy rövid listát a biztonságos parancsokról, mint például a df és az uptime, anélkül, hogy minden alkalommal rákérdezne. Bármi, ami megváltoztat egy szervert, mindig elsőként kerül felkérésre.", + "modelDetectFailed": "Nem sikerült elérni a szolgáltatót, ezért ez egy általános lista. Bármelyik modellnevet beírhatja.", + "modelCustom": "Adjon meg egy modellnevet", + "modelRefresh": "Lista frissítése", + "modelPlaceholder": "Válasszon vagy írjon be egy modellt", + "attachHint": "Írjon be @ jelet egy gazdagépre, kódrészletre vagy automatizálásra való hivatkozáshoz. A rendszer módosításokat javasol jóváhagyásra.", + "runCommandTitle": "Parancs futtatása", + "assistant": "MI asszisztens", + "terminalPanelEmpty": "Kérdezd meg az asszisztenst erről a házigazdáról. Bármi, ami megváltoztatja az állapotát, először a jóváhagyásodra van szükség.", + "terminalPanelPlaceholder": "Kérdezz rá erre a házigazdára...", + "noProvidersConfigured": "Még nincs konfigurálva AI-szolgáltató. Adjon hozzá egyet az AI-asszisztens fülön.", + "runsInOpenTerminal": "A megnyitott terminál munkamenetben fut.", + "runInTerminal": "Fut" + }, + "nav": { + "ai": "MI" + }, + "onboarding": { + "aiTitle": "MI asszisztens", + "aiIntro": "A Termix tartalmazhat opcionális mesterséges intelligencia asszisztenst. Ezt később módosíthatja a beállításokban.", + "aiSkipTitle": "Hagyd ki", + "aiSkipDesc": "A Termix ugyanúgy működik, mint most. Az asszisztens rejtve marad.", + "aiEnableTitle": "Kapcsold be", + "aiEnableDesc": "Hozzáad egy asszisztenst, amely beolvassa a beállításait, és javaslatokat tesz az Ön által jóváhagyott módosításokra. Szükség van egy Ön által biztosított szolgáltatóra, például egy helyi Ollama szakemberre.", + "aiNote": "Semmi sem kerül sehova, amíg nem adsz hozzá egy szolgáltatót és nem küldesz üzenetet." + }, + "admin": { + "aiGloballyEnabled": "MI asszisztens", + "aiGloballyEnabledDesc": "Engedélyezheti a felhasználóknak a mesterséges intelligencia asszisztens bekapcsolását. Amíg ez ki van kapcsolva, az asszisztens rejtett és blokkolt mindenki számára.", + "aiPrivateEndpoints": "Engedélyezett privát AI-gazdagépek", + "aiPrivateEndpointsDesc": "A privát hálózatodon található olyan hosztok, amelyekre a felhasználók szolgáltatót irányíthatnak, például egy saját hosztolt Ollama. Vesszővel válaszd el őket.", + "updateAiEnabledFailed": "Nem sikerült frissíteni a mesterséges intelligencia beállítását", + "updateAiEndpointsFailed": "Nem sikerült frissíteni az engedélyezett gazdagépeket" + } +} diff --git a/plugins/ai/locales/translated/id_ID.json b/plugins/ai/locales/translated/id_ID.json new file mode 100644 index 000000000..491c48826 --- /dev/null +++ b/plugins/ai/locales/translated/id_ID.json @@ -0,0 +1,78 @@ +{ + "ai": { + "title": "Asisten", + "send": "Mengirim", + "stop": "Berhenti", + "save": "Menyimpan", + "cancel": "Membatalkan", + "running": "berlari", + "approve": "Menyetujui", + "reject": "Menolak", + "inputPlaceholder": "Tanyakan tentang server Anda, atau jelaskan perubahan yang ingin Anda usulkan.", + "selectProvider": "Pilih penyedia", + "providerSettings": "Pengaturan penyedia", + "addProvider": "Tambahkan penyedia", + "editProvider": "Penyedia pengeditan", + "removeProvider": "Hapus penyedia", + "providerType": "Penyedia", + "providerLabel": "Nama", + "providerLabelPlaceholder": "Contohnya: Ollama setempat", + "baseUrl": "Alamat server", + "apiKey": "Kunci API", + "defaultModel": "Model default", + "defaultModelPlaceholder": "Misalnya: llama3.1 atau claude-opus-5", + "labelRequired": "Beri nama penyedia ini", + "providerSaveFailed": "Penyedia layanan tidak dapat disimpan.", + "providerUpdated": "Penyedia diperbarui", + "providerDeleteFailed": "Penyedia layanan tidak dapat dihapus.", + "privateEndpointHint": "Alamat-alamat di jaringan pribadi Anda memerlukan izin administrator terlebih dahulu untuk host tersebut.", + "providerOllama": "Ollama", + "providerAnthropic": "Antropis", + "providerOpenai": "OpenAI", + "providerGemini": "Google Gemini", + "providerOpenaiCompatible": "Kompatibel dengan OpenAI", + "toolArguments": "Masukan", + "toolResult": "Hasil", + "statusApplied": "Terapan", + "statusRejected": "Ditolak", + "proposalApplied": "Perubahan diterapkan", + "proposalApplyFailed": "Perubahan tidak dapat diterapkan.", + "proposalRejectFailed": "Tidak bisa menolak perubahan tersebut", + "enableTitle": "Aktifkan asisten AI", + "enableDescription": "Biarkan asisten membaca pengaturan Anda dan menyarankan perubahan yang perlu Anda setujui.", + "readOnlyCommands": "Izinkan perintah diagnostik hanya baca.", + "readOnlyCommandsDescription": "Asisten dapat menjalankan daftar singkat perintah aman seperti df dan uptime tanpa bertanya setiap kali. Apa pun yang mengubah server selalu diusulkan terlebih dahulu.", + "modelDetectFailed": "Tidak dapat menghubungi penyedia, jadi ini adalah daftar umum. Anda dapat mengetikkan nama model apa pun.", + "modelCustom": "Masukkan nama model", + "modelRefresh": "Perbarui daftar", + "modelPlaceholder": "Pilih atau ketik model", + "attachHint": "Ketik @ untuk merujuk ke host, cuplikan kode, atau otomatisasi. Perubahan diajukan untuk Anda setujui.", + "runCommandTitle": "Jalankan perintah", + "assistant": "Asisten AI", + "terminalPanelEmpty": "Tanyakan kepada asisten tentang tuan rumah ini. Segala sesuatu yang berubah status memerlukan persetujuan Anda terlebih dahulu.", + "terminalPanelPlaceholder": "Tanyakan tentang tuan rumah ini...", + "noProvidersConfigured": "Belum ada penyedia AI yang dikonfigurasi. Tambahkan satu di tab asisten AI.", + "runsInOpenTerminal": "Berjalan di sesi terminal Anda yang sedang terbuka.", + "runInTerminal": "Berlari" + }, + "nav": { + "ai": "AI" + }, + "onboarding": { + "aiTitle": "Asisten AI", + "aiIntro": "Termix dapat menyertakan asisten AI opsional. Anda dapat mengubahnya nanti di pengaturan Anda.", + "aiSkipTitle": "Biarkan saja", + "aiSkipDesc": "Termix berfungsi seperti sekarang. Asisten tetap tersembunyi.", + "aiEnableTitle": "Nyalakan", + "aiEnableDesc": "Menambahkan asisten yang membaca pengaturan Anda dan menyarankan perubahan yang Anda setujui. Membutuhkan penyedia yang Anda berikan, seperti Ollama lokal.", + "aiNote": "Tidak ada data yang dikirim ke mana pun sampai Anda menambahkan penyedia dan mengirim pesan." + }, + "admin": { + "aiGloballyEnabled": "Asisten AI", + "aiGloballyEnabledDesc": "Izinkan pengguna untuk mengaktifkan asisten AI. Saat dinonaktifkan, asisten akan disembunyikan dan diblokir untuk semua orang.", + "aiPrivateEndpoints": "Host AI pribadi yang diizinkan", + "aiPrivateEndpointsDesc": "Host di jaringan pribadi Anda yang mungkin ditunjuk pengguna untuk penyedia layanan, seperti Ollama yang dihosting sendiri. Pisahkan dengan koma.", + "updateAiEnabledFailed": "Pengaturan AI tidak dapat diperbarui.", + "updateAiEndpointsFailed": "Tidak dapat memperbarui host yang diizinkan." + } +} diff --git a/plugins/ai/locales/translated/it_IT.json b/plugins/ai/locales/translated/it_IT.json new file mode 100644 index 000000000..48d505a66 --- /dev/null +++ b/plugins/ai/locales/translated/it_IT.json @@ -0,0 +1,78 @@ +{ + "ai": { + "title": "Assistente", + "send": "Inviare", + "stop": "Fermare", + "save": "Salva", + "cancel": "Cancellare", + "running": "corsa", + "approve": "Approvare", + "reject": "Rifiutare", + "inputPlaceholder": "Chiedi informazioni sui tuoi server o descrivi una modifica da proporre", + "selectProvider": "Seleziona un fornitore", + "providerSettings": "Impostazioni del provider", + "addProvider": "Aggiungi fornitore", + "editProvider": "Fornitore di modifica", + "removeProvider": "Rimuovi il fornitore", + "providerType": "Fornitore", + "providerLabel": "Nome", + "providerLabelPlaceholder": "Ad esempio: Ollama locale", + "baseUrl": "Indirizzo del server", + "apiKey": "Chiave API", + "defaultModel": "Modello predefinito", + "defaultModelPlaceholder": "Ad esempio: llama3.1 o claude-opus-5", + "labelRequired": "Assegna un nome a questo fornitore", + "providerSaveFailed": "Impossibile salvare il provider", + "providerUpdated": "Fornitore aggiornato", + "providerDeleteFailed": "Impossibile rimuovere il provider", + "privateEndpointHint": "Gli indirizzi sulla tua rete privata richiedono prima l'autorizzazione di un amministratore per l'host.", + "providerOllama": "Ollama", + "providerAnthropic": "Antropico", + "providerOpenai": "OpenAI", + "providerGemini": "Google Gemini", + "providerOpenaiCompatible": "Compatibile con OpenAI", + "toolArguments": "Ingresso", + "toolResult": "Risultato", + "statusApplied": "Applicato", + "statusRejected": "Respinto", + "proposalApplied": "Modifica applicata", + "proposalApplyFailed": "Impossibile applicare la modifica", + "proposalRejectFailed": "Impossibile rifiutare la modifica", + "enableTitle": "Abilita l'assistente IA", + "enableDescription": "Lascia che l'assistente legga la tua configurazione e ti suggerisca delle modifiche da approvare.", + "readOnlyCommands": "Consenti comandi diagnostici di sola lettura", + "readOnlyCommandsDescription": "L'assistente può eseguire un breve elenco di comandi sicuri come df e uptime senza chiedere conferma ogni volta. Qualsiasi operazione che modifichi un server viene sempre proposta in anticipo.", + "modelDetectFailed": "Non è stato possibile contattare il fornitore, quindi questo è un elenco generico. È possibile digitare qualsiasi nome di modello.", + "modelCustom": "Inserisci il nome del modello", + "modelRefresh": "Aggiorna elenco", + "modelPlaceholder": "Scegli o digita un modello", + "attachHint": "Digita @ per fare riferimento a un host, uno snippet o un'automazione. Le modifiche proposte sono da approvare.", + "runCommandTitle": "Esegui il comando", + "assistant": "Assistente AI", + "terminalPanelEmpty": "Chiedi all'assistente informazioni su questo host. Qualsiasi modifica allo stato richiede la tua approvazione preventiva.", + "terminalPanelPlaceholder": "Chiedi informazioni su questo host...", + "noProvidersConfigured": "Non è ancora configurato alcun provider di IA. Aggiungine uno nella scheda Assistente IA.", + "runsInOpenTerminal": "Viene eseguito nella sessione del terminale aperta.", + "runInTerminal": "Correre" + }, + "nav": { + "ai": "IA" + }, + "onboarding": { + "aiTitle": "Assistente basato sull'intelligenza artificiale", + "aiIntro": "Termix può includere un assistente AI opzionale. Puoi modificare questa impostazione in seguito.", + "aiSkipTitle": "Lascialo spento", + "aiSkipDesc": "Termix funziona come ora. L'assistente rimane nascosto.", + "aiEnableTitle": "Accendilo", + "aiEnableDesc": "Aggiunge un assistente che legge la tua configurazione e suggerisce modifiche che approvi. Richiede un provider che tu fornisca, come ad esempio un Ollama locale.", + "aiNote": "Non viene inviato nulla finché non si aggiunge un provider e si invia un messaggio." + }, + "admin": { + "aiGloballyEnabled": "Assistente basato sull'intelligenza artificiale", + "aiGloballyEnabledDesc": "Consenti agli utenti di attivare l'assistente AI. Quando è disattivato, l'assistente è nascosto e bloccato per tutti.", + "aiPrivateEndpoints": "Host di IA privati consentiti", + "aiPrivateEndpointsDesc": "Host sulla tua rete privata a cui gli utenti possono indirizzare un provider, come ad esempio un'istanza di Ollama autogestita. Separali con delle virgole.", + "updateAiEnabledFailed": "Impossibile aggiornare le impostazioni dell'IA", + "updateAiEndpointsFailed": "Impossibile aggiornare gli host consentiti" + } +} diff --git a/plugins/ai/locales/translated/ja_JP.json b/plugins/ai/locales/translated/ja_JP.json new file mode 100644 index 000000000..4ea3f16d5 --- /dev/null +++ b/plugins/ai/locales/translated/ja_JP.json @@ -0,0 +1,78 @@ +{ + "ai": { + "title": "アシスタント", + "send": "送信", + "stop": "停止", + "save": "保存", + "cancel": "キャンセル", + "running": "ランニング", + "approve": "承認する", + "reject": "拒否する", + "inputPlaceholder": "サーバーについて質問するか、変更案を説明する", + "selectProvider": "プロバイダーを選択してください", + "providerSettings": "プロバイダー設定", + "addProvider": "プロバイダーを追加", + "editProvider": "プロバイダーを編集", + "removeProvider": "プロバイダーを削除", + "providerType": "プロバイダー", + "providerLabel": "名前", + "providerLabelPlaceholder": "例えば:地元のオラマ", + "baseUrl": "サーバーアドレス", + "apiKey": "APIキー", + "defaultModel": "デフォルトモデル", + "defaultModelPlaceholder": "例えば、llama3.1 や claude-opus-5 など。", + "labelRequired": "このプロバイダーに名前を付けてください", + "providerSaveFailed": "プロバイダーを保存できませんでした", + "providerUpdated": "プロバイダーが更新されました", + "providerDeleteFailed": "プロバイダーを削除できませんでした", + "privateEndpointHint": "プライベートネットワーク上のアドレスを使用するには、まず管理者がホストを許可する必要があります。", + "providerOllama": "オラマ", + "providerAnthropic": "人間", + "providerOpenai": "OpenAI", + "providerGemini": "Google Gemini", + "providerOpenaiCompatible": "OpenAI対応", + "toolArguments": "入力", + "toolResult": "結果", + "statusApplied": "適用済み", + "statusRejected": "拒否されました", + "proposalApplied": "変更が適用されました", + "proposalApplyFailed": "変更を適用できませんでした", + "proposalRejectFailed": "変更を拒否できませんでした", + "enableTitle": "AIアシスタントを有効にする", + "enableDescription": "アシスタントにあなたの設定を読み取らせ、承認が必要な変更案を提案させましょう。", + "readOnlyCommands": "読み取り専用の診断コマンドを許可する", + "readOnlyCommandsDescription": "アシスタントは、dfやuptimeといった安全なコマンドを毎回確認することなく実行する場合があります。サーバーに変更を加える操作は、常に最初に提案されます。", + "modelDetectFailed": "プロバイダーに連絡が取れなかったため、これは一般的なリストです。任意のモデル名を入力してください。", + "modelCustom": "モデル名を入力してください", + "modelRefresh": "リストを更新", + "modelPlaceholder": "モデルを選択または入力してください", + "attachHint": "ホスト、スニペット、またはオートメーションを参照するには、「@」を入力してください。変更案が表示され、承認が必要となります。", + "runCommandTitle": "コマンドを実行する", + "assistant": "AIアシスタント", + "terminalPanelEmpty": "このホストについてアシスタントにお問い合わせください。状態変更を伴う変更はすべて、事前にあなたの承認が必要です。", + "terminalPanelPlaceholder": "このホストについて質問する...", + "noProvidersConfigured": "AIプロバイダーがまだ設定されていません。AIアシスタントタブで追加してください。", + "runsInOpenTerminal": "開いているターミナルセッションで実行されます。", + "runInTerminal": "走る" + }, + "nav": { + "ai": "AI" + }, + "onboarding": { + "aiTitle": "AIアシスタント", + "aiIntro": "TermixにはオプションでAIアシスタントを搭載できます。これは後で設定画面で変更できます。", + "aiSkipTitle": "オフにしておく", + "aiSkipDesc": "Termixは現状のまま動作します。アシスタントは非表示のままです。", + "aiEnableTitle": "電源を入れる", + "aiEnableDesc": "設定内容を読み取り、承認した上で変更案を提案するアシスタント機能を追加します。ローカルのOllamaなど、お客様ご自身で手配するプロバイダーが必要です。", + "aiNote": "プロバイダーを追加してメッセージを送信するまで、データはどこにも送信されません。" + }, + "admin": { + "aiGloballyEnabled": "AIアシスタント", + "aiGloballyEnabledDesc": "ユーザーがAIアシスタントをオンにできるようにします。オフになっている間は、アシスタントは非表示になり、誰からも利用できなくなります。", + "aiPrivateEndpoints": "プライベートAIホストを許可", + "aiPrivateEndpointsDesc": "ユーザーがプロバイダに指定できる、プライベートネットワーク上のホスト(自己ホスト型のOllamaなど)を指定します。カンマで区切ってください。", + "updateAiEnabledFailed": "AI設定を更新できませんでした", + "updateAiEndpointsFailed": "許可されたホストを更新できませんでした" + } +} diff --git a/plugins/ai/locales/translated/ko_KR.json b/plugins/ai/locales/translated/ko_KR.json new file mode 100644 index 000000000..dd1e8c263 --- /dev/null +++ b/plugins/ai/locales/translated/ko_KR.json @@ -0,0 +1,78 @@ +{ + "ai": { + "title": "어시스턴트", + "send": "보내다", + "stop": "멈추다", + "save": "구하다", + "cancel": "취소", + "running": "달리기", + "approve": "승인하다", + "reject": "거부하다", + "inputPlaceholder": "서버에 대해 문의하거나, 변경 사항을 제안해 보세요.", + "selectProvider": "제공업체를 선택하세요", + "providerSettings": "공급자 설정", + "addProvider": "공급자 추가", + "editProvider": "제공자 수정", + "removeProvider": "제공업체를 제거하세요", + "providerType": "공급자", + "providerLabel": "이름", + "providerLabelPlaceholder": "예: 지역 올라마", + "baseUrl": "서버 주소", + "apiKey": "API 키", + "defaultModel": "기본 모델", + "defaultModelPlaceholder": "예를 들어: llama3.1 또는 claude-opus-5", + "labelRequired": "이 제공업체에 이름을 지정하세요", + "providerSaveFailed": "공급자를 저장할 수 없습니다.", + "providerUpdated": "제공업체 업데이트됨", + "providerDeleteFailed": "공급자를 제거할 수 없습니다.", + "privateEndpointHint": "개인 네트워크의 주소에 접근하려면 관리자가 먼저 호스트를 허용해야 합니다.", + "providerOllama": "올라마", + "providerAnthropic": "인류", + "providerOpenai": "오픈아이", + "providerGemini": "구글 제미니", + "providerOpenaiCompatible": "OpenAI와 호환 가능", + "toolArguments": "입력", + "toolResult": "결과", + "statusApplied": "적용된", + "statusRejected": "거절됨", + "proposalApplied": "변경 사항이 적용되었습니다", + "proposalApplyFailed": "변경 사항을 적용할 수 없습니다.", + "proposalRejectFailed": "변경을 거부할 수 없었습니다", + "enableTitle": "AI 비서를 활성화하세요", + "enableDescription": "도우미가 사용자의 설정을 읽고 승인할 변경 사항을 제안하도록 하세요.", + "readOnlyCommands": "읽기 전용 진단 명령을 허용합니다.", + "readOnlyCommandsDescription": "도우미는 매번 묻지 않고 df 및 uptime과 같은 안전한 명령어 목록을 실행할 수 있습니다. 서버를 변경하는 작업은 항상 먼저 제안됩니다.", + "modelDetectFailed": "공급업체에 연결할 수 없어서 일반적인 목록을 제공합니다. 모델명을 입력하셔도 됩니다.", + "modelCustom": "모델명을 입력하세요", + "modelRefresh": "목록 새로 고침", + "modelPlaceholder": "모델을 선택하거나 입력하세요.", + "attachHint": "호스트, 코드 조각 또는 자동화를 참조하려면 @를 입력하세요. 승인을 위해 변경 사항이 제안됩니다.", + "runCommandTitle": "명령어를 실행하세요", + "assistant": "AI 어시스턴트", + "terminalPanelEmpty": "이 호스트에 대해 담당자에게 문의하십시오. 상태가 변경되는 모든 사항은 먼저 사용자의 승인이 필요합니다.", + "terminalPanelPlaceholder": "이 호스트에 대해 문의해 보세요...", + "noProvidersConfigured": "아직 AI 제공업체가 구성되지 않았습니다. AI 도우미 탭에서 추가하세요.", + "runsInOpenTerminal": "열려 있는 터미널 세션에서 실행됩니다.", + "runInTerminal": "달리다" + }, + "nav": { + "ai": "일체 포함" + }, + "onboarding": { + "aiTitle": "AI 비서", + "aiIntro": "Termix에는 선택적으로 AI 비서 기능이 포함될 수 있습니다. 이 기능은 나중에 설정에서 변경할 수 있습니다.", + "aiSkipTitle": "꺼두세요", + "aiSkipDesc": "Termix는 현재와 같이 작동합니다. 어시스턴트는 숨겨진 상태로 유지됩니다.", + "aiEnableTitle": "켜세요", + "aiEnableDesc": "설정을 읽고 사용자가 승인하는 변경 사항을 제안하는 도우미를 추가합니다. 사용자가 제공하는 공급업체(예: 지역 Ollama)가 필요합니다.", + "aiNote": "공급자를 추가하고 메시지를 보내기 전까지는 아무것도 전송되지 않습니다." + }, + "admin": { + "aiGloballyEnabled": "AI 비서", + "aiGloballyEnabledDesc": "사용자가 AI 비서를 켜고 끌 수 있도록 하세요. AI 비서가 꺼져 있으면 모든 사용자에게 비서 기능이 숨겨지고 차단됩니다.", + "aiPrivateEndpoints": "개인 AI 호스트 허용", + "aiPrivateEndpointsDesc": "사용자가 공급자에게 연결할 수 있는 개인 네트워크의 호스트(예: 자체 호스팅 Ollama)를 나열하세요. 호스트는 쉼표로 구분하세요.", + "updateAiEnabledFailed": "AI 설정을 업데이트할 수 없습니다.", + "updateAiEndpointsFailed": "허용된 호스트를 업데이트할 수 없습니다." + } +} diff --git a/plugins/ai/locales/translated/nl_NL.json b/plugins/ai/locales/translated/nl_NL.json new file mode 100644 index 000000000..0276e0502 --- /dev/null +++ b/plugins/ai/locales/translated/nl_NL.json @@ -0,0 +1,78 @@ +{ + "ai": { + "title": "Assistent", + "send": "Versturen", + "stop": "Stop", + "save": "Redden", + "cancel": "Annuleren", + "running": "rennen", + "approve": "Goedkeuren", + "reject": "Afwijzen", + "inputPlaceholder": "Vraag naar uw servers of beschrijf een voorgestelde wijziging.", + "selectProvider": "Selecteer een aanbieder", + "providerSettings": "Aanbiederinstellingen", + "addProvider": "Aanbieder toevoegen", + "editProvider": "Bewerk provider", + "removeProvider": "Verwijder provider", + "providerType": "Aanbieder", + "providerLabel": "Naam", + "providerLabelPlaceholder": "Bijvoorbeeld: Lokale Ollama", + "baseUrl": "Serveradres", + "apiKey": "API-sleutel", + "defaultModel": "Standaardmodel", + "defaultModelPlaceholder": "Bijvoorbeeld: llama3.1 of claude-opus-5", + "labelRequired": "Geef deze aanbieder een naam", + "providerSaveFailed": "De provider kon niet worden opgeslagen.", + "providerUpdated": "Aanbieder bijgewerkt", + "providerDeleteFailed": "De provider kon niet worden verwijderd.", + "privateEndpointHint": "IP-adressen op uw privénetwerk moeten eerst door een beheerder worden toegestaan.", + "providerOllama": "Ollama", + "providerAnthropic": "Antropisch", + "providerOpenai": "OpenAI", + "providerGemini": "Google Gemini", + "providerOpenaiCompatible": "OpenAI-compatibel", + "toolArguments": "Invoer", + "toolResult": "Resultaat", + "statusApplied": "Toegepast", + "statusRejected": "Afgewezen", + "proposalApplied": "Toegepaste wijziging", + "proposalApplyFailed": "De wijziging kon niet worden toegepast.", + "proposalRejectFailed": "Kon de wijziging niet afwijzen", + "enableTitle": "Schakel de AI-assistent in", + "enableDescription": "Laat de assistent je instellingen lezen en wijzigingen voorstellen die je vervolgens kunt goedkeuren.", + "readOnlyCommands": "Sta alleen-lezen diagnostische opdrachten toe.", + "readOnlyCommandsDescription": "De assistent kan een korte lijst met veilige commando's zoals df en uptime uitvoeren zonder telkens opnieuw toestemming te vragen. Alles wat een server wijzigt, wordt altijd eerst voorgesteld.", + "modelDetectFailed": "De aanbieder kon niet worden bereikt, daarom is dit een algemene lijst. U kunt elke modelnaam invoeren.", + "modelCustom": "Voer een modelnaam in", + "modelRefresh": "Vernieuw de lijst", + "modelPlaceholder": "Kies of typ een model", + "attachHint": "Typ @ om te verwijzen naar een host, codefragment of automatisering. Wijzigingen worden voorgesteld ter goedkeuring.", + "runCommandTitle": "Voer het commando uit", + "assistant": "AI-assistent", + "terminalPanelEmpty": "Vraag de assistent naar deze host. Alles wat de status wijzigt, vereist eerst uw goedkeuring.", + "terminalPanelPlaceholder": "Vraag naar deze host...", + "noProvidersConfigured": "Er is nog geen AI-provider geconfigureerd. Voeg er een toe via het tabblad AI-assistent.", + "runsInOpenTerminal": "Wordt uitgevoerd in uw geopende terminalsessie.", + "runInTerminal": "Loop" + }, + "nav": { + "ai": "AI" + }, + "onboarding": { + "aiTitle": "AI-assistent", + "aiIntro": "Termix kan optioneel een AI-assistent bevatten. Je kunt dit later in je instellingen wijzigen.", + "aiSkipTitle": "Laat het weg", + "aiSkipDesc": "Termix werkt zoals het nu werkt. De assistent blijft verborgen.", + "aiEnableTitle": "Schakel het in.", + "aiEnableDesc": "Voegt een assistent toe die je instellingen leest en wijzigingen voorstelt die je kunt goedkeuren. Vereist een leverancier die je zelf aanlevert, zoals een lokale Ollama.", + "aiNote": "Er wordt niets verzonden totdat je een provider toevoegt en een bericht verstuurt." + }, + "admin": { + "aiGloballyEnabled": "AI-assistent", + "aiGloballyEnabledDesc": "Gebruikers kunnen de AI-assistent inschakelen. Wanneer deze is uitgeschakeld, is de assistent verborgen en voor iedereen geblokkeerd.", + "aiPrivateEndpoints": "Toegestane privé-AI-hosts", + "aiPrivateEndpointsDesc": "Hosts op uw privénetwerk waarnaar gebruikers een provider kunnen verwijzen, zoals een zelfgehoste Ollama. Scheid ze met komma's.", + "updateAiEnabledFailed": "De AI-instelling kon niet worden bijgewerkt.", + "updateAiEndpointsFailed": "Het lukte niet om de lijst met toegestane hosts bij te werken." + } +} diff --git a/plugins/ai/locales/translated/no_NO.json b/plugins/ai/locales/translated/no_NO.json new file mode 100644 index 000000000..6ec4f43a4 --- /dev/null +++ b/plugins/ai/locales/translated/no_NO.json @@ -0,0 +1,78 @@ +{ + "ai": { + "title": "Assistent", + "send": "Sende", + "stop": "Stoppe", + "save": "Spare", + "cancel": "Kansellere", + "running": "løping", + "approve": "Vedta", + "reject": "Avvis", + "inputPlaceholder": "Spør om servitørene dine, eller beskriv en endring du vil foreslå", + "selectProvider": "Velg en leverandør", + "providerSettings": "Leverandørinnstillinger", + "addProvider": "Legg til leverandør", + "editProvider": "Rediger leverandør", + "removeProvider": "Fjern leverandør", + "providerType": "Leverandør", + "providerLabel": "Navn", + "providerLabelPlaceholder": "For eksempel: Lokal Ollama", + "baseUrl": "Serveradresse", + "apiKey": "API-nøkkel", + "defaultModel": "Standardmodell", + "defaultModelPlaceholder": "For eksempel: llama3.1 eller claude-opus-5", + "labelRequired": "Gi denne leverandøren et navn", + "providerSaveFailed": "Kunne ikke lagre leverandøren", + "providerUpdated": "Leverandøren er oppdatert", + "providerDeleteFailed": "Kunne ikke fjerne leverandøren", + "privateEndpointHint": "Adresser på ditt private nettverk krever at en administrator tillater verten først.", + "providerOllama": "Ollama", + "providerAnthropic": "Antropisk", + "providerOpenai": "Åpen kunstig intelligens", + "providerGemini": "Google Gemini", + "providerOpenaiCompatible": "OpenAI-kompatibel", + "toolArguments": "Inndata", + "toolResult": "Resultat", + "statusApplied": "Anvendt", + "statusRejected": "Avvist", + "proposalApplied": "Endringen er brukt", + "proposalApplyFailed": "Kunne ikke bruke endringen", + "proposalRejectFailed": "Kunne ikke avvise endringen", + "enableTitle": "Aktiver AI-assistenten", + "enableDescription": "La assistenten lese oppsettet ditt og foreslå endringer du kan godkjenne.", + "readOnlyCommands": "Tillat skrivebeskyttede diagnostiske kommandoer", + "readOnlyCommandsDescription": "Assistenten kan kjøre en kort liste med sikre kommandoer som df og uptime uten å spørre hver gang. Alt som endrer en server blir alltid foreslått først.", + "modelDetectFailed": "Kunne ikke nå leverandøren, så dette er en generell liste. Du kan skrive inn et hvilket som helst modellnavn.", + "modelCustom": "Skriv inn et modellnavn", + "modelRefresh": "Oppdater listen", + "modelPlaceholder": "Velg eller skriv inn en modell", + "attachHint": "Skriv inn @ for å referere til en vert, et kodeutdrag eller en automatisering. Endringer foreslås som du kan godkjenne.", + "runCommandTitle": "Kjør kommandoen", + "assistant": "AI-assistent", + "terminalPanelEmpty": "Spør assistenten om denne verten. Alt som endrer status trenger din godkjenning først.", + "terminalPanelPlaceholder": "Spør om denne verten...", + "noProvidersConfigured": "Ingen AI-leverandør er konfigurert ennå. Legg til en i AI-assistent-fanen.", + "runsInOpenTerminal": "Kjører i din åpne terminaløkt.", + "runInTerminal": "Løp" + }, + "nav": { + "ai": "AI" + }, + "onboarding": { + "aiTitle": "AI-assistent", + "aiIntro": "Termix kan inkludere en valgfri AI-assistent. Du kan endre dette senere i innstillingene dine.", + "aiSkipTitle": "La det være av", + "aiSkipDesc": "Termix fungerer som den gjør nå. Assistenten forblir skjult.", + "aiEnableTitle": "Slå den på", + "aiEnableDesc": "Legger til en assistent som leser oppsettet ditt og foreslår endringer du godkjenner. Krever en leverandør du oppgir, for eksempel en lokal Ollama.", + "aiNote": "Ingenting sendes noe sted før du legger til en leverandør og sender en melding." + }, + "admin": { + "aiGloballyEnabled": "AI-assistent", + "aiGloballyEnabledDesc": "La brukere slå på AI-assistenten. Mens dette er av, er assistenten skjult og blokkert for alle.", + "aiPrivateEndpoints": "Tillatte private AI-verter", + "aiPrivateEndpointsDesc": "Verter på ditt private nettverk som brukere kan peke en leverandør til, for eksempel en selvhostet Ollama. Skill dem med komma.", + "updateAiEnabledFailed": "Kunne ikke oppdatere AI-innstillingen", + "updateAiEndpointsFailed": "Kunne ikke oppdatere de tillatte vertene" + } +} diff --git a/plugins/ai/locales/translated/pl_PL.json b/plugins/ai/locales/translated/pl_PL.json new file mode 100644 index 000000000..19094a517 --- /dev/null +++ b/plugins/ai/locales/translated/pl_PL.json @@ -0,0 +1,78 @@ +{ + "ai": { + "title": "Asystent", + "send": "Wyślij", + "stop": "Zatrzymaj", + "save": "Zapisz", + "cancel": "Anuluj", + "running": "działa", + "approve": "Zatwierdź", + "reject": "Odrzuć", + "inputPlaceholder": "Zapytaj o swoje serwery lub opisz proponowaną zmianę", + "selectProvider": "Wybierz dostawcę", + "providerSettings": "Ustawienia dostawcy", + "addProvider": "Dodaj dostawcę", + "editProvider": "Edytuj dostawcę", + "removeProvider": "Usuń dostawcę", + "providerType": "Dostawca", + "providerLabel": "Nazwa", + "providerLabelPlaceholder": "Na przykład: Ollama lokalnie", + "baseUrl": "Adres serwera", + "apiKey": "Klucz API", + "defaultModel": "Model domyślny", + "defaultModelPlaceholder": "Na przykład: llama3.1 lub claude-opus-5", + "labelRequired": "Podaj nazwę tego dostawcy", + "providerSaveFailed": "Nie udało się zapisać dostawcy", + "providerUpdated": "Zaktualizowano dostawcę", + "providerDeleteFailed": "Nie można usunąć dostawcy", + "privateEndpointHint": "Adresy w sieci prywatnej wymagają, aby administrator najpierw dopuścił dany host.", + "providerOllama": "Ollama", + "providerAnthropic": "Anthropic", + "providerOpenai": "OpenAI", + "providerGemini": "Google Gemini", + "providerOpenaiCompatible": "Kompatybilny z OpenAI", + "toolArguments": "Dane wejściowe", + "toolResult": "Wynik", + "statusApplied": "Zastosowano", + "statusRejected": "Odrzucono", + "proposalApplied": "Zastosowano zmianę", + "proposalApplyFailed": "Nie można zastosować zmiany", + "proposalRejectFailed": "Nie można odrzucić zmiany", + "enableTitle": "Włącz asystenta AI", + "enableDescription": "Pozwól asystentowi odczytać konfigurację i proponować zmiany do Twojego zatwierdzenia.", + "readOnlyCommands": "Zezwalaj na polecenia diagnostyczne tylko do odczytu", + "readOnlyCommandsDescription": "Asystent może uruchamiać krótką listę bezpiecznych poleceń, takich jak df czy uptime, bez pytania za każdym razem. Wszystko, co zmienia serwer, jest zawsze najpierw proponowane do zatwierdzenia.", + "modelDetectFailed": "Nie udało się skontaktować z dostawcą, więc jest to lista ogólna. Możesz wpisać dowolną nazwę modelu.", + "modelCustom": "Wprowadź nazwę modelu", + "modelRefresh": "Odśwież listę", + "modelPlaceholder": "Wybierz lub wpisz model", + "attachHint": "Wpisz @, aby odwołać się do hosta, snippetu lub automatyzacji. Zmiany są proponowane do Twojego zatwierdzenia.", + "runCommandTitle": "Uruchom polecenie", + "assistant": "Asystent AI", + "terminalPanelEmpty": "Zapytaj asystenta o tego hosta. Każda zmiana stanu wymaga Twojej zgody.", + "terminalPanelPlaceholder": "Zapytaj o tego gospodarza...", + "noProvidersConfigured": "Nie skonfigurowano jeszcze żadnego dostawcy AI. Dodaj go w zakładce Asystent AI.", + "runsInOpenTerminal": "Działa w otwartej sesji terminalowej.", + "runInTerminal": "Uruchomić" + }, + "nav": { + "ai": "AI" + }, + "onboarding": { + "aiTitle": "Asystent AI", + "aiIntro": "Termix może zawierać opcjonalnego asystenta AI. Możesz to później zmienić w ustawieniach.", + "aiSkipTitle": "Zostaw wyłączone", + "aiSkipDesc": "Termix działa tak jak teraz. Asystent pozostaje ukryty.", + "aiEnableTitle": "Włącz", + "aiEnableDesc": "Dodaje asystenta, który odczytuje Twoją konfigurację i sugeruje zmiany, które zatwierdzasz. Wymaga wskazanego przez Ciebie dostawcy, np. lokalnej Ollamy.", + "aiNote": "Dopóki nie dodasz dostawcy i nie wyślesz wiadomości, nic nie zostanie wysłane." + }, + "admin": { + "aiGloballyEnabled": "Asystent AI", + "aiGloballyEnabledDesc": "Pozwól użytkownikom włączyć asystenta AI. Gdy ta opcja jest wyłączona, asystent jest ukryty i zablokowany dla wszystkich.", + "aiPrivateEndpoints": "Dozwolone prywatne hosty AI", + "aiPrivateEndpointsDesc": "Hosty w Twojej sieci prywatnej, na które użytkownicy mogą wskazać dostawcę, na przykład własna instancja Ollamy. Rozdziel je przecinkami.", + "updateAiEnabledFailed": "Nie można zaktualizować ustawień AI", + "updateAiEndpointsFailed": "Nie można zaktualizować dozwolonych hostów" + } +} diff --git a/plugins/ai/locales/translated/pt_BR.json b/plugins/ai/locales/translated/pt_BR.json new file mode 100644 index 000000000..b27ec6fe1 --- /dev/null +++ b/plugins/ai/locales/translated/pt_BR.json @@ -0,0 +1,78 @@ +{ + "ai": { + "title": "Assistente", + "send": "Enviar", + "stop": "Parar", + "save": "Salvar", + "cancel": "Cancelar", + "running": "correndo", + "approve": "Aprovar", + "reject": "Rejeitar", + "inputPlaceholder": "Pergunte sobre seus servidores ou descreva uma alteração que você gostaria de propor.", + "selectProvider": "Selecione um fornecedor", + "providerSettings": "Configurações do provedor", + "addProvider": "Adicionar provedor", + "editProvider": "Editar provedor", + "removeProvider": "Remover provedor", + "providerType": "Fornecedor", + "providerLabel": "Nome", + "providerLabelPlaceholder": "Por exemplo: Ollama local", + "baseUrl": "Endereço do servidor", + "apiKey": "Chave de API", + "defaultModel": "Modelo padrão", + "defaultModelPlaceholder": "Por exemplo: llama3.1 ou claude-opus-5", + "labelRequired": "Dê um nome a este fornecedor.", + "providerSaveFailed": "Não foi possível salvar o provedor.", + "providerUpdated": "Fornecedor atualizado", + "providerDeleteFailed": "Não foi possível remover o provedor.", + "privateEndpointHint": "Os endereços na sua rede privada precisam que um administrador autorize o host primeiro.", + "providerOllama": "Ollama", + "providerAnthropic": "Antrópico", + "providerOpenai": "OpenAI", + "providerGemini": "Google Gemini", + "providerOpenaiCompatible": "Compatível com OpenAI", + "toolArguments": "Entrada", + "toolResult": "Resultado", + "statusApplied": "Aplicado", + "statusRejected": "Rejeitado", + "proposalApplied": "Alteração aplicada", + "proposalApplyFailed": "Não foi possível aplicar a alteração.", + "proposalRejectFailed": "Não foi possível rejeitar a alteração.", + "enableTitle": "Ative o assistente de IA", + "enableDescription": "Deixe o assistente ler sua configuração e sugerir alterações para você aprovar.", + "readOnlyCommands": "Permitir comandos de diagnóstico somente leitura", + "readOnlyCommandsDescription": "O assistente pode executar uma pequena lista de comandos seguros, como `df` e `uptime`, sem perguntar a cada vez. Qualquer alteração que faça no servidor será sempre sugerida primeiro.", + "modelDetectFailed": "Não foi possível contatar o fornecedor, portanto esta é uma lista genérica. Você pode digitar o nome de qualquer modelo.", + "modelCustom": "Insira o nome do modelo", + "modelRefresh": "Atualizar lista", + "modelPlaceholder": "Selecione ou digite um modelo", + "attachHint": "Digite @ para fazer referência a um host, snippet ou automação. As alterações são propostas para sua aprovação.", + "runCommandTitle": "Executar comando", + "assistant": "Assistente de IA", + "terminalPanelEmpty": "Pergunte ao assistente sobre este anfitrião. Qualquer alteração de estado precisa da sua aprovação prévia.", + "terminalPanelPlaceholder": "Pergunte sobre este anfitrião...", + "noProvidersConfigured": "Nenhum provedor de IA está configurado ainda. Adicione um na aba do assistente de IA.", + "runsInOpenTerminal": "Executa na sua sessão de terminal aberta.", + "runInTerminal": "Correr" + }, + "nav": { + "ai": "IA" + }, + "onboarding": { + "aiTitle": "assistente de IA", + "aiIntro": "O Termix pode incluir um assistente de IA opcional. Você pode alterar isso posteriormente nas suas configurações.", + "aiSkipTitle": "Deixe desligado", + "aiSkipDesc": "O Termix funciona como está agora. O assistente permanece oculto.", + "aiEnableTitle": "Ligue-o", + "aiEnableDesc": "Adiciona um assistente que lê sua configuração e sugere alterações que você aprova. Requer um provedor fornecido por você, como um Ollama local.", + "aiNote": "Nada será enviado até que você adicione um provedor e envie uma mensagem." + }, + "admin": { + "aiGloballyEnabled": "assistente de IA", + "aiGloballyEnabledDesc": "Permita que os usuários ativem o assistente de IA. Quando estiver desativado, o assistente ficará oculto e bloqueado para todos.", + "aiPrivateEndpoints": "Hosts de IA privados permitidos", + "aiPrivateEndpointsDesc": "Hosts em sua rede privada que os usuários podem usar como provedores, como um Ollama auto-hospedado. Separe-os com vírgulas.", + "updateAiEnabledFailed": "Não foi possível atualizar as configurações de IA.", + "updateAiEndpointsFailed": "Não foi possível atualizar os hosts permitidos." + } +} diff --git a/plugins/ai/locales/translated/pt_PT.json b/plugins/ai/locales/translated/pt_PT.json new file mode 100644 index 000000000..498afaf77 --- /dev/null +++ b/plugins/ai/locales/translated/pt_PT.json @@ -0,0 +1,78 @@ +{ + "ai": { + "title": "Assistente", + "send": "Enviar", + "stop": "Parar", + "save": "Guardar", + "cancel": "Cancelar", + "running": "corrida", + "approve": "Aprovar", + "reject": "Rejeitar", + "inputPlaceholder": "Pergunte pelos seus servidores ou descreva uma alteração que gostaria de propor.", + "selectProvider": "Selecione um fornecedor", + "providerSettings": "Configurações do fornecedor", + "addProvider": "Adicionar provedor", + "editProvider": "Editar provedor", + "removeProvider": "Remover fornecedor", + "providerType": "Fornecedor", + "providerLabel": "Nome", + "providerLabelPlaceholder": "Por exemplo: Ollama local", + "baseUrl": "Endereço do servidor", + "apiKey": "Chave API", + "defaultModel": "Modelo padrão", + "defaultModelPlaceholder": "Por exemplo: llama3.1 ou claude-opus-5", + "labelRequired": "Dê um nome a este fornecedor.", + "providerSaveFailed": "Não foi possível guardar o fornecedor.", + "providerUpdated": "Fornecedor atualizado", + "providerDeleteFailed": "Não foi possível remover o fornecedor.", + "privateEndpointHint": "Os endereços na sua rede privada necessitam que um administrador autorize primeiro o host.", + "providerOllama": "Ollama", + "providerAnthropic": "Antrópico", + "providerOpenai": "OpenAI", + "providerGemini": "Google Gemini", + "providerOpenaiCompatible": "Compatível com OpenAI", + "toolArguments": "Entrada", + "toolResult": "Resultado", + "statusApplied": "Aplicado", + "statusRejected": "Rejeitado", + "proposalApplied": "Alteração aplicada", + "proposalApplyFailed": "Não foi possível aplicar a alteração.", + "proposalRejectFailed": "Não foi possível rejeitar a alteração.", + "enableTitle": "Ative o assistente de IA", + "enableDescription": "Deixe o assistente ler a sua configuração e sugerir alterações para que a aprove.", + "readOnlyCommands": "Permitir comandos de diagnóstico de leitura apenas", + "readOnlyCommandsDescription": "O assistente pode executar uma pequena lista de comandos seguros, como `df` e `uptime`, sem perguntar de cada vez. Qualquer alteração que faça no servidor será sempre sugerida em primeiro lugar.", + "modelDetectFailed": "Não foi possível contactar o fornecedor, pelo que esta é uma lista genérica. Pode digitar o nome de qualquer modelo.", + "modelCustom": "Introduza o nome do modelo", + "modelRefresh": "Atualizar lista", + "modelPlaceholder": "Selecione ou introduza um modelo", + "attachHint": "Digite @ para fazer referência a um host, snippet ou automação. As alterações são propostas para a sua aprovação.", + "runCommandTitle": "Executar comando", + "assistant": "Assistente de IA", + "terminalPanelEmpty": "Pergunte ao assistente sobre este anfitrião. Qualquer alteração de estado necessita da sua aprovação prévia.", + "terminalPanelPlaceholder": "Pergunte sobre este anfitrião...", + "noProvidersConfigured": "Nenhum fornecedor de IA está configurado ainda. Adicione um no separador do assistente de IA.", + "runsInOpenTerminal": "Executa na sua sessão de terminal aberta.", + "runInTerminal": "Correr" + }, + "nav": { + "ai": "IA" + }, + "onboarding": { + "aiTitle": "assistente de IA", + "aiIntro": "O Termix pode incluir um assistente de IA opcional. Pode alterar isso posteriormente nas suas definições.", + "aiSkipTitle": "Deixe desligado", + "aiSkipDesc": "O Termix funciona como está agora. O assistente permanece oculto.", + "aiEnableTitle": "Ligue-o", + "aiEnableDesc": "Adiciona um assistente que lê a sua configuração e sugere alterações que aprova. Requer um fornecedor fornecido por si, como um Ollama local.", + "aiNote": "Nada será enviado até que adicione um fornecedor e envie uma mensagem." + }, + "admin": { + "aiGloballyEnabled": "assistente de IA", + "aiGloballyEnabledDesc": "Permita que os utilizadores ativem o assistente de IA. Quando estiver desativado, o assistente ficará oculto e bloqueado para todos.", + "aiPrivateEndpoints": "Hosts de IA privados permitidos", + "aiPrivateEndpointsDesc": "Hosts na sua rede privada que os utilizadores podem utilizar como fornecedores, como um Ollama auto-hospedado. Separe-os com vírgulas.", + "updateAiEnabledFailed": "Não foi possível atualizar as definições de IA.", + "updateAiEndpointsFailed": "Não foi possível atualizar os hosts permitidos." + } +} diff --git a/plugins/ai/locales/translated/ro_RO.json b/plugins/ai/locales/translated/ro_RO.json new file mode 100644 index 000000000..8a6e43e32 --- /dev/null +++ b/plugins/ai/locales/translated/ro_RO.json @@ -0,0 +1,78 @@ +{ + "ai": { + "title": "Asistent", + "send": "Trimite", + "stop": "Stop", + "save": "Salva", + "cancel": "Anula", + "running": "funcţionare", + "approve": "Aproba", + "reject": "Respinge", + "inputPlaceholder": "Întreabă despre chelnerii tăi sau descrie o schimbare pe care o propui.", + "selectProvider": "Selectați un furnizor", + "providerSettings": "Setări furnizor", + "addProvider": "Adăugați furnizor", + "editProvider": "Editați furnizorul", + "removeProvider": "Eliminați furnizorul", + "providerType": "Furnizor", + "providerLabel": "Nume", + "providerLabelPlaceholder": "De exemplu: Ollama locală", + "baseUrl": "Adresa serverului", + "apiKey": "Cheie API", + "defaultModel": "Model implicit", + "defaultModelPlaceholder": "De exemplu: llama3.1 sau claude-opus-5", + "labelRequired": "Dați un nume acestui furnizor", + "providerSaveFailed": "Nu s-a putut salva furnizorul", + "providerUpdated": "Furnizor actualizat", + "providerDeleteFailed": "Nu s-a putut elimina furnizorul", + "privateEndpointHint": "Adresele din rețeaua privată necesită mai întâi permisiunea unui administrator pentru gazdă.", + "providerOllama": "Ollama", + "providerAnthropic": "Antropic", + "providerOpenai": "OpenAI", + "providerGemini": "Google Gemeni", + "providerOpenaiCompatible": "Compatibil cu OpenAI", + "toolArguments": "Intrare", + "toolResult": "Rezultat", + "statusApplied": "Aplicat", + "statusRejected": "Respins", + "proposalApplied": "Modificare aplicată", + "proposalApplyFailed": "Nu s-a putut aplica modificarea", + "proposalRejectFailed": "Nu s-a putut respinge modificarea", + "enableTitle": "Activează asistentul AI", + "enableDescription": "Permiteți asistentului să citească configurația și să sugereze modificări pentru aprobare.", + "readOnlyCommands": "Permite comenzi de diagnosticare doar în citire", + "readOnlyCommandsDescription": "Asistentul poate rula o listă scurtă de comenzi sigure, cum ar fi df și uptime, fără a întreba de fiecare dată. Orice modificare a unui server este întotdeauna propusă prima.", + "modelDetectFailed": "Nu s-a putut contacta furnizorul, așadar aceasta este o listă generală. Puteți introduce orice nume de model.", + "modelCustom": "Introduceți un nume de model", + "modelRefresh": "Reîmprospătați lista", + "modelPlaceholder": "Alegeți sau introduceți un model", + "attachHint": "Tastați @ pentru a face referire la o gazdă, un fragment de cod sau o automatizare. Sunt propuse modificări pentru aprobare.", + "runCommandTitle": "Comandă de rulare", + "assistant": "Asistent AI", + "terminalPanelEmpty": "Întreabă asistentul despre această gazdă. Orice modificare a stării necesită mai întâi aprobarea ta.", + "terminalPanelPlaceholder": "Întreabă despre această gazdă...", + "noProvidersConfigured": "Încă nu este configurat niciun furnizor de inteligență artificială. Adăugați unul în fila Asistent de inteligență artificială.", + "runsInOpenTerminal": "Rulează în sesiunea de terminal deschisă.", + "runInTerminal": "Aleargă" + }, + "nav": { + "ai": "IA" + }, + "onboarding": { + "aiTitle": "Asistent AI", + "aiIntro": "Termix poate include un asistent AI opțional. Puteți modifica acest lucru ulterior în setări.", + "aiSkipTitle": "Lasă-l deoparte", + "aiSkipDesc": "Termix funcționează ca acum. Asistentul rămâne ascuns.", + "aiEnableTitle": "Pornește-l", + "aiEnableDesc": "Adaugă un asistent care citește configurația și sugerează modificări pe care le aprobi. Necesită un furnizor furnizat de tine, cum ar fi un Ollama local.", + "aiNote": "Nimic nu este trimis nicăieri până nu adăugați un furnizor și nu trimiteți un mesaj." + }, + "admin": { + "aiGloballyEnabled": "Asistent AI", + "aiGloballyEnabledDesc": "Permiteți utilizatorilor să activeze asistentul AI. Cât timp este dezactivat, asistentul este ascuns și blocat pentru toată lumea.", + "aiPrivateEndpoints": "Gazde private AI permise", + "aiPrivateEndpointsDesc": "Gazde din rețeaua privată către care utilizatorii pot direcționa un furnizor, cum ar fi un Ollama auto-găzduit. Separați-le prin virgule.", + "updateAiEnabledFailed": "Nu s-a putut actualiza setarea AI", + "updateAiEndpointsFailed": "Nu s-au putut actualiza gazdele permise" + } +} diff --git a/plugins/ai/locales/translated/ru_RU.json b/plugins/ai/locales/translated/ru_RU.json new file mode 100644 index 000000000..e2388859f --- /dev/null +++ b/plugins/ai/locales/translated/ru_RU.json @@ -0,0 +1,78 @@ +{ + "ai": { + "title": "Помощник", + "send": "Отправлять", + "stop": "Останавливаться", + "save": "Сохранять", + "cancel": "Отмена", + "running": "бег", + "approve": "Утвердить", + "reject": "Отклонять", + "inputPlaceholder": "Поинтересуйтесь состоянием ваших серверов или предложите внести изменения.", + "selectProvider": "Выберите поставщика", + "providerSettings": "Настройки поставщика", + "addProvider": "Добавить поставщика", + "editProvider": "Поставщик редактирования", + "removeProvider": "Удалить поставщика", + "providerType": "Поставщик", + "providerLabel": "Имя", + "providerLabelPlaceholder": "Например: Местная лама", + "baseUrl": "Адрес сервера", + "apiKey": "ключ API", + "defaultModel": "Модель по умолчанию", + "defaultModelPlaceholder": "Например: llama3.1 или claude-opus-5", + "labelRequired": "Укажите имя этого поставщика услуг.", + "providerSaveFailed": "Не удалось сохранить поставщика услуг.", + "providerUpdated": "Поставщик обновлен", + "providerDeleteFailed": "Не удалось удалить поставщика услуг.", + "privateEndpointHint": "Для доступа к адресам в вашей частной сети необходимо предварительное разрешение администратора.", + "providerOllama": "оллама", + "providerAnthropic": "Антропический", + "providerOpenai": "OpenAI", + "providerGemini": "Google Gemini", + "providerOpenaiCompatible": "Совместимость с OpenAI", + "toolArguments": "Вход", + "toolResult": "Результат", + "statusApplied": "Применяемый", + "statusRejected": "Отклоненный", + "proposalApplied": "Внесены изменения.", + "proposalApplyFailed": "Не удалось применить изменения.", + "proposalRejectFailed": "Не мог отклонить изменение.", + "enableTitle": "Включите ИИ-помощника", + "enableDescription": "Позвольте ассистенту ознакомиться с вашими настройками и предложить изменения для утверждения.", + "readOnlyCommands": "Разрешить диагностические команды только для чтения", + "readOnlyCommandsDescription": "Ассистент может выполнить короткий список безопасных команд, таких как df и uptime, не запрашивая подтверждения каждый раз. Любая команда, изменяющая состояние сервера, всегда предлагается в первую очередь.", + "modelDetectFailed": "Не удалось связаться с поставщиком, поэтому это общий список. Вы можете ввести любое название модели.", + "modelCustom": "Введите название модели", + "modelRefresh": "Обновить список", + "modelPlaceholder": "Выберите или введите модель", + "attachHint": "Введите @ для ссылки на хост, фрагмент кода или автоматизацию. Предлагаются изменения для вашего утверждения.", + "runCommandTitle": "Выполните команду", + "assistant": "ИИ-помощник", + "terminalPanelEmpty": "Спросите помощника об этом хосте. Любое изменение состояния требует вашего предварительного одобрения.", + "terminalPanelPlaceholder": "Спросите об этом хостинге...", + "noProvidersConfigured": "Поставщик ИИ пока не настроен. Добавьте его на вкладке «Помощник ИИ».", + "runsInOpenTerminal": "Запускается в открытой терминальной сессии.", + "runInTerminal": "Бегать" + }, + "nav": { + "ai": "ИИ" + }, + "onboarding": { + "aiTitle": "ИИ-помощник", + "aiIntro": "В Termix можно добавить опционального ИИ-помощника. Это можно изменить позже в настройках.", + "aiSkipTitle": "Оставьте это выключенным.", + "aiSkipDesc": "Termix работает так, как сейчас. Ассистент остается скрытым.", + "aiEnableTitle": "Включите его", + "aiEnableDesc": "Добавляет помощника, который считывает ваши настройки и предлагает изменения, которые вы одобряете. Требуется поставщик, которого вы предоставляете, например, локальный Ollama.", + "aiNote": "Ничего никуда не отправляется, пока вы не добавите поставщика услуг и не отправите сообщение." + }, + "admin": { + "aiGloballyEnabled": "ИИ-помощник", + "aiGloballyEnabledDesc": "Разрешите пользователям включить голосового помощника. Если он выключен, помощник скрыт и заблокирован для всех.", + "aiPrivateEndpoints": "Разрешены частные хосты ИИ", + "aiPrivateEndpointsDesc": "Укажите хосты в вашей частной сети, на которые пользователи могут направлять запросы провайдера, например, самостоятельно размещенный Ollama. Разделяйте их запятыми.", + "updateAiEnabledFailed": "Не удалось обновить настройки ИИ.", + "updateAiEndpointsFailed": "Не удалось обновить список разрешенных хостов." + } +} diff --git a/plugins/ai/locales/translated/sr_SP.json b/plugins/ai/locales/translated/sr_SP.json new file mode 100644 index 000000000..2fa67be85 --- /dev/null +++ b/plugins/ai/locales/translated/sr_SP.json @@ -0,0 +1,78 @@ +{ + "ai": { + "title": "Асистент", + "send": "Пошаљи", + "stop": "Заустави", + "save": "Сачувај", + "cancel": "Откажи", + "running": "трчање", + "approve": "Одобри", + "reject": "Одбиј", + "inputPlaceholder": "Питајте о својим серверима или опишите промену коју желите да предложите", + "selectProvider": "Изаберите добављача", + "providerSettings": "Подешавања добављача", + "addProvider": "Додај добављача", + "editProvider": "Измени добављача", + "removeProvider": "Уклони добављача", + "providerType": "Провајдер", + "providerLabel": "Име", + "providerLabelPlaceholder": "На пример: Локална Олама", + "baseUrl": "Адреса сервера", + "apiKey": "API кључ", + "defaultModel": "Подразумевани модел", + "defaultModelPlaceholder": "На пример: llama3.1 или claude-opus-5", + "labelRequired": "Дајте име овом добављачу", + "providerSaveFailed": "Није могуће сачувати добављача", + "providerUpdated": "Провајдер је ажуриран", + "providerDeleteFailed": "Није могуће уклонити добављача", + "privateEndpointHint": "Адресе на вашој приватној мрежи прво треба да дозволе администратору хоста.", + "providerOllama": "Олама", + "providerAnthropic": "Антропски", + "providerOpenai": "OpenAI", + "providerGemini": "Гугл Џемини", + "providerOpenaiCompatible": "Компатибилно са OpenAI-ом", + "toolArguments": "Унос", + "toolResult": "Резултат", + "statusApplied": "Примењено", + "statusRejected": "Одбијено", + "proposalApplied": "Промена је примењена", + "proposalApplyFailed": "Није могуће применити промену", + "proposalRejectFailed": "Није могуће одбити промену", + "enableTitle": "Омогућите вештачку интелигенцију (AI) асистента", + "enableDescription": "Нека асистент прочита ваша подешавања и предложи измене које ћете одобрити.", + "readOnlyCommands": "Дозволи дијагностичке команде само за читање", + "readOnlyCommandsDescription": "Асистент може да покрене кратку листу безбедних команди као што су df и uptime без сваког питања. Све што мења сервер се увек прво предлаже.", + "modelDetectFailed": "Нисмо могли да контактирамо добављача, тако да је ово општа листа. Можете да унесете било који назив модела.", + "modelCustom": "Унесите назив модела", + "modelRefresh": "Освежи листу", + "modelPlaceholder": "Изаберите или унесите модел", + "attachHint": "Унесите @ да бисте референцирали хост, исечак кода или аутоматизацију. Промене се предлажу да бисте их одобрили.", + "runCommandTitle": "Покрени команду", + "assistant": "АИ асистент", + "terminalPanelEmpty": "Питајте асистента о овом домаћину. Све што мења стање прво захтева ваше одобрење.", + "terminalPanelPlaceholder": "Питајте о овом домаћину...", + "noProvidersConfigured": "Још увек није конфигурисан ниједан добављач вештачке интелигенције. Додајте га на картици помоћника за вештачку интелигенцију.", + "runsInOpenTerminal": "Покреће се у вашој отвореној терминалној сесији.", + "runInTerminal": "Трчи" + }, + "nav": { + "ai": "Вештачка интелигенција" + }, + "onboarding": { + "aiTitle": "Асистент за вештачку интелигенцију", + "aiIntro": "Termix може да укључи опционог AI асистента. Ово можете касније променити у подешавањима.", + "aiSkipTitle": "Остави то искључено", + "aiSkipDesc": "Термикс ради као и сада. Асистент остаје скривен.", + "aiEnableTitle": "Укључи га", + "aiEnableDesc": "Додаје асистента који чита ваша подешавања и предлаже измене које одобравате. Потребан је добављач кога ви обезбедите, као што је локални Олама.", + "aiNote": "Ништа се не шаље нигде док не додате провајдера и не пошаљете поруку." + }, + "admin": { + "aiGloballyEnabled": "Асистент за вештачку интелигенцију", + "aiGloballyEnabledDesc": "Дозволите корисницима да укључе вештачку интелигенцију асистента. Док је ово искључено, асистент је скривен и блокиран за све.", + "aiPrivateEndpoints": "Дозвољени приватни AI хостови", + "aiPrivateEndpointsDesc": "Домаћини на вашој приватној мрежи на које корисници могу усмерити провајдера, као што је самостално хостована Ollama. Раздвојите их зарезима.", + "updateAiEnabledFailed": "Није могуће ажурирати подешавање вештачке интелигенције", + "updateAiEndpointsFailed": "Није могуће ажурирати дозвољене хостове" + } +} diff --git a/plugins/ai/locales/translated/sv_SE.json b/plugins/ai/locales/translated/sv_SE.json new file mode 100644 index 000000000..31718fbe7 --- /dev/null +++ b/plugins/ai/locales/translated/sv_SE.json @@ -0,0 +1,78 @@ +{ + "ai": { + "title": "Assistent", + "send": "Skicka", + "stop": "Stopp", + "save": "Spara", + "cancel": "Avboka", + "running": "spring", + "approve": "Godkänna", + "reject": "Avvisa", + "inputPlaceholder": "Fråga om era servrar, eller beskriv en förändring att föreslå", + "selectProvider": "Välj en leverantör", + "providerSettings": "Leverantörsinställningar", + "addProvider": "Lägg till leverantör", + "editProvider": "Redigera leverantör", + "removeProvider": "Ta bort leverantör", + "providerType": "Leverantör", + "providerLabel": "Namn", + "providerLabelPlaceholder": "Till exempel: Lokal Ollama", + "baseUrl": "Serveradress", + "apiKey": "API-nyckel", + "defaultModel": "Standardmodell", + "defaultModelPlaceholder": "Till exempel: llama3.1 eller claude-opus-5", + "labelRequired": "Ge den här leverantören ett namn", + "providerSaveFailed": "Kunde inte spara leverantören", + "providerUpdated": "Leverantören uppdaterad", + "providerDeleteFailed": "Kunde inte ta bort leverantören", + "privateEndpointHint": "Adresser i ditt privata nätverk behöver en administratör som först tillåter värden.", + "providerOllama": "Ollama", + "providerAnthropic": "Antropisk", + "providerOpenai": "Öppen AI", + "providerGemini": "Google Gemini", + "providerOpenaiCompatible": "OpenAI-kompatibel", + "toolArguments": "Input", + "toolResult": "Resultat", + "statusApplied": "Tillämpad", + "statusRejected": "Avvisad", + "proposalApplied": "Ändring tillämpad", + "proposalApplyFailed": "Kunde inte tillämpa ändringen", + "proposalRejectFailed": "Kunde inte avvisa ändringen", + "enableTitle": "Aktivera AI-assistenten", + "enableDescription": "Låt assistenten läsa dina inställningar och föreslå ändringar som du kan godkänna.", + "readOnlyCommands": "Tillåt skrivskyddade diagnostikkommandon", + "readOnlyCommandsDescription": "Assistenten kan köra en kort lista med säkra kommandon som df och uptime utan att fråga varje gång. Allt som ändrar en server föreslås alltid först.", + "modelDetectFailed": "Kunde inte nå leverantören, så detta är en allmän lista. Du kan skriva in vilket modellnamn som helst.", + "modelCustom": "Ange ett modellnamn", + "modelRefresh": "Uppdatera listan", + "modelPlaceholder": "Välj eller skriv en modell", + "attachHint": "Skriv @ för att referera till en värd, ett kodavsnitt eller en automatisering. Ändringar föreslås för dig att godkänna.", + "runCommandTitle": "Kör kommando", + "assistant": "AI-assistent", + "terminalPanelEmpty": "Fråga assistenten om den här värden. Allt som ändras kräver ditt godkännande först.", + "terminalPanelPlaceholder": "Fråga om den här värden...", + "noProvidersConfigured": "Ingen AI-leverantör är konfigurerad ännu. Lägg till en på fliken AI-assistent.", + "runsInOpenTerminal": "Körs i din öppna terminalsession.", + "runInTerminal": "Sikt" + }, + "nav": { + "ai": "AI" + }, + "onboarding": { + "aiTitle": "AI-assistent", + "aiIntro": "Termix kan inkludera en valfri AI-assistent. Du kan ändra detta senare i dina inställningar.", + "aiSkipTitle": "Lämna den av", + "aiSkipDesc": "Termix fungerar som den gör nu. Assistenten förblir dold.", + "aiEnableTitle": "Slå på den", + "aiEnableDesc": "Lägger till en assistent som läser din installation och föreslår ändringar som du godkänner. Kräver en leverantör som du tillhandahåller, till exempel en lokal Ollama.", + "aiNote": "Ingenting skickas någonstans förrän du lägger till en leverantör och skickar ett meddelande." + }, + "admin": { + "aiGloballyEnabled": "AI-assistent", + "aiGloballyEnabledDesc": "Låt användare aktivera AI-assistenten. Medan detta är avstängt är assistenten dold och blockerad för alla.", + "aiPrivateEndpoints": "Tillåtna privata AI-värdar", + "aiPrivateEndpointsDesc": "Värdar på ditt privata nätverk som användare kan hänvisa en leverantör till, till exempel en egenhostad Ollama. Separera dem med kommatecken.", + "updateAiEnabledFailed": "Kunde inte uppdatera AI-inställningen", + "updateAiEndpointsFailed": "Kunde inte uppdatera de tillåtna värdarna" + } +} diff --git a/plugins/ai/locales/translated/th_TH.json b/plugins/ai/locales/translated/th_TH.json new file mode 100644 index 000000000..9d15e11c9 --- /dev/null +++ b/plugins/ai/locales/translated/th_TH.json @@ -0,0 +1,78 @@ +{ + "ai": { + "title": "ผู้ช่วย", + "send": "ส่ง", + "stop": "หยุด", + "save": "บันทึก", + "cancel": "ยกเลิก", + "running": "วิ่ง", + "approve": "อนุมัติ", + "reject": "ปฏิเสธ", + "inputPlaceholder": "สอบถามเกี่ยวกับเซิร์ฟเวอร์ของคุณ หรืออธิบายการเปลี่ยนแปลงที่คุณต้องการเสนอแนะ", + "selectProvider": "เลือกผู้ให้บริการ", + "providerSettings": "การตั้งค่าผู้ให้บริการ", + "addProvider": "เพิ่มผู้ให้บริการ", + "editProvider": "แก้ไขผู้ให้บริการ", + "removeProvider": "ลบผู้ให้บริการ", + "providerType": "ผู้ให้บริการ", + "providerLabel": "ชื่อ", + "providerLabelPlaceholder": "ตัวอย่างเช่น: Ollama ท้องถิ่น", + "baseUrl": "ที่อยู่เซิร์ฟเวอร์", + "apiKey": "คีย์ API", + "defaultModel": "โมเดลเริ่มต้น", + "defaultModelPlaceholder": "ตัวอย่างเช่น: llama3.1 หรือ claude-opus-5", + "labelRequired": "ตั้งชื่อให้ผู้ให้บริการรายนี้", + "providerSaveFailed": "ไม่สามารถบันทึกผู้ให้บริการได้", + "providerUpdated": "ผู้ให้บริการได้รับการอัปเดตแล้ว", + "providerDeleteFailed": "ไม่สามารถลบผู้ให้บริการได้", + "privateEndpointHint": "การเข้าถึงที่อยู่บนเครือข่ายส่วนตัวของคุณนั้น จำเป็นต้องให้ผู้ดูแลระบบอนุญาตก่อน", + "providerOllama": "โอลาม่า", + "providerAnthropic": "แอนโทรปิก", + "providerOpenai": "โอเพ่นไอ", + "providerGemini": "กูเกิล เจมินี", + "providerOpenaiCompatible": "เข้ากันได้กับ OpenAI", + "toolArguments": "ป้อนข้อมูล", + "toolResult": "ผลลัพธ์", + "statusApplied": "สมัครแล้ว", + "statusRejected": "ถูกปฏิเสธ", + "proposalApplied": "มีการเปลี่ยนแปลงเกิดขึ้น", + "proposalApplyFailed": "ไม่สามารถทำการเปลี่ยนแปลงได้", + "proposalRejectFailed": "ไม่สามารถปฏิเสธการเปลี่ยนแปลงได้", + "enableTitle": "เปิดใช้งานผู้ช่วย AI", + "enableDescription": "ให้ผู้ช่วยอ่านการตั้งค่าของคุณและแนะนำการเปลี่ยนแปลงเพื่อให้คุณอนุมัติ", + "readOnlyCommands": "อนุญาตคำสั่งวินิจฉัยแบบอ่านอย่างเดียว", + "readOnlyCommandsDescription": "ผู้ช่วยอาจเรียกใช้คำสั่งที่ปลอดภัยเพียงไม่กี่คำสั่ง เช่น df และ uptime โดยไม่ต้องถามทุกครั้ง คำสั่งใดๆ ที่เปลี่ยนแปลงสถานะของเซิร์ฟเวอร์จะถูกเสนอให้ดำเนินการก่อนเสมอ", + "modelDetectFailed": "ไม่สามารถติดต่อผู้ให้บริการได้ ดังนั้นนี่จึงเป็นรายการทั่วไป คุณสามารถพิมพ์ชื่อรุ่นใดก็ได้", + "modelCustom": "ป้อนชื่อรุ่น", + "modelRefresh": "รีเฟรชรายการ", + "modelPlaceholder": "เลือกหรือพิมพ์แบบจำลอง", + "attachHint": "พิมพ์ @ เพื่ออ้างอิงถึงโฮสต์ สนิปเป็ต หรือระบบอัตโนมัติ การเปลี่ยนแปลงที่เสนอจะถูกนำมาให้คุณอนุมัติ", + "runCommandTitle": "เรียกใช้คำสั่ง", + "assistant": "ผู้ช่วย AI", + "terminalPanelEmpty": "สอบถามผู้ช่วยเกี่ยวกับโฮสต์นี้ การเปลี่ยนแปลงสถานะใดๆ ต้องได้รับการอนุมัติจากคุณก่อน", + "terminalPanelPlaceholder": "สอบถามเกี่ยวกับโฮสต์รายนี้...", + "noProvidersConfigured": "ยังไม่ได้ตั้งค่าผู้ให้บริการ AI เพิ่มผู้ให้บริการในแท็บผู้ช่วย AI", + "runsInOpenTerminal": "ทำงานในเซสชันเทอร์มินัลที่เปิดอยู่ของคุณ", + "runInTerminal": "วิ่ง" + }, + "nav": { + "ai": "AI" + }, + "onboarding": { + "aiTitle": "ผู้ช่วย AI", + "aiIntro": "Termix อาจมีผู้ช่วย AI เสริม คุณสามารถเปลี่ยนการตั้งค่าได้ในภายหลัง", + "aiSkipTitle": "ปิดมันไว้", + "aiSkipDesc": "Termix ทำงานเหมือนเดิมทุกประการ ตัวช่วยยังคงซ่อนอยู่", + "aiEnableTitle": "เปิดใช้งาน", + "aiEnableDesc": "เพิ่มผู้ช่วยที่จะอ่านการตั้งค่าของคุณและแนะนำการเปลี่ยนแปลงที่คุณต้องอนุมัติ จำเป็นต้องมีผู้ให้บริการที่คุณจัดหาให้ เช่น Ollama ในพื้นที่ของคุณ", + "aiNote": "จะไม่มีการส่งข้อมูลใดๆ จนกว่าคุณจะเพิ่มผู้ให้บริการและส่งข้อความ" + }, + "admin": { + "aiGloballyEnabled": "ผู้ช่วย AI", + "aiGloballyEnabledDesc": "อนุญาตให้ผู้ใช้เปิดใช้งานผู้ช่วย AI ได้ เมื่อปิดใช้งานอยู่ ผู้ช่วยจะถูกซ่อนและบล็อกไม่ให้ใครเห็น", + "aiPrivateEndpoints": "อนุญาตให้โฮสต์ AI ส่วนตัว", + "aiPrivateEndpointsDesc": "โฮสต์บนเครือข่ายส่วนตัวของคุณที่ผู้ใช้สามารถชี้ไปยังผู้ให้บริการได้ เช่น Ollama ที่ติดตั้งเอง คั่นด้วยเครื่องหมายจุลภาค", + "updateAiEnabledFailed": "ไม่สามารถอัปเดตการตั้งค่า AI ได้", + "updateAiEndpointsFailed": "ไม่สามารถอัปเดตโฮสต์ที่อนุญาตได้" + } +} diff --git a/plugins/ai/locales/translated/tr_TR.json b/plugins/ai/locales/translated/tr_TR.json new file mode 100644 index 000000000..726b80533 --- /dev/null +++ b/plugins/ai/locales/translated/tr_TR.json @@ -0,0 +1,78 @@ +{ + "ai": { + "title": "Asistan", + "send": "Göndermek", + "stop": "Durmak", + "save": "Kaydetmek", + "cancel": "İptal etmek", + "running": "koşma", + "approve": "Onaylamak", + "reject": "Reddetmek", + "inputPlaceholder": "Sunucularınız hakkında bilgi isteyin veya önereceğiniz bir değişikliği açıklayın.", + "selectProvider": "Bir sağlayıcı seçin", + "providerSettings": "Sağlayıcı ayarları", + "addProvider": "Sağlayıcı ekle", + "editProvider": "Sağlayıcıyı düzenle", + "removeProvider": "Sağlayıcıyı kaldır", + "providerType": "Sağlayıcı", + "providerLabel": "İsim", + "providerLabelPlaceholder": "Örneğin: Yerel Ollama", + "baseUrl": "Sunucu adresi", + "apiKey": "API anahtarı", + "defaultModel": "Varsayılan model", + "defaultModelPlaceholder": "Örneğin: llama3.1 veya claude-opus-5", + "labelRequired": "Bu sağlayıcıya bir isim verin.", + "providerSaveFailed": "Sağlayıcı kaydedilemedi.", + "providerUpdated": "Sağlayıcı güncellendi.", + "providerDeleteFailed": "Sağlayıcı kaldırılamadı.", + "privateEndpointHint": "Özel ağınızdaki adreslerin kullanılabilmesi için öncelikle yöneticinin sunucuya izin vermesi gerekmektedir.", + "providerOllama": "Ollama", + "providerAnthropic": "Antropik", + "providerOpenai": "OpenAI", + "providerGemini": "Google Gemini", + "providerOpenaiCompatible": "OpenAI uyumlu", + "toolArguments": "Giriş", + "toolResult": "Sonuç", + "statusApplied": "Uygulandı", + "statusRejected": "Reddedilmiş", + "proposalApplied": "Değişiklik uygulandı.", + "proposalApplyFailed": "Değişiklik uygulanamadı.", + "proposalRejectFailed": "Değişikliği reddedemedim.", + "enableTitle": "Yapay zekâ asistanını etkinleştirin", + "enableDescription": "Asistanın ayarlarınızı okumasını ve onaylamanız için değişiklik önerileri sunmasını sağlayın.", + "readOnlyCommands": "Yalnızca okuma amaçlı tanı komutlarına izin ver", + "readOnlyCommandsDescription": "Yardımcı program, her seferinde sormadan df ve uptime gibi kısa bir güvenli komut listesini çalıştırabilir. Sunucuda değişiklik yapan her şey her zaman önce önerilir.", + "modelDetectFailed": "Sağlayıcıya ulaşılamadı, bu nedenle bu genel bir listedir. İstediğiniz model adını yazabilirsiniz.", + "modelCustom": "Bir model adı girin", + "modelRefresh": "Listeyi yenile", + "modelPlaceholder": "Bir model seçin veya yazın.", + "attachHint": "Bir sunucuya, kod parçasına veya otomasyona referans vermek için @ işaretini kullanın. Onaylamanız için değişiklikler öneriliyor.", + "runCommandTitle": "Çalıştır komutu", + "assistant": "Yapay Zeka Asistanı", + "terminalPanelEmpty": "Bu ev sahibi hakkında asistana danışın. Durum değişikliği gerektiren her şey önce sizin onayınızı gerektirir.", + "terminalPanelPlaceholder": "Bu ev sahibi hakkında bilgi isteyin...", + "noProvidersConfigured": "Henüz hiçbir yapay zeka sağlayıcısı yapılandırılmadı. Yapay zeka asistanı sekmesinden bir tane ekleyin.", + "runsInOpenTerminal": "Açık terminal oturumunuzda çalışır.", + "runInTerminal": "Koşmak" + }, + "nav": { + "ai": "Yapay zeka" + }, + "onboarding": { + "aiTitle": "Yapay zeka asistanı", + "aiIntro": "Termix isteğe bağlı bir yapay zeka asistanı içerebilir. Bunu daha sonra ayarlarınızdan değiştirebilirsiniz.", + "aiSkipTitle": "Kapalı bırakın", + "aiSkipDesc": "Termix şu anki haliyle çalışıyor. Asistan gizli kalıyor.", + "aiEnableTitle": "Açın", + "aiEnableDesc": "Ayarlarınızı okuyan ve onaylamanız halinde değişiklikler öneren bir asistan ekler. Yerel bir Ollama gibi, sizin sağladığınız bir sağlayıcıya ihtiyaç duyar.", + "aiNote": "Bir sağlayıcı ekleyip mesaj gönderene kadar hiçbir şey hiçbir yere gönderilmez." + }, + "admin": { + "aiGloballyEnabled": "Yapay zeka asistanı", + "aiGloballyEnabledDesc": "Kullanıcıların yapay zeka asistanını açmasına izin verin. Bu özellik kapalıyken, asistan gizlenir ve herkes için engellenir.", + "aiPrivateEndpoints": "Özel yapay zeka sunucularına izin verildi.", + "aiPrivateEndpointsDesc": "Kullanıcıların bir sağlayıcıya yönlendirebileceği, özel ağınızdaki sunucular (örneğin, kendi sunucunuzda barındırdığınız Ollama). Bunları virgülle ayırın.", + "updateAiEnabledFailed": "Yapay zeka ayarları güncellenemedi.", + "updateAiEndpointsFailed": "İzin verilen sunucular güncellenemedi." + } +} diff --git a/plugins/ai/locales/translated/uk_UA.json b/plugins/ai/locales/translated/uk_UA.json new file mode 100644 index 000000000..da6b58f62 --- /dev/null +++ b/plugins/ai/locales/translated/uk_UA.json @@ -0,0 +1,78 @@ +{ + "ai": { + "title": "Помічник", + "send": "Надіслати", + "stop": "СТІЙ", + "save": "Зберегти", + "cancel": "Скасувати", + "running": "біг", + "approve": "Схвалити", + "reject": "Відхилити", + "inputPlaceholder": "Запитайте про ваші сервери або опишіть зміну, яку ви хочете запропонувати", + "selectProvider": "Виберіть постачальника", + "providerSettings": "Налаштування постачальника", + "addProvider": "Додати постачальника", + "editProvider": "Редагувати постачальника", + "removeProvider": "Видалити постачальника", + "providerType": "Постачальник", + "providerLabel": "Ім'я", + "providerLabelPlaceholder": "Наприклад: Місцевий Оллама", + "baseUrl": "Адреса сервера", + "apiKey": "Ключ API", + "defaultModel": "Модель за замовчуванням", + "defaultModelPlaceholder": "Наприклад: llama3.1 або claude-opus-5", + "labelRequired": "Введіть назву цього постачальника", + "providerSaveFailed": "Не вдалося зберегти постачальника", + "providerUpdated": "Постачальника оновлено", + "providerDeleteFailed": "Не вдалося видалити постачальника", + "privateEndpointHint": "Адреси у вашій приватній мережі спочатку потребують дозволу адміністратора хоста.", + "providerOllama": "Оллама", + "providerAnthropic": "Антропний", + "providerOpenai": "OpenAI", + "providerGemini": "Google Близнюки", + "providerOpenaiCompatible": "Сумісний з OpenAI", + "toolArguments": "Вхід", + "toolResult": "Результат", + "statusApplied": "Застосовано", + "statusRejected": "Відхилено", + "proposalApplied": "Зміну застосовано", + "proposalApplyFailed": "Не вдалося застосувати зміну", + "proposalRejectFailed": "Не вдалося відхилити зміну", + "enableTitle": "Увімкнути помічника зі штучним інтелектом", + "enableDescription": "Дозвольте асистенту прочитати ваші налаштування та запропонувати зміни для вашого схвалення.", + "readOnlyCommands": "Дозволити діагностичні команди лише для читання", + "readOnlyCommandsDescription": "Помічник може виконувати короткий список безпечних команд, таких як df та uptime, не запитуючи щоразу. Будь-які зміни на сервері завжди пропонуються першими.", + "modelDetectFailed": "Не вдалося зв’язатися з постачальником, тому це загальний список. Ви можете ввести будь-яку назву моделі.", + "modelCustom": "Введіть назву моделі", + "modelRefresh": "Оновити список", + "modelPlaceholder": "Виберіть або введіть модель", + "attachHint": "Введіть @, щоб посилатися на хост, фрагмент або автоматизацію. Зміни пропонуються для вашого схвалення.", + "runCommandTitle": "Виконати команду", + "assistant": "Помічник зі штучним інтелектом", + "terminalPanelEmpty": "Запитайте асистента про цього хоста. Будь-яка зміна стану потребує вашого попереднього схвалення.", + "terminalPanelPlaceholder": "Запитайте про цього хоста...", + "noProvidersConfigured": "Постачальника штучного інтелекту ще не налаштовано. Додайте його на вкладці помічника штучного інтелекту.", + "runsInOpenTerminal": "Працює у вашому відкритому термінальному сеансі.", + "runInTerminal": "Бігти" + }, + "nav": { + "ai": "Штучний інтелект" + }, + "onboarding": { + "aiTitle": "Асистент зі штучним інтелектом", + "aiIntro": "Termix може включати додатковий помічник зі штучним інтелектом. Ви можете змінити це пізніше в налаштуваннях.", + "aiSkipTitle": "Залиште це вимкненим", + "aiSkipDesc": "Termix працює як і зараз. Помічник залишається прихованим.", + "aiEnableTitle": "Увімкніть це", + "aiEnableDesc": "Додає помічника, який читає ваші налаштування та пропонує зміни, які ви схвалюєте. Потрібен постачальник, якого ви надаєте, наприклад, місцевий Ollama.", + "aiNote": "Нічого нікуди не надсилається, доки ви не додасте постачальника та не надішлете повідомлення." + }, + "admin": { + "aiGloballyEnabled": "Асистент зі штучним інтелектом", + "aiGloballyEnabledDesc": "Дозвольте користувачам увімкнути помічника зі штучним інтелектом. Коли це вимкнено, помічник прихований і заблокований для всіх.", + "aiPrivateEndpoints": "Дозволені приватні хости ШІ", + "aiPrivateEndpointsDesc": "Хости у вашій приватній мережі, на які користувачі можуть вказувати провайдера, наприклад, Ollama з власним хостингом. Розділяйте їх комами.", + "updateAiEnabledFailed": "Не вдалося оновити налаштування штучного інтелекту", + "updateAiEndpointsFailed": "Не вдалося оновити дозволені хости" + } +} diff --git a/plugins/ai/locales/translated/vi_VN.json b/plugins/ai/locales/translated/vi_VN.json new file mode 100644 index 000000000..c43fec486 --- /dev/null +++ b/plugins/ai/locales/translated/vi_VN.json @@ -0,0 +1,78 @@ +{ + "ai": { + "title": "Trợ lý", + "send": "Gửi", + "stop": "Dừng lại", + "save": "Cứu", + "cancel": "Hủy bỏ", + "running": "đang chạy", + "approve": "Chấp thuận", + "reject": "Từ chối", + "inputPlaceholder": "Hãy hỏi về máy chủ của bạn, hoặc mô tả một thay đổi mà bạn muốn đề xuất.", + "selectProvider": "Chọn nhà cung cấp", + "providerSettings": "Cài đặt nhà cung cấp", + "addProvider": "Thêm nhà cung cấp", + "editProvider": "Chỉnh sửa nhà cung cấp", + "removeProvider": "Xóa nhà cung cấp", + "providerType": "Nhà cung cấp", + "providerLabel": "Tên", + "providerLabelPlaceholder": "Ví dụ: Ollama địa phương", + "baseUrl": "Địa chỉ máy chủ", + "apiKey": "Khóa API", + "defaultModel": "Mô hình mặc định", + "defaultModelPlaceholder": "Ví dụ: llama3.1 hoặc claude-opus-5", + "labelRequired": "Đặt tên cho nhà cung cấp này", + "providerSaveFailed": "Không thể lưu nhà cung cấp", + "providerUpdated": "Nhà cung cấp đã cập nhật", + "providerDeleteFailed": "Không thể xóa nhà cung cấp", + "privateEndpointHint": "Các địa chỉ trên mạng riêng của bạn cần được quản trị viên cho phép truy cập trước.", + "providerOllama": "Ollama", + "providerAnthropic": "Nhân loại", + "providerOpenai": "OpenAI", + "providerGemini": "Google Gemini", + "providerOpenaiCompatible": "Tương thích với OpenAI", + "toolArguments": "Đầu vào", + "toolResult": "Kết quả", + "statusApplied": "Đã áp dụng", + "statusRejected": "Vật bị loại bỏ", + "proposalApplied": "Thay đổi đã được áp dụng", + "proposalApplyFailed": "Không thể áp dụng thay đổi", + "proposalRejectFailed": "Không thể từ chối thay đổi", + "enableTitle": "Kích hoạt trợ lý AI", + "enableDescription": "Hãy để trợ lý đọc cấu hình của bạn và đề xuất các thay đổi để bạn phê duyệt.", + "readOnlyCommands": "Cho phép các lệnh chẩn đoán chỉ đọc", + "readOnlyCommandsDescription": "Trợ lý có thể chạy một danh sách ngắn các lệnh an toàn như df và uptime mà không cần hỏi mỗi lần. Bất kỳ lệnh nào thay đổi máy chủ đều được đề xuất trước tiên.", + "modelDetectFailed": "Không thể liên lạc được với nhà cung cấp, vì vậy đây là danh sách chung. Bạn có thể nhập bất kỳ tên mẫu nào.", + "modelCustom": "Nhập tên mẫu", + "modelRefresh": "Làm mới danh sách", + "modelPlaceholder": "Chọn hoặc nhập mô hình", + "attachHint": "Nhập @ để tham chiếu đến máy chủ, đoạn mã hoặc quy trình tự động hóa. Các thay đổi được đề xuất để bạn phê duyệt.", + "runCommandTitle": "Chạy lệnh", + "assistant": "Trợ lý AI", + "terminalPanelEmpty": "Hãy hỏi trợ lý về máy chủ này. Bất cứ thay đổi nào về trạng thái đều cần sự chấp thuận của bạn trước.", + "terminalPanelPlaceholder": "Hãy hỏi về chủ nhà này...", + "noProvidersConfigured": "Chưa có nhà cung cấp AI nào được cấu hình. Hãy thêm một nhà cung cấp trong tab trợ lý AI.", + "runsInOpenTerminal": "Chương trình này chạy trong cửa sổ dòng lệnh đang mở của bạn.", + "runInTerminal": "Chạy" + }, + "nav": { + "ai": "Trí tuệ nhân tạo" + }, + "onboarding": { + "aiTitle": "Trợ lý AI", + "aiIntro": "Termix có thể bao gồm trợ lý AI tùy chọn. Bạn có thể thay đổi điều này sau trong phần cài đặt.", + "aiSkipTitle": "Đừng làm vậy", + "aiSkipDesc": "Termix vẫn hoạt động như hiện tại. Trợ lý ảo vẫn ẩn mình.", + "aiEnableTitle": "Bật nó lên", + "aiEnableDesc": "Thêm một trợ lý đọc cấu hình của bạn và đề xuất các thay đổi mà bạn chấp thuận. Cần có nhà cung cấp do bạn chỉ định, chẳng hạn như Ollama địa phương.", + "aiNote": "Không có dữ liệu nào được gửi đi cho đến khi bạn thêm nhà cung cấp và gửi tin nhắn." + }, + "admin": { + "aiGloballyEnabled": "Trợ lý AI", + "aiGloballyEnabledDesc": "Cho phép người dùng bật trợ lý AI. Khi trợ lý này tắt, nó sẽ bị ẩn và chặn đối với tất cả mọi người.", + "aiPrivateEndpoints": "Cho phép máy chủ AI riêng", + "aiPrivateEndpointsDesc": "Các máy chủ trên mạng riêng của bạn mà người dùng có thể trỏ đến nhà cung cấp, chẳng hạn như Ollama tự lưu trữ. Phân tách chúng bằng dấu phẩy.", + "updateAiEnabledFailed": "Không thể cập nhật cài đặt AI.", + "updateAiEndpointsFailed": "Không thể cập nhật các máy chủ được cho phép" + } +} diff --git a/plugins/ai/locales/translated/zh_CN.json b/plugins/ai/locales/translated/zh_CN.json new file mode 100644 index 000000000..761d5f815 --- /dev/null +++ b/plugins/ai/locales/translated/zh_CN.json @@ -0,0 +1,78 @@ +{ + "ai": { + "title": "助手", + "send": "发送", + "stop": "停止", + "save": "保存", + "cancel": "取消", + "running": "运行中", + "approve": "批准", + "reject": "拒绝", + "inputPlaceholder": "询问服务器相关情况,或描述要提出的变更建议", + "selectProvider": "选择服务提供商", + "providerSettings": "提供商设置", + "addProvider": "添加提供商", + "editProvider": "编辑提供商", + "removeProvider": "移除提供者", + "providerType": "提供商", + "providerLabel": "名称", + "providerLabelPlaceholder": "例如:本地 Ollama", + "baseUrl": "服务器地址", + "apiKey": "API 密钥", + "defaultModel": "默认模型", + "defaultModelPlaceholder": "例如:llama3.1 或 claude-opus-5", + "labelRequired": "给此提供商起个名字", + "providerSaveFailed": "无法保存提供商", + "providerUpdated": "提供商已更新", + "providerDeleteFailed": "无法移除提供商", + "privateEndpointHint": "您私有网络上的地址需要管理员先允许主机访问。", + "providerOllama": "Ollama", + "providerAnthropic": "Anthropic", + "providerOpenai": "OpenAI", + "providerGemini": "Google Gemini", + "providerOpenaiCompatible": "兼容 OpenAI", + "toolArguments": "输入", + "toolResult": "结果", + "statusApplied": "已应用", + "statusRejected": "已拒绝", + "proposalApplied": "变更已生效", + "proposalApplyFailed": "无法应用更改", + "proposalRejectFailed": "无法拒绝更改", + "enableTitle": "启用 AI 助手", + "enableDescription": "让助手读取您的设置并提出更改建议,供您批准。", + "readOnlyCommands": "允许只读诊断命令", + "readOnlyCommandsDescription": "助手可能会在不每次都询问的情况下运行一些安全的命令,例如 `df` 和 `uptime`。任何会更改服务器的操作都会优先被提出。", + "modelDetectFailed": "无法联系到提供商,所以这里提供的是通用列表。您可以输入任何模型名称。", + "modelCustom": "请输入模型名称", + "modelRefresh": "刷新列表", + "modelPlaceholder": "选择或输入模型", + "attachHint": "输入 @ 符号可引用主机、代码片段或自动化流程。系统会提出更改建议,供您批准。", + "runCommandTitle": "运行命令", + "assistant": "人工智能助手", + "terminalPanelEmpty": "向助理询问有关此房东的信息。任何状态变更都需要您先批准。", + "terminalPanelPlaceholder": "询问一下这位房东的情况……", + "noProvidersConfigured": "尚未配置任何 AI 提供商。请在 AI 助手选项卡中添加。", + "runsInOpenTerminal": "在打开的终端会话中运行。", + "runInTerminal": "跑步" + }, + "nav": { + "ai": "AI" + }, + "onboarding": { + "aiTitle": "AI 助手", + "aiIntro": "Termix 可以包含一个可选的 AI 助手。您可以稍后在设置中更改此选项。", + "aiSkipTitle": "禁用", + "aiSkipDesc": "Termix 正常工作,AI 助手将保持隐藏状态。", + "aiEnableTitle": "启用", + "aiEnableDesc": "启用 AI 助手,它将分析您的配置并提供优化建议。需自行配置服务商,例如本地运行的 Ollama。", + "aiNote": "在您配置服务商并主动发送消息之前,绝不会向外发送任何数据。" + }, + "admin": { + "aiGloballyEnabled": "AI 助手", + "aiGloballyEnabledDesc": "允许用户开启 AI 助手。关闭此功能后,助手将被隐藏,所有用户均无法使用。", + "aiPrivateEndpoints": "允许的私有 AI 主机", + "aiPrivateEndpointsDesc": "用户可能将服务提供商指向的私有网络上的主机,例如自托管的 Ollama。用逗号分隔。", + "updateAiEnabledFailed": "无法更新 AI 设置", + "updateAiEndpointsFailed": "无法更新允许的主机列表。" + } +} diff --git a/plugins/ai/locales/translated/zh_TW.json b/plugins/ai/locales/translated/zh_TW.json new file mode 100644 index 000000000..b5abcfbe2 --- /dev/null +++ b/plugins/ai/locales/translated/zh_TW.json @@ -0,0 +1,78 @@ +{ + "ai": { + "title": "助理", + "send": "傳送", + "stop": "停止", + "save": "節省", + "cancel": "取消", + "running": "跑步", + "approve": "核准", + "reject": "拒絕", + "inputPlaceholder": "詢問伺服器相關情況,或描述要提出的變更建議", + "selectProvider": "選擇服務提供者", + "providerSettings": "提供者設定", + "addProvider": "新增提供者", + "editProvider": "編輯提供者", + "removeProvider": "移除提供者", + "providerType": "提供者", + "providerLabel": "姓名", + "providerLabelPlaceholder": "例如:本地奧拉馬", + "baseUrl": "伺服器位址", + "apiKey": "API金鑰", + "defaultModel": "預設模型", + "defaultModelPlaceholder": "例如:llama3.1 或 claude-opus-5", + "labelRequired": "給這家服務提供者取個名字", + "providerSaveFailed": "無法儲存提供者", + "providerUpdated": "提供者已更新", + "providerDeleteFailed": "無法移除提供者", + "privateEndpointHint": "您私有網路上的位址需要管理員先允許主機存取。", + "providerOllama": "奧拉瑪", + "providerAnthropic": "人類學", + "providerOpenai": "OpenAI", + "providerGemini": "Google Gemini", + "providerOpenaiCompatible": "相容 OpenAI", + "toolArguments": "輸入", + "toolResult": "結果", + "statusApplied": "應用", + "statusRejected": "已拒絕", + "proposalApplied": "變更已生效", + "proposalApplyFailed": "無法套用變更", + "proposalRejectFailed": "無法拒絕更改", + "enableTitle": "啟用人工智慧助手", + "enableDescription": "請助手讀取您的設定並提出更改建議,供您批准。", + "readOnlyCommands": "允許只讀診斷命令", + "readOnlyCommandsDescription": "助手可能會在不每次都詢問的情況下執行一些安全的命令,例如 `df` 和 `uptime`。任何會更改伺服器的操作都會優先被提出。", + "modelDetectFailed": "無法聯繫到供應商,所以這裡提供的是通用清單。您可以輸入任何型號名稱。", + "modelCustom": "請輸入型號名稱", + "modelRefresh": "重新整理清單", + "modelPlaceholder": "選擇或輸入型號", + "attachHint": "輸入 @ 符號可引用主機、程式碼片段或自動化流程。系統會提出更改建議,供您批准。", + "runCommandTitle": "運行命令", + "assistant": "人工智慧助手", + "terminalPanelEmpty": "向助理詢問有關此房東的資訊。任何狀態變更都需要您先批准。", + "terminalPanelPlaceholder": "詢問一下這位房東的狀況…", + "noProvidersConfigured": "尚未配置任何 AI 提供者。請在 AI 助理標籤中新增。", + "runsInOpenTerminal": "在開啟的終端機會話中運行。", + "runInTerminal": "跑步" + }, + "nav": { + "ai": "人工智慧" + }, + "onboarding": { + "aiTitle": "人工智慧助手", + "aiIntro": "Termix 可以包含一個可選的 AI 助手。您可以稍後在設定中變更此選項。", + "aiSkipTitle": "丟開", + "aiSkipDesc": "Termix 的運作方式與現在相同。助手保持隱藏狀態。", + "aiEnableTitle": "打開它", + "aiEnableDesc": "添加一個助手,它可以讀取您的設定並提出您批准的更改建議。需要您提供服務提供者,例如當地的 Ollama 服務提供者。", + "aiNote": "在您新增服務提供者並發送訊息之前,任何內容都不會發送到任何地方。" + }, + "admin": { + "aiGloballyEnabled": "人工智慧助手", + "aiGloballyEnabledDesc": "允許用戶開啟AI助理。關閉此功能後,助手將被隱藏,所有使用者均無法使用。", + "aiPrivateEndpoints": "允許的私有人工智慧主機", + "aiPrivateEndpointsDesc": "使用者可能將服務提供者指向的私有網路上的主機,例如自架的 Ollama。用逗號分隔。", + "updateAiEnabledFailed": "無法更新AI設定", + "updateAiEndpointsFailed": "無法更新允許的主機清單。" + } +} diff --git a/plugins/ai/manifest.json b/plugins/ai/manifest.json index 2b42971f6..493ab7f63 100644 --- a/plugins/ai/manifest.json +++ b/plugins/ai/manifest.json @@ -87,7 +87,23 @@ "descriptionKey": "permissions.secrets.share.description", "defaultRoles": ["user"] } - ] + ], + "settings": { + "admin": [ + { + "key": "access", + "type": "custom", + "component": "access" + } + ], + "user": [ + { + "key": "assistant", + "type": "custom", + "component": "assistant" + } + ] + } }, "locales": "locales", "platforms": ["linux", "win32", "darwin"] diff --git a/src/ui/onboarding/steps/AiAssistantStep.tsx b/plugins/ai/src/frontend/AiAssistantStep.tsx similarity index 79% rename from src/ui/onboarding/steps/AiAssistantStep.tsx rename to plugins/ai/src/frontend/AiAssistantStep.tsx index 13a6d2b1e..6bc93e932 100644 --- a/src/ui/onboarding/steps/AiAssistantStep.tsx +++ b/plugins/ai/src/frontend/AiAssistantStep.tsx @@ -1,8 +1,7 @@ import { useEffect, useState } from "react"; -import { useTranslation } from "react-i18next"; import { Check } from "lucide-react"; -import { saveUserPreferences } from "@/main-axios"; -import { readHiddenRailTabs } from "@/sidebar/hidden-rail-tabs"; +import { useTranslation } from "@termix/plugin-sdk/frontend"; +import { setAssistantEnabledForUser } from "./settings/AiUserSettings"; /** * Asks once, plainly. @@ -18,21 +17,7 @@ export function AiAssistantStep() { function apply(next: boolean) { setEnabled(next); - - const hidden = readHiddenRailTabs(); - if (next) hidden.delete("ai"); - else hidden.add("ai"); - - const serialized = JSON.stringify([...hidden]); - localStorage.setItem("hiddenRailTabs", serialized); - window.dispatchEvent(new Event("hiddenRailTabsChanged")); - - saveUserPreferences({ - aiAssistantEnabled: next, - hiddenRailTabs: serialized, - }).catch(() => { - // The local choice still applies if the write fails. - }); + setAssistantEnabledForUser(next); } // Skipping the step entirely still has to mean off, not unset. diff --git a/src/ui/features/ai/AiMessage.tsx b/plugins/ai/src/frontend/AiMessage.tsx similarity index 100% rename from src/ui/features/ai/AiMessage.tsx rename to plugins/ai/src/frontend/AiMessage.tsx diff --git a/src/ui/features/ai/AiPanel.tsx b/plugins/ai/src/frontend/AiPanel.tsx similarity index 99% rename from src/ui/features/ai/AiPanel.tsx rename to plugins/ai/src/frontend/AiPanel.tsx index b01e2b6e9..937abdf6d 100644 --- a/src/ui/features/ai/AiPanel.tsx +++ b/plugins/ai/src/frontend/AiPanel.tsx @@ -1,5 +1,5 @@ import { useCallback, useEffect, useRef, useState } from "react"; -import { useTranslation } from "react-i18next"; +import { useTranslation } from "@termix/plugin-sdk/frontend"; import { Loader2, Send, Settings2, Sparkles, Square } from "lucide-react"; import { Button } from "@/components/button"; import { Textarea } from "@/components/textarea"; @@ -17,7 +17,7 @@ import { getAiStatus, type AiProposal, type AiProvider, -} from "@/api/ai-api"; +} from "./ai-api"; import { AiMessage } from "./AiMessage"; import { AiProviderSettings } from "./AiProviderSettings"; import { AiToolCall } from "./AiToolCall"; diff --git a/src/ui/features/ai/AiProviderSettings.tsx b/plugins/ai/src/frontend/AiProviderSettings.tsx similarity index 99% rename from src/ui/features/ai/AiProviderSettings.tsx rename to plugins/ai/src/frontend/AiProviderSettings.tsx index 7aad68705..92012640e 100644 --- a/src/ui/features/ai/AiProviderSettings.tsx +++ b/plugins/ai/src/frontend/AiProviderSettings.tsx @@ -1,6 +1,6 @@ -import { getErrorMessage } from "../../lib/error-message.js"; +import { getErrorMessage } from "@/lib/error-message"; import { useCallback, useEffect, useState } from "react"; -import { useTranslation } from "react-i18next"; +import { useTranslation } from "@termix/plugin-sdk/frontend"; import { toast } from "sonner"; import { Loader2, Pencil, Plus, RefreshCw, Trash2 } from "lucide-react"; import { Button } from "@/components/button"; @@ -21,7 +21,7 @@ import { updateAiProvider, type AiProvider, type AiProviderType, -} from "@/api/ai-api"; +} from "./ai-api"; const PROVIDER_TYPES: Array<{ value: AiProviderType; diff --git a/src/ui/features/ai/AiToolCall.tsx b/plugins/ai/src/frontend/AiToolCall.tsx similarity index 97% rename from src/ui/features/ai/AiToolCall.tsx rename to plugins/ai/src/frontend/AiToolCall.tsx index 2ab5ebae5..8927a423b 100644 --- a/src/ui/features/ai/AiToolCall.tsx +++ b/plugins/ai/src/frontend/AiToolCall.tsx @@ -1,5 +1,5 @@ import { useState } from "react"; -import { useTranslation } from "react-i18next"; +import { useTranslation } from "@termix/plugin-sdk/frontend"; import { ChevronDown, ChevronRight, Loader2, Wrench } from "lucide-react"; import type { ToolActivity } from "./use-ai-stream"; import { toolLabel } from "./labels"; diff --git a/src/ui/features/ai/ProposalCard.tsx b/plugins/ai/src/frontend/ProposalCard.tsx similarity index 97% rename from src/ui/features/ai/ProposalCard.tsx rename to plugins/ai/src/frontend/ProposalCard.tsx index 479ed0ec1..f0e92515d 100644 --- a/src/ui/features/ai/ProposalCard.tsx +++ b/plugins/ai/src/frontend/ProposalCard.tsx @@ -1,14 +1,10 @@ -import { getErrorMessage } from "../../lib/error-message.js"; +import { getErrorMessage } from "@/lib/error-message"; import { useState } from "react"; -import { useTranslation } from "react-i18next"; +import { useTranslation } from "@termix/plugin-sdk/frontend"; import { toast } from "sonner"; import { Check, Loader2, TriangleAlert, X } from "lucide-react"; import { Button } from "@/components/button"; -import { - applyAiProposal, - rejectAiProposal, - type AiProposal, -} from "@/api/ai-api"; +import { applyAiProposal, rejectAiProposal, type AiProposal } from "./ai-api"; import { fieldLabel, toolLabel } from "./labels"; interface ProposalCardProps { diff --git a/src/ui/api/ai-api.ts b/plugins/ai/src/frontend/ai-api.ts similarity index 78% rename from src/ui/api/ai-api.ts rename to plugins/ai/src/frontend/ai-api.ts index cbeb1bf66..6841f218c 100644 --- a/src/ui/api/ai-api.ts +++ b/plugins/ai/src/frontend/ai-api.ts @@ -245,64 +245,3 @@ export async function setAiPrivateEndpoints( throw handleApiError(error, "update AI endpoint allowlist"); } } - -export async function getNotificationPrivateEndpoints(): Promise { - try { - return (await authApi.get("/users/notification-private-endpoints")).data - .hosts; - } catch (error) { - throw handleApiError(error, "get notification endpoint allowlist"); - } -} - -export async function getStepCaPrivateEndpoints(): Promise { - try { - return (await authApi.get("/users/step-ca-private-endpoints")).data.hosts; - } catch (error) { - throw handleApiError(error, "get Step CA endpoint allowlist"); - } -} - -export async function setStepCaPrivateEndpoints( - hosts: string[], -): Promise { - try { - return (await authApi.patch("/users/step-ca-private-endpoints", { hosts })) - .data.hosts; - } catch (error) { - throw handleApiError(error, "update Step CA endpoint allowlist"); - } -} - -export async function getSecretSourcePrivateEndpoints(): Promise { - try { - return (await authApi.get("/users/secret-source-private-endpoints")).data - .hosts; - } catch (error) { - throw handleApiError(error, "get secret source endpoint allowlist"); - } -} - -export async function setSecretSourcePrivateEndpoints( - hosts: string[], -): Promise { - try { - return ( - await authApi.patch("/users/secret-source-private-endpoints", { hosts }) - ).data.hosts; - } catch (error) { - throw handleApiError(error, "update secret source endpoint allowlist"); - } -} - -export async function setNotificationPrivateEndpoints( - hosts: string[], -): Promise { - try { - return ( - await authApi.patch("/users/notification-private-endpoints", { hosts }) - ).data.hosts; - } catch (error) { - throw handleApiError(error, "update notification endpoint allowlist"); - } -} diff --git a/plugins/ai/src/frontend/index.mjs b/plugins/ai/src/frontend/index.mjs deleted file mode 100644 index 1c4a3d694..000000000 --- a/plugins/ai/src/frontend/index.mjs +++ /dev/null @@ -1,68 +0,0 @@ -/** - * Frontend half of the ai plugin. - * - * AiPanel and the rest of src/ui/features/ai/ stay in core rather than - * moving here: TerminalAiPanel.tsx and TerminalProposalCard.tsx in - * src/ui/features/terminal/ (also core) import AiMessage, AiToolCall, - * useAiStream and ProposalCard directly, for the terminal's own docked AI - * panel. That is a real external dependency, the same reason session-manager - * stays in core for ssh-terminal rather than being copied into that plugin. - * - * The "ai" surface itself is not registered through registerTabComponent: - * it is a rail-view/right-dock panel baked into AppShell.tsx and - * tabUtils.tsx (railView === "ai", case "ai"), the same way the terminal's - * tab is baked into Terminal.tsx rather than going through the generic tab - * registry. What gates it is isTabTypeAvailable("ai") in - * src/ui/shell/pluginLoader.ts's BUILT_IN_TABS_BY_PLUGIN map. - * - * What this file DOES contribute is the terminal toolbar's AI button, through - * the action registry: ai.openWithContext, declared in manifest.json and - * gated on ai.services.use. The button used to be hardwired into - * TerminalToolbar.tsx behind a showAiAssistant prop. - * - * There is still no frontend plugin loader, so nothing imports this file yet - * (see src/ui/tests/sidebar/plugin-extension-seam.test.tsx). Until one exists, - * pluginLoader.ts performs the same registration itself when the ai plugin is - * enabled. This file is the version that runs once a loader lands, and the two - * must be kept in step. - */ - -export const id = "ai"; -export const tabId = "ai"; -export const actionId = "ai.openWithContext"; - -/** Asks the focused terminal to open its AI panel seeded with `context`. */ -export function openWithContext(context) { - window.dispatchEvent( - new CustomEvent("termix:ai:openWithContext", { - detail: { context: typeof context === "string" ? context : "" }, - }), - ); -} - -export async function register({ - registerAction, - registerSlotContribution, - icons, -}) { - registerAction(actionId, openWithContext, { - permission: "ai.services.use", - pluginId: id, - }); - - registerSlotContribution("terminal.toolbar", { - actionId, - titleKey: "ai.assistant", - icon: icons.Bot, - kind: "button", - pluginId: id, - }); -} - -export async function unregister({ - unregisterAction, - unregisterSlotContribution, -}) { - unregisterSlotContribution("terminal.toolbar", actionId); - unregisterAction(actionId); -} diff --git a/plugins/ai/src/frontend/index.tsx b/plugins/ai/src/frontend/index.tsx new file mode 100644 index 000000000..8939bd071 --- /dev/null +++ b/plugins/ai/src/frontend/index.tsx @@ -0,0 +1,183 @@ +import type { ComponentType } from "react"; +import { Bot, Sparkles } from "lucide-react"; +import type { + PanelProps, + TabProps, + TermixApp, +} from "@termix/plugin-sdk/frontend"; +import type { + TerminalDockProps, + TerminalSlotApi, +} from "@/features/terminal/terminal-slots"; +import { AiPanel } from "./AiPanel"; +import { TerminalAiPanel } from "./terminal/TerminalAiPanel"; +import { AiAssistantStep } from "./AiAssistantStep"; +import { AiAccessSettings } from "./settings/AiAccessSettings"; +import { AI_RAIL_ID, AiUserSettings } from "./settings/AiUserSettings"; +import { getAiStatus } from "./ai-api"; +import { AI_STATUS_CHANGED_EVENT } from "./use-ai-availability"; + +const ASSISTANT_ACTION = "ai.openWithContext"; +const DOCK_ID = "ai.assistant"; + +function AssistantPanel({ activeTabType }: PanelProps) { + return ( +
+ +
+ ); +} + +function AssistantTab() { + return ; +} + +/** The assistant docked beside a terminal. */ +function TerminalDock({ + host, + hostId, + hostLabel, + dockProps, + onClose, + onRunInTerminal, +}: TerminalDockProps) { + if (!hostId) return null; + return ( + + ); +} + +export function activate(app: TermixApp): void { + let globallyEnabled = false; + let userEnabled = false; + const surface: (() => void)[] = []; + + const clearSurface = () => { + while (surface.length > 0) surface.pop()!(); + }; + + // What the assistant shows depends on the admin switch and the user's own + // choice, so it is re-registered whenever either changes. + const applyStatus = () => { + clearSurface(); + + surface.push( + app.registerRailItem({ + id: AI_RAIL_ID, + icon: Sparkles, + titleKey: "nav.ai", + promotable: true, + rightDockable: true, + after: "macros", + order: 40, + // Off for everyone: not even a Navigation toggle. + hidden: !globallyEnabled, + }), + ); + + if (!globallyEnabled) { + app.tabs.closeTab(AI_RAIL_ID); + return; + } + + surface.push( + app.registerTab(AI_RAIL_ID, AssistantTab as ComponentType, { + icon: Sparkles, + titleKey: "nav.ai", + singleton: true, + hostless: true, + panelFrame: true, + }), + ); + + const offeredOnHost = (context: Record) => + userEnabled && + (context.host as { enableAiAssistant?: boolean } | undefined) + ?.enableAiAssistant === true; + + surface.push( + app.registerSlotContribution("terminal.toolbar", { + actionId: ASSISTANT_ACTION, + titleKey: "ai.assistant", + icon: Bot, + kind: "button", + when: offeredOnHost, + }), + ); + surface.push( + app.registerSlotContribution("terminal.dock", { + actionId: DOCK_ID, + titleKey: "ai.assistant", + icon: Bot, + kind: "component", + component: TerminalDock as unknown as ComponentType< + Record + >, + when: offeredOnHost, + }), + ); + surface.push( + app.registerSlotContribution("onboarding.steps", { + actionId: "ai.onboarding", + titleKey: "onboarding.aiTitle", + kind: "component", + component: AiAssistantStep as unknown as ComponentType< + Record + >, + }), + ); + }; + + const refresh = () => { + getAiStatus() + .then((status) => { + globallyEnabled = status.globallyEnabled; + userEnabled = status.globallyEnabled && status.enabled; + }) + .catch(() => { + globallyEnabled = false; + userEnabled = false; + }) + .finally(() => { + if (!disposed) applyStatus(); + }); + }; + + let disposed = false; + app.onDispose(() => { + disposed = true; + clearSurface(); + }); + + app.registerPanel(AI_RAIL_ID, AssistantPanel); + + // Opens the docked assistant on the terminal it was clicked from, seeded + // with what is on screen. + app.registerAction( + ASSISTANT_ACTION, + (terminal: TerminalSlotApi) => + terminal?.openDock(DOCK_ID, { context: terminal.getBufferText() }), + { permission: "services.use" }, + ); + + app.registerSettingsComponent("access", AiAccessSettings); + app.registerSettingsComponent("assistant", AiUserSettings); + + applyStatus(); + refresh(); + window.addEventListener(AI_STATUS_CHANGED_EVENT, refresh); + window.addEventListener("hiddenRailTabsChanged", refresh); + app.onDispose(() => { + window.removeEventListener(AI_STATUS_CHANGED_EVENT, refresh); + window.removeEventListener("hiddenRailTabsChanged", refresh); + }); +} diff --git a/src/ui/features/ai/labels.ts b/plugins/ai/src/frontend/labels.ts similarity index 100% rename from src/ui/features/ai/labels.ts rename to plugins/ai/src/frontend/labels.ts diff --git a/plugins/ai/src/frontend/settings/AiAccessSettings.tsx b/plugins/ai/src/frontend/settings/AiAccessSettings.tsx new file mode 100644 index 000000000..866462e65 --- /dev/null +++ b/plugins/ai/src/frontend/settings/AiAccessSettings.tsx @@ -0,0 +1,95 @@ +import { useEffect, useState } from "react"; +import { useToast, useTranslation } from "@termix/plugin-sdk/frontend"; +import { FakeSwitch, Input, SettingRow } from "@termix/plugin-sdk/ui"; +import { + getAiGloballyEnabled, + getAiPrivateEndpoints, + setAiGloballyEnabled, + setAiPrivateEndpoints, +} from "../ai-api"; +import { notifyAiStatusChanged } from "../use-ai-availability"; + +/** + * The instance-wide switch and the private address allowlist. Stored in the + * assistant's own backend rather than plugin settings, so this saves on + * change instead of through the page's Save. + */ +export function AiAccessSettings() { + const { t } = useTranslation(); + const toast = useToast(); + const [enabled, setEnabled] = useState(false); + const [endpoints, setEndpoints] = useState(null); + + useEffect(() => { + let cancelled = false; + void Promise.allSettled([ + getAiGloballyEnabled(), + getAiPrivateEndpoints(), + ]).then(([enabledResult, endpointsResult]) => { + if (cancelled) return; + if (enabledResult.status === "fulfilled") setEnabled(enabledResult.value); + setEndpoints( + endpointsResult.status === "fulfilled" ? endpointsResult.value : [], + ); + }); + return () => { + cancelled = true; + }; + }, []); + + const toggle = async (next: boolean) => { + setEnabled(next); + try { + await setAiGloballyEnabled(next); + notifyAiStatusChanged(); + } catch { + setEnabled(!next); + toast.error(t("admin.updateAiEnabledFailed")); + } + }; + + const saveEndpoints = async (hosts: string[]) => { + const previous = endpoints ?? []; + setEndpoints(hosts); + try { + setEndpoints(await setAiPrivateEndpoints(hosts)); + } catch { + setEndpoints(previous); + toast.error(t("admin.updateAiEndpointsFailed")); + } + }; + + return ( +
+ + void toggle(next)} /> + + {enabled && endpoints !== null && ( +
+ + {t("admin.aiPrivateEndpoints")} + + + {t("admin.aiPrivateEndpointsDesc")} + + + void saveEndpoints( + event.target.value + .split(",") + .map((entry) => entry.trim()) + .filter(Boolean), + ) + } + /> +
+ )} +
+ ); +} diff --git a/plugins/ai/src/frontend/settings/AiUserSettings.tsx b/plugins/ai/src/frontend/settings/AiUserSettings.tsx new file mode 100644 index 000000000..1ed59557a --- /dev/null +++ b/plugins/ai/src/frontend/settings/AiUserSettings.tsx @@ -0,0 +1,112 @@ +import { useEffect, useState } from "react"; +import { useTranslation } from "@termix/plugin-sdk/frontend"; +import { FakeSwitch, SettingRow } from "@termix/plugin-sdk/ui"; +import { saveUserPreferences } from "@/main-axios"; +import { readHiddenRailTabs } from "@/sidebar/hidden-rail-tabs"; +import { getAiStatus } from "../ai-api"; +import { notifyAiStatusChanged } from "../use-ai-availability"; + +/** The rail id the assistant registers under. */ +export const AI_RAIL_ID = "ai"; + +/** + * Turns the assistant on or off for one person. Off also hides its rail + * entry, so declining removes the feature from view rather than leaving an + * inert button behind. Stored in core user preferences, where it has always + * lived, so it roams with the rest of a user's settings. + */ +export function setAssistantEnabledForUser(enabled: boolean): void { + const hidden = readHiddenRailTabs(); + if (enabled) hidden.delete(AI_RAIL_ID); + else hidden.add(AI_RAIL_ID); + + const serialized = JSON.stringify([...hidden]); + localStorage.setItem("hiddenRailTabs", serialized); + window.dispatchEvent(new Event("hiddenRailTabsChanged")); + + saveUserPreferences({ + aiAssistantEnabled: enabled, + hiddenRailTabs: serialized, + }) + .catch(() => { + // The local choice still applies if the write fails. + }) + .finally(() => notifyAiStatusChanged()); +} + +export function AiUserSettings() { + const { t } = useTranslation(); + const [status, setStatus] = useState<{ + globallyEnabled: boolean; + enabled: boolean; + readOnly: boolean; + } | null>(null); + + useEffect(() => { + let cancelled = false; + getAiStatus() + .then((next) => { + if (!cancelled) { + setStatus({ + globallyEnabled: next.globallyEnabled, + enabled: next.enabled, + readOnly: next.allowReadOnlyCommands, + }); + } + }) + .catch(() => { + if (!cancelled) { + setStatus({ + globallyEnabled: false, + enabled: false, + readOnly: false, + }); + } + }); + return () => { + cancelled = true; + }; + }, []); + + // A user who cannot have the feature is not told about it. + if (!status?.globallyEnabled) { + return ( +

+ {t("settings.assistantUnavailable")} +

+ ); + } + + return ( +
+ + { + setStatus({ ...status, enabled }); + setAssistantEnabledForUser(enabled); + }} + /> + + {status.enabled && ( + + { + setStatus({ ...status, readOnly }); + saveUserPreferences({ aiReadOnlyCommands: readOnly }).catch( + () => {}, + ); + }} + /> + + )} +
+ ); +} diff --git a/src/ui/features/terminal/TerminalAiPanel.tsx b/plugins/ai/src/frontend/terminal/TerminalAiPanel.tsx similarity index 97% rename from src/ui/features/terminal/TerminalAiPanel.tsx rename to plugins/ai/src/frontend/terminal/TerminalAiPanel.tsx index 5c3e5a26e..a14bf3c65 100644 --- a/src/ui/features/terminal/TerminalAiPanel.tsx +++ b/plugins/ai/src/frontend/terminal/TerminalAiPanel.tsx @@ -5,20 +5,20 @@ import { useRef, useState, } from "react"; -import { useTranslation } from "react-i18next"; +import { useTranslation } from "@termix/plugin-sdk/frontend"; import { Bot, GripVertical, Send, Square, X } from "lucide-react"; import { Button } from "@/components/button"; -import { getAiProviders, type AiProposal, type AiProvider } from "@/api/ai-api"; -import { AiMessage } from "@/features/ai/AiMessage"; -import { AiToolCall } from "@/features/ai/AiToolCall"; -import { useAiStream } from "@/features/ai/use-ai-stream"; +import { getAiProviders, type AiProposal, type AiProvider } from "../ai-api"; +import { AiMessage } from "../AiMessage"; +import { AiToolCall } from "../AiToolCall"; +import { useAiStream } from "../use-ai-stream"; import { TerminalProposalCard } from "./TerminalProposalCard"; import { clampToolbarPosition, persistAiPanelPosition, readStoredAiPanelPosition, type ToolbarPosition, -} from "./toolbar-geometry"; +} from "@/features/terminal/toolbar-geometry"; interface HistoryEntry { role: "user" | "assistant"; @@ -35,7 +35,7 @@ type TimelineItem = | { kind: "tool"; key: string; - tool: import("@/features/ai/use-ai-stream").ToolActivity; + tool: import("../use-ai-stream").ToolActivity; } | { kind: "proposal"; key: string; proposal: AiProposal }; diff --git a/src/ui/features/terminal/TerminalProposalCard.tsx b/plugins/ai/src/frontend/terminal/TerminalProposalCard.tsx similarity index 95% rename from src/ui/features/terminal/TerminalProposalCard.tsx rename to plugins/ai/src/frontend/terminal/TerminalProposalCard.tsx index 4b6b214bf..d68efb45b 100644 --- a/src/ui/features/terminal/TerminalProposalCard.tsx +++ b/plugins/ai/src/frontend/terminal/TerminalProposalCard.tsx @@ -1,6 +1,6 @@ -import { getErrorMessage } from "../../lib/error-message.js"; +import { getErrorMessage } from "@/lib/error-message"; import { useState } from "react"; -import { useTranslation } from "react-i18next"; +import { useTranslation } from "@termix/plugin-sdk/frontend"; import { toast } from "sonner"; import { Check, Loader2, TriangleAlert, X } from "lucide-react"; import { Button } from "@/components/button"; @@ -8,8 +8,8 @@ import { markAiProposalRunInTerminal, rejectAiProposal, type AiProposal, -} from "@/api/ai-api"; -import { ProposalCard } from "@/features/ai/ProposalCard"; +} from "../ai-api"; +import { ProposalCard } from "../ProposalCard"; interface TerminalProposalCardProps { proposal: AiProposal; diff --git a/src/ui/hooks/use-ai-availability.ts b/plugins/ai/src/frontend/use-ai-availability.ts similarity index 98% rename from src/ui/hooks/use-ai-availability.ts rename to plugins/ai/src/frontend/use-ai-availability.ts index c58e3ac27..e34868716 100644 --- a/src/ui/hooks/use-ai-availability.ts +++ b/plugins/ai/src/frontend/use-ai-availability.ts @@ -34,7 +34,7 @@ export function useAiAvailability(): AiAvailability { useEffect(() => { let cancelled = false; const refresh = () => { - import("@/api/ai-api") + import("./ai-api") .then(({ getAiStatus }) => getAiStatus()) .then((status) => { if (cancelled) return; diff --git a/src/ui/features/ai/use-ai-stream.ts b/plugins/ai/src/frontend/use-ai-stream.ts similarity index 98% rename from src/ui/features/ai/use-ai-stream.ts rename to plugins/ai/src/frontend/use-ai-stream.ts index 3ba2c16c3..d251dbef4 100644 --- a/src/ui/features/ai/use-ai-stream.ts +++ b/plugins/ai/src/frontend/use-ai-stream.ts @@ -1,7 +1,7 @@ -import { getErrorMessage } from "../../lib/error-message.js"; +import { getErrorMessage } from "@/lib/error-message"; import { useCallback, useRef, useState } from "react"; import { authApi } from "@/main-axios"; -import type { AiProposal } from "@/api/ai-api"; +import type { AiProposal } from "./ai-api"; /** * Reuses whatever base authApi resolved to, so the stream follows the same diff --git a/src/ui/features/ai/useMentions.ts b/plugins/ai/src/frontend/useMentions.ts similarity index 84% rename from src/ui/features/ai/useMentions.ts rename to plugins/ai/src/frontend/useMentions.ts index 8f2a74c8e..5b9d94a42 100644 --- a/src/ui/features/ai/useMentions.ts +++ b/plugins/ai/src/frontend/useMentions.ts @@ -1,7 +1,7 @@ import { useCallback, useEffect, useMemo, useState } from "react"; import { getSSHHosts } from "@/api/ssh-host-management-api"; import { getSnippets } from "@/api/snippets-api"; -import { listAutomations } from "../../../../plugins/automations/src/frontend/automations-api"; +import { invokeAction } from "@termix/plugin-sdk/frontend"; /** * Backs the @-mention picker in the composer. @@ -39,6 +39,16 @@ export function activeMentionQuery( return { query, start: at }; } +/** The automations plugin's list, or nothing when it is not running. */ +async function listAutomationsForMentions(): Promise< + { id: number; name: string }[] +> { + const result = await invokeAction("automations.list"); + return Array.isArray(result) + ? (result as { id: number; name: string }[]) + : []; +} + export function useMentions(enabled: boolean) { const [items, setItems] = useState([]); @@ -50,7 +60,9 @@ export function useMentions(enabled: boolean) { const [hosts, snippets, automations] = await Promise.allSettled([ getSSHHosts(), getSnippets(), - listAutomations(), + // Through the automations plugin's action, so the assistant works + // without it and never imports its code. + listAutomationsForMentions(), ]); if (cancelled) return; diff --git a/plugins/ai/tests/frontend/AiProviderSettings.test.tsx b/plugins/ai/tests/frontend/AiProviderSettings.test.tsx index c49a3e495..ed3e9b766 100644 --- a/plugins/ai/tests/frontend/AiProviderSettings.test.tsx +++ b/plugins/ai/tests/frontend/AiProviderSettings.test.tsx @@ -6,7 +6,7 @@ import { screen, waitFor, } from "@testing-library/react"; -import type { AiProvider } from "@/api/ai-api"; +import type { AiProvider } from "../../src/frontend/ai-api"; const api = vi.hoisted(() => ({ createAiProvider: vi.fn(), @@ -16,7 +16,7 @@ const api = vi.hoisted(() => ({ updateAiProvider: vi.fn(), })); -vi.mock("@/api/ai-api", () => api); +vi.mock("../../src/frontend/ai-api", () => api); vi.mock("react-i18next", () => ({ useTranslation: () => ({ t: (key: string) => key }), })); @@ -24,7 +24,7 @@ vi.mock("sonner", () => ({ toast: { success: vi.fn(), error: vi.fn() }, })); -import { AiProviderSettings } from "@/features/ai/AiProviderSettings"; +import { AiProviderSettings } from "../../src/frontend/AiProviderSettings"; const provider: AiProvider = { id: 7, diff --git a/plugins/ai/tests/frontend/activate.test.tsx b/plugins/ai/tests/frontend/activate.test.tsx new file mode 100644 index 000000000..814097280 --- /dev/null +++ b/plugins/ai/tests/frontend/activate.test.tsx @@ -0,0 +1,53 @@ +import { afterEach, describe, expect, it } from "vitest"; +import { + renderWithApp, + type RenderedPluginApp, +} from "@termix/plugin-sdk/testing"; +import type { PluginManifest } from "@termix/plugin-sdk/manifest"; +import * as plugin from "../../src/frontend/index"; +import manifestJson from "../../manifest.json"; +import locales from "../../locales/en.json"; + +const manifest = manifestJson as unknown as PluginManifest; + +const declared = (views?: Array<{ id: string }>) => + (views ?? []).map((view) => view.id).sort(); + +let rendered: RenderedPluginApp | null = null; + +afterEach(async () => { + await rendered?.deactivate(); + rendered = null; +}); + +describe(`${manifest.id} activate`, () => { + it("activates and registers only views its manifest declares", async () => { + rendered = await renderWithApp(plugin, { manifest, locales }); + const contributes = manifest.contributes as unknown as Record< + string, + Array<{ id: string }> | undefined + >; + const tabs = declared(contributes.tabs); + // A rail panel may reuse one of the plugin's tab ids. + const panels = [...declared(contributes.panels), ...tabs]; + const cards = declared(contributes.dashboardCards); + for (const id of rendered.registered.tabs()) expect(tabs).toContain(id); + for (const id of rendered.registered.panels()) expect(panels).toContain(id); + for (const id of rendered.registered.dashboardCards()) { + expect(cards).toContain(id); + } + }); + + it("removes everything it registered on deactivate", async () => { + const app = await renderWithApp(plugin, { manifest, locales }); + await app.deactivate(); + expect(app.registered.tabs()).toEqual([]); + expect(app.registered.panels()).toEqual([]); + expect(app.registered.railItems()).toEqual([]); + expect(app.registered.hostActions()).toEqual([]); + expect(app.registered.hostEditorSections()).toEqual([]); + expect(app.registered.dashboardCards()).toEqual([]); + expect(app.registered.settingsComponents()).toEqual([]); + expect(app.registered.actions()).toEqual([]); + }); +}); diff --git a/plugins/ai/tests/frontend/labels.test.ts b/plugins/ai/tests/frontend/labels.test.ts index f16bc00cd..8f165f713 100644 --- a/plugins/ai/tests/frontend/labels.test.ts +++ b/plugins/ai/tests/frontend/labels.test.ts @@ -4,7 +4,7 @@ import { humanize, mentionLabel, toolLabel, -} from "@/features/ai/labels"; +} from "../../src/frontend/labels"; import { AI_TOOLS } from "../../src/backend/tools/catalog.js"; describe("humanize", () => { diff --git a/src/ui/tests/hooks/use-ai-availability.test.ts b/plugins/ai/tests/frontend/use-ai-availability.test.ts similarity index 96% rename from src/ui/tests/hooks/use-ai-availability.test.ts rename to plugins/ai/tests/frontend/use-ai-availability.test.ts index d6e99b98c..1398dba5e 100644 --- a/src/ui/tests/hooks/use-ai-availability.test.ts +++ b/plugins/ai/tests/frontend/use-ai-availability.test.ts @@ -2,10 +2,10 @@ import { describe, it, expect, vi, beforeEach, afterEach } from "vitest"; import { renderHook, waitFor, act } from "@testing-library/react"; const getAiStatus = vi.fn(); -vi.mock("@/api/ai-api", () => ({ getAiStatus })); +vi.mock("../../src/frontend/ai-api", () => ({ getAiStatus })); const { useAiAvailability, notifyAiStatusChanged } = - await import("../../hooks/use-ai-availability.js"); + await import("../../src/frontend/use-ai-availability"); beforeEach(() => { getAiStatus.mockReset(); diff --git a/plugins/automations/locales/en.json b/plugins/automations/locales/en.json index 0967ef424..732c00570 100644 --- a/plugins/automations/locales/en.json +++ b/plugins/automations/locales/en.json @@ -1 +1,171 @@ -{} +{ + "permissions": { + "view": { + "title": "View automations", + "description": "See the automations and their history." + }, + "create": { + "title": "Create automations", + "description": "Add new automations." + }, + "edit": { + "title": "Edit automations", + "description": "Change existing automations." + }, + "delete": { + "title": "Delete automations", + "description": "Remove automations." + }, + "run": { + "title": "Run automations", + "description": "Trigger an automation by hand." + } + }, + "newUi": { + "sidebar": { + "automations": { + "title": "Automations", + "tabAutomations": "Automations", + "tabRuns": "Runs", + "tabChannels": "Channels", + "createAutomation": "New Automation", + "backToAutomations": "Back to Automations", + "createTitle": "New Automation", + "editTitle": "Edit Automation", + "empty": "No automations yet. Create one to react to a metric, a schedule, or an event.", + "emptyRuns": "No runs yet.", + "emptyChannels": "No channels yet. Add one to send notifications somewhere.", + "noChannelsHint": "No channels set up yet. Add one in the Channels tab.", + "addChannel": "Add Channel", + "testChannel": "Test", + "channelTestSent": "Test notification sent", + "channelTestFailed": "Test notification failed", + "channelDeleted": "Channel deleted", + "deleteChannelConfirm": "Delete this channel? Automations using it will stop notifying.", + "nameLabel": "Name", + "namePlaceholder": "e.g., Clean up /data when it fills", + "nameRequired": "Name is required", + "descriptionLabel": "Description", + "descriptionPlaceholder": "Optional description", + "enabledLabel": "Enabled", + "concurrencyLabel": "If it is already running", + "concurrencyHint": "What to do when this is triggered again before the last run has finished.", + "concurrency": { + "skip": "Skip the new run", + "queue": "Wait and run after", + "allow": "Run both at once" + }, + "save": "Save", + "created": "Automation created", + "updated": "Automation saved", + "deleted": "Automation deleted", + "deleteConfirm": "Delete this automation? Its run history is deleted too.", + "runNow": "Run now", + "testRun": "Test run", + "testRunHint": "Runs every step but does not touch anything outside Termix.", + "runStarted": "Run started", + "runFinished": "Run finished: {{status}}", + "trigger": "Trigger", + "steps": "Steps", + "addStep": "Add step", + "removeStep": "Remove step", + "moveUp": "Move up", + "moveDown": "Move down", + "noSteps": "No steps yet. Add one to say what should happen.", + "webhookTokenTitle": "Webhook URL", + "webhookTokenDescription": "This is shown once. Save it now, it cannot be retrieved later.", + "copy": "Copy", + "copied": "Copied", + "viewJson": "JSON", + "viewBuilder": "Builder", + "viewGraph": "Graph", + "lastRun": "Last run", + "never": "Never", + "duration": "{{seconds}}s", + "stepOutput": "Output", + "stepError": "Error", + "dryRunBadge": "Test run", + "hostSelector": { + "trigger": "Triggering host", + "host": "Specific host", + "fleet": "Fleet", + "all": "All hosts" + }, + "triggerKinds": { + "metric_threshold": "Metric threshold", + "host_status": "Host goes up or down", + "health_check": "Health check changes", + "schedule": "On a schedule", + "docker_event": "Container event", + "internal_event": "Termix event", + "webhook": "Incoming webhook" + }, + "stepTypes": { + "notify": "Send a notification", + "http": "Call a URL", + "run_snippet": "Run a snippet", + "run_command": "Run a command", + "docker": "Control a container", + "tunnel": "Control a tunnel", + "wol": "Wake a host", + "wait": "Wait", + "set_var": "Set a variable", + "if": "If / otherwise", + "run_automation": "Run another automation", + "stop": "Stop" + }, + "statuses": { + "running": "Running", + "success": "Success", + "failed": "Failed", + "timeout": "Timed out", + "skipped": "Skipped", + "cancelled": "Cancelled" + }, + "fields": { + "host": "Host", + "metric": "Metric", + "mount": "Mount point", + "operator": "Is", + "value": "Value", + "forSeconds": "Sustained for (seconds)", + "cooldown": "Cooldown (minutes)", + "cron": "Cron expression", + "intervalSeconds": "Every (seconds)", + "timezone": "Time zone", + "timezoneServer": "Server time", + "timezoneHint": "Cron times are read in this zone. Does not apply to interval schedules.", + "container": "Container", + "command": "Command", + "url": "URL", + "method": "Method", + "body": "Body", + "channels": "Channels", + "title": "Title", + "message": "Message", + "snippet": "Snippet", + "seconds": "Seconds", + "conditionLeftPlaceholder": "Value to check", + "conditionRightPlaceholder": "Compare against", + "variableName": "Variable name", + "variableValue": "Value", + "elevated": "Run with sudo", + "onError": "If this fails", + "allowPrivateNetwork": "Allow local network addresses", + "allowPrivateNetworkHint": "Needed for a self-hosted service on your LAN. Off by default to prevent requests to internal addresses." + }, + "onError": { + "stop": "Stop the run", + "continue": "Carry on" + } + } + } + }, + "nav": { + "automations": "Automations" + }, + "onboarding": { + "feature_automations": "Automations", + "feature_automations_desc": "Run steps automatically when something happens, and get notified." + } +} diff --git a/plugins/automations/locales/translated/af_ZA.json b/plugins/automations/locales/translated/af_ZA.json new file mode 100644 index 000000000..134386398 --- /dev/null +++ b/plugins/automations/locales/translated/af_ZA.json @@ -0,0 +1,149 @@ +{ + "newUi": { + "sidebar": { + "automations": { + "title": "Outomatisasies", + "tabAutomations": "Outomatisasies", + "tabRuns": "Loopbane", + "tabChannels": "Kanale", + "createAutomation": "Nuwe Outomatisering", + "backToAutomations": "Terug na Outomatisasies", + "createTitle": "Nuwe Outomatisering", + "editTitle": "Wysig Outomatisering", + "empty": "Geen outomatisasies nog nie. Skep een om op 'n maatstaf, 'n skedule of 'n gebeurtenis te reageer.", + "emptyRuns": "Geen lopies nog nie.", + "emptyChannels": "Geen kanale nog nie. Voeg een by om kennisgewings êrens heen te stuur.", + "noChannelsHint": "Geen kanale nog opgestel nie. Voeg een by in die Kanale-oortjie.", + "addChannel": "Voeg kanaal by", + "testChannel": "Toets", + "channelTestSent": "Toetskennisgewing gestuur", + "channelTestFailed": "Toetskennisgewing het misluk", + "channelDeleted": "Kanaal uitgevee", + "deleteChannelConfirm": "Vee hierdie kanaal uit? Outomatiserings wat dit gebruik, sal ophou om kennisgewings te stuur.", + "nameLabel": "Naam", + "namePlaceholder": "bv. Maak /data skoon wanneer dit vol is", + "nameRequired": "Naam word vereis", + "descriptionLabel": "Beskrywing", + "descriptionPlaceholder": "Opsionele beskrywing", + "enabledLabel": "Geaktiveer", + "concurrencyLabel": "As dit reeds aan die gang is", + "concurrencyHint": "Wat om te doen wanneer dit weer geaktiveer word voordat die laaste lopie klaar is.", + "concurrency": { + "skip": "Slaan die nuwe lopie oor", + "queue": "Wag en hardloop agterna", + "allow": "Begin albei gelyktydig" + }, + "save": "Stoor", + "created": "Outomatisering geskep", + "updated": "Outomatisering gestoor", + "deleted": "Outomatisering uitgevee", + "deleteConfirm": "Vee hierdie outomatisering uit? Die loopgeskiedenis daarvan word ook uitgevee.", + "runNow": "Hardloop nou", + "testRun": "Toetslopie", + "testRunHint": "Loop elke stap, maar raak niks buite Termix aan nie.", + "runStarted": "Loop het begin", + "runFinished": "Loop voltooi: {{status}}", + "trigger": "Sneller", + "steps": "Stappe", + "addStep": "Voeg stap by", + "removeStep": "Verwyder stap", + "moveUp": "Beweeg op", + "moveDown": "Beweeg af", + "noSteps": "Geen stappe nog nie. Voeg een by om te sê wat moet gebeur.", + "webhookTokenTitle": "Webhook-URL", + "webhookTokenDescription": "Dit word een keer gewys. Stoor dit nou, dit kan nie later herwin word nie.", + "copy": "Kopieer", + "copied": "Gekopieer", + "viewJson": "JSON", + "viewBuilder": "Bouer", + "viewGraph": "Grafiek", + "lastRun": "Laaste lopie", + "never": "Nooit", + "duration": "{{seconds}}s", + "stepOutput": "Uitset", + "stepError": "Fout", + "dryRunBadge": "Toetslopie", + "hostSelector": { + "trigger": "Aanvallende gasheer", + "host": "Spesifieke gasheer", + "fleet": "Vloot", + "all": "Alle gashere" + }, + "triggerKinds": { + "metric_threshold": "Metrieke drempel", + "host_status": "Gasheer gaan op of af", + "health_check": "Veranderinge in gesondheidstoetse", + "schedule": "Op 'n skedule", + "docker_event": "Houergebeurtenis", + "internal_event": "Termix-geleentheid", + "webhook": "Inkomende webhook" + }, + "stepTypes": { + "notify": "Stuur 'n kennisgewing", + "http": "Roep 'n URL op", + "run_snippet": "Voer 'n brokkie uit", + "run_command": "Voer 'n opdrag uit", + "docker": "Beheer 'n houer", + "tunnel": "Beheer 'n tonnel", + "wol": "Maak 'n gasheer wakker", + "wait": "Wag", + "set_var": "Stel 'n veranderlike", + "if": "Indien / andersins", + "run_automation": "Begin nog 'n outomatisering", + "stop": "Stop" + }, + "statuses": { + "running": "Hardloop", + "success": "Sukses", + "failed": "Misluk", + "timeout": "Tyd verstryk", + "skipped": "Oorgeslaan", + "cancelled": "Gekanselleer" + }, + "fields": { + "host": "Gasheer", + "metric": "Metrieke", + "mount": "Monteerpunt", + "operator": "Is", + "value": "Waarde", + "forSeconds": "Aangehou vir (sekondes)", + "cooldown": "Afkoeltyd (minute)", + "cron": "Cron-uitdrukking", + "intervalSeconds": "Elke (sekondes)", + "timezone": "Tydsone", + "timezoneServer": "Bedienertyd", + "timezoneHint": "Cron-tye word in hierdie sone gelees. Geld nie vir intervalskedules nie.", + "container": "Houer", + "command": "Bevel", + "url": "URL", + "method": "Metode", + "body": "Liggaam", + "channels": "Kanale", + "title": "Titel", + "message": "Boodskap", + "snippet": "Brokkie", + "seconds": "Sekondes", + "conditionLeftPlaceholder": "Waarde om na te gaan", + "conditionRightPlaceholder": "Vergelyk teen", + "variableName": "Veranderlike naam", + "variableValue": "Waarde", + "elevated": "Begin met sudo", + "onError": "As dit misluk", + "allowPrivateNetwork": "Laat plaaslike netwerkadresse toe", + "allowPrivateNetworkHint": "Nodig vir 'n selfgehoste diens op jou LAN. Standaard afgeskakel om versoeke na interne adresse te voorkom." + }, + "onError": { + "stop": "Stop die hardloop", + "continue": "Gaan voort" + } + } + } + }, + "nav": { + "automations": "Outomatisasies" + }, + "onboarding": { + "feature_automations": "Outomatisasies", + "feature_automations_desc": "Voer stappe outomaties uit wanneer iets gebeur, en word in kennis gestel." + } +} diff --git a/plugins/automations/locales/translated/ar_SA.json b/plugins/automations/locales/translated/ar_SA.json new file mode 100644 index 000000000..860c17fd5 --- /dev/null +++ b/plugins/automations/locales/translated/ar_SA.json @@ -0,0 +1,149 @@ +{ + "newUi": { + "sidebar": { + "automations": { + "title": "الأتمتة", + "tabAutomations": "الأتمتة", + "tabRuns": "يركض", + "tabChannels": "القنوات", + "createAutomation": "الأتمتة الجديدة", + "backToAutomations": "العودة إلى الأتمتة", + "createTitle": "الأتمتة الجديدة", + "editTitle": "أتمتة التحرير", + "empty": "لا توجد عمليات أتمتة حتى الآن. أنشئ واحدة للتفاعل مع مقياس أو جدول زمني أو حدث.", + "emptyRuns": "لم يتم تسجيل أي نقاط حتى الآن.", + "emptyChannels": "لا توجد قنوات حتى الآن. أضف قناة لإرسال الإشعارات إلى مكان ما.", + "noChannelsHint": "لم يتم إعداد أي قنوات بعد. أضف قناة في تبويب القنوات.", + "addChannel": "إضافة قناة", + "testChannel": "امتحان", + "channelTestSent": "تم إرسال إشعار الاختبار", + "channelTestFailed": "فشل إشعار الاختبار", + "channelDeleted": "تم حذف القناة", + "deleteChannelConfirm": "هل تريد حذف هذه القناة؟ ستتوقف عمليات التشغيل الآلي التي تستخدمها عن إرسال الإشعارات.", + "nameLabel": "اسم", + "namePlaceholder": "مثال: تنظيف /data عند امتلائها", + "nameRequired": "الاسم مطلوب", + "descriptionLabel": "وصف", + "descriptionPlaceholder": "وصف اختياري", + "enabledLabel": "مُفعّل", + "concurrencyLabel": "إذا كان قيد التشغيل بالفعل", + "concurrencyHint": "ماذا نفعل عندما يتم تشغيل هذا مرة أخرى قبل انتهاء التشغيل الأخير؟", + "concurrency": { + "skip": "تخطَّ الجولة الجديدة", + "queue": "انتظر واركض خلفه", + "allow": "قم بتشغيل كليهما في وقت واحد" + }, + "save": "يحفظ", + "created": "تم إنشاء الأتمتة", + "updated": "تم حفظ الأتمتة", + "deleted": "تم حذف الأتمتة", + "deleteConfirm": "هل تريد حذف هذه العملية الآلية؟ سيتم حذف سجل تشغيلها أيضاً.", + "runNow": "انطلق الآن", + "testRun": "تشغيل تجريبي", + "testRunHint": "يقوم بتنفيذ كل خطوة ولكنه لا يلمس أي شيء خارج Termix.", + "runStarted": "بدأ الجري", + "runFinished": "انتهت العملية: {{status}}", + "trigger": "مشغل", + "steps": "خطوات", + "addStep": "خطوات إضافية", + "removeStep": "خطوة الإزالة", + "moveUp": "انتقل إلى مستوى أعلى", + "moveDown": "انزل لأسفل", + "noSteps": "لم تُتخذ أي خطوات بعد. أضف خطوة واحدة لتوضيح ما ينبغي أن يحدث.", + "webhookTokenTitle": "رابط الويب هوك", + "webhookTokenDescription": "هذا يظهر مرة واحدة فقط. احفظه الآن، فلن تتمكن من استعادته لاحقاً.", + "copy": "ينسخ", + "copied": "تم النسخ", + "viewJson": "JSON", + "viewBuilder": "باني", + "viewGraph": "الرسم البياني", + "lastRun": "الجولة الأخيرة", + "never": "أبداً", + "duration": "{{seconds}}s", + "stepOutput": "الناتج", + "stepError": "خطأ", + "dryRunBadge": "تشغيل تجريبي", + "hostSelector": { + "trigger": "تشغيل المضيف", + "host": "مضيف محدد", + "fleet": "أسطول", + "all": "جميع المضيفين" + }, + "triggerKinds": { + "metric_threshold": "العتبة المترية", + "host_status": "يرتفع أو ينخفض مستوى المضيف", + "health_check": "تغييرات في الفحص الصحي", + "schedule": "وفقًا لجدول زمني", + "docker_event": "حدث الحاوية", + "internal_event": "حدث تيرميكس", + "webhook": "رابط الويب الوارد" + }, + "stepTypes": { + "notify": "إرسال إشعار", + "http": "استدعاء عنوان URL", + "run_snippet": "قم بتشغيل جزء من التعليمات البرمجية", + "run_command": "نفّذ أمرًا", + "docker": "التحكم في حاوية", + "tunnel": "التحكم في نفق", + "wol": "أيقظ مضيفًا", + "wait": "انتظر", + "set_var": "قم بتعيين متغير", + "if": "إذا / خلاف ذلك", + "run_automation": "قم بتشغيل عملية أتمتة أخرى", + "stop": "قف" + }, + "statuses": { + "running": "جري", + "success": "نجاح", + "failed": "فشل", + "timeout": "انتهت مهلة الاتصال", + "skipped": "تم التخطي", + "cancelled": "تم الإلغاء" + }, + "fields": { + "host": "يستضيف", + "metric": "متري", + "mount": "نقطة التثبيت", + "operator": "يكون", + "value": "قيمة", + "forSeconds": "استمر لمدة (ثوانٍ)", + "cooldown": "فترة التهدئة (بالدقائق)", + "cron": "تعبير كرون", + "intervalSeconds": "كل (ثانية)", + "timezone": "المنطقة الزمنية", + "timezoneServer": "وقت الخادم", + "timezoneHint": "تُقرأ أوقات Cron في هذه المنطقة. لا ينطبق ذلك على الجداول الزمنية الفاصلة.", + "container": "حاوية", + "command": "يأمر", + "url": "عنوان URL", + "method": "طريقة", + "body": "جسم", + "channels": "القنوات", + "title": "عنوان", + "message": "رسالة", + "snippet": "مقتطف", + "seconds": "ثوانٍ", + "conditionLeftPlaceholder": "قيمة يجب التحقق منها", + "conditionRightPlaceholder": "قارن بـ", + "variableName": "اسم المتغير", + "variableValue": "قيمة", + "elevated": "قم بتشغيل الأمر sudo", + "onError": "إذا فشل هذا", + "allowPrivateNetwork": "السماح بعناوين الشبكة المحلية", + "allowPrivateNetworkHint": "هذا الخيار ضروري لخدمة مُستضافة ذاتيًا على شبكتك المحلية. وهو مُعطّل افتراضيًا لمنع الطلبات إلى العناوين الداخلية." + }, + "onError": { + "stop": "أوقف الجري", + "continue": "حمل" + } + } + } + }, + "nav": { + "automations": "الأتمتة" + }, + "onboarding": { + "feature_automations": "الأتمتة", + "feature_automations_desc": "قم بتشغيل الخطوات تلقائيًا عند حدوث شيء ما، واحصل على إشعار بذلك." + } +} diff --git a/plugins/automations/locales/translated/bg_BG.json b/plugins/automations/locales/translated/bg_BG.json new file mode 100644 index 000000000..1c1e71809 --- /dev/null +++ b/plugins/automations/locales/translated/bg_BG.json @@ -0,0 +1,149 @@ +{ + "newUi": { + "sidebar": { + "automations": { + "title": "Автоматизации", + "tabAutomations": "Автоматизации", + "tabRuns": "Бягания", + "tabChannels": "Канали", + "createAutomation": "Нова автоматизация", + "backToAutomations": "Обратно към Автоматизации", + "createTitle": "Нова автоматизация", + "editTitle": "Редактиране на автоматизация", + "empty": "Все още няма автоматизации. Създайте такава, която да реагира на показател, график или събитие.", + "emptyRuns": "Все още няма бягания.", + "emptyChannels": "Все още няма канали. Добавете такъв, за да изпращате известия някъде.", + "noChannelsHint": "Все още няма настроени канали. Добавете такъв в раздела „Канали“.", + "addChannel": "Добавяне на канал", + "testChannel": "Тест", + "channelTestSent": "Тестово известие е изпратено", + "channelTestFailed": "Тестовото известие не беше успешно", + "channelDeleted": "Каналът е изтрит", + "deleteChannelConfirm": "Да се изтрие ли този канал? Автоматизациите, които го използват, ще спрат да получават известия.", + "nameLabel": "Име", + "namePlaceholder": "напр. Почистване на /данни, когато се запълни", + "nameRequired": "Името е задължително", + "descriptionLabel": "Описание", + "descriptionPlaceholder": "Незадължително описание", + "enabledLabel": "Активирано", + "concurrencyLabel": "Ако вече работи", + "concurrencyHint": "Какво да направите, когато това се задейства отново, преди да е завършило последното изпълнение.", + "concurrency": { + "skip": "Пропуснете новото бягане", + "queue": "Изчакай и бягай след това", + "allow": "Изпълнете и двете едновременно" + }, + "save": "Запазване", + "created": "Автоматизация, създадена", + "updated": "Автоматизацията е запазена", + "deleted": "Автоматизацията е изтрита", + "deleteConfirm": "Да се изтрие ли тази автоматизация? Историята на нейните изпълнения също ще бъде изтрита.", + "runNow": "Бягай сега", + "testRun": "Тестов пробег", + "testRunHint": "Изпълнява всяка стъпка, но не докосва нищо извън Termix.", + "runStarted": "Бягането започна", + "runFinished": "Изпълнението е завършено: {{status}}", + "trigger": "Спусък", + "steps": "Стъпки", + "addStep": "Добавяне на стъпка", + "removeStep": "Премахване на стъпка", + "moveUp": "Премести нагоре", + "moveDown": "Премести надолу", + "noSteps": "Все още няма стъпки. Добавете една, за да кажете какво трябва да се случи.", + "webhookTokenTitle": "URL адрес на уебкукичката", + "webhookTokenDescription": "Това се показва веднъж. Запазете го сега, не може да бъде извлечено по-късно.", + "copy": "Копиране", + "copied": "Копирано", + "viewJson": "JSON", + "viewBuilder": "Строител", + "viewGraph": "Графика", + "lastRun": "Последно бягане", + "never": "Никога", + "duration": "{{seconds}}с", + "stepOutput": "Изход", + "stepError": "Грешка", + "dryRunBadge": "Тестов пробег", + "hostSelector": { + "trigger": "Задействащ хост", + "host": "Специфичен хост", + "fleet": "Флот", + "all": "Всички хостове" + }, + "triggerKinds": { + "metric_threshold": "Праг на показателя", + "host_status": "Домакинът се изкачва или слиза", + "health_check": "Промени в проверката на състоянието", + "schedule": "По график", + "docker_event": "Събитие в контейнера", + "internal_event": "Събитие Termix", + "webhook": "Входящ уеб кукичка" + }, + "stepTypes": { + "notify": "Изпращане на известие", + "http": "Извикване на URL адрес", + "run_snippet": "Изпълнете фрагмент", + "run_command": "Изпълнете команда", + "docker": "Контрол на контейнер", + "tunnel": "Контрол на тунел", + "wol": "Събудете домакин", + "wait": "Чакай", + "set_var": "Задаване на променлива", + "if": "Ако / в противен случай", + "run_automation": "Изпълнете друга автоматизация", + "stop": "Спри" + }, + "statuses": { + "running": "Бягане", + "success": "Успех", + "failed": "Неуспешно", + "timeout": "Времето за изчакване изтече", + "skipped": "Пропуснато", + "cancelled": "Отменено" + }, + "fields": { + "host": "Домакин", + "metric": "Метричен", + "mount": "Точка на монтиране", + "operator": "Е", + "value": "Стойност", + "forSeconds": "Задържа се за (секунди)", + "cooldown": "Охлаждане (минути)", + "cron": "Cron израз", + "intervalSeconds": "Всеки (секунди)", + "timezone": "Часова зона", + "timezoneServer": "Време на сървъра", + "timezoneHint": "Cron времената се отчитат в тази зона. Не се отнася за интервални графици.", + "container": "Контейнер", + "command": "Команда", + "url": "URL адрес", + "method": "Метод", + "body": "Тяло", + "channels": "Канали", + "title": "Заглавие", + "message": "Съобщение", + "snippet": "Фрагмент", + "seconds": "Секунди", + "conditionLeftPlaceholder": "Стойност за проверка", + "conditionRightPlaceholder": "Сравнете с", + "variableName": "Име на променлива", + "variableValue": "Стойност", + "elevated": "Стартирай със sudo", + "onError": "Ако това не успее", + "allowPrivateNetwork": "Разрешаване на локални мрежови адреси", + "allowPrivateNetworkHint": "Необходимо за самостоятелно хоствана услуга във вашата локална мрежа. Изключено по подразбиране, за да се предотвратят заявки към вътрешни адреси." + }, + "onError": { + "stop": "Спрете бягането", + "continue": "Продължавай" + } + } + } + }, + "nav": { + "automations": "Автоматизации" + }, + "onboarding": { + "feature_automations": "Автоматизации", + "feature_automations_desc": "Изпълнявайте стъпките автоматично, когато нещо се случи, и получавайте известия." + } +} diff --git a/plugins/automations/locales/translated/bn_BD.json b/plugins/automations/locales/translated/bn_BD.json new file mode 100644 index 000000000..7a29f0613 --- /dev/null +++ b/plugins/automations/locales/translated/bn_BD.json @@ -0,0 +1,149 @@ +{ + "newUi": { + "sidebar": { + "automations": { + "title": "অটোমেশন", + "tabAutomations": "অটোমেশন", + "tabRuns": "রান", + "tabChannels": "চ্যানেল", + "createAutomation": "নতুন অটোমেশন", + "backToAutomations": "অটোমেশনে ফিরে যান", + "createTitle": "নতুন অটোমেশন", + "editTitle": "সম্পাদনা অটোমেশন", + "empty": "এখনো কোনো অটোমেশন নেই। কোনো মেট্রিক, শিডিউল বা ইভেন্টের প্রতিক্রিয়ায় একটি তৈরি করুন।", + "emptyRuns": "এখনো কোনো রান হয়নি।", + "emptyChannels": "এখনো কোনো চ্যানেল নেই। নোটিফিকেশন পাঠানোর জন্য একটি চ্যানেল যোগ করুন।", + "noChannelsHint": "এখনো কোনো চ্যানেল সেট আপ করা হয়নি। চ্যানেল ট্যাবে একটি চ্যানেল যোগ করুন।", + "addChannel": "চ্যানেল যোগ করুন", + "testChannel": "পরীক্ষা", + "channelTestSent": "পরীক্ষার বিজ্ঞপ্তি পাঠানো হয়েছে", + "channelTestFailed": "পরীক্ষার বিজ্ঞপ্তি ব্যর্থ হয়েছে", + "channelDeleted": "চ্যানেল মুছে ফেলা হয়েছে", + "deleteChannelConfirm": "এই চ্যানেলটি মুছে ফেললে? এটি ব্যবহার করা অটোমেশনগুলো নোটিফিকেশন পাঠানো বন্ধ করে দেবে।", + "nameLabel": "নাম", + "namePlaceholder": "যেমন, /data পূর্ণ হয়ে গেলে তা পরিষ্কার করুন।", + "nameRequired": "নাম আবশ্যক", + "descriptionLabel": "বর্ণনা", + "descriptionPlaceholder": "ঐচ্ছিক বিবরণ", + "enabledLabel": "সক্ষম করা হয়েছে", + "concurrencyLabel": "যদি এটি ইতিমধ্যে চালু থাকে", + "concurrencyHint": "শেষ রান শেষ হওয়ার আগেই এটি আবার চালু হলে কী করতে হবে।", + "concurrency": { + "skip": "নতুন রানটি এড়িয়ে যান।", + "queue": "অপেক্ষা করো এবং পিছনে দৌড়াও", + "allow": "একসাথে দুটোই চালান" + }, + "save": "সংরক্ষণ করুন", + "created": "অটোমেশন তৈরি করা হয়েছে", + "updated": "অটোমেশন সংরক্ষিত", + "deleted": "অটোমেশন মুছে ফেলা হয়েছে", + "deleteConfirm": "এই অটোমেশনটি ডিলিট করলে, এর রান হিস্ট্রিও ডিলিট হয়ে যাবে।", + "runNow": "এখনই দৌড়ান", + "testRun": "পরীক্ষামূলক চালনা", + "testRunHint": "প্রতিটি ধাপ চলে কিন্তু টার্মিক্সের বাইরের কোনো কিছু স্পর্শ করে না।", + "runStarted": "দৌড় শুরু হলো", + "runFinished": "দৌড় শেষ: {{status}}", + "trigger": "ট্রিগার", + "steps": "পদক্ষেপ", + "addStep": "ধাপ যোগ করুন", + "removeStep": "ধাপটি সরান", + "moveUp": "উপরে উঠুন", + "moveDown": "নিচে নামুন", + "noSteps": "এখনো কোনো ধাপ যোগ করা হয়নি। কী হওয়া উচিত তা জানাতে একটি ধাপ যোগ করুন।", + "webhookTokenTitle": "ওয়েবহুক ইউআরএল", + "webhookTokenDescription": "এটি একবারই দেখানো হবে। এখনই সংরক্ষণ করুন, পরে আর পুনরুদ্ধার করা যাবে না।", + "copy": "অনুলিপি", + "copied": "অনুলিপি করা হয়েছে", + "viewJson": "JSON", + "viewBuilder": "নির্মাতা", + "viewGraph": "গ্রাফ", + "lastRun": "শেষ দৌড়", + "never": "কখনো না", + "duration": "{{seconds}}s", + "stepOutput": "আউটপুট", + "stepError": "ত্রুটি", + "dryRunBadge": "পরীক্ষামূলক চালনা", + "hostSelector": { + "trigger": "ট্রিগারিং হোস্ট", + "host": "নির্দিষ্ট হোস্ট", + "fleet": "ফ্লিট", + "all": "সকল হোস্ট" + }, + "triggerKinds": { + "metric_threshold": "মেট্রিক থ্রেশহোল্ড", + "host_status": "হোস্ট উপরে বা নিচে যায়", + "health_check": "স্বাস্থ্য পরীক্ষার পরিবর্তন", + "schedule": "একটি সময়সূচী অনুযায়ী", + "docker_event": "কন্টেইনার ইভেন্ট", + "internal_event": "টারমিক্স ইভেন্ট", + "webhook": "ইনকামিং ওয়েবহুক" + }, + "stepTypes": { + "notify": "একটি বিজ্ঞপ্তি পাঠান", + "http": "একটি URL কল করুন", + "run_snippet": "একটি স্নিপেট চালান", + "run_command": "একটি কমান্ড চালান", + "docker": "একটি কন্টেইনার নিয়ন্ত্রণ করুন", + "tunnel": "একটি টানেল নিয়ন্ত্রণ করুন", + "wol": "একজন হোস্টকে জাগান", + "wait": "অপেক্ষা করুন", + "set_var": "একটি ভেরিয়েবল সেট করুন", + "if": "যদি / অন্যথায়", + "run_automation": "আরেকটি অটোমেশন চালান", + "stop": "থামুন" + }, + "statuses": { + "running": "দৌড়ানো", + "success": "সাফল্য", + "failed": "ব্যর্থ", + "timeout": "সময়সীমা শেষ", + "skipped": "বাদ দেওয়া হয়েছে", + "cancelled": "বাতিল করা হয়েছে" + }, + "fields": { + "host": "হোস্ট", + "metric": "মেট্রিক", + "mount": "মাউন্ট পয়েন্ট", + "operator": "হয়", + "value": "মূল্য", + "forSeconds": "(সেকেন্ড) ধরে স্থায়ী", + "cooldown": "কুলডাউন (মিনিট)", + "cron": "ক্রোন এক্সপ্রেশন", + "intervalSeconds": "প্রতি (সেকেন্ডে)", + "timezone": "সময় অঞ্চল", + "timezoneServer": "সার্ভারের সময়", + "timezoneHint": "এই জোনে ক্রন টাইম পড়া হয়। এটি ইন্টারভাল শিডিউলের ক্ষেত্রে প্রযোজ্য নয়।", + "container": "কন্টেইনার", + "command": "আদেশ", + "url": "ইউআরএল", + "method": "পদ্ধতি", + "body": "শরীর", + "channels": "চ্যানেল", + "title": "শিরোনাম", + "message": "বার্তা", + "snippet": "স্নিপেট", + "seconds": "সেকেন্ড", + "conditionLeftPlaceholder": "যাচাই করার মান", + "conditionRightPlaceholder": "তুলনা করুন", + "variableName": "ভেরিয়েবলের নাম", + "variableValue": "মূল্য", + "elevated": "sudo দিয়ে চালান", + "onError": "যদি এটি ব্যর্থ হয়", + "allowPrivateNetwork": "স্থানীয় নেটওয়ার্ক ঠিকানাগুলির অনুমতি দিন", + "allowPrivateNetworkHint": "আপনার ল্যানে সেলফ-হোস্টেড সার্ভিসের জন্য প্রয়োজন। অভ্যন্তরীণ অ্যাড্রেসে অনুরোধ পাঠানো প্রতিরোধ করতে এটি ডিফল্টরূপে বন্ধ থাকে।" + }, + "onError": { + "stop": "দৌড় থামাও", + "continue": "চালিয়ে যান" + } + } + } + }, + "nav": { + "automations": "অটোমেশন" + }, + "onboarding": { + "feature_automations": "অটোমেশন", + "feature_automations_desc": "কোনো ঘটনা ঘটলে স্বয়ংক্রিয়ভাবে ধাপগুলো সম্পন্ন করুন এবং বিজ্ঞপ্তি পান।" + } +} diff --git a/plugins/automations/locales/translated/ca_ES.json b/plugins/automations/locales/translated/ca_ES.json new file mode 100644 index 000000000..eb1394e65 --- /dev/null +++ b/plugins/automations/locales/translated/ca_ES.json @@ -0,0 +1,149 @@ +{ + "newUi": { + "sidebar": { + "automations": { + "title": "Automatitzacions", + "tabAutomations": "Automatitzacions", + "tabRuns": "Carreres", + "tabChannels": "Canals", + "createAutomation": "Nova automatització", + "backToAutomations": "Torna a Automatitzacions", + "createTitle": "Nova automatització", + "editTitle": "Edita l'automatització", + "empty": "Encara no hi ha automatitzacions. Crea'n una per reaccionar a una mètrica, una programació o un esdeveniment.", + "emptyRuns": "Encara no hi ha curses.", + "emptyChannels": "Encara no hi ha cap canal. Afegeix-ne un per enviar notificacions a algun lloc.", + "noChannelsHint": "Encara no s'ha configurat cap canal. Afegeix-ne un a la pestanya Canals.", + "addChannel": "Afegeix un canal", + "testChannel": "Prova", + "channelTestSent": "Notificació de prova enviada", + "channelTestFailed": "La notificació de prova ha fallat", + "channelDeleted": "Canal suprimit", + "deleteChannelConfirm": "Voleu suprimir aquest canal? Les automatitzacions que l'utilitzen deixaran de notificar.", + "nameLabel": "Nom", + "namePlaceholder": "p. ex., Neteja /dades quan s'ompli", + "nameRequired": "El nom és obligatori", + "descriptionLabel": "Descripció", + "descriptionPlaceholder": "Descripció opcional", + "enabledLabel": "Activat", + "concurrencyLabel": "Si ja està en funcionament", + "concurrencyHint": "Què cal fer quan això es torna a activar abans que s'hagi acabat l'última execució.", + "concurrency": { + "skip": "Omet la nova cursa", + "queue": "Espera i corre darrere", + "allow": "Executa tots dos alhora" + }, + "save": "Desa", + "created": "Automatització creada", + "updated": "Automatització desada", + "deleted": "Automatització suprimida", + "deleteConfirm": "Voleu suprimir aquesta automatització? També se n'esborra l'historial d'execucions.", + "runNow": "Executa ara", + "testRun": "Prova de funcionament", + "testRunHint": "Corre cada pas però no toca res fora de Termix.", + "runStarted": "Execució iniciada", + "runFinished": "Execució acabada: {{status}}", + "trigger": "Disparador", + "steps": "Passos", + "addStep": "Afegeix un pas", + "removeStep": "Elimina el pas", + "moveUp": "Puja", + "moveDown": "Moure cap avall", + "noSteps": "Encara no hi ha cap pas. Afegeix-ne un per indicar què hauria de passar.", + "webhookTokenTitle": "URL del webhook", + "webhookTokenDescription": "Això es mostra una vegada. Desa-ho ara, no es podrà recuperar més tard.", + "copy": "Còpia", + "copied": "Copiat", + "viewJson": "JSON", + "viewBuilder": "Constructor", + "viewGraph": "Gràfic", + "lastRun": "Última cursa", + "never": "Mai", + "duration": "{{seconds}}s", + "stepOutput": "Sortida", + "stepError": "Error", + "dryRunBadge": "Prova de funcionament", + "hostSelector": { + "trigger": "Host activador", + "host": "Amfitrió específic", + "fleet": "Flota", + "all": "Tots els amfitrions" + }, + "triggerKinds": { + "metric_threshold": "Llindar mètric", + "host_status": "L'amfitrió puja o baixa", + "health_check": "Canvis en la revisió de salut", + "schedule": "En un horari", + "docker_event": "Esdeveniment de contenidor", + "internal_event": "Esdeveniment de Termix", + "webhook": "Webhook entrant" + }, + "stepTypes": { + "notify": "Enviar una notificació", + "http": "Crida a una URL", + "run_snippet": "Executa un fragment", + "run_command": "Executa una ordre", + "docker": "Controlar un contenidor", + "tunnel": "Controlar un túnel", + "wol": "Despertar un amfitrió", + "wait": "Espera", + "set_var": "Defineix una variable", + "if": "Si / altrament", + "run_automation": "Executa una altra automatització", + "stop": "Atura" + }, + "statuses": { + "running": "Córrer", + "success": "Èxit", + "failed": "Fallat", + "timeout": "Temps d'espera esgotat", + "skipped": "Omès", + "cancelled": "Cancel·lat" + }, + "fields": { + "host": "Amfitrió", + "metric": "Mètrica", + "mount": "Punt de muntatge", + "operator": "És", + "value": "Valor", + "forSeconds": "Sostingut durant (segons)", + "cooldown": "Refredament (minuts)", + "cron": "Expressió cron", + "intervalSeconds": "Cada (segons)", + "timezone": "Zona horària", + "timezoneServer": "Hora del servidor", + "timezoneHint": "Els temps cron es llegeixen en aquesta zona. No s'aplica a les programacions per intervals.", + "container": "Contenidor", + "command": "Comandament", + "url": "URL", + "method": "Mètode", + "body": "Cos", + "channels": "Canals", + "title": "Títol", + "message": "Missatge", + "snippet": "Fragment", + "seconds": "Segons", + "conditionLeftPlaceholder": "Valor a comprovar", + "conditionRightPlaceholder": "Comparar amb", + "variableName": "Nom de la variable", + "variableValue": "Valor", + "elevated": "Executar amb sudo", + "onError": "Si això falla", + "allowPrivateNetwork": "Permetre adreces de xarxa locals", + "allowPrivateNetworkHint": "Necessari per a un servei autoallotjat a la vostra LAN. Desactivat per defecte per evitar sol·licituds a adreces internes." + }, + "onError": { + "stop": "Atura la cursa", + "continue": "Continua" + } + } + } + }, + "nav": { + "automations": "Automatitzacions" + }, + "onboarding": { + "feature_automations": "Automatitzacions", + "feature_automations_desc": "Executa els passos automàticament quan passi alguna cosa i rep notificacions." + } +} diff --git a/plugins/automations/locales/translated/cs_CZ.json b/plugins/automations/locales/translated/cs_CZ.json new file mode 100644 index 000000000..5c7776c8b --- /dev/null +++ b/plugins/automations/locales/translated/cs_CZ.json @@ -0,0 +1,149 @@ +{ + "newUi": { + "sidebar": { + "automations": { + "title": "Automatizace", + "tabAutomations": "Automatizace", + "tabRuns": "Běhy", + "tabChannels": "Kanály", + "createAutomation": "Nová automatizace", + "backToAutomations": "Zpět k automatizaci", + "createTitle": "Nová automatizace", + "editTitle": "Upravit automatizaci", + "empty": "Zatím žádné automatizace. Vytvořte si automatizaci, která bude reagovat na metriku, plán nebo událost.", + "emptyRuns": "Zatím žádné běhy.", + "emptyChannels": "Zatím žádné kanály. Přidejte jeden, abyste někam mohli odesílat oznámení.", + "noChannelsHint": "Zatím nejsou nastaveny žádné kanály. Přidejte jeden na kartě Kanály.", + "addChannel": "Přidat kanál", + "testChannel": "Test", + "channelTestSent": "Testovací oznámení odesláno", + "channelTestFailed": "Testovací oznámení selhalo", + "channelDeleted": "Kanál smazán", + "deleteChannelConfirm": "Smazat tento kanál? Automatizace, které ho používají, přestanou zasílat upozornění.", + "nameLabel": "Jméno", + "namePlaceholder": "např. Vyčistit /data, když se zaplní", + "nameRequired": "Jméno je povinné", + "descriptionLabel": "Popis", + "descriptionPlaceholder": "Volitelný popis", + "enabledLabel": "Povoleno", + "concurrencyLabel": "Pokud již běží", + "concurrencyHint": "Co dělat, když se to spustí znovu před dokončením posledního běhu.", + "concurrency": { + "skip": "Přeskočit nový běh", + "queue": "Čekej a běž za ním", + "allow": "Spustit obojí najednou" + }, + "save": "Uložit", + "created": "Automatizace vytvořena", + "updated": "Automatizace uložena", + "deleted": "Automatizace smazána", + "deleteConfirm": "Smazat tuto automatizaci? Její historie spuštění bude také smazána.", + "runNow": "Běhej hned", + "testRun": "Zkušební provoz", + "testRunHint": "Provádí každý krok, ale nedotýká se ničeho mimo Termix.", + "runStarted": "Běh byl zahájen", + "runFinished": "Běh dokončen: {{status}}", + "trigger": "Spoušť", + "steps": "Kroky", + "addStep": "Přidat krok", + "removeStep": "Odebrat krok", + "moveUp": "Posunout nahoru", + "moveDown": "Přesunout dolů", + "noSteps": "Zatím žádné kroky. Přidejte jeden, který popisuje, co by se mělo stát.", + "webhookTokenTitle": "URL webhooku", + "webhookTokenDescription": "Toto se zobrazí jednou. Uložte si to nyní, později to nelze načíst.", + "copy": "Kopie", + "copied": "Zkopírováno", + "viewJson": "JSON", + "viewBuilder": "Stavitel", + "viewGraph": "Graf", + "lastRun": "Poslední běh", + "never": "Nikdy", + "duration": "{{seconds}}s", + "stepOutput": "Výstup", + "stepError": "Chyba", + "dryRunBadge": "Zkušební provoz", + "hostSelector": { + "trigger": "Spouštěcí hostitel", + "host": "Specifický hostitel", + "fleet": "Loďstvo", + "all": "Všichni hostitelé" + }, + "triggerKinds": { + "metric_threshold": "Prahová hodnota metriky", + "host_status": "Hostitel jde nahoru nebo dolů", + "health_check": "Změny v kontrolách stavu", + "schedule": "Podle plánu", + "docker_event": "Událost kontejneru", + "internal_event": "Událost Termix", + "webhook": "Příchozí webhook" + }, + "stepTypes": { + "notify": "Odeslat oznámení", + "http": "Zavolat URL", + "run_snippet": "Spustit úryvek", + "run_command": "Spusťte příkaz", + "docker": "Ovládání kontejneru", + "tunnel": "Ovládejte tunel", + "wol": "Probuďte hostitele", + "wait": "Počkejte", + "set_var": "Nastavení proměnné", + "if": "Pokud / jinak", + "run_automation": "Spusťte další automatizaci", + "stop": "Zastávka" + }, + "statuses": { + "running": "Běh", + "success": "Úspěch", + "failed": "Selhalo", + "timeout": "Časový limit vypršel", + "skipped": "Přeskočeno", + "cancelled": "Zrušeno" + }, + "fields": { + "host": "Hostitel", + "metric": "Metrický", + "mount": "Bod připojení", + "operator": "Je", + "value": "Hodnota", + "forSeconds": "Trvalé po dobu (sekund)", + "cooldown": "Doba ochlazování (minuty)", + "cron": "Cron výraz", + "intervalSeconds": "Každých (sekund)", + "timezone": "Časové pásmo", + "timezoneServer": "Čas serveru", + "timezoneHint": "V této zóně se odečítají časy Cron. Nevztahuje se na intervalové plány.", + "container": "Kontejner", + "command": "Příkaz", + "url": "URL", + "method": "Metoda", + "body": "Tělo", + "channels": "Kanály", + "title": "Titul", + "message": "Zpráva", + "snippet": "Úryvek", + "seconds": "Sekundy", + "conditionLeftPlaceholder": "Hodnota ke kontrole", + "conditionRightPlaceholder": "Porovnat s", + "variableName": "Název proměnné", + "variableValue": "Hodnota", + "elevated": "Spusťte pomocí sudo", + "onError": "Pokud se to nepodaří", + "allowPrivateNetwork": "Povolit lokální síťové adresy", + "allowPrivateNetworkHint": "Vyžadováno pro službu hostovanou na vašem lokálním serveru (LAN). Ve výchozím nastavení vypnuto, aby se zabránilo požadavkům na interní adresy." + }, + "onError": { + "stop": "Zastav běh", + "continue": "Pokračovat" + } + } + } + }, + "nav": { + "automations": "Automatizace" + }, + "onboarding": { + "feature_automations": "Automatizace", + "feature_automations_desc": "Automaticky spouštět kroky, když se něco stane, a dostávat upozornění." + } +} diff --git a/plugins/automations/locales/translated/da_DK.json b/plugins/automations/locales/translated/da_DK.json new file mode 100644 index 000000000..ce479f3be --- /dev/null +++ b/plugins/automations/locales/translated/da_DK.json @@ -0,0 +1,149 @@ +{ + "newUi": { + "sidebar": { + "automations": { + "title": "Automatiseringer", + "tabAutomations": "Automatiseringer", + "tabRuns": "Løber", + "tabChannels": "Kanaler", + "createAutomation": "Ny automatisering", + "backToAutomations": "Tilbage til Automatiseringer", + "createTitle": "Ny automatisering", + "editTitle": "Rediger automatisering", + "empty": "Ingen automatiseringer endnu. Opret en for at reagere på en metric, en tidsplan eller en begivenhed.", + "emptyRuns": "Ingen løb endnu.", + "emptyChannels": "Ingen kanaler endnu. Tilføj en for at sende notifikationer et sted hen.", + "noChannelsHint": "Ingen kanaler er konfigureret endnu. Tilføj en i fanen Kanaler.", + "addChannel": "Tilføj kanal", + "testChannel": "Prøve", + "channelTestSent": "Testnotifikation sendt", + "channelTestFailed": "Testnotifikation mislykkedes", + "channelDeleted": "Kanal slettet", + "deleteChannelConfirm": "Vil du slette denne kanal? Automatiseringer, der bruger den, vil stoppe med at sende dig notifikationer.", + "nameLabel": "Navn", + "namePlaceholder": "f.eks. Ryd op i /data når den fyldes op", + "nameRequired": "Navn er påkrævet", + "descriptionLabel": "Beskrivelse", + "descriptionPlaceholder": "Valgfri beskrivelse", + "enabledLabel": "Aktiveret", + "concurrencyLabel": "Hvis den allerede kører", + "concurrencyHint": "Hvad skal man gøre, når dette udløses igen, før den sidste kørsel er færdig.", + "concurrency": { + "skip": "Spring den nye kørsel over", + "queue": "Vent og løb efter", + "allow": "Kør begge på én gang" + }, + "save": "Spare", + "created": "Automatisering skabt", + "updated": "Automatisering gemt", + "deleted": "Automatisering slettet", + "deleteConfirm": "Vil du slette denne automatisering? Dens kørselshistorik slettes også.", + "runNow": "Løb nu", + "testRun": "Testkørsel", + "testRunHint": "Kører hvert trin, men rører ikke noget uden for Termix.", + "runStarted": "Løbet startede", + "runFinished": "Kørsel færdig: {{status}}", + "trigger": "Udløser", + "steps": "Trin", + "addStep": "Tilføj trin", + "removeStep": "Fjern trin", + "moveUp": "Flyt op", + "moveDown": "Flyt ned", + "noSteps": "Ingen trin endnu. Tilføj et trin for at angive, hvad der skal ske.", + "webhookTokenTitle": "Webhook-URL", + "webhookTokenDescription": "Dette vises én gang. Gem det nu, det kan ikke hentes senere.", + "copy": "Kopi", + "copied": "Kopieret", + "viewJson": "JSON", + "viewBuilder": "Byggefirma", + "viewGraph": "Kurve", + "lastRun": "Sidste løb", + "never": "Aldrig", + "duration": "{{seconds}}s", + "stepOutput": "Produktion", + "stepError": "Fejl", + "dryRunBadge": "Testkørsel", + "hostSelector": { + "trigger": "Udløsende vært", + "host": "Specifik vært", + "fleet": "Flåde", + "all": "Alle værter" + }, + "triggerKinds": { + "metric_threshold": "Metrisk tærskel", + "host_status": "Værten går op eller ned", + "health_check": "Ændringer i sundhedstjek", + "schedule": "På en tidsplan", + "docker_event": "Containerhændelse", + "internal_event": "Termix-begivenhed", + "webhook": "Indgående webhook" + }, + "stepTypes": { + "notify": "Send en notifikation", + "http": "Kald en URL", + "run_snippet": "Kør et uddrag", + "run_command": "Kør en kommando", + "docker": "Styr en container", + "tunnel": "Kontroller en tunnel", + "wol": "Væk en vært", + "wait": "Vente", + "set_var": "Angiv en variabel", + "if": "Hvis / ellers", + "run_automation": "Kør en anden automatisering", + "stop": "Stop" + }, + "statuses": { + "running": "Løb", + "success": "Succes", + "failed": "Mislykkedes", + "timeout": "Timeout", + "skipped": "Springet over", + "cancelled": "Annulleret" + }, + "fields": { + "host": "Vært", + "metric": "Metrisk", + "mount": "Monteringspunkt", + "operator": "Er", + "value": "Værdi", + "forSeconds": "Vedvarende i (sekunder)", + "cooldown": "Nedkølingstid (minutter)", + "cron": "Cron-udtryk", + "intervalSeconds": "Hvert (sekund)", + "timezone": "Tidszone", + "timezoneServer": "Servertid", + "timezoneHint": "Cron-tider aflæses i denne zone. Gælder ikke for intervalplaner.", + "container": "Beholder", + "command": "Kommando", + "url": "URL", + "method": "Metode", + "body": "Legeme", + "channels": "Kanaler", + "title": "Titel", + "message": "Besked", + "snippet": "Uddrag", + "seconds": "Sekunder", + "conditionLeftPlaceholder": "Værdi at kontrollere", + "conditionRightPlaceholder": "Sammenlign med", + "variableName": "Variabelnavn", + "variableValue": "Værdi", + "elevated": "Kør med sudo", + "onError": "Hvis dette mislykkes", + "allowPrivateNetwork": "Tillad lokale netværksadresser", + "allowPrivateNetworkHint": "Nødvendig for en selvhostet tjeneste på dit LAN. Deaktiveret som standard for at forhindre anmodninger til interne adresser." + }, + "onError": { + "stop": "Stop løbet", + "continue": "Fortsæt" + } + } + } + }, + "nav": { + "automations": "Automatiseringer" + }, + "onboarding": { + "feature_automations": "Automatiseringer", + "feature_automations_desc": "Kør trin automatisk, når der sker noget, og få besked." + } +} diff --git a/plugins/automations/locales/translated/de_DE.json b/plugins/automations/locales/translated/de_DE.json new file mode 100644 index 000000000..035e3a490 --- /dev/null +++ b/plugins/automations/locales/translated/de_DE.json @@ -0,0 +1,149 @@ +{ + "newUi": { + "sidebar": { + "automations": { + "title": "Automatisierungen", + "tabAutomations": "Automatisierungen", + "tabRuns": "Läufe", + "tabChannels": "Kanäle", + "createAutomation": "Neue Automatisierung", + "backToAutomations": "Zurück zu Automatisierungen", + "createTitle": "Neue Automatisierung", + "editTitle": "Automatisierung bearbeiten", + "empty": "Noch keine Automatisierungen. Erstellen Sie eine, um auf eine Kennzahl, einen Zeitplan oder ein Ereignis zu reagieren.", + "emptyRuns": "Bisher keine Läufe.", + "emptyChannels": "Noch keine Kanäle. Fügen Sie einen hinzu, um Benachrichtigungen an einen bestimmten Ort zu senden.", + "noChannelsHint": "Es sind noch keine Kanäle eingerichtet. Fügen Sie einen im Tab „Kanäle“ hinzu.", + "addChannel": "Kanal hinzufügen", + "testChannel": "Prüfen", + "channelTestSent": "Testbenachrichtigung gesendet", + "channelTestFailed": "Testbenachrichtigung fehlgeschlagen", + "channelDeleted": "Kanal gelöscht", + "deleteChannelConfirm": "Diesen Kanal löschen? Automatisierungen, die diesen Kanal verwenden, werden keine Benachrichtigungen mehr senden.", + "nameLabel": "Name", + "namePlaceholder": "z.B. das Verzeichnis /data leeren, wenn es voll ist", + "nameRequired": "Name erforderlich", + "descriptionLabel": "Beschreibung", + "descriptionPlaceholder": "Optionale Beschreibung", + "enabledLabel": "Ermöglicht", + "concurrencyLabel": "Wenn es bereits läuft", + "concurrencyHint": "Was ist zu tun, wenn dies erneut ausgelöst wird, bevor der letzte Durchlauf abgeschlossen ist?", + "concurrency": { + "skip": "Den neuen Lauf überspringen.", + "queue": "Warten und dann hinterherlaufen", + "allow": "Führe beide gleichzeitig aus" + }, + "save": "Speichern", + "created": "Automatisierung erstellt", + "updated": "Automatisierung gerettet", + "deleted": "Automatisierung gelöscht", + "deleteConfirm": "Wenn Sie diese Automatisierung löschen, wird auch ihr Ausführungsverlauf gelöscht.", + "runNow": "Jetzt laufen", + "testRun": "Probelauf", + "testRunHint": "Führt jeden Schritt aus, greift aber auf nichts außerhalb von Termix ein.", + "runStarted": "Lauf gestartet", + "runFinished": "Lauf beendet: {{status}}", + "trigger": "Auslösen", + "steps": "Schritte", + "addStep": "Schritt hinzufügen", + "removeStep": "Schritt entfernen", + "moveUp": "Aufsteigen", + "moveDown": "Nach unten schieben", + "noSteps": "Noch keine Schritte. Füge einen hinzu, um zu beschreiben, was passieren soll.", + "webhookTokenTitle": "Webhook-URL", + "webhookTokenDescription": "Dies wird nur einmal angezeigt. Speichern Sie es jetzt, es kann später nicht mehr abgerufen werden.", + "copy": "Kopie", + "copied": "Kopiert", + "viewJson": "JSON", + "viewBuilder": "Bauherr", + "viewGraph": "Graph", + "lastRun": "Letzter Lauf", + "never": "Niemals", + "duration": "{{seconds}}s", + "stepOutput": "Ausgabe", + "stepError": "Fehler", + "dryRunBadge": "Probelauf", + "hostSelector": { + "trigger": "Auslösender Host", + "host": "Spezifischer Wirt", + "fleet": "Flotte", + "all": "Alle Gastgeber" + }, + "triggerKinds": { + "metric_threshold": "Metrischer Schwellenwert", + "host_status": "Der Host steigt oder fällt ab", + "health_check": "Änderungen bei Gesundheitschecks", + "schedule": "Nach einem Zeitplan", + "docker_event": "Container-Ereignis", + "internal_event": "Termix-Ereignis", + "webhook": "Eingehender Webhook" + }, + "stepTypes": { + "notify": "Sende eine Benachrichtigung", + "http": "URL aufrufen", + "run_snippet": "Führe einen Codeausschnitt aus", + "run_command": "Führe einen Befehl aus", + "docker": "Einen Container steuern", + "tunnel": "Einen Tunnel steuern", + "wol": "Wecken Sie einen Gastgeber", + "wait": "Warten", + "set_var": "Eine Variable setzen", + "if": "Falls / andernfalls", + "run_automation": "Führe eine weitere Automatisierung aus", + "stop": "Stoppen" + }, + "statuses": { + "running": "Läuft", + "success": "Erfolg", + "failed": "Fehlgeschlagen", + "timeout": "Zeitüberschreitung", + "skipped": "Übersprungen", + "cancelled": "Abgesagt" + }, + "fields": { + "host": "Gastgeber", + "metric": "Metrisch", + "mount": "Montagepunkt", + "operator": "Ist", + "value": "Wert", + "forSeconds": "Anhaltend für (Sekunden)", + "cooldown": "Abkühlzeit (Minuten)", + "cron": "Cron-Ausdruck", + "intervalSeconds": "Alle (Sekunden)", + "timezone": "Zeitzone", + "timezoneServer": "Serverzeit", + "timezoneHint": "In dieser Zone werden Cron-Zeiten gelesen. Gilt nicht für Intervallpläne.", + "container": "Container", + "command": "Befehl", + "url": "URL", + "method": "Verfahren", + "body": "Körper", + "channels": "Kanäle", + "title": "Titel", + "message": "Nachricht", + "snippet": "Ausschnitt", + "seconds": "Sekunden", + "conditionLeftPlaceholder": "Zu prüfender Wert", + "conditionRightPlaceholder": "Vergleiche mit", + "variableName": "Variablenname", + "variableValue": "Wert", + "elevated": "Mit sudo ausführen", + "onError": "Wenn das fehlschlägt", + "allowPrivateNetwork": "Lokale Netzwerkadressen zulassen", + "allowPrivateNetworkHint": "Wird für einen selbstgehosteten Dienst in Ihrem LAN benötigt. Standardmäßig deaktiviert, um Anfragen an interne Adressen zu verhindern." + }, + "onError": { + "stop": "Stoppt die Flucht!", + "continue": "Weiter geht's" + } + } + } + }, + "nav": { + "automations": "Automatisierungen" + }, + "onboarding": { + "feature_automations": "Automatisierungen", + "feature_automations_desc": "Schritte automatisch ausführen, wenn etwas passiert, und Benachrichtigungen erhalten." + } +} diff --git a/plugins/automations/locales/translated/el_GR.json b/plugins/automations/locales/translated/el_GR.json new file mode 100644 index 000000000..614728faa --- /dev/null +++ b/plugins/automations/locales/translated/el_GR.json @@ -0,0 +1,149 @@ +{ + "newUi": { + "sidebar": { + "automations": { + "title": "Αυτοματισμοί", + "tabAutomations": "Αυτοματισμοί", + "tabRuns": "Τρεξίματα", + "tabChannels": "Κανάλια", + "createAutomation": "Νέος Αυτοματισμός", + "backToAutomations": "Επιστροφή στους Αυτοματισμούς", + "createTitle": "Νέος Αυτοματισμός", + "editTitle": "Επεξεργασία αυτοματισμού", + "empty": "Δεν υπάρχουν ακόμη αυτοματοποιήσεις. Δημιουργήστε μία για να αντιδράτε σε μια μέτρηση, ένα πρόγραμμα ή ένα συμβάν.", + "emptyRuns": "Δεν υπάρχουν τρεξίματα ακόμα.", + "emptyChannels": "Δεν υπάρχουν ακόμη κανάλια. Προσθέστε ένα για να στέλνετε ειδοποιήσεις κάπου.", + "noChannelsHint": "Δεν έχουν ρυθμιστεί ακόμη κανάλια. Προσθέστε ένα στην καρτέλα Κανάλια.", + "addChannel": "Προσθήκη καναλιού", + "testChannel": "Δοκιμή", + "channelTestSent": "Αποστολή ειδοποίησης δοκιμής", + "channelTestFailed": "Η ειδοποίηση δοκιμής απέτυχε.", + "channelDeleted": "Το κανάλι διαγράφηκε", + "deleteChannelConfirm": "Διαγραφή αυτού του καναλιού; Οι αυτοματοποιήσεις που το χρησιμοποιούν θα σταματήσουν να ειδοποιούν.", + "nameLabel": "Ονομα", + "namePlaceholder": "π.χ., Καθαρισμός /data όταν γεμίσει", + "nameRequired": "Απαιτείται όνομα", + "descriptionLabel": "Περιγραφή", + "descriptionPlaceholder": "Προαιρετική περιγραφή", + "enabledLabel": "Ενεργοποιημένο", + "concurrencyLabel": "Εάν ήδη εκτελείται", + "concurrencyHint": "Τι πρέπει να κάνετε όταν αυτό ενεργοποιηθεί ξανά πριν ολοκληρωθεί η τελευταία εκτέλεση.", + "concurrency": { + "skip": "Παράλειψη της νέας διαδρομής", + "queue": "Περίμενε και τρέχα πίσω", + "allow": "Εκτελέστε και τα δύο ταυτόχρονα" + }, + "save": "Εκτός", + "created": "Αυτοματοποίηση που δημιουργήθηκε", + "updated": "Ο αυτοματισμός αποθηκεύτηκε", + "deleted": "Ο αυτοματισμός διαγράφηκε.", + "deleteConfirm": "Διαγραφή αυτού του αυτοματισμού; Το ιστορικό εκτέλεσής του διαγράφεται επίσης.", + "runNow": "Εκτέλεση τώρα", + "testRun": "Δοκιμαστική εκτέλεση", + "testRunHint": "Εκτελεί κάθε βήμα αλλά δεν αγγίζει τίποτα εκτός του Termix.", + "runStarted": "Η εκτέλεση ξεκίνησε", + "runFinished": "Η εκτέλεση ολοκληρώθηκε: {{status}}", + "trigger": "Σκανδάλη", + "steps": "Βήματα", + "addStep": "Προσθήκη βήματος", + "removeStep": "Αφαίρεση βήματος", + "moveUp": "Μετακίνηση προς τα πάνω", + "moveDown": "Μετακίνηση προς τα κάτω", + "noSteps": "Δεν υπάρχουν ακόμη βήματα. Προσθέστε ένα για να πείτε τι πρέπει να συμβεί.", + "webhookTokenTitle": "URL ιστού", + "webhookTokenDescription": "Αυτό εμφανίζεται μία φορά. Αποθηκεύστε το τώρα, δεν μπορεί να ανακτηθεί αργότερα.", + "copy": "Αντίγραφο", + "copied": "Αντιγράφηκε", + "viewJson": "JSON", + "viewBuilder": "Οικοδόμος", + "viewGraph": "Γραφική παράσταση", + "lastRun": "Τελευταία εκτέλεση", + "never": "Ποτέ", + "duration": "{{seconds}}s", + "stepOutput": "Παραγωγή", + "stepError": "Σφάλμα", + "dryRunBadge": "Δοκιμαστική εκτέλεση", + "hostSelector": { + "trigger": "Ενεργοποίηση κεντρικού υπολογιστή", + "host": "Συγκεκριμένος κεντρικός υπολογιστής", + "fleet": "Στόλος", + "all": "Όλοι οι οικοδεσπότες" + }, + "triggerKinds": { + "metric_threshold": "Μετρικό όριο", + "host_status": "Ο κεντρικός υπολογιστής ανεβαίνει ή κατεβαίνει", + "health_check": "Αλλαγές στον έλεγχο υγείας", + "schedule": "Σε πρόγραμμα", + "docker_event": "Συμβάν κοντέινερ", + "internal_event": "Συμβάν Termix", + "webhook": "Εισερχόμενο webhook" + }, + "stepTypes": { + "notify": "Αποστολή ειδοποίησης", + "http": "Κλήση μιας διεύθυνσης URL", + "run_snippet": "Εκτέλεση ενός αποσπάσματος", + "run_command": "Εκτέλεση εντολής", + "docker": "Έλεγχος ενός κοντέινερ", + "tunnel": "Έλεγχος μιας σήραγγας", + "wol": "Ξυπνήστε έναν οικοδεσπότη", + "wait": "Περιμένετε", + "set_var": "Ορισμός μεταβλητής", + "if": "Εάν / διαφορετικά", + "run_automation": "Εκτελέστε έναν άλλο αυτοματισμό", + "stop": "Στάση" + }, + "statuses": { + "running": "Τρέξιμο", + "success": "Επιτυχία", + "failed": "Αποτυχημένος", + "timeout": "Λήξη χρονικού ορίου", + "skipped": "Παραλήφθηκε", + "cancelled": "Ακυρώθηκε" + }, + "fields": { + "host": "Πλήθος", + "metric": "Μετρικός", + "mount": "Σημείο προσάρτησης", + "operator": "Είναι", + "value": "Αξία", + "forSeconds": "Διαρκεί για (δευτερόλεπτα)", + "cooldown": "Χρόνος αναμονής (λεπτά)", + "cron": "Έκφραση Cron", + "intervalSeconds": "Κάθε (δευτερόλεπτα)", + "timezone": "Ζώνη ώρας", + "timezoneServer": "Ώρα διακομιστή", + "timezoneHint": "Οι χρόνοι Cron διαβάζονται σε αυτήν τη ζώνη. Δεν ισχύει για τα χρονοδιαγράμματα διαστημάτων.", + "container": "Δοχείο", + "command": "Εντολή", + "url": "URL", + "method": "Μέθοδος", + "body": "Σώμα", + "channels": "Κανάλια", + "title": "Τίτλος", + "message": "Μήνυμα", + "snippet": "Απόσπασμα", + "seconds": "Δευτερόλεπτα", + "conditionLeftPlaceholder": "Τιμή προς έλεγχο", + "conditionRightPlaceholder": "Σύγκριση με", + "variableName": "Όνομα μεταβλητής", + "variableValue": "Αξία", + "elevated": "Εκτέλεση με sudo", + "onError": "Εάν αυτό αποτύχει", + "allowPrivateNetwork": "Επιτρέψτε τις τοπικές διευθύνσεις δικτύου", + "allowPrivateNetworkHint": "Απαιτείται για μια αυτο-φιλοξενούμενη υπηρεσία στο LAN σας. Απενεργοποιημένο από προεπιλογή για την αποτροπή αιτημάτων σε εσωτερικές διευθύνσεις." + }, + "onError": { + "stop": "Σταμάτα το τρέξιμο", + "continue": "Συνεχίζω" + } + } + } + }, + "nav": { + "automations": "Αυτοματισμοί" + }, + "onboarding": { + "feature_automations": "Αυτοματισμοί", + "feature_automations_desc": "Εκτελέστε αυτόματα βήματα όταν συμβεί κάτι και λάβετε ειδοποίηση." + } +} diff --git a/plugins/automations/locales/translated/es_ES.json b/plugins/automations/locales/translated/es_ES.json new file mode 100644 index 000000000..47226cef4 --- /dev/null +++ b/plugins/automations/locales/translated/es_ES.json @@ -0,0 +1,149 @@ +{ + "newUi": { + "sidebar": { + "automations": { + "title": "Automatizaciones", + "tabAutomations": "Automatizaciones", + "tabRuns": "Corre", + "tabChannels": "Canales", + "createAutomation": "Nueva automatización", + "backToAutomations": "Volver a Automatizaciones", + "createTitle": "Nueva automatización", + "editTitle": "Automatización de edición", + "empty": "Aún no hay automatizaciones. Crea una para que reaccione a una métrica, una programación o un evento.", + "emptyRuns": "Aún no hay carreras.", + "emptyChannels": "Aún no hay canales. Añade uno para enviar notificaciones a algún lugar.", + "noChannelsHint": "Aún no hay canales configurados. Añade uno en la pestaña Canales.", + "addChannel": "Agregar canal", + "testChannel": "Prueba", + "channelTestSent": "Notificación de prueba enviada", + "channelTestFailed": "Falló la notificación de prueba", + "channelDeleted": "Canal eliminado", + "deleteChannelConfirm": "¿Eliminar este canal? Las automatizaciones que lo utilicen dejarán de enviar notificaciones.", + "nameLabel": "Nombre", + "namePlaceholder": "Por ejemplo, limpiar /data cuando se llena", + "nameRequired": "Se requiere el nombre", + "descriptionLabel": "Descripción", + "descriptionPlaceholder": "Descripción opcional", + "enabledLabel": "Activado", + "concurrencyLabel": "Si ya está en funcionamiento", + "concurrencyHint": "Qué hacer si esto se activa de nuevo antes de que finalice la última ejecución.", + "concurrency": { + "skip": "Saltarse la nueva carrera", + "queue": "Espera y corre tras", + "allow": "Ejecuta ambos a la vez" + }, + "save": "Ahorrar", + "created": "Automatización creada", + "updated": "Automatización guardada", + "deleted": "Automatización eliminada", + "deleteConfirm": "¿Eliminar esta automatización? Su historial de ejecución también se eliminará.", + "runNow": "Corre ahora", + "testRun": "Ejecución de prueba", + "testRunHint": "Ejecuta todos los pasos, pero no toca nada fuera de Termix.", + "runStarted": "La carrera ha comenzado.", + "runFinished": "Ejecución finalizada: {{status}}", + "trigger": "Desencadenar", + "steps": "Pasos", + "addStep": "Agregar paso", + "removeStep": "Eliminar paso", + "moveUp": "Subir", + "moveDown": "Baja", + "noSteps": "Aún no hay pasos a seguir. Añade uno para indicar qué debería suceder.", + "webhookTokenTitle": "URL del webhook", + "webhookTokenDescription": "Esto se muestra una sola vez. Guárdalo ahora, no se podrá recuperar más tarde.", + "copy": "Copiar", + "copied": "Copiado", + "viewJson": "JSON", + "viewBuilder": "Constructor", + "viewGraph": "Gráfico", + "lastRun": "Última carrera", + "never": "Nunca", + "duration": "{{seconds}}s", + "stepOutput": "Producción", + "stepError": "Error", + "dryRunBadge": "Ejecución de prueba", + "hostSelector": { + "trigger": "Host desencadenante", + "host": "Anfitrión específico", + "fleet": "Flota", + "all": "Todos los anfitriones" + }, + "triggerKinds": { + "metric_threshold": "Umbral métrico", + "host_status": "El host sube o baja", + "health_check": "Cambios en los chequeos médicos", + "schedule": "Según un horario", + "docker_event": "Evento de contenedor", + "internal_event": "Evento Termix", + "webhook": "Webhook entrante" + }, + "stepTypes": { + "notify": "Enviar una notificación", + "http": "Llamar a una URL", + "run_snippet": "Ejecutar un fragmento", + "run_command": "Ejecutar un comando", + "docker": "Controlar un contenedor", + "tunnel": "Controlar un túnel", + "wol": "Despierta a un anfitrión", + "wait": "Esperar", + "set_var": "Establecer una variable", + "if": "Si / de lo contrario", + "run_automation": "Ejecuta otra automatización", + "stop": "Detener" + }, + "statuses": { + "running": "Correr", + "success": "Éxito", + "failed": "Fallido", + "timeout": "Tiempo de espera agotado", + "skipped": "Saltado", + "cancelled": "Cancelado" + }, + "fields": { + "host": "Anfitrión", + "metric": "Métrico", + "mount": "Punto de montaje", + "operator": "Es", + "value": "Valor", + "forSeconds": "Mantenido durante (segundos)", + "cooldown": "Tiempo de enfriamiento (minutos)", + "cron": "Expresión cron", + "intervalSeconds": "Cada (segundos)", + "timezone": "Huso horario", + "timezoneServer": "Hora del servidor", + "timezoneHint": "En esta zona se leen las horas cron. No se aplica a los horarios de intervalo.", + "container": "Recipiente", + "command": "Dominio", + "url": "URL", + "method": "Método", + "body": "Cuerpo", + "channels": "Canales", + "title": "Título", + "message": "Mensaje", + "snippet": "Retazo", + "seconds": "Artículos de segunda clase", + "conditionLeftPlaceholder": "Valor a comprobar", + "conditionRightPlaceholder": "Comparar con", + "variableName": "nombre de la variable", + "variableValue": "Valor", + "elevated": "Ejecutar con sudo", + "onError": "Si esto falla", + "allowPrivateNetwork": "Permitir direcciones de red local", + "allowPrivateNetworkHint": "Necesario para un servicio autohospedado en su LAN. Desactivado por defecto para evitar solicitudes a direcciones internas." + }, + "onError": { + "stop": "Detengan la carrera", + "continue": "Continuar" + } + } + } + }, + "nav": { + "automations": "Automatizaciones" + }, + "onboarding": { + "feature_automations": "Automatizaciones", + "feature_automations_desc": "Ejecuta pasos automáticamente cuando ocurra algo y recibe notificaciones." + } +} diff --git a/plugins/automations/locales/translated/fi_FI.json b/plugins/automations/locales/translated/fi_FI.json new file mode 100644 index 000000000..416104441 --- /dev/null +++ b/plugins/automations/locales/translated/fi_FI.json @@ -0,0 +1,149 @@ +{ + "newUi": { + "sidebar": { + "automations": { + "title": "Automaatiot", + "tabAutomations": "Automaatiot", + "tabRuns": "Juoksut", + "tabChannels": "Kanavat", + "createAutomation": "Uusi automaatio", + "backToAutomations": "Takaisin automaatioihin", + "createTitle": "Uusi automaatio", + "editTitle": "Muokkaa automatisointia", + "empty": "Ei vielä automaatioita. Luo sellainen reagoimaan mittariin, aikatauluun tai tapahtumaan.", + "emptyRuns": "Ei vielä juoksuja.", + "emptyChannels": "Ei kanavia vielä. Lisää yksi lähettääksesi ilmoituksia jonnekin.", + "noChannelsHint": "Kanavia ei ole vielä määritetty. Lisää yksi Kanavat-välilehdellä.", + "addChannel": "Lisää kanava", + "testChannel": "Testata", + "channelTestSent": "Testi-ilmoitus lähetetty", + "channelTestFailed": "Testi-ilmoitus epäonnistui", + "channelDeleted": "Kanava poistettu", + "deleteChannelConfirm": "Poistetaanko tämä kanava? Sitä käyttävät automaatiot lakkaavat lähettämästä ilmoituksia.", + "nameLabel": "Nimi", + "namePlaceholder": "esim. Siivoa /data, kun se täyttyy", + "nameRequired": "Nimi on pakollinen", + "descriptionLabel": "Kuvaus", + "descriptionPlaceholder": "Valinnainen kuvaus", + "enabledLabel": "Käytössä", + "concurrencyLabel": "Jos se on jo käynnissä", + "concurrencyHint": "Mitä tehdä, kun tämä laukeaa uudelleen ennen viimeisen ajon päättymistä.", + "concurrency": { + "skip": "Ohita uusi juoksu", + "queue": "Odota ja juokse perässä", + "allow": "Suorita molemmat yhtä aikaa" + }, + "save": "Tallentaa", + "created": "Automaatio luotu", + "updated": "Automaatio tallennettu", + "deleted": "Automaatio poistettu", + "deleteConfirm": "Poistetaanko tämä automaatio? Myös sen suoritushistoria poistetaan.", + "runNow": "Juokse nyt", + "testRun": "Koeajo", + "testRunHint": "Juoksee jokaisen askeleen, mutta ei koske mihinkään Termixin ulkopuolella.", + "runStarted": "Juoksu aloitettu", + "runFinished": "Suoritus päättynyt: {{status}}", + "trigger": "Laukaista", + "steps": "Askeleet", + "addStep": "Lisää vaihe", + "removeStep": "Poista vaihe", + "moveUp": "Siirry ylös", + "moveDown": "Siirrä alas", + "noSteps": "Ei vielä vaiheita. Lisää yksi, joka kertoo, mitä pitäisi tapahtua.", + "webhookTokenTitle": "Webhookin URL-osoite", + "webhookTokenDescription": "Tämä näytetään kerran. Tallenna se nyt, sitä ei voi palauttaa myöhemmin.", + "copy": "Kopioida", + "copied": "Kopioitu", + "viewJson": "JSON", + "viewBuilder": "Rakentaja", + "viewGraph": "Kaavio", + "lastRun": "Viimeisin juoksu", + "never": "Ei koskaan", + "duration": "{{seconds}}s", + "stepOutput": "Lähtö", + "stepError": "Virhe", + "dryRunBadge": "Koeajo", + "hostSelector": { + "trigger": "Käynnistävä isäntä", + "host": "Tietty isäntä", + "fleet": "Laivasto", + "all": "Kaikki isännät" + }, + "triggerKinds": { + "metric_threshold": "Metrinen kynnysarvo", + "host_status": "Isäntä nousee tai laskee", + "health_check": "Terveystarkastusten muutokset", + "schedule": "Aikataulussa", + "docker_event": "Säiliötapahtuma", + "internal_event": "Termix-tapahtuma", + "webhook": "Saapuva webhook" + }, + "stepTypes": { + "notify": "Lähetä ilmoitus", + "http": "Soita URL-osoitteeseen", + "run_snippet": "Suorita koodinpätkä", + "run_command": "Suorita komento", + "docker": "Säiliön hallinta", + "tunnel": "Hallitse tunnelia", + "wol": "Herätä isäntä", + "wait": "Odota", + "set_var": "Aseta muuttuja", + "if": "Jos / muuten", + "run_automation": "Suorita toinen automaatio", + "stop": "Stop" + }, + "statuses": { + "running": "Juoksu", + "success": "Menestys", + "failed": "Epäonnistui", + "timeout": "Aikakatkaisu", + "skipped": "Ohitettu", + "cancelled": "Peruutettu" + }, + "fields": { + "host": "Isäntä", + "metric": "Metrinen", + "mount": "Kiinnityskohta", + "operator": "On", + "value": "Arvo", + "forSeconds": "Jatkuu (sekuntia)", + "cooldown": "Jäähdyttelyaika (minuuttia)", + "cron": "Cron-lauseke", + "intervalSeconds": "Joka (sekunti)", + "timezone": "Aikavyöhyke", + "timezoneServer": "Palvelimen aika", + "timezoneHint": "Cron-ajat luetaan tällä alueella. Ei koske intervalliaikatauluja.", + "container": "Kontti", + "command": "Komento", + "url": "URL-osoite", + "method": "Menetelmä", + "body": "Keho", + "channels": "Kanavat", + "title": "Otsikko", + "message": "Viesti", + "snippet": "Katkelma", + "seconds": "Sekuntia", + "conditionLeftPlaceholder": "Tarkistettava arvo", + "conditionRightPlaceholder": "Vertaa", + "variableName": "Muuttujan nimi", + "variableValue": "Arvo", + "elevated": "Suorita sudon avulla", + "onError": "Jos tämä epäonnistuu", + "allowPrivateNetwork": "Salli paikallisverkko-osoitteet", + "allowPrivateNetworkHint": "Tarvitaan lähiverkossasi itse isännöidylle palvelulle. Oletusarvoisesti pois päältä estääkseen pyynnöt sisäisiin osoitteisiin." + }, + "onError": { + "stop": "Pysäytä juoksu", + "continue": "Jatkaa" + } + } + } + }, + "nav": { + "automations": "Automaatiot" + }, + "onboarding": { + "feature_automations": "Automaatiot", + "feature_automations_desc": "Suorita vaiheet automaattisesti, kun jotain tapahtuu, ja saat ilmoituksen." + } +} diff --git a/plugins/automations/locales/translated/fr_FR.json b/plugins/automations/locales/translated/fr_FR.json new file mode 100644 index 000000000..2186f410f --- /dev/null +++ b/plugins/automations/locales/translated/fr_FR.json @@ -0,0 +1,149 @@ +{ + "newUi": { + "sidebar": { + "automations": { + "title": "Automatisations", + "tabAutomations": "Automatisations", + "tabRuns": "Courses", + "tabChannels": "Chaînes", + "createAutomation": "Nouvelle automatisation", + "backToAutomations": "Retour aux automatisations", + "createTitle": "Nouvelle automatisation", + "editTitle": "Automatisation de la modification", + "empty": "Aucune automatisation pour le moment. Créez-en une pour qu'elle réagisse à une mesure, une planification ou un événement.", + "emptyRuns": "Pas encore de runs.", + "emptyChannels": "Aucun canal pour le moment. Ajoutez-en un pour envoyer des notifications.", + "noChannelsHint": "Aucune chaîne n'est encore configurée. Ajoutez-en une dans l'onglet Chaînes.", + "addChannel": "Ajouter une chaîne", + "testChannel": "Test", + "channelTestSent": "Notification de test envoyée", + "channelTestFailed": "La notification de test a échoué", + "channelDeleted": "Chaîne supprimée", + "deleteChannelConfirm": "Supprimer ce canal ? Les automatisations qui l'utilisent cesseront d'envoyer des notifications.", + "nameLabel": "Nom", + "namePlaceholder": "Par exemple, nettoyer le répertoire /data lorsqu'il est plein.", + "nameRequired": "Le nom est requis.", + "descriptionLabel": "Description", + "descriptionPlaceholder": "Description facultative", + "enabledLabel": "Activé", + "concurrencyLabel": "S'il est déjà en cours d'exécution", + "concurrencyHint": "Que faire si ce problème se reproduit avant la fin de la dernière exécution ?", + "concurrency": { + "skip": "Évitez la nouvelle course", + "queue": "Attendez et courez après", + "allow": "Exécutez les deux simultanément." + }, + "save": "Sauvegarder", + "created": "L'automatisation a créé", + "updated": "L'automatisation a permis de sauver", + "deleted": "Automatisation supprimée", + "deleteConfirm": "Supprimer cette automatisation ? Son historique d'exécution est également supprimé.", + "runNow": "Courez maintenant", + "testRun": "Essai", + "testRunHint": "Exécute chaque étape mais ne touche à rien en dehors de Termix.", + "runStarted": "La course a commencé", + "runFinished": "Course terminée : {{status}}", + "trigger": "Déclenchement", + "steps": "Mesures", + "addStep": "Ajouter une étape", + "removeStep": "Supprimer l'étape", + "moveUp": "Monter en gamme", + "moveDown": "Descendre", + "noSteps": "Aucune étape pour l'instant. Ajoutez-en une pour décrire ce qui doit se passer.", + "webhookTokenTitle": "URL du webhook", + "webhookTokenDescription": "Ceci ne s'affiche qu'une seule fois. Enregistrez-le maintenant, il ne pourra pas être récupéré ultérieurement.", + "copy": "Copie", + "copied": "Copié", + "viewJson": "JSON", + "viewBuilder": "Constructeur", + "viewGraph": "Graphique", + "lastRun": "Dernière course", + "never": "Jamais", + "duration": "{{seconds}}s", + "stepOutput": "Sortir", + "stepError": "Erreur", + "dryRunBadge": "Essai", + "hostSelector": { + "trigger": "Hôte déclencheur", + "host": "hôte spécifique", + "fleet": "Flotte", + "all": "Tous les hôtes" + }, + "triggerKinds": { + "metric_threshold": "Seuil métrique", + "host_status": "L'hôte monte ou descend", + "health_check": "changements au bilan de santé", + "schedule": "Selon un horaire", + "docker_event": "événement conteneur", + "internal_event": "Événement Termix", + "webhook": "Webhook entrant" + }, + "stepTypes": { + "notify": "Envoyer une notification", + "http": "Appeler une URL", + "run_snippet": "Exécuter un extrait de code", + "run_command": "Exécuter une commande", + "docker": "Contrôler un conteneur", + "tunnel": "Contrôler un tunnel", + "wol": "Réveillez un hôte", + "wait": "Attendez", + "set_var": "Définir une variable", + "if": "Si / sinon", + "run_automation": "Exécutez une autre automatisation", + "stop": "Arrêt" + }, + "statuses": { + "running": "En cours d'exécution", + "success": "Succès", + "failed": "Échoué", + "timeout": "Délai d'attente dépassé", + "skipped": "Omission", + "cancelled": "Annulé" + }, + "fields": { + "host": "Hôte", + "metric": "Métrique", + "mount": "Point de montage", + "operator": "Est", + "value": "Valeur", + "forSeconds": "Maintenu pendant (secondes)", + "cooldown": "Temps de récupération (minutes)", + "cron": "Expression de Cron", + "intervalSeconds": "Toutes les (secondes)", + "timezone": "Fuseau horaire", + "timezoneServer": "Heure du serveur", + "timezoneHint": "Les heures des tâches cron sont lues dans cette zone. Ceci ne s'applique pas aux planifications par intervalles.", + "container": "Récipient", + "command": "Commande", + "url": "URL", + "method": "Méthode", + "body": "Corps", + "channels": "Chaînes", + "title": "Titre", + "message": "Message", + "snippet": "Fragment", + "seconds": "Secondes", + "conditionLeftPlaceholder": "Valeur à vérifier", + "conditionRightPlaceholder": "Comparer à", + "variableName": "Nom de la variable", + "variableValue": "Valeur", + "elevated": "Exécuter avec sudo", + "onError": "Si cela échoue", + "allowPrivateNetwork": "Autoriser les adresses réseau locales", + "allowPrivateNetworkHint": "Nécessaire pour un service auto-hébergé sur votre réseau local. Désactivé par défaut pour empêcher les requêtes vers des adresses internes." + }, + "onError": { + "stop": "Arrêtez la course", + "continue": "Continuer" + } + } + } + }, + "nav": { + "automations": "Automatisations" + }, + "onboarding": { + "feature_automations": "Automatisations", + "feature_automations_desc": "Exécutez des actions automatiquement lorsqu'un événement se produit et recevez une notification." + } +} diff --git a/plugins/automations/locales/translated/he_IL.json b/plugins/automations/locales/translated/he_IL.json new file mode 100644 index 000000000..930eef807 --- /dev/null +++ b/plugins/automations/locales/translated/he_IL.json @@ -0,0 +1,149 @@ +{ + "newUi": { + "sidebar": { + "automations": { + "title": "אוטומציות", + "tabAutomations": "אוטומציות", + "tabRuns": "ריצות", + "tabChannels": "ערוצים", + "createAutomation": "אוטומציה חדשה", + "backToAutomations": "חזרה לאוטומציות", + "createTitle": "אוטומציה חדשה", + "editTitle": "עריכה אוטומציה", + "empty": "אין עדיין אוטומציות. צור אחת שתגיב למדד, לוח זמנים או אירוע.", + "emptyRuns": "עדיין אין ריצות.", + "emptyChannels": "אין עדיין ערוצים. הוסף ערוצים כדי לשלוח התראות לאנשהו.", + "noChannelsHint": "עדיין לא הוגדרו ערוצים. הוסף אחד בכרטיסייה ערוצים.", + "addChannel": "הוסף ערוץ", + "testChannel": "מִבְחָן", + "channelTestSent": "הודעת בדיקה נשלחה", + "channelTestFailed": "הודעת הבדיקה נכשלה", + "channelDeleted": "הערוץ נמחק", + "deleteChannelConfirm": "למחוק את הערוץ הזה? אוטומציות המשתמשות בו יפסיקו לשלוח התראות.", + "nameLabel": "שֵׁם", + "namePlaceholder": "לדוגמה, ניקוי /נתונים כאשר הוא מתמלא", + "nameRequired": "שם נדרש", + "descriptionLabel": "תֵאוּר", + "descriptionPlaceholder": "תיאור אופציונלי", + "enabledLabel": "מופעל", + "concurrencyLabel": "אם זה כבר פועל", + "concurrencyHint": "מה לעשות כאשר זה מופעל שוב לפני שהריצה האחרונה הסתיימה.", + "concurrency": { + "skip": "דלג על הריצה החדשה", + "queue": "חכו ורצנו אחרי", + "allow": "הפעל את שניהם בו זמנית" + }, + "save": "לְהַצִיל", + "created": "אוטומציה נוצרה", + "updated": "אוטומציה נשמרה", + "deleted": "אוטומציה נמחקה", + "deleteConfirm": "למחוק את האוטומציה הזו? גם היסטוריית הריצות שלה נמחקת.", + "runNow": "רוץ עכשיו", + "testRun": "ריצת מבחן", + "testRunHint": "רץ כל שלב אבל לא נוגע בשום דבר מחוץ לטרמיקס.", + "runStarted": "הריצה התחילה", + "runFinished": "ריצה הסתיימה: {{status}}", + "trigger": "לְהַפְעִיל", + "steps": "צעדים", + "addStep": "הוסף שלב", + "removeStep": "הסר שלב", + "moveUp": "הזז למעלה", + "moveDown": "הזז למטה", + "noSteps": "אין עדיין שלבים. הוסף שלבים כדי לומר מה אמור לקרות.", + "webhookTokenTitle": "כתובת אתר של Webhook", + "webhookTokenDescription": "זה מוצג פעם אחת. שמור את זה עכשיו, לא ניתן לאחזר את זה מאוחר יותר.", + "copy": "לְהַעְתִיק", + "copied": "מוּעֲתָק", + "viewJson": "JSON", + "viewBuilder": "בּוֹנֶה", + "viewGraph": "גרָף", + "lastRun": "ריצה אחרונה", + "never": "לְעוֹלָם לֹא", + "duration": "{{seconds}}ים", + "stepOutput": "תְפוּקָה", + "stepError": "שְׁגִיאָה", + "dryRunBadge": "ריצת מבחן", + "hostSelector": { + "trigger": "מארח מפעיל", + "host": "מארח ספציפי", + "fleet": "צִי", + "all": "כל המארחים" + }, + "triggerKinds": { + "metric_threshold": "סף מטרי", + "host_status": "המארח עולה או יורד", + "health_check": "שינויים בבדיקת הבריאות", + "schedule": "על פי לוח זמנים", + "docker_event": "אירוע מיכל", + "internal_event": "אירוע טרמיקס", + "webhook": "וובהוק נכנס" + }, + "stepTypes": { + "notify": "שלח הודעה", + "http": "קריאה לכתובת URL", + "run_snippet": "הפעלת קטע קוד", + "run_command": "הפעל פקודה", + "docker": "שליטה על מכולה", + "tunnel": "שליטה במנהרה", + "wol": "להעיר מארח", + "wait": "לַחֲכוֹת", + "set_var": "הגדר משתנה", + "if": "אם / אחרת", + "run_automation": "הפעל אוטומציה נוספת", + "stop": "לְהַפְסִיק" + }, + "statuses": { + "running": "רִיצָה", + "success": "הַצלָחָה", + "failed": "נִכשָׁל", + "timeout": "תם הזמן", + "skipped": "דילג", + "cancelled": "בּוּטלָה" + }, + "fields": { + "host": "מְאָרֵחַ", + "metric": "מֶטרִי", + "mount": "נקודת הרכבה", + "operator": "האם", + "value": "עֵרֶך", + "forSeconds": "נמשך (שניות)", + "cooldown": "זמן קירור (דקות)", + "cron": "ביטוי קרון", + "intervalSeconds": "כל (שניות)", + "timezone": "אזור זמן", + "timezoneServer": "זמן שרת", + "timezoneHint": "זמני Cron נקראים באזור זה. לא חל על לוחות זמנים של מרווחים.", + "container": "מְכוֹלָה", + "command": "פְּקוּדָה", + "url": "כתובת אתר", + "method": "שִׁיטָה", + "body": "גוּף", + "channels": "ערוצים", + "title": "כּוֹתֶרֶת", + "message": "הוֹדָעָה", + "snippet": "קטע", + "seconds": "שניות", + "conditionLeftPlaceholder": "ערך לבדיקה", + "conditionRightPlaceholder": "השווה מול", + "variableName": "שם משתנה", + "variableValue": "עֵרֶך", + "elevated": "רוץ עם סודו", + "onError": "אם זה ייכשל", + "allowPrivateNetwork": "אפשר כתובות רשת מקומיות", + "allowPrivateNetworkHint": "נדרש עבור שירות אירוח עצמי ברשת הרשת המקומית שלך. כבוי כברירת מחדל כדי למנוע בקשות לכתובות פנימיות." + }, + "onError": { + "stop": "עצור את הריצה", + "continue": "לְהַמשִׁיך" + } + } + } + }, + "nav": { + "automations": "אוטומציות" + }, + "onboarding": { + "feature_automations": "אוטומציות", + "feature_automations_desc": "הפעל שלבים באופן אוטומטי כאשר משהו קורה, וקבל הודעה." + } +} diff --git a/plugins/automations/locales/translated/hi_IN.json b/plugins/automations/locales/translated/hi_IN.json new file mode 100644 index 000000000..509772b20 --- /dev/null +++ b/plugins/automations/locales/translated/hi_IN.json @@ -0,0 +1,149 @@ +{ + "newUi": { + "sidebar": { + "automations": { + "title": "स्वचालन", + "tabAutomations": "स्वचालन", + "tabRuns": "दौड़ें", + "tabChannels": "चैनल", + "createAutomation": "नया स्वचालन", + "backToAutomations": "स्वचालन पर वापस जाएँ", + "createTitle": "नया स्वचालन", + "editTitle": "संपादन स्वचालन", + "empty": "अभी तक कोई ऑटोमेशन नहीं है। किसी मेट्रिक, शेड्यूल या इवेंट के आधार पर प्रतिक्रिया देने के लिए एक ऑटोमेशन बनाएं।", + "emptyRuns": "अभी तक कोई रन नहीं बना है।", + "emptyChannels": "अभी तक कोई चैनल नहीं है। सूचनाएं भेजने के लिए एक चैनल जोड़ें।", + "noChannelsHint": "अभी तक कोई चैनल सेट अप नहीं किया गया है। चैनल टैब में एक चैनल जोड़ें।", + "addChannel": "चैनल जोड़ें", + "testChannel": "परीक्षा", + "channelTestSent": "परीक्षण अधिसूचना भेजी गई", + "channelTestFailed": "टेस्ट नोटिफिकेशन विफल रहा", + "channelDeleted": "चैनल हटा दिया गया", + "deleteChannelConfirm": "क्या इस चैनल को हटा दें? इसका उपयोग करने वाले ऑटोमेशन नोटिफिकेशन भेजना बंद कर देंगे।", + "nameLabel": "नाम", + "namePlaceholder": "उदाहरण के लिए, जब /data भर जाए तो उसे साफ़ कर दें।", + "nameRequired": "नाम आवश्यक है", + "descriptionLabel": "विवरण", + "descriptionPlaceholder": "वैकल्पिक विवरण", + "enabledLabel": "सक्रिय", + "concurrencyLabel": "यदि यह पहले से चल रहा है", + "concurrencyHint": "पिछली बार रन पूरा होने से पहले ही अगर यह समस्या दोबारा उत्पन्न हो जाए तो क्या करें।", + "concurrency": { + "skip": "नए रन को छोड़ दें", + "queue": "प्रतीक्षा करो और उसके पीछे दौड़ो", + "allow": "दोनों को एक साथ चलाएं" + }, + "save": "बचाना", + "created": "स्वचालन द्वारा निर्मित", + "updated": "स्वचालन ने बचत की", + "deleted": "स्वचालित रूप से हटा दिया गया", + "deleteConfirm": "इस ऑटोमेशन को डिलीट करने पर, इसका रन हिस्ट्री भी डिलीट हो जाएगा।", + "runNow": "अब दौड़े", + "testRun": "परीक्षण के लिए चलाना", + "testRunHint": "यह हर चरण में दौड़ता है लेकिन टर्मिक्स के बाहर किसी भी चीज को नहीं छूता है।", + "runStarted": "दौड़ शुरू हो गई", + "runFinished": "रन समाप्त: {{status}}", + "trigger": "चालू कर देना", + "steps": "चरण", + "addStep": "चरण जोड़ें", + "removeStep": "चरण हटाएँ", + "moveUp": "बढ़ाना", + "moveDown": "नीचे की ओर", + "noSteps": "अभी तक कोई चरण निर्धारित नहीं हैं। कृपया एक चरण जोड़कर बताएं कि आगे क्या होना चाहिए।", + "webhookTokenTitle": "वेबहुक यूआरएल", + "webhookTokenDescription": "यह केवल एक बार दिखाया जाएगा। इसे अभी सहेज लें, बाद में इसे पुनः प्राप्त नहीं किया जा सकेगा।", + "copy": "प्रतिलिपि", + "copied": "कॉपी किया गया", + "viewJson": "जेएन", + "viewBuilder": "निर्माता", + "viewGraph": "ग्राफ़", + "lastRun": "आखरी बार", + "never": "कभी नहीं", + "duration": "{{seconds}}s", + "stepOutput": "उत्पादन", + "stepError": "गलती", + "dryRunBadge": "परीक्षण के लिए चलाना", + "hostSelector": { + "trigger": "ट्रिगरिंग होस्ट", + "host": "विशिष्ट मेज़बान", + "fleet": "बेड़ा", + "all": "सभी मेजबान" + }, + "triggerKinds": { + "metric_threshold": "मीट्रिक सीमा", + "host_status": "होस्ट ऊपर या नीचे जाता है", + "health_check": "स्वास्थ्य जांच में बदलाव", + "schedule": "एक निर्धारित कार्यक्रम के अनुसार", + "docker_event": "कंटेनर घटना", + "internal_event": "टर्मिक्स घटना", + "webhook": "इनकमिंग वेबहुक" + }, + "stepTypes": { + "notify": "सूचना भेजें", + "http": "किसी URL को कॉल करें", + "run_snippet": "एक स्निपेट चलाएँ", + "run_command": "एक कमांड चलाएँ", + "docker": "एक कंटेनर को नियंत्रित करें", + "tunnel": "एक सुरंग को नियंत्रित करें", + "wol": "किसी मेजबान को जगाओ", + "wait": "इंतज़ार", + "set_var": "एक चर सेट करें", + "if": "यदि / अन्यथा", + "run_automation": "एक और ऑटोमेशन चलाएँ", + "stop": "रुकना" + }, + "statuses": { + "running": "दौड़ना", + "success": "सफलता", + "failed": "असफल", + "timeout": "समय समााप्त", + "skipped": "छोड़ा गया", + "cancelled": "रद्द कर दिया गया" + }, + "fields": { + "host": "मेज़बान", + "metric": "मीट्रिक", + "mount": "माउंट पॉइंट", + "operator": "है", + "value": "कीमत", + "forSeconds": "(सेकंड) तक कायम रहा", + "cooldown": "कूलडाउन (मिनटों में)", + "cron": "क्रोन अभिव्यक्ति", + "intervalSeconds": "हर (सेकंड)", + "timezone": "समय क्षेत्र", + "timezoneServer": "सर्वर समय", + "timezoneHint": "इस ज़ोन में क्रॉन टाइम पढ़े जाते हैं। यह इंटरवल शेड्यूल पर लागू नहीं होता है।", + "container": "पात्र", + "command": "आज्ञा", + "url": "यूआरएल", + "method": "तरीका", + "body": "शरीर", + "channels": "चैनल", + "title": "शीर्षक", + "message": "संदेश", + "snippet": "टुकड़ा", + "seconds": "सेकंड", + "conditionLeftPlaceholder": "जाँच करने के लिए मान", + "conditionRightPlaceholder": "तुलना करें", + "variableName": "चर का नाम", + "variableValue": "कीमत", + "elevated": "sudo के साथ चलाएँ", + "onError": "यदि यह विफल हो जाता है", + "allowPrivateNetwork": "स्थानीय नेटवर्क पतों की अनुमति दें", + "allowPrivateNetworkHint": "आपके लोकल एरिया नेटवर्क (LAN) पर सेल्फ-होस्टेड सेवा के लिए आवश्यक। आंतरिक पतों पर अनुरोधों को रोकने के लिए डिफ़ॉल्ट रूप से बंद।" + }, + "onError": { + "stop": "दौड़ रोको", + "continue": "जारी रखो" + } + } + } + }, + "nav": { + "automations": "स्वचालन" + }, + "onboarding": { + "feature_automations": "स्वचालन", + "feature_automations_desc": "कुछ घटित होने पर चरणों को स्वचालित रूप से चलाएं और सूचना प्राप्त करें।" + } +} diff --git a/plugins/automations/locales/translated/hu_HU.json b/plugins/automations/locales/translated/hu_HU.json new file mode 100644 index 000000000..23f06e1c3 --- /dev/null +++ b/plugins/automations/locales/translated/hu_HU.json @@ -0,0 +1,149 @@ +{ + "newUi": { + "sidebar": { + "automations": { + "title": "Automatizálások", + "tabAutomations": "Automatizálások", + "tabRuns": "Futások", + "tabChannels": "Csatornák", + "createAutomation": "Új automatizálás", + "backToAutomations": "Vissza az automatizálásokhoz", + "createTitle": "Új automatizálás", + "editTitle": "Szerkesztési automatizálás", + "empty": "Még nincsenek automatizálások. Hozz létre egyet, amely egy mérőszámra, ütemezésre vagy eseményre reagál.", + "emptyRuns": "Még nincsenek futások.", + "emptyChannels": "Még nincsenek csatornák. Adj hozzá egyet, hogy értesítéseket küldhess valahova.", + "noChannelsHint": "Még nincsenek beállítva csatornák. Adjon hozzá egyet a Csatornák fülön.", + "addChannel": "Csatorna hozzáadása", + "testChannel": "Teszt", + "channelTestSent": "Tesztértesítés elküldve", + "channelTestFailed": "Tesztértesítés sikertelen", + "channelDeleted": "Csatorna törölve", + "deleteChannelConfirm": "Törlöd ezt a csatornát? Az azt használó automatizálások nem fognak értesítéseket küldeni.", + "nameLabel": "Név", + "namePlaceholder": "pl. /data törlése, amikor megtelik", + "nameRequired": "Név megadása kötelező", + "descriptionLabel": "Leírás", + "descriptionPlaceholder": "Opcionális leírás", + "enabledLabel": "Engedélyezve", + "concurrencyLabel": "Ha már fut", + "concurrencyHint": "Mi a teendő, ha ez ismét aktiválódik, mielőtt az utolsó futtatás befejeződött?", + "concurrency": { + "skip": "Kihagyja az új futást", + "queue": "Várj és fuss utána", + "allow": "Futtassa mindkettőt egyszerre" + }, + "save": "Megtakarítás", + "created": "Automatizálás létrehozva", + "updated": "Automatizálás mentve", + "deleted": "Automatizálás törölve", + "deleteConfirm": "Törli ezt az automatizálást? A futási előzményei is törlődnek.", + "runNow": "Futtatás most", + "testRun": "Próbaüzem", + "testRunHint": "Minden lépést lefuttat, de a Termixen kívül semmihez sem ér hozzá.", + "runStarted": "Futtatás elkezdve", + "runFinished": "Futtatás befejezve: {{status}}", + "trigger": "Trigger", + "steps": "Lépések", + "addStep": "Lépés hozzáadása", + "removeStep": "Lépés eltávolítása", + "moveUp": "Feljebb mozgatás", + "moveDown": "Lejjebb mozgatás", + "noSteps": "Még nincsenek lépések. Írj be egyet, ami leírja, hogy minek kellene történnie.", + "webhookTokenTitle": "Webhook URL-címe", + "webhookTokenDescription": "Ez egyszer jelenik meg. Mentsd el most, később nem lesz elérhető.", + "copy": "Másolat", + "copied": "Másolva", + "viewJson": "JSON", + "viewBuilder": "Építész", + "viewGraph": "Grafikon", + "lastRun": "Utolsó futás", + "never": "Soha", + "duration": "{{seconds}}s", + "stepOutput": "Kimenet", + "stepError": "Hiba", + "dryRunBadge": "Próbaüzem", + "hostSelector": { + "trigger": "Kiváltó gazdagép", + "host": "Adott gazdagép", + "fleet": "Flotta", + "all": "Minden házigazda" + }, + "triggerKinds": { + "metric_threshold": "Metrikus küszöbérték", + "host_status": "A host fel- vagy lekapcsolódik", + "health_check": "Egészségügyi ellenőrzés változásai", + "schedule": "Ütemterv szerint", + "docker_event": "Konténeresemény", + "internal_event": "Termix esemény", + "webhook": "Bejövő webhook" + }, + "stepTypes": { + "notify": "Értesítés küldése", + "http": "URL hívása", + "run_snippet": "Kódrészlet futtatása", + "run_command": "Parancs futtatása", + "docker": "Egy konténer vezérlése", + "tunnel": "Irányíts egy alagutat", + "wol": "Ébresszen fel egy házigazdát", + "wait": "Várjon", + "set_var": "Változó beállítása", + "if": "Ha / egyébként", + "run_automation": "Futtasson egy másik automatizálást", + "stop": "Stop" + }, + "statuses": { + "running": "Futás", + "success": "Siker", + "failed": "Sikertelen", + "timeout": "Időtúllépés történt", + "skipped": "Kihagyva", + "cancelled": "Lemondva" + }, + "fields": { + "host": "Házigazda", + "metric": "Metrika", + "mount": "Csatlakozási pont", + "operator": "Van", + "value": "Érték", + "forSeconds": "Fenntartott (másodperc)", + "cooldown": "Lehűlési idő (perc)", + "cron": "Cron kifejezés", + "intervalSeconds": "Minden (másodperc)", + "timezone": "Időzóna", + "timezoneServer": "Szerveridő", + "timezoneHint": "A Cron idők leolvasása ebben a zónában történik. Nem vonatkozik az intervallumos ütemtervekre.", + "container": "Tartály", + "command": "Parancs", + "url": "URL-cím", + "method": "Módszer", + "body": "Test", + "channels": "Csatornák", + "title": "Cím", + "message": "Üzenet", + "snippet": "Töredék", + "seconds": "Másodperc", + "conditionLeftPlaceholder": "Ellenőrizendő érték", + "conditionRightPlaceholder": "Összevet", + "variableName": "Változó neve", + "variableValue": "Érték", + "elevated": "Futtassa a sudo paranccsal", + "onError": "Ha ez nem sikerül", + "allowPrivateNetwork": "Helyi hálózati címek engedélyezése", + "allowPrivateNetworkHint": "Szükséges egy saját tárhelyen futó szolgáltatáshoz a helyi hálózaton. Alapértelmezés szerint ki van kapcsolva, hogy megakadályozza a belső címekre irányuló kéréseket." + }, + "onError": { + "stop": "Állítsd meg a futást", + "continue": "Folytat" + } + } + } + }, + "nav": { + "automations": "Automatizálások" + }, + "onboarding": { + "feature_automations": "Automatizálások", + "feature_automations_desc": "Automatikusan futtassa a lépéseket, amikor valami történik, és kapjon értesítést." + } +} diff --git a/plugins/automations/locales/translated/id_ID.json b/plugins/automations/locales/translated/id_ID.json new file mode 100644 index 000000000..4f52e8a49 --- /dev/null +++ b/plugins/automations/locales/translated/id_ID.json @@ -0,0 +1,149 @@ +{ + "newUi": { + "sidebar": { + "automations": { + "title": "Otomatisasi", + "tabAutomations": "Otomatisasi", + "tabRuns": "Lari", + "tabChannels": "Saluran", + "createAutomation": "Otomatisasi Baru", + "backToAutomations": "Kembali ke Otomatisasi", + "createTitle": "Otomatisasi Baru", + "editTitle": "Edit Otomatisasi", + "empty": "Belum ada otomatisasi. Buat satu untuk bereaksi terhadap metrik, jadwal, atau peristiwa.", + "emptyRuns": "Belum ada percobaan lari.", + "emptyChannels": "Belum ada saluran. Tambahkan satu untuk mengirim notifikasi ke suatu tempat.", + "noChannelsHint": "Belum ada saluran yang dibuat. Tambahkan satu di tab Saluran.", + "addChannel": "Tambahkan Saluran", + "testChannel": "Tes", + "channelTestSent": "Notifikasi pengujian telah dikirim.", + "channelTestFailed": "Notifikasi pengujian gagal", + "channelDeleted": "Saluran dihapus", + "deleteChannelConfirm": "Hapus saluran ini? Otomatisasi yang menggunakannya akan berhenti memberi notifikasi.", + "nameLabel": "Nama", + "namePlaceholder": "misalnya, Bersihkan /data saat sudah penuh", + "nameRequired": "Nama wajib diisi.", + "descriptionLabel": "Keterangan", + "descriptionPlaceholder": "Deskripsi opsional", + "enabledLabel": "Diaktifkan", + "concurrencyLabel": "Jika sudah berjalan", + "concurrencyHint": "Apa yang harus dilakukan jika ini terpicu lagi sebelum proses terakhir selesai.", + "concurrency": { + "skip": "Lewati lari baru", + "queue": "Tunggu dan lari setelahnya", + "allow": "Jalankan keduanya sekaligus" + }, + "save": "Menyimpan", + "created": "Otomatisasi dibuat", + "updated": "Otomatisasi tersimpan", + "deleted": "Otomatisasi dihapus", + "deleteConfirm": "Hapus otomatisasi ini? Riwayat eksekusinya juga akan terhapus.", + "runNow": "Lari sekarang", + "testRun": "Uji coba", + "testRunHint": "Berjalan di setiap langkah tetapi tidak menyentuh apa pun di luar Termix.", + "runStarted": "Lari dimulai", + "runFinished": "Eksekusi selesai: {{status}}", + "trigger": "Pemicu", + "steps": "Tangga", + "addStep": "Tambahkan langkah", + "removeStep": "Hapus langkah", + "moveUp": "Naikkan", + "moveDown": "Turun ke bawah", + "noSteps": "Belum ada langkah. Tambahkan satu langkah untuk menjelaskan apa yang seharusnya terjadi.", + "webhookTokenTitle": "URL Webhook", + "webhookTokenDescription": "Ini hanya ditampilkan sekali. Simpan sekarang, karena tidak dapat diambil kembali nanti.", + "copy": "Menyalin", + "copied": "Disalin", + "viewJson": "JSON", + "viewBuilder": "Pembangun", + "viewGraph": "Grafik", + "lastRun": "Lari terakhir", + "never": "Tidak pernah", + "duration": "{{seconds}}s", + "stepOutput": "Keluaran", + "stepError": "Kesalahan", + "dryRunBadge": "Uji coba", + "hostSelector": { + "trigger": "Host pemicu", + "host": "Host spesifik", + "fleet": "Armada", + "all": "Semua tuan rumah" + }, + "triggerKinds": { + "metric_threshold": "Ambang batas metrik", + "host_status": "Pembawa acara naik atau turun", + "health_check": "Perubahan pemeriksaan kesehatan", + "schedule": "Sesuai jadwal", + "docker_event": "Acara kontainer", + "internal_event": "Acara Termix", + "webhook": "Webhook masuk" + }, + "stepTypes": { + "notify": "Kirim pemberitahuan", + "http": "Memanggil URL", + "run_snippet": "Jalankan cuplikan kode", + "run_command": "Jalankan perintah", + "docker": "Mengendalikan sebuah kontainer", + "tunnel": "Mengendalikan terowongan", + "wol": "Bangunkan tuan rumah", + "wait": "Tunggu", + "set_var": "Tetapkan sebuah variabel", + "if": "Jika/sebaliknya", + "run_automation": "Jalankan otomatisasi lainnya", + "stop": "Berhenti" + }, + "statuses": { + "running": "Berlari", + "success": "Kesuksesan", + "failed": "Gagal", + "timeout": "Waktu habis", + "skipped": "Dilewati", + "cancelled": "Dibatalkan" + }, + "fields": { + "host": "Tuan rumah", + "metric": "Metrik", + "mount": "Titik pemasangan", + "operator": "Adalah", + "value": "Nilai", + "forSeconds": "Berlangsung selama (detik)", + "cooldown": "Waktu pendinginan (menit)", + "cron": "Ekspresi Cron", + "intervalSeconds": "Setiap (detik)", + "timezone": "Zona waktu", + "timezoneServer": "Waktu server", + "timezoneHint": "Waktu Cron dibaca di zona ini. Tidak berlaku untuk jadwal interval.", + "container": "Wadah", + "command": "Memerintah", + "url": "URL", + "method": "Metode", + "body": "Tubuh", + "channels": "Saluran", + "title": "Judul", + "message": "Pesan", + "snippet": "Potongan", + "seconds": "Detik", + "conditionLeftPlaceholder": "Nilai yang perlu diperiksa", + "conditionRightPlaceholder": "Bandingkan dengan", + "variableName": "Nama variabel", + "variableValue": "Nilai", + "elevated": "Jalankan dengan sudo", + "onError": "Jika ini gagal", + "allowPrivateNetwork": "Izinkan alamat jaringan lokal", + "allowPrivateNetworkHint": "Diperlukan untuk layanan yang dihosting sendiri di LAN Anda. Secara default dinonaktifkan untuk mencegah permintaan ke alamat internal." + }, + "onError": { + "stop": "Hentikan larinya", + "continue": "Melanjutkan" + } + } + } + }, + "nav": { + "automations": "Otomatisasi" + }, + "onboarding": { + "feature_automations": "Otomatisasi", + "feature_automations_desc": "Jalankan langkah-langkah secara otomatis saat sesuatu terjadi, dan dapatkan notifikasi." + } +} diff --git a/plugins/automations/locales/translated/it_IT.json b/plugins/automations/locales/translated/it_IT.json new file mode 100644 index 000000000..a46c29cf3 --- /dev/null +++ b/plugins/automations/locales/translated/it_IT.json @@ -0,0 +1,149 @@ +{ + "newUi": { + "sidebar": { + "automations": { + "title": "Automazioni", + "tabAutomations": "Automazioni", + "tabRuns": "Corse", + "tabChannels": "Canali", + "createAutomation": "Nuova automazione", + "backToAutomations": "Torna alle automazioni", + "createTitle": "Nuova automazione", + "editTitle": "Automazione di modifica", + "empty": "Nessuna automazione ancora disponibile. Creane una per reagire a una metrica, a una pianificazione o a un evento.", + "emptyRuns": "Nessuna corsa ancora.", + "emptyChannels": "Nessun canale ancora. Aggiungine uno per inviare notifiche da qualche parte.", + "noChannelsHint": "Nessun canale configurato al momento. Aggiungine uno nella scheda Canali.", + "addChannel": "Aggiungi canale", + "testChannel": "Test", + "channelTestSent": "Notifica di test inviata", + "channelTestFailed": "Notifica di prova non riuscita", + "channelDeleted": "Canale eliminato", + "deleteChannelConfirm": "Eliminare questo canale? Le automazioni che lo utilizzano smetteranno di inviare notifiche.", + "nameLabel": "Nome", + "namePlaceholder": "Ad esempio, pulire /data quando è pieno", + "nameRequired": "Il nome è obbligatorio", + "descriptionLabel": "Descrizione", + "descriptionPlaceholder": "Descrizione facoltativa", + "enabledLabel": "Abilitato", + "concurrencyLabel": "Se è già in esecuzione", + "concurrencyHint": "Cosa fare se questo problema si ripresenta prima che l'ultima esecuzione sia terminata.", + "concurrency": { + "skip": "Salta la nuova corsa", + "queue": "Aspetta e corri dopo", + "allow": "Eseguili entrambi contemporaneamente" + }, + "save": "Salva", + "created": "Automazione creata", + "updated": "Automazione salvata", + "deleted": "Automazione eliminata", + "deleteConfirm": "Eliminare questa automazione? Anche la sua cronologia di esecuzione verrà eliminata.", + "runNow": "Corri adesso", + "testRun": "Esecuzione del test", + "testRunHint": "Esegue ogni passaggio ma non tocca nulla al di fuori di Termix.", + "runStarted": "Corsa iniziata", + "runFinished": "Corsa terminata: {{status}}", + "trigger": "Grilletto", + "steps": "Passaggi", + "addStep": "Aggiungi passaggio", + "removeStep": "Rimuovere il passaggio", + "moveUp": "Spostarsi verso l'alto", + "moveDown": "Scendendo", + "noSteps": "Nessun passaggio ancora. Aggiungine uno per specificare cosa dovrebbe succedere.", + "webhookTokenTitle": "URL del webhook", + "webhookTokenDescription": "Questa immagine viene visualizzata una sola volta. Salvala ora, non sarà possibile recuperarla in seguito.", + "copy": "Copia", + "copied": "Copiato", + "viewJson": "JSON", + "viewBuilder": "Costruttore", + "viewGraph": "Grafico", + "lastRun": "Prima corsa", + "never": "Mai", + "duration": "{{seconds}}s", + "stepOutput": "Produzione", + "stepError": "Errore", + "dryRunBadge": "Esecuzione del test", + "hostSelector": { + "trigger": "Host che ha attivato l'evento", + "host": "Ospite specifico", + "fleet": "Flotta", + "all": "Tutti gli host" + }, + "triggerKinds": { + "metric_threshold": "Soglia metrica", + "host_status": "L'host sale o scende", + "health_check": "modifiche al controllo sanitario", + "schedule": "Secondo un programma", + "docker_event": "evento contenitore", + "internal_event": "Evento Termix", + "webhook": "Webhook in entrata" + }, + "stepTypes": { + "notify": "Invia una notifica", + "http": "Chiamare un medico", + "run_snippet": "Esegui uno snippet", + "run_command": "Eseguire un comando", + "docker": "Controllare un contenitore", + "tunnel": "Controllare un tunnel", + "wol": "Svegliare un ospite", + "wait": "Aspettare", + "set_var": "Imposta una variabile", + "if": "Se / altrimenti", + "run_automation": "Esegui un'altra automazione", + "stop": "Fermare" + }, + "statuses": { + "running": "Corsa", + "success": "Successo", + "failed": "Fallito", + "timeout": "Tempo scaduto", + "skipped": "Saltato", + "cancelled": "Annullato" + }, + "fields": { + "host": "Ospite", + "metric": "metrico", + "mount": "Punto di appoggio", + "operator": "È", + "value": "Valore", + "forSeconds": "Sostenuto per (secondi)", + "cooldown": "Tempo di raffreddamento (minuti)", + "cron": "espressione Cron", + "intervalSeconds": "Ogni (secondi)", + "timezone": "Fuso orario", + "timezoneServer": "Ora del server", + "timezoneHint": "In questa zona vengono letti i tempi di Cron. Non si applica alle programmazioni a intervalli.", + "container": "Contenitore", + "command": "Comando", + "url": "URL", + "method": "Metodo", + "body": "Corpo", + "channels": "Canali", + "title": "Titolo", + "message": "Messaggio", + "snippet": "Frammento", + "seconds": "secondi", + "conditionLeftPlaceholder": "Valore da controllare", + "conditionRightPlaceholder": "Confronta con", + "variableName": "Nome variabile", + "variableValue": "Valore", + "elevated": "Esegui con sudo", + "onError": "Se questo non funziona", + "allowPrivateNetwork": "Consenti indirizzi di rete locale", + "allowPrivateNetworkHint": "Necessario per un servizio self-hosted sulla tua LAN. Disattivato per impostazione predefinita per impedire richieste a indirizzi interni." + }, + "onError": { + "stop": "Ferma la corsa", + "continue": "Proseguire" + } + } + } + }, + "nav": { + "automations": "Automazioni" + }, + "onboarding": { + "feature_automations": "Automazioni", + "feature_automations_desc": "Esegui automaticamente i passaggi quando si verifica un evento e ricevi una notifica." + } +} diff --git a/plugins/automations/locales/translated/ja_JP.json b/plugins/automations/locales/translated/ja_JP.json new file mode 100644 index 000000000..986e159b9 --- /dev/null +++ b/plugins/automations/locales/translated/ja_JP.json @@ -0,0 +1,149 @@ +{ + "newUi": { + "sidebar": { + "automations": { + "title": "自動化", + "tabAutomations": "自動化", + "tabRuns": "走る", + "tabChannels": "チャンネル", + "createAutomation": "新しい自動化", + "backToAutomations": "自動化に戻る", + "createTitle": "新しい自動化", + "editTitle": "編集自動化", + "empty": "自動化はまだ設定されていません。指標、スケジュール、またはイベントに応じて自動化を設定してください。", + "emptyRuns": "まだ得点はありません。", + "emptyChannels": "まだチャンネルがありません。通知を送信するチャンネルを追加してください。", + "noChannelsHint": "チャンネルがまだ設定されていません。チャンネルタブで追加してください。", + "addChannel": "チャンネルを追加", + "testChannel": "テスト", + "channelTestSent": "テスト通知が送信されました", + "channelTestFailed": "テスト通知が失敗しました", + "channelDeleted": "チャンネルが削除されました", + "deleteChannelConfirm": "このチャンネルを削除しますか?このチャンネルを使用している自動化機能は通知を停止します。", + "nameLabel": "名前", + "namePlaceholder": "例:/data がいっぱいになったらクリーンアップする", + "nameRequired": "名前は必須です", + "descriptionLabel": "説明", + "descriptionPlaceholder": "オプションの説明", + "enabledLabel": "有効", + "concurrencyLabel": "既に実行中の場合", + "concurrencyHint": "前回の実行が終了する前に、これが再び発生した場合の対処法。", + "concurrency": { + "skip": "新しいランをスキップ", + "queue": "待ってから追いかける", + "allow": "両方を同時に実行する" + }, + "save": "保存", + "created": "自動化が作成しました", + "updated": "自動化が保存されました", + "deleted": "自動化が削除されました", + "deleteConfirm": "この自動化を削除すると、実行履歴も削除されます。", + "runNow": "今すぐ実行", + "testRun": "試運転", + "testRunHint": "すべてのステップを実行しますが、Termix以外のものには一切触れません。", + "runStarted": "ランニング開始", + "runFinished": "実行完了: {{status}}", + "trigger": "トリガー", + "steps": "手順", + "addStep": "ステップを追加する", + "removeStep": "削除手順", + "moveUp": "上へ進む", + "moveDown": "下へ移動", + "noSteps": "まだ手順がありません。何が起こるべきかを記述する手順を追加してください。", + "webhookTokenTitle": "Webhook URL", + "webhookTokenDescription": "これは一度しか表示されません。今すぐ保存してください。後で取り出すことはできません。", + "copy": "コピー", + "copied": "コピーしました", + "viewJson": "JSON", + "viewBuilder": "ビルダー", + "viewGraph": "グラフ", + "lastRun": "最後の走行", + "never": "一度もない", + "duration": "{{seconds}}s", + "stepOutput": "出力", + "stepError": "エラー", + "dryRunBadge": "試運転", + "hostSelector": { + "trigger": "トリガーホスト", + "host": "特定の宿主", + "fleet": "艦隊", + "all": "すべてのホスト" + }, + "triggerKinds": { + "metric_threshold": "メトリックしきい値", + "host_status": "ホストが起動または停止する", + "health_check": "健康チェックの変更点", + "schedule": "スケジュール通りに", + "docker_event": "コンテナイベント", + "internal_event": "ターミックスイベント", + "webhook": "受信ウェブフック" + }, + "stepTypes": { + "notify": "通知を送信する", + "http": "URLを呼び出す", + "run_snippet": "スニペットを実行する", + "run_command": "コマンドを実行する", + "docker": "コンテナを制御する", + "tunnel": "トンネルを制御する", + "wol": "ホストを起こす", + "wait": "待って", + "set_var": "変数を設定する", + "if": "もし/そうでなければ", + "run_automation": "別の自動化を実行する", + "stop": "停止" + }, + "statuses": { + "running": "ランニング", + "success": "成功", + "failed": "失敗した", + "timeout": "タイムアウト", + "skipped": "スキップしました", + "cancelled": "キャンセル" + }, + "fields": { + "host": "ホスト", + "metric": "メトリック", + "mount": "取り付けポイント", + "operator": "は", + "value": "価値", + "forSeconds": "(秒)の間持続", + "cooldown": "クールダウン時間(分)", + "cron": "Cron発現", + "intervalSeconds": "(秒)ごとに", + "timezone": "タイムゾーン", + "timezoneServer": "サーバー時間", + "timezoneHint": "このゾーンでは、cronの実行時間が読み取られます。インターバルスケジュールには適用されません。", + "container": "容器", + "command": "指示", + "url": "URL", + "method": "方法", + "body": "体", + "channels": "チャンネル", + "title": "タイトル", + "message": "メッセージ", + "snippet": "抜粋", + "seconds": "秒", + "conditionLeftPlaceholder": "チェックすべき値", + "conditionRightPlaceholder": "比較対象", + "variableName": "変数名", + "variableValue": "価値", + "elevated": "sudo を付けて実行", + "onError": "これが失敗した場合", + "allowPrivateNetwork": "ローカルネットワークアドレスを許可する", + "allowPrivateNetworkHint": "LAN上でセルフホスト型サービスを実行する場合に必要です。内部アドレスへのリクエストを防ぐため、デフォルトでは無効になっています。" + }, + "onError": { + "stop": "走るのをやめろ", + "continue": "続ける" + } + } + } + }, + "nav": { + "automations": "自動化" + }, + "onboarding": { + "feature_automations": "自動化", + "feature_automations_desc": "何かが発生した際に自動的に手順を実行し、通知を受け取ります。" + } +} diff --git a/plugins/automations/locales/translated/ko_KR.json b/plugins/automations/locales/translated/ko_KR.json new file mode 100644 index 000000000..69f2013b1 --- /dev/null +++ b/plugins/automations/locales/translated/ko_KR.json @@ -0,0 +1,149 @@ +{ + "newUi": { + "sidebar": { + "automations": { + "title": "자동화", + "tabAutomations": "자동화", + "tabRuns": "실행", + "tabChannels": "채널", + "createAutomation": "새로운 자동화", + "backToAutomations": "자동화 목록으로 돌아가기", + "createTitle": "새로운 자동화", + "editTitle": "편집 자동화", + "empty": "아직 자동화가 설정되어 있지 않습니다. 지표, 일정 또는 이벤트에 반응하는 자동화를 생성하세요.", + "emptyRuns": "아직 실행된 적이 없습니다.", + "emptyChannels": "아직 채널이 없습니다. 알림을 보낼 채널을 추가하세요.", + "noChannelsHint": "아직 채널이 설정되지 않았습니다. 채널 탭에서 채널을 추가하세요.", + "addChannel": "채널 추가", + "testChannel": "시험", + "channelTestSent": "테스트 알림이 전송되었습니다.", + "channelTestFailed": "테스트 알림 실패", + "channelDeleted": "채널이 삭제되었습니다", + "deleteChannelConfirm": "이 채널을 삭제하시겠습니까? 그러면 해당 채널을 사용하는 자동화 기능이 더 이상 알림을 보내지 않게 됩니다.", + "nameLabel": "이름", + "namePlaceholder": "예: /data 폴더가 가득 차면 정리합니다.", + "nameRequired": "이름은 필수 입력 사항입니다.", + "descriptionLabel": "설명", + "descriptionPlaceholder": "선택적 설명", + "enabledLabel": "활성화됨", + "concurrencyLabel": "이미 실행 중인 경우", + "concurrencyHint": "마지막 실행이 완료되기 전에 이 문제가 다시 발생할 경우 어떻게 해야 할까요?", + "concurrency": { + "skip": "새로운 실행을 건너뛰세요", + "queue": "기다렸다가 실행하세요", + "allow": "두 가지를 동시에 실행하세요" + }, + "save": "구하다", + "created": "자동화 생성됨", + "updated": "자동화 저장됨", + "deleted": "자동화 삭제됨", + "deleteConfirm": "이 자동화를 삭제하시겠습니까? 실행 기록도 함께 삭제됩니다.", + "runNow": "지금 실행하세요", + "testRun": "테스트 실행", + "testRunHint": "모든 단계를 실행하지만 Termix 외부의 어떤 것도 건드리지 않습니다.", + "runStarted": "실행 시작됨", + "runFinished": "실행 완료: {{status}}", + "trigger": "방아쇠", + "steps": "단계", + "addStep": "단계 추가", + "removeStep": "제거 단계", + "moveUp": "위로 이동", + "moveDown": "아래로 이동", + "noSteps": "아직 단계가 없습니다. 어떤 일이 일어나야 하는지 설명하는 단계를 추가하세요.", + "webhookTokenTitle": "웹훅 URL", + "webhookTokenDescription": "이 내용은 한 번만 표시됩니다. 지금 저장하세요. 나중에 불러올 수 없습니다.", + "copy": "복사", + "copied": "복사됨", + "viewJson": "JSON", + "viewBuilder": "건축업자", + "viewGraph": "그래프", + "lastRun": "마지막 실행", + "never": "절대", + "duration": "{{seconds}}s", + "stepOutput": "산출", + "stepError": "오류", + "dryRunBadge": "테스트 실행", + "hostSelector": { + "trigger": "트리거링 호스트", + "host": "특정 호스트", + "fleet": "함대", + "all": "모든 호스트" + }, + "triggerKinds": { + "metric_threshold": "측정 임계값", + "host_status": "호스트가 올라가거나 내려갑니다.", + "health_check": "건강 검진 변경 사항", + "schedule": "정해진 일정에 따라", + "docker_event": "컨테이너 이벤트", + "internal_event": "터믹스 이벤트", + "webhook": "수신 웹훅" + }, + "stepTypes": { + "notify": "알림 보내기", + "http": "URL을 호출합니다", + "run_snippet": "코드 조각을 실행하세요", + "run_command": "명령어를 실행하세요", + "docker": "컨테이너를 제어하세요", + "tunnel": "터널을 제어하세요", + "wol": "호스트를 깨우세요", + "wait": "기다리다", + "set_var": "변수를 설정하세요", + "if": "만약 / 그렇지 않다면", + "run_automation": "다른 자동화를 실행합니다", + "stop": "멈추다" + }, + "statuses": { + "running": "달리기", + "success": "성공", + "failed": "실패한", + "timeout": "시간 초과됨", + "skipped": "건너뛰었습니다", + "cancelled": "취소" + }, + "fields": { + "host": "주인", + "metric": "미터법", + "mount": "마운트 포인트", + "operator": "~이다", + "value": "값", + "forSeconds": "(초) 동안 지속됨", + "cooldown": "재사용 대기 시간(분)", + "cron": "크론 발현", + "intervalSeconds": "매 (초)", + "timezone": "시간대", + "timezoneServer": "서버 시간", + "timezoneHint": "크론 시간은 이 영역에서 읽습니다. 간격 스케줄에는 적용되지 않습니다.", + "container": "컨테이너", + "command": "명령", + "url": "URL", + "method": "방법", + "body": "몸", + "channels": "채널", + "title": "제목", + "message": "메시지", + "snippet": "단편", + "seconds": "초", + "conditionLeftPlaceholder": "확인할 값", + "conditionRightPlaceholder": "~와 비교하세요", + "variableName": "변수 이름", + "variableValue": "값", + "elevated": "sudo를 사용하여 실행하세요", + "onError": "이것이 실패하면", + "allowPrivateNetwork": "로컬 네트워크 주소를 허용합니다", + "allowPrivateNetworkHint": "LAN에서 자체 호스팅 서비스를 운영하는 데 필요합니다. 내부 주소로의 요청을 방지하기 위해 기본적으로 비활성화되어 있습니다." + }, + "onError": { + "stop": "달리기를 멈춰라", + "continue": "계속하세요" + } + } + } + }, + "nav": { + "automations": "자동화" + }, + "onboarding": { + "feature_automations": "자동화", + "feature_automations_desc": "어떤 상황이 발생하면 자동으로 단계를 실행하고 알림을 받으세요." + } +} diff --git a/plugins/automations/locales/translated/nl_NL.json b/plugins/automations/locales/translated/nl_NL.json new file mode 100644 index 000000000..4ff9589cc --- /dev/null +++ b/plugins/automations/locales/translated/nl_NL.json @@ -0,0 +1,149 @@ +{ + "newUi": { + "sidebar": { + "automations": { + "title": "Automatiseringen", + "tabAutomations": "Automatiseringen", + "tabRuns": "Loopt", + "tabChannels": "Kanalen", + "createAutomation": "Nieuwe automatisering", + "backToAutomations": "Terug naar automatiseringen", + "createTitle": "Nieuwe automatisering", + "editTitle": "Automatisering bewerken", + "empty": "Nog geen automatiseringen. Maak er een aan die reageert op een meetwaarde, een planning of een gebeurtenis.", + "emptyRuns": "Nog geen runs.", + "emptyChannels": "Nog geen kanalen. Voeg er een toe om meldingen ergens naartoe te sturen.", + "noChannelsHint": "Er zijn nog geen kanalen ingesteld. Voeg er een toe via het tabblad Kanalen.", + "addChannel": "Kanaal toevoegen", + "testChannel": "Test", + "channelTestSent": "Testmelding verzonden", + "channelTestFailed": "Testmelding mislukt", + "channelDeleted": "Kanaal verwijderd", + "deleteChannelConfirm": "Als u dit kanaal wilt verwijderen, zullen automatiseringsprocessen die ervan gebruikmaken geen meldingen meer versturen.", + "nameLabel": "Naam", + "namePlaceholder": "Bijvoorbeeld: maak /data leeg wanneer het vol is.", + "nameRequired": "Naam is verplicht", + "descriptionLabel": "Beschrijving", + "descriptionPlaceholder": "Optionele beschrijving", + "enabledLabel": "Ingeschakeld", + "concurrencyLabel": "Als het al draait", + "concurrencyHint": "Wat te doen als dit opnieuw wordt geactiveerd voordat de laatste run is voltooid?", + "concurrency": { + "skip": "Sla de nieuwe run over", + "queue": "Wacht en ren erachteraan.", + "allow": "Voer ze allebei tegelijk uit." + }, + "save": "Redden", + "created": "Automatisering gecreëerd", + "updated": "Automatisering opgeslagen", + "deleted": "Automatisering verwijderd", + "deleteConfirm": "Als je deze automatisering verwijdert, wordt ook de uitvoeringsgeschiedenis ervan verwijderd.", + "runNow": "Ren nu", + "testRun": "Testrun", + "testRunHint": "Voert elke stap uit, maar raakt niets buiten Termix aan.", + "runStarted": "De run is gestart.", + "runFinished": "Run voltooid: {{status}}", + "trigger": "Trekker", + "steps": "Stappen", + "addStep": "Voeg stap toe", + "removeStep": "Verwijder stap", + "moveUp": "Omhoog gaan", + "moveDown": "Ga naar beneden", + "noSteps": "Nog geen stappen. Voeg er een toe om aan te geven wat er moet gebeuren.", + "webhookTokenTitle": "Webhook-URL", + "webhookTokenDescription": "Dit wordt eenmalig weergegeven. Sla het nu op, het kan later niet meer worden opgevraagd.", + "copy": "Kopiëren", + "copied": "Gekopieerd", + "viewJson": "JSON", + "viewBuilder": "Bouwer", + "viewGraph": "Grafiek", + "lastRun": "Laatste run", + "never": "Nooit", + "duration": "{{seconds}}s", + "stepOutput": "Uitvoer", + "stepError": "Fout", + "dryRunBadge": "Testrun", + "hostSelector": { + "trigger": "Activerende host", + "host": "Specifieke gastheer", + "fleet": "Vloot", + "all": "Alle hosts" + }, + "triggerKinds": { + "metric_threshold": "Metrische drempelwaarde", + "host_status": "De host gaat omhoog of omlaag.", + "health_check": "Wijzigingen in de gezondheidscontrole", + "schedule": "Volgens een schema", + "docker_event": "Container-gebeurtenis", + "internal_event": "Termix-evenement", + "webhook": "Inkomende webhook" + }, + "stepTypes": { + "notify": "Een melding verzenden", + "http": "Roep een URL aan", + "run_snippet": "Voer een codefragment uit", + "run_command": "Voer een commando uit", + "docker": "Een container besturen", + "tunnel": "Beheer een tunnel", + "wol": "Maak een gastheer wakker", + "wait": "Wachten", + "set_var": "Een variabele instellen", + "if": "Indien / anders", + "run_automation": "Voer nog een automatisering uit", + "stop": "Stop" + }, + "statuses": { + "running": "Rennen", + "success": "Succes", + "failed": "Mislukt", + "timeout": "De tijd is verlopen.", + "skipped": "Overgeslagen", + "cancelled": "Geannuleerd" + }, + "fields": { + "host": "Gastheer", + "metric": "Metrisch", + "mount": "Bergpunt", + "operator": "Is", + "value": "Waarde", + "forSeconds": "Aangehouden gedurende (seconden)", + "cooldown": "Afkoeltijd (minuten)", + "cron": "Cron-expressie", + "intervalSeconds": "Elke (seconden)", + "timezone": "Tijdzone", + "timezoneServer": "Servertijd", + "timezoneHint": "In deze zone worden de cron-tijden gelezen. Dit geldt niet voor intervalschema's.", + "container": "Container", + "command": "Commando", + "url": "URL", + "method": "Methode", + "body": "Lichaam", + "channels": "Kanalen", + "title": "Titel", + "message": "Bericht", + "snippet": "Fragment", + "seconds": "Seconden", + "conditionLeftPlaceholder": "Waarde om te controleren", + "conditionRightPlaceholder": "Vergelijk met", + "variableName": "Variabelenaam", + "variableValue": "Waarde", + "elevated": "Uitvoeren met sudo", + "onError": "Als dit mislukt", + "allowPrivateNetwork": "Sta lokale netwerkadressen toe.", + "allowPrivateNetworkHint": "Nodig voor een zelfgehoste service op uw LAN. Standaard uitgeschakeld om verzoeken naar interne adressen te voorkomen." + }, + "onError": { + "stop": "Stop de loop", + "continue": "Ga zo door" + } + } + } + }, + "nav": { + "automations": "Automatiseringen" + }, + "onboarding": { + "feature_automations": "Automatiseringen", + "feature_automations_desc": "Voer stappen automatisch uit wanneer er iets gebeurt en ontvang meldingen." + } +} diff --git a/plugins/automations/locales/translated/no_NO.json b/plugins/automations/locales/translated/no_NO.json new file mode 100644 index 000000000..226688470 --- /dev/null +++ b/plugins/automations/locales/translated/no_NO.json @@ -0,0 +1,149 @@ +{ + "newUi": { + "sidebar": { + "automations": { + "title": "Automatiseringer", + "tabAutomations": "Automatiseringer", + "tabRuns": "Løper", + "tabChannels": "Kanaler", + "createAutomation": "Ny automatisering", + "backToAutomations": "Tilbake til automatiseringer", + "createTitle": "Ny automatisering", + "editTitle": "Rediger automatisering", + "empty": "Ingen automatiseringer ennå. Opprett en for å reagere på en beregning, en tidsplan eller en hendelse.", + "emptyRuns": "Ingen løp ennå.", + "emptyChannels": "Ingen kanaler ennå. Legg til en for å sende varsler et sted.", + "noChannelsHint": "Ingen kanaler er konfigurert ennå. Legg til en i Kanaler-fanen.", + "addChannel": "Legg til kanal", + "testChannel": "Test", + "channelTestSent": "Testvarsel sendt", + "channelTestFailed": "Testvarsel mislyktes", + "channelDeleted": "Kanalen slettet", + "deleteChannelConfirm": "Vil du slette denne kanalen? Automatiseringer som bruker den, vil slutte å varsle.", + "nameLabel": "Navn", + "namePlaceholder": "f.eks. Rydd opp i /data når den fylles", + "nameRequired": "Navn er obligatorisk", + "descriptionLabel": "Beskrivelse", + "descriptionPlaceholder": "Valgfri beskrivelse", + "enabledLabel": "Aktivert", + "concurrencyLabel": "Hvis den allerede kjører", + "concurrencyHint": "Hva skal man gjøre når dette utløses igjen før siste kjøring er ferdig?", + "concurrency": { + "skip": "Hopp over den nye kjøringen", + "queue": "Vent og løp etter", + "allow": "Kjør begge samtidig" + }, + "save": "Spare", + "created": "Automatisering opprettet", + "updated": "Automatisering lagret", + "deleted": "Automatisering slettet", + "deleteConfirm": "Vil du slette denne automatiseringen? Kjørehistorikken slettes også.", + "runNow": "Løp nå", + "testRun": "Testkjøring", + "testRunHint": "Kjører hvert trinn, men berører ikke noe utenfor Termix.", + "runStarted": "Løpet startet", + "runFinished": "Kjøring fullført: {{status}}", + "trigger": "Avtrekker", + "steps": "Trinn", + "addStep": "Legg til trinn", + "removeStep": "Fjern trinn", + "moveUp": "Flytt opp", + "moveDown": "Flytt ned", + "noSteps": "Ingen trinn ennå. Legg til ett for å si hva som skal skje.", + "webhookTokenTitle": "Webhook-URL", + "webhookTokenDescription": "Dette vises én gang. Lagre det nå, det kan ikke hentes frem senere.", + "copy": "Kopiere", + "copied": "Kopiert", + "viewJson": "JSON", + "viewBuilder": "Bygger", + "viewGraph": "Kurve", + "lastRun": "Siste løp", + "never": "Aldri", + "duration": "{{seconds}}s", + "stepOutput": "Produksjon", + "stepError": "Feil", + "dryRunBadge": "Testkjøring", + "hostSelector": { + "trigger": "Utløsende vert", + "host": "Spesifikk vert", + "fleet": "Flåte", + "all": "Alle verter" + }, + "triggerKinds": { + "metric_threshold": "Metrisk terskel", + "host_status": "Verten går opp eller ned", + "health_check": "Endringer i helsesjekken", + "schedule": "På en tidsplan", + "docker_event": "Containerhendelse", + "internal_event": "Termix-arrangementet", + "webhook": "Innkommende webhook" + }, + "stepTypes": { + "notify": "Send et varsel", + "http": "Kall en URL", + "run_snippet": "Kjør et utdrag", + "run_command": "Kjør en kommando", + "docker": "Kontroller en container", + "tunnel": "Kontroller en tunnel", + "wol": "Vekk en vert", + "wait": "Vente", + "set_var": "Angi en variabel", + "if": "Hvis / ellers", + "run_automation": "Kjør en annen automatisering", + "stop": "Stoppe" + }, + "statuses": { + "running": "Løping", + "success": "Suksess", + "failed": "Mislyktes", + "timeout": "Tidsavbrutt", + "skipped": "Hoppet over", + "cancelled": "Avlyst" + }, + "fields": { + "host": "Vert", + "metric": "Metrisk", + "mount": "Monteringspunkt", + "operator": "Er", + "value": "Verdi", + "forSeconds": "Vedvarende i (sekunder)", + "cooldown": "Nedkjølingstid (minutter)", + "cron": "Cron-uttrykk", + "intervalSeconds": "Hvert (sekund)", + "timezone": "Tidssone", + "timezoneServer": "Servertid", + "timezoneHint": "Cron-tider leses i denne sonen. Gjelder ikke for intervallplaner.", + "container": "Container", + "command": "Kommando", + "url": "URL-adresse", + "method": "Metode", + "body": "Kropp", + "channels": "Kanaler", + "title": "Tittel", + "message": "Beskjed", + "snippet": "Utdrag", + "seconds": "Sekunder", + "conditionLeftPlaceholder": "Verdi å sjekke", + "conditionRightPlaceholder": "Sammenlign mot", + "variableName": "Variabelnavn", + "variableValue": "Verdi", + "elevated": "Kjør med sudo", + "onError": "Hvis dette mislykkes", + "allowPrivateNetwork": "Tillat lokale nettverksadresser", + "allowPrivateNetworkHint": "Nødvendig for en selvhostet tjeneste på LAN-et ditt. Av som standard for å forhindre forespørsler til interne adresser." + }, + "onError": { + "stop": "Stopp løpet", + "continue": "Fortsett" + } + } + } + }, + "nav": { + "automations": "Automatiseringer" + }, + "onboarding": { + "feature_automations": "Automatiseringer", + "feature_automations_desc": "Kjør trinnene automatisk når noe skjer, og bli varslet." + } +} diff --git a/plugins/automations/locales/translated/pl_PL.json b/plugins/automations/locales/translated/pl_PL.json new file mode 100644 index 000000000..06bcac36c --- /dev/null +++ b/plugins/automations/locales/translated/pl_PL.json @@ -0,0 +1,149 @@ +{ + "newUi": { + "sidebar": { + "automations": { + "title": "Automatyzacje", + "tabAutomations": "Automatyzacje", + "tabRuns": "Uruchomienia", + "tabChannels": "Kanały", + "createAutomation": "Nowa automatyzacja", + "backToAutomations": "Powrót do automatyzacji", + "createTitle": "Nowa automatyzacja", + "editTitle": "Edytuj automatyzację", + "empty": "Brak jeszcze automatyzacji. Utwórz automatyzację, która będzie reagować na metrykę, harmonogram lub zdarzenie.", + "emptyRuns": "Brak uruchomień.", + "emptyChannels": "Brak kanałów. Dodaj jeden, aby wysyłać powiadomienia.", + "noChannelsHint": "Nie skonfigurowano jeszcze żadnych kanałów. Dodaj jeden w zakładce Kanały.", + "addChannel": "Dodaj kanał", + "testChannel": "Test", + "channelTestSent": "Wysłano powiadomienie testowe", + "channelTestFailed": "Powiadomienie testowe nie powiodło się", + "channelDeleted": "Kanał usunięty", + "deleteChannelConfirm": "Usunąć ten kanał? Automatyzacje z niego korzystające przestaną wysyłać powiadomienia.", + "nameLabel": "Nazwa", + "namePlaceholder": "np. Wyczyść /data, gdy się zapełni", + "nameRequired": "Nazwa jest wymagana", + "descriptionLabel": "Opis", + "descriptionPlaceholder": "Opis opcjonalny", + "enabledLabel": "Włączona", + "concurrencyLabel": "Jeśli już działa", + "concurrencyHint": "Co zrobić, gdy zostanie wyzwolona ponownie przed zakończeniem poprzedniego uruchomienia.", + "concurrency": { + "skip": "Pomiń nowe uruchomienie", + "queue": "Poczekaj i uruchom po zakończeniu", + "allow": "Uruchom oba naraz" + }, + "save": "Zapisz", + "created": "Utworzono automatyzację", + "updated": "Zapisano automatyzację", + "deleted": "Usunięto automatyzację", + "deleteConfirm": "Usunąć tę automatyzację? Jej historia uruchomień również zostanie usunięta.", + "runNow": "Uruchom teraz", + "testRun": "Uruchomienie próbne", + "testRunHint": "Wykonuje każdy krok, ale nie zmienia niczego poza Termixem.", + "runStarted": "Uruchomiono", + "runFinished": "Zakończono: {{status}}", + "trigger": "Wyzwalacz", + "steps": "Kroki", + "addStep": "Dodaj krok", + "removeStep": "Usuń krok", + "moveUp": "W górę", + "moveDown": "W dół", + "noSteps": "Brak kroków. Dodaj jeden, aby określić, co powinno się stać.", + "webhookTokenTitle": "Adres URL webhooka", + "webhookTokenDescription": "Pokazywany tylko raz. Zapisz go teraz, później nie da się go odzyskać.", + "copy": "Kopiuj", + "copied": "Skopiowano", + "viewJson": "JSON", + "viewBuilder": "Kreator", + "viewGraph": "Graf", + "lastRun": "Ostatnie uruchomienie", + "never": "Nigdy", + "duration": "{{seconds}}s", + "stepOutput": "Wyjście", + "stepError": "Błąd", + "dryRunBadge": "Uruchomienie próbne", + "hostSelector": { + "trigger": "Host wyzwalający", + "host": "Konkretny host", + "fleet": "Flota", + "all": "Wszystkie hosty" + }, + "triggerKinds": { + "metric_threshold": "Próg metryki", + "host_status": "Host wstaje lub pada", + "health_check": "Zmiana kontroli stanu", + "schedule": "Zgodnie z harmonogramem", + "docker_event": "Zdarzenie kontenera", + "internal_event": "Zdarzenie Termixa", + "webhook": "Przychodzący webhook" + }, + "stepTypes": { + "notify": "Wyślij powiadomienie", + "http": "Wywołaj adres URL", + "run_snippet": "Uruchom snippet", + "run_command": "Uruchom polecenie", + "docker": "Kontroluj kontener", + "tunnel": "Kontroluj tunel", + "wol": "Obudź host", + "wait": "Czekaj", + "set_var": "Ustaw zmienną", + "if": "Jeśli / w przeciwnym razie", + "run_automation": "Uruchom inną automatyzację", + "stop": "Zatrzymaj" + }, + "statuses": { + "running": "Działa", + "success": "Powodzenie", + "failed": "Niepowodzenie", + "timeout": "Przekroczono limit czasu", + "skipped": "Pominięto", + "cancelled": "Anulowano" + }, + "fields": { + "host": "Host", + "metric": "Metryka", + "mount": "Punkt montowania", + "operator": "Jest", + "value": "Wartość", + "forSeconds": "Utrzymywany przez (sekundy)", + "cooldown": "Czas wyciszenia (minuty)", + "cron": "Wyrażenie cron", + "intervalSeconds": "Co (sekundy)", + "timezone": "Strefa czasowa", + "timezoneServer": "Czas serwera", + "timezoneHint": "Czasy cron są odczytywane w tej strefie. Nie dotyczy harmonogramów interwałowych.", + "container": "Kontener", + "command": "Polecenie", + "url": "Adres URL", + "method": "Metoda", + "body": "Treść", + "channels": "Kanały", + "title": "Tytuł", + "message": "Wiadomość", + "snippet": "Snippet", + "seconds": "Sekundy", + "conditionLeftPlaceholder": "Wartość do sprawdzenia", + "conditionRightPlaceholder": "Porównaj z", + "variableName": "Nazwa zmiennej", + "variableValue": "Wartość", + "elevated": "Uruchom z sudo", + "onError": "Jeśli to się nie powiedzie", + "allowPrivateNetwork": "Zezwalaj na lokalne adresy sieciowe", + "allowPrivateNetworkHint": "Wymagane dla własnej usługi w sieci LAN. Domyślnie wyłączone, aby zapobiec żądaniom do adresów wewnętrznych." + }, + "onError": { + "stop": "Zatrzymaj uruchomienie", + "continue": "Kontynuuj" + } + } + } + }, + "nav": { + "automations": "Automatyzacje" + }, + "onboarding": { + "feature_automations": "Automatyzacje", + "feature_automations_desc": "Uruchamiaj kroki automatycznie, gdy coś się wydarzy, i otrzymuj powiadomienia." + } +} diff --git a/plugins/automations/locales/translated/pt_BR.json b/plugins/automations/locales/translated/pt_BR.json new file mode 100644 index 000000000..b198fcf0d --- /dev/null +++ b/plugins/automations/locales/translated/pt_BR.json @@ -0,0 +1,149 @@ +{ + "newUi": { + "sidebar": { + "automations": { + "title": "Automações", + "tabAutomations": "Automações", + "tabRuns": "Corridas", + "tabChannels": "Canais", + "createAutomation": "Nova Automação", + "backToAutomations": "Voltar para Automações", + "createTitle": "Nova Automação", + "editTitle": "Editar Automação", + "empty": "Ainda não há automações. Crie uma para reagir a uma métrica, a um agendamento ou a um evento.", + "emptyRuns": "Ainda não houve nenhuma corrida.", + "emptyChannels": "Ainda não há canais. Adicione um para enviar notificações para algum lugar.", + "noChannelsHint": "Nenhum canal configurado ainda. Adicione um na aba Canais.", + "addChannel": "Adicionar canal", + "testChannel": "Teste", + "channelTestSent": "Notificação de teste enviada", + "channelTestFailed": "Falha na notificação de teste", + "channelDeleted": "Canal excluído", + "deleteChannelConfirm": "Excluir este canal? As automações que o utilizam deixarão de enviar notificações.", + "nameLabel": "Nome", + "namePlaceholder": "Por exemplo, limpe a pasta /data quando ela estiver cheia.", + "nameRequired": "O nome é obrigatório.", + "descriptionLabel": "Descrição", + "descriptionPlaceholder": "Descrição opcional", + "enabledLabel": "Habilitado", + "concurrencyLabel": "Se já estiver em execução", + "concurrencyHint": "O que fazer quando isso for acionado novamente antes da última execução terminar?", + "concurrency": { + "skip": "Pule a nova corrida", + "queue": "Espere e corra atrás.", + "allow": "Execute ambos simultaneamente" + }, + "save": "Salvar", + "created": "Automação criada", + "updated": "Automação economizou", + "deleted": "Automação excluída", + "deleteConfirm": "Excluir esta automação? O histórico de execução dela também será excluído.", + "runNow": "Corra agora", + "testRun": "Teste de execução", + "testRunHint": "Executa cada etapa, mas não toca em nada fora do Termix.", + "runStarted": "A corrida começou.", + "runFinished": "Execução concluída: {{status}}", + "trigger": "Acionar", + "steps": "Passos", + "addStep": "Adicionar etapa", + "removeStep": "Remover etapa", + "moveUp": "Suba", + "moveDown": "Desça", + "noSteps": "Ainda não há etapas. Adicione uma para descrever o que deve acontecer.", + "webhookTokenTitle": "URL do Webhook", + "webhookTokenDescription": "Esta mensagem será exibida apenas uma vez. Salve-a agora, pois não poderá ser recuperada posteriormente.", + "copy": "Cópia", + "copied": "Copiado", + "viewJson": "JSON", + "viewBuilder": "Construtor", + "viewGraph": "Gráfico", + "lastRun": "Última corrida", + "never": "Nunca", + "duration": "{{seconds}}s", + "stepOutput": "Saída", + "stepError": "Erro", + "dryRunBadge": "Teste de execução", + "hostSelector": { + "trigger": "Host que desencadeia o ataque", + "host": "hospedeiro específico", + "fleet": "Frota", + "all": "Todos os anfitriões" + }, + "triggerKinds": { + "metric_threshold": "Limiar métrico", + "host_status": "O host sobe ou desce.", + "health_check": "Alterações na verificação de saúde", + "schedule": "De acordo com um cronograma", + "docker_event": "Evento de contêiner", + "internal_event": "Evento Termix", + "webhook": "Webhook de entrada" + }, + "stepTypes": { + "notify": "Enviar notificação", + "http": "Chamar um URL", + "run_snippet": "Executar um trecho de código", + "run_command": "Executar um comando", + "docker": "Controle um contêiner", + "tunnel": "Controle um túnel", + "wol": "Acorde um anfitrião", + "wait": "Espere", + "set_var": "Defina uma variável", + "if": "Se/caso contrário", + "run_automation": "Execute outra automação", + "stop": "Parar" + }, + "statuses": { + "running": "Correndo", + "success": "Sucesso", + "failed": "Fracassado", + "timeout": "Tempo limite excedido", + "skipped": "Ignorado", + "cancelled": "Cancelado" + }, + "fields": { + "host": "Hospedar", + "metric": "Métrica", + "mount": "Ponto de montagem", + "operator": "É", + "value": "Valor", + "forSeconds": "Sustentado por (segundos)", + "cooldown": "Tempo de resfriamento (minutos)", + "cron": "Expressão de Cron", + "intervalSeconds": "A cada (segundos)", + "timezone": "Fuso horário", + "timezoneServer": "Hora do servidor", + "timezoneHint": "Os horários cron são lidos nesta zona. Não se aplica a agendamentos por intervalo.", + "container": "Recipiente", + "command": "Comando", + "url": "URL", + "method": "Método", + "body": "Corpo", + "channels": "Canais", + "title": "Título", + "message": "Mensagem", + "snippet": "Trecho", + "seconds": "Segundos", + "conditionLeftPlaceholder": "Valor a verificar", + "conditionRightPlaceholder": "Compare com", + "variableName": "Nome da variável", + "variableValue": "Valor", + "elevated": "Executar com sudo", + "onError": "Se isso falhar", + "allowPrivateNetwork": "Permitir endereços de rede local", + "allowPrivateNetworkHint": "Necessário para um serviço autohospedado em sua rede local (LAN). Desativado por padrão para evitar solicitações a endereços internos." + }, + "onError": { + "stop": "Pare a corrida", + "continue": "Continuar" + } + } + } + }, + "nav": { + "automations": "Automações" + }, + "onboarding": { + "feature_automations": "Automações", + "feature_automations_desc": "Execute etapas automaticamente quando algo acontecer e receba notificações." + } +} diff --git a/plugins/automations/locales/translated/pt_PT.json b/plugins/automations/locales/translated/pt_PT.json new file mode 100644 index 000000000..7c6244394 --- /dev/null +++ b/plugins/automations/locales/translated/pt_PT.json @@ -0,0 +1,149 @@ +{ + "newUi": { + "sidebar": { + "automations": { + "title": "Automações", + "tabAutomations": "Automações", + "tabRuns": "Corridas", + "tabChannels": "Canais", + "createAutomation": "Nova Automação", + "backToAutomations": "Voltar para Automações", + "createTitle": "Nova Automação", + "editTitle": "Editar Automação", + "empty": "Ainda não há automatizações. Crie uma para reagir a uma métrica, a um agendamento ou a um evento.", + "emptyRuns": "Ainda não houve qualquer corrida.", + "emptyChannels": "Ainda não há canais. Adicione um para enviar notificações para algum lugar.", + "noChannelsHint": "Nenhum canal configurado ainda. Adicione um no separador Canais.", + "addChannel": "Adicionar canal", + "testChannel": "Teste", + "channelTestSent": "Notificação de teste enviada", + "channelTestFailed": "Falha na notificação de teste", + "channelDeleted": "Canal excluído", + "deleteChannelConfirm": "Apagar este canal? As automatizações que o utilizam deixarão de enviar notificações.", + "nameLabel": "Nome", + "namePlaceholder": "Por exemplo, limpe a pasta /data quando esta estiver cheia.", + "nameRequired": "O nome é obrigatório.", + "descriptionLabel": "Descrição", + "descriptionPlaceholder": "Descrição opcional", + "enabledLabel": "Habilitado", + "concurrencyLabel": "Se já estiver em execução", + "concurrencyHint": "O que fazer quando este for novamente acionado antes da última execução terminar?", + "concurrency": { + "skip": "Salte a nova corrida", + "queue": "Espere e corra atrás.", + "allow": "Execute ambos em simultâneo" + }, + "save": "Guardar", + "created": "Automação criada", + "updated": "A automação economizou", + "deleted": "Automação excluída", + "deleteConfirm": "Apagar esta automação? O histórico de execução da mesma também será eliminado.", + "runNow": "Corra agora", + "testRun": "Teste de execução", + "testRunHint": "Executa cada passo, mas não toca em nada fora do Termix.", + "runStarted": "A corrida começou.", + "runFinished": "Execução concluída: {{status}}", + "trigger": "Gatilho", + "steps": "Passos", + "addStep": "Adicionar etapa", + "removeStep": "Remover etapa", + "moveUp": "Suba", + "moveDown": "Desça", + "noSteps": "Ainda não há etapas. Adicione uma para descrever o que deve acontecer.", + "webhookTokenTitle": "URL do Webhook", + "webhookTokenDescription": "Esta mensagem será apresentada apenas uma vez. Guarde-a agora, pois não poderá ser recuperada posteriormente.", + "copy": "Cópia", + "copied": "Copiado", + "viewJson": "JSON", + "viewBuilder": "Construtor", + "viewGraph": "Gráfico", + "lastRun": "Última corrida", + "never": "Nunca", + "duration": "{{seconds}}s", + "stepOutput": "Saída", + "stepError": "Erro", + "dryRunBadge": "Teste de execução", + "hostSelector": { + "trigger": "Host que desencadeia o ataque", + "host": "hospedeiro específico", + "fleet": "Frota", + "all": "Todos os anfitriões" + }, + "triggerKinds": { + "metric_threshold": "Limiar métrico", + "host_status": "O host sobe ou desce.", + "health_check": "Alterações na verificação de saúde", + "schedule": "De acordo com um cronograma", + "docker_event": "Evento de contentor", + "internal_event": "Evento Termix", + "webhook": "Webhook de entrada" + }, + "stepTypes": { + "notify": "Enviar notificação", + "http": "Chamar um URL", + "run_snippet": "Executar um excerto de código", + "run_command": "Executar um comando", + "docker": "Controle um contentor", + "tunnel": "Controle um túnel", + "wol": "Acorde um anfitrião", + "wait": "Espera", + "set_var": "Defina uma variável", + "if": "Se/caso contrário", + "run_automation": "Execute outra automatização", + "stop": "Parar" + }, + "statuses": { + "running": "Corrida", + "success": "Sucesso", + "failed": "Falhou", + "timeout": "Tempo limite excedido", + "skipped": "Ignorado", + "cancelled": "Cancelado" + }, + "fields": { + "host": "Anfitrião", + "metric": "Métrica", + "mount": "Ponto de montagem", + "operator": "É", + "value": "Valor", + "forSeconds": "Sustentado por (segundos)", + "cooldown": "Tempo de arrefecimento (minutos)", + "cron": "Expressão de Cron", + "intervalSeconds": "A cada (segundos)", + "timezone": "Fuso horário", + "timezoneServer": "Hora do servidor", + "timezoneHint": "Os tempos cron são lidos nesta zona. Não se aplica a agendamentos por intervalo.", + "container": "Recipiente", + "command": "Comando", + "url": "URL", + "method": "Método", + "body": "Corpo", + "channels": "Canais", + "title": "Título", + "message": "Mensagem", + "snippet": "Trecho", + "seconds": "Segundos", + "conditionLeftPlaceholder": "Valor a verificar", + "conditionRightPlaceholder": "Compare com", + "variableName": "Nome da variável", + "variableValue": "Valor", + "elevated": "Executar com sudo", + "onError": "Se isso falhar", + "allowPrivateNetwork": "Permitir endereços de rede local", + "allowPrivateNetworkHint": "Necessário para um serviço auto-hospedado na sua rede local (LAN). Desativado por defeito para evitar pedidos a endereços internos." + }, + "onError": { + "stop": "Pare a corrida", + "continue": "Continuar" + } + } + } + }, + "nav": { + "automations": "Automações" + }, + "onboarding": { + "feature_automations": "Automações", + "feature_automations_desc": "Execute automaticamente os passos quando algo acontece e receba notificações." + } +} diff --git a/plugins/automations/locales/translated/ro_RO.json b/plugins/automations/locales/translated/ro_RO.json new file mode 100644 index 000000000..c829b9647 --- /dev/null +++ b/plugins/automations/locales/translated/ro_RO.json @@ -0,0 +1,149 @@ +{ + "newUi": { + "sidebar": { + "automations": { + "title": "Automatizări", + "tabAutomations": "Automatizări", + "tabRuns": "Aleargă", + "tabChannels": "Canale", + "createAutomation": "Automatizare nouă", + "backToAutomations": "Înapoi la Automatizări", + "createTitle": "Automatizare nouă", + "editTitle": "Editare automatizare", + "empty": "Încă nu există automatizări. Creați una pentru a reacționa la o metrică, un program sau un eveniment.", + "emptyRuns": "Nicio alergare încă.", + "emptyChannels": "Încă nu există canale. Adaugă unul pentru a trimite notificări undeva.", + "noChannelsHint": "Încă nu a fost configurat niciun canal. Adăugați unul în fila Canale.", + "addChannel": "Adăugați canal", + "testChannel": "Test", + "channelTestSent": "Notificare de testare trimisă", + "channelTestFailed": "Notificarea de testare a eșuat", + "channelDeleted": "Canalul a fost șters", + "deleteChannelConfirm": "Ștergeți acest canal? Automatizările care îl folosesc vor înceta să mai trimită notificări.", + "nameLabel": "Nume", + "namePlaceholder": "De exemplu, curățați /data când se umple", + "nameRequired": "Numele este obligatoriu", + "descriptionLabel": "Descriere", + "descriptionPlaceholder": "Descriere opțională", + "enabledLabel": "Activat", + "concurrencyLabel": "Dacă deja rulează", + "concurrencyHint": "Ce trebuie făcut când acest lucru este declanșat din nou înainte de finalizarea ultimei rulări.", + "concurrency": { + "skip": "Sari peste noua cursă", + "queue": "Așteaptă și aleargă după", + "allow": "Rulați ambele simultan" + }, + "save": "Salva", + "created": "Automatizare creată", + "updated": "Automatizare salvată", + "deleted": "Automatizare ștearsă", + "deleteConfirm": "Ștergeți această automatizare? Și istoricul execuțiilor sale este șters.", + "runNow": "Aleargă acum", + "testRun": "Test de funcționare", + "testRunHint": "Aleargă la fiecare pas, dar nu atinge nimic din afara Termixului.", + "runStarted": "Cursa a început", + "runFinished": "Execuția s-a încheiat: {{status}}", + "trigger": "Declanșator", + "steps": "Pași", + "addStep": "Adăugați un pas", + "removeStep": "Eliminați pasul", + "moveUp": "Mută în sus", + "moveDown": "Mută în jos", + "noSteps": "Încă nu există pași. Adăugați unul pentru a specifica ce ar trebui să se întâmple.", + "webhookTokenTitle": "URL-ul webhook-ului", + "webhookTokenDescription": "Aceasta se afișează o singură dată. Salvați-o acum, nu poate fi recuperată ulterior.", + "copy": "Copie", + "copied": "Copiat", + "viewJson": "JSON", + "viewBuilder": "Constructor", + "viewGraph": "Grafic", + "lastRun": "Ultima alergare", + "never": "Nu", + "duration": "{{seconds}}s", + "stepOutput": "Ieșire", + "stepError": "Eroare", + "dryRunBadge": "Test de funcționare", + "hostSelector": { + "trigger": "Gazdă declanșatoare", + "host": "Gazdă specifică", + "fleet": "Flotă", + "all": "Toate gazdele" + }, + "triggerKinds": { + "metric_threshold": "Pragul metric", + "host_status": "Gazda se activează sau se deconectează", + "health_check": "Modificări la verificarea stării de sănătate", + "schedule": "Pe un program", + "docker_event": "Eveniment container", + "internal_event": "Evenimentul Termix", + "webhook": "Webhook de intrare" + }, + "stepTypes": { + "notify": "Trimiteți o notificare", + "http": "Apelați o adresă URL", + "run_snippet": "Executați un fragment", + "run_command": "Executați o comandă", + "docker": "Controlează un container", + "tunnel": "Controlează un tunel", + "wol": "Trezește o gazdă", + "wait": "Așteaptă", + "set_var": "Setați o variabilă", + "if": "Dacă / altfel", + "run_automation": "Rulați o altă automatizare", + "stop": "Stop" + }, + "statuses": { + "running": "Funcţionare", + "success": "Succes", + "failed": "Eșuat", + "timeout": "Expirat", + "skipped": "Omis", + "cancelled": "Anulat" + }, + "fields": { + "host": "Gazdă", + "metric": "Metric", + "mount": "Punct de montare", + "operator": "Este", + "value": "Valoare", + "forSeconds": "Menținut timp de (secunde)", + "cooldown": "Timp de răcire (minute)", + "cron": "Expresie Cron", + "intervalSeconds": "La fiecare (secunde)", + "timezone": "Fus orar", + "timezoneServer": "Ora serverului", + "timezoneHint": "Timpii cron sunt citiți în această zonă. Nu se aplică programărilor cu intervale.", + "container": "Container", + "command": "Comanda", + "url": "URL-ul", + "method": "Metodă", + "body": "Corp", + "channels": "Canale", + "title": "Titlu", + "message": "Mesaj", + "snippet": "Fragment", + "seconds": "Secunde", + "conditionLeftPlaceholder": "Valoare de verificat", + "conditionRightPlaceholder": "Comparați cu", + "variableName": "Nume variabilă", + "variableValue": "Valoare", + "elevated": "Execută cu sudo", + "onError": "Dacă acest lucru eșuează", + "allowPrivateNetwork": "Permiteți adrese de rețea locală", + "allowPrivateNetworkHint": "Necesar pentru un serviciu auto-găzduit în rețeaua locală. Dezactivat în mod implicit pentru a preveni solicitările către adrese interne." + }, + "onError": { + "stop": "Oprește alergarea", + "continue": "Continuă" + } + } + } + }, + "nav": { + "automations": "Automatizări" + }, + "onboarding": { + "feature_automations": "Automatizări", + "feature_automations_desc": "Execută pașii automat când se întâmplă ceva și primește notificări." + } +} diff --git a/plugins/automations/locales/translated/ru_RU.json b/plugins/automations/locales/translated/ru_RU.json new file mode 100644 index 000000000..0e1f489cd --- /dev/null +++ b/plugins/automations/locales/translated/ru_RU.json @@ -0,0 +1,149 @@ +{ + "newUi": { + "sidebar": { + "automations": { + "title": "Автоматизация", + "tabAutomations": "Автоматизация", + "tabRuns": "Беги", + "tabChannels": "Каналы", + "createAutomation": "Новая автоматизация", + "backToAutomations": "Назад к автоматизации", + "createTitle": "Новая автоматизация", + "editTitle": "Редактировать автоматизацию", + "empty": "Автоматизации пока нет. Создайте автоматизацию, которая будет реагировать на показатель, расписание или событие.", + "emptyRuns": "Пока ни одного заезда.", + "emptyChannels": "Каналов пока нет. Добавьте канал, чтобы отправлять уведомления куда-нибудь.", + "noChannelsHint": "Каналы пока не созданы. Добавьте его на вкладке «Каналы».", + "addChannel": "Добавить канал", + "testChannel": "Тест", + "channelTestSent": "Уведомление о тестировании отправлено.", + "channelTestFailed": "Тестовое уведомление не удалось.", + "channelDeleted": "Канал удален", + "deleteChannelConfirm": "Удалить этот канал? Тогда автоматизация, использующая его, перестанет отправлять уведомления.", + "nameLabel": "Имя", + "namePlaceholder": "Например, очищать каталог /data, когда он заполняется.", + "nameRequired": "Имя обязательно для указания.", + "descriptionLabel": "Описание", + "descriptionPlaceholder": "Дополнительное описание", + "enabledLabel": "Включено", + "concurrencyLabel": "Если он уже запущен", + "concurrencyHint": "Что делать, если это снова произойдет до завершения последнего запуска?", + "concurrency": { + "skip": "Пропустите новый запуск", + "queue": "Подожди и беги после", + "allow": "Запустите оба одновременно." + }, + "save": "Сохранять", + "created": "Создана автоматизация", + "updated": "Автоматизация спасла", + "deleted": "Автоматизация удалена", + "deleteConfirm": "Удалить эту автоматизацию? История её выполнения также будет удалена.", + "runNow": "Запустите сейчас", + "testRun": "Тестовый запуск", + "testRunHint": "Программа выполняет каждый этап, но не затрагивает ничего за пределами Termix.", + "runStarted": "Запуск начался", + "runFinished": "Выполнение завершено: {{status}}", + "trigger": "Курок", + "steps": "Шаги", + "addStep": "Добавить шаг", + "removeStep": "Удалить шаг", + "moveUp": "Поднимитесь выше", + "moveDown": "Спуститесь вниз", + "noSteps": "Шагов пока нет. Добавьте один, чтобы указать, что должно произойти.", + "webhookTokenTitle": "URL веб-перехватчика", + "webhookTokenDescription": "Эта информация отображается только один раз. Сохраните её сейчас, позже восстановить её будет невозможно.", + "copy": "Копия", + "copied": "Скопировано", + "viewJson": "JSON", + "viewBuilder": "Строитель", + "viewGraph": "График", + "lastRun": "Последний забег", + "never": "Никогда", + "duration": "{{seconds}}с", + "stepOutput": "Выход", + "stepError": "Ошибка", + "dryRunBadge": "Тестовый запуск", + "hostSelector": { + "trigger": "Запуск хоста", + "host": "Конкретный хост", + "fleet": "Флот", + "all": "Все хосты" + }, + "triggerKinds": { + "metric_threshold": "Пороговое значение метрики", + "host_status": "Хост переходит в режим повышения или понижения.", + "health_check": "Изменения в результатах медицинского осмотра", + "schedule": "По расписанию", + "docker_event": "Событие контейнера", + "internal_event": "Мероприятие Termix", + "webhook": "Входящий веб-хук" + }, + "stepTypes": { + "notify": "Отправить уведомление", + "http": "Вызов URL-адреса", + "run_snippet": "Запустить фрагмент кода", + "run_command": "Выполните команду", + "docker": "Управлять контейнером", + "tunnel": "Контролировать туннель", + "wol": "Разбудить хозяина", + "wait": "Ждать", + "set_var": "Задайте переменную", + "if": "Если / в противном случае", + "run_automation": "Запустите еще одну автоматизацию", + "stop": "Останавливаться" + }, + "statuses": { + "running": "Бег", + "success": "Успех", + "failed": "Неуспешный", + "timeout": "Время истекло", + "skipped": "Пропущено", + "cancelled": "Отменено" + }, + "fields": { + "host": "Хозяин", + "metric": "Метрика", + "mount": "Маунт-Пойнт", + "operator": "Является", + "value": "Ценить", + "forSeconds": "Длительность (секунды)", + "cooldown": "Время восстановления (минуты)", + "cron": "Выражение Cron", + "intervalSeconds": "Каждые (секунды)", + "timezone": "Часовой пояс", + "timezoneServer": "Время сервера", + "timezoneHint": "В этой зоне считываются временные параметры Cron. Это не относится к интервальным расписаниям.", + "container": "Контейнер", + "command": "Командование", + "url": "URL", + "method": "Метод", + "body": "Тело", + "channels": "Каналы", + "title": "Заголовок", + "message": "Сообщение", + "snippet": "Фрагмент", + "seconds": "Секунды", + "conditionLeftPlaceholder": "Значение для проверки", + "conditionRightPlaceholder": "Сравните с", + "variableName": "Имя переменной", + "variableValue": "Ценить", + "elevated": "Запустить с правами суперпользователя (sudo)", + "onError": "Если это не поможет", + "allowPrivateNetwork": "Разрешить использование локальных сетевых адресов", + "allowPrivateNetworkHint": "Необходим для самостоятельного размещения сервиса в вашей локальной сети. По умолчанию отключен, чтобы предотвратить запросы к внутренним адресам." + }, + "onError": { + "stop": "Остановить бег", + "continue": "Продолжать" + } + } + } + }, + "nav": { + "automations": "Автоматизация" + }, + "onboarding": { + "feature_automations": "Автоматизация", + "feature_automations_desc": "Запускайте шаги автоматически при возникновении событий и получайте уведомления." + } +} diff --git a/plugins/automations/locales/translated/sr_SP.json b/plugins/automations/locales/translated/sr_SP.json new file mode 100644 index 000000000..a3eb6fc7c --- /dev/null +++ b/plugins/automations/locales/translated/sr_SP.json @@ -0,0 +1,149 @@ +{ + "newUi": { + "sidebar": { + "automations": { + "title": "Аутоматизације", + "tabAutomations": "Аутоматизације", + "tabRuns": "Трчања", + "tabChannels": "Канали", + "createAutomation": "Нова аутоматизација", + "backToAutomations": "Назад на аутоматизацију", + "createTitle": "Нова аутоматизација", + "editTitle": "Уреди аутоматизацију", + "empty": "Још увек нема аутоматизација. Направите једну да бисте реаговали на метрику, распоред или догађај.", + "emptyRuns": "Још нема трчања.", + "emptyChannels": "Још нема канала. Додајте један да бисте слали обавештења негде.", + "noChannelsHint": "Још увек нема подешених канала. Додајте један на картици Канали.", + "addChannel": "Додај канал", + "testChannel": "Тест", + "channelTestSent": "Обавештење о тестирању је послато", + "channelTestFailed": "Обавештење о тестирању није успело", + "channelDeleted": "Канал је обрисан", + "deleteChannelConfirm": "Да ли желите да обришете овај канал? Аутоматизације које га користе ће престати да шаљу обавештења.", + "nameLabel": "Име", + "namePlaceholder": "нпр. Очисти /подаци када се попуне", + "nameRequired": "Име је обавезно", + "descriptionLabel": "Опис", + "descriptionPlaceholder": "Опциони опис", + "enabledLabel": "Омогућено", + "concurrencyLabel": "Ако већ ради", + "concurrencyHint": "Шта урадити када се ово поново покрене пре него што се заврши последње покретање.", + "concurrency": { + "skip": "Прескочи нову вожњу", + "queue": "Чекај и трчи за њим", + "allow": "Покрени оба одједном" + }, + "save": "Сачувај", + "created": "Аутоматизација је креирана", + "updated": "Аутоматизација је сачувана", + "deleted": "Аутоматизација је обрисана", + "deleteConfirm": "Да ли желите да обришете ову аутоматизацију? Њена историја покретања је такође обрисана.", + "runNow": "Трчи сада", + "testRun": "Тестирање", + "testRunHint": "Покреће сваки корак, али не додирује ништа изван Термикса.", + "runStarted": "Трчање је започето", + "runFinished": "Трка завршена: {{status}}", + "trigger": "Окидач", + "steps": "Кораци", + "addStep": "Додај корак", + "removeStep": "Уклони корак", + "moveUp": "Помери горе", + "moveDown": "Помери надоле", + "noSteps": "Још нема корака. Додајте један да бисте рекли шта треба да се деси.", + "webhookTokenTitle": "URL вебхука", + "webhookTokenDescription": "Ово се приказује једном. Сачувајте то сада, не можете то касније преузети.", + "copy": "Копија", + "copied": "Копирано", + "viewJson": "JSON", + "viewBuilder": "Градитељ", + "viewGraph": "График", + "lastRun": "Последње трчање", + "never": "Никад", + "duration": "{{seconds}}с", + "stepOutput": "Излаз", + "stepError": "Грешка", + "dryRunBadge": "Тестирање", + "hostSelector": { + "trigger": "Покретач хоста", + "host": "Одређени домаћин", + "fleet": "Флота", + "all": "Сви домаћини" + }, + "triggerKinds": { + "metric_threshold": "Праг метрике", + "host_status": "Домаћин иде горе или доле", + "health_check": "Промене у провери исправности", + "schedule": "По распореду", + "docker_event": "Догађај контејнера", + "internal_event": "Термикс догађај", + "webhook": "Долазни вебхук" + }, + "stepTypes": { + "notify": "Пошаљи обавештење", + "http": "Позовите URL", + "run_snippet": "Покрени исечак", + "run_command": "Покрените команду", + "docker": "Контролишите контејнер", + "tunnel": "Контролишите тунел", + "wol": "Пробудите домаћина", + "wait": "Чекај", + "set_var": "Поставите променљиву", + "if": "Ако / иначе", + "run_automation": "Покрените још једну аутоматизацију", + "stop": "Заустави" + }, + "statuses": { + "running": "Трчање", + "success": "Успех", + "failed": "Неуспешно", + "timeout": "Временско ограничење је истекло", + "skipped": "Прескочено", + "cancelled": "Отказано" + }, + "fields": { + "host": "Домаћин", + "metric": "Метрика", + "mount": "Тачка монтирања", + "operator": "Је", + "value": "Вредност", + "forSeconds": "Задржано (секунде)", + "cooldown": "Хлађење (минути)", + "cron": "Cron израз", + "intervalSeconds": "Сваких (секунде)", + "timezone": "Временска зона", + "timezoneServer": "Време сервера", + "timezoneHint": "Cron времена се очитавају у овој зони. Не односи се на интервалне распореде.", + "container": "Контејнер", + "command": "Команда", + "url": "URL", + "method": "Метод", + "body": "Тело", + "channels": "Канали", + "title": "Наслов", + "message": "Порука", + "snippet": "Исечак", + "seconds": "Секунде", + "conditionLeftPlaceholder": "Вредност за проверу", + "conditionRightPlaceholder": "Упореди са", + "variableName": "Назив променљиве", + "variableValue": "Вредност", + "elevated": "Покрени са sudo-ом", + "onError": "Ако ово не успе", + "allowPrivateNetwork": "Дозволи локалне мрежне адресе", + "allowPrivateNetworkHint": "Потребно за самостално хостовану услугу на вашој локалној мрежи. Подразумевано искључено да би се спречили захтеви ка интерним адресама." + }, + "onError": { + "stop": "Заустави трчање", + "continue": "Настави" + } + } + } + }, + "nav": { + "automations": "Аутоматизације" + }, + "onboarding": { + "feature_automations": "Аутоматизације", + "feature_automations_desc": "Аутоматски покрените кораке када се нешто деси и добијте обавештења." + } +} diff --git a/plugins/automations/locales/translated/sv_SE.json b/plugins/automations/locales/translated/sv_SE.json new file mode 100644 index 000000000..b17ab3315 --- /dev/null +++ b/plugins/automations/locales/translated/sv_SE.json @@ -0,0 +1,149 @@ +{ + "newUi": { + "sidebar": { + "automations": { + "title": "Automatiseringar", + "tabAutomations": "Automatiseringar", + "tabRuns": "Löpningar", + "tabChannels": "Kanaler", + "createAutomation": "Ny automatisering", + "backToAutomations": "Tillbaka till Automatiseringar", + "createTitle": "Ny automatisering", + "editTitle": "Redigera automatisering", + "empty": "Inga automatiseringar ännu. Skapa en för att reagera på ett mätvärde, ett schema eller en händelse.", + "emptyRuns": "Inga löpningar än.", + "emptyChannels": "Inga kanaler ännu. Lägg till en för att skicka aviseringar någonstans.", + "noChannelsHint": "Inga kanaler är konfigurerade än. Lägg till en på fliken Kanaler.", + "addChannel": "Lägg till kanal", + "testChannel": "Testa", + "channelTestSent": "Testmeddelande skickat", + "channelTestFailed": "Testmeddelandet misslyckades", + "channelDeleted": "Kanalen raderad", + "deleteChannelConfirm": "Vill du ta bort den här kanalen? Automatiseringar som använder den kommer att sluta skicka aviseringar.", + "nameLabel": "Namn", + "namePlaceholder": "t.ex. Rensa upp /data när den fylls", + "nameRequired": "Namn krävs", + "descriptionLabel": "Beskrivning", + "descriptionPlaceholder": "Valfri beskrivning", + "enabledLabel": "Aktiverad", + "concurrencyLabel": "Om den redan är igång", + "concurrencyHint": "Vad man ska göra när detta utlöses igen innan den sista körningen är klar.", + "concurrency": { + "skip": "Hoppa över den nya körningen", + "queue": "Vänta och spring efter", + "allow": "Kör båda samtidigt" + }, + "save": "Spara", + "created": "Automatisering skapad", + "updated": "Automatisering sparad", + "deleted": "Automatisering borttagen", + "deleteConfirm": "Vill du ta bort den här automatiseringen? Dess körhistorik raderas också.", + "runNow": "Kör nu", + "testRun": "Testkörning", + "testRunHint": "Kör varje steg men rör ingenting utanför Termix.", + "runStarted": "Löpningen har startat", + "runFinished": "Körning avslutad: {{status}}", + "trigger": "Utlösare", + "steps": "Steg", + "addStep": "Lägg till steg", + "removeStep": "Ta bort steg", + "moveUp": "Flytta upp", + "moveDown": "Flytta nedåt", + "noSteps": "Inga steg ännu. Lägg till ett för att ange vad som ska hända.", + "webhookTokenTitle": "Webhook-URL", + "webhookTokenDescription": "Detta visas en gång. Spara det nu, det kan inte hämtas senare.", + "copy": "Kopiera", + "copied": "Kopierad", + "viewJson": "JSON", + "viewBuilder": "Byggmästare", + "viewGraph": "Graf", + "lastRun": "Sista körningen", + "never": "Aldrig", + "duration": "{{seconds}}s", + "stepOutput": "Produktion", + "stepError": "Fel", + "dryRunBadge": "Testkörning", + "hostSelector": { + "trigger": "Utlösande värd", + "host": "Specifik värd", + "fleet": "Flotta", + "all": "Alla värdar" + }, + "triggerKinds": { + "metric_threshold": "Metrisk tröskelvärde", + "host_status": "Värden går upp eller ner", + "health_check": "Ändringar i hälsokontrollen", + "schedule": "Enligt ett schema", + "docker_event": "Containerhändelse", + "internal_event": "Termix-evenemang", + "webhook": "Inkommande webhook" + }, + "stepTypes": { + "notify": "Skicka en avisering", + "http": "Anropa en URL", + "run_snippet": "Kör ett utdrag", + "run_command": "Kör ett kommando", + "docker": "Styr en container", + "tunnel": "Kontrollera en tunnel", + "wol": "Väck en värd", + "wait": "Vänta", + "set_var": "Ställ in en variabel", + "if": "Om / annars", + "run_automation": "Kör en annan automatisering", + "stop": "Stopp" + }, + "statuses": { + "running": "Spring", + "success": "Framgång", + "failed": "Misslyckades", + "timeout": "Timeout", + "skipped": "Hoppade över", + "cancelled": "Avbruten" + }, + "fields": { + "host": "Värd", + "metric": "Metrisk", + "mount": "Monteringspunkt", + "operator": "Är", + "value": "Värde", + "forSeconds": "Uthållen i (sekunder)", + "cooldown": "Nedkylningstid (minuter)", + "cron": "Cron-uttryck", + "intervalSeconds": "Varje (sekund)", + "timezone": "Tidszon", + "timezoneServer": "Servertid", + "timezoneHint": "Cron-tider läses i denna zon. Gäller inte för intervallscheman.", + "container": "Behållare", + "command": "Kommando", + "url": "URL", + "method": "Metod", + "body": "Kropp", + "channels": "Kanaler", + "title": "Titel", + "message": "Meddelande", + "snippet": "Utdrag", + "seconds": "Sekunder", + "conditionLeftPlaceholder": "Värde att kontrollera", + "conditionRightPlaceholder": "Jämför mot", + "variableName": "Variabelnamn", + "variableValue": "Värde", + "elevated": "Kör med sudo", + "onError": "Om detta misslyckas", + "allowPrivateNetwork": "Tillåt lokala nätverksadresser", + "allowPrivateNetworkHint": "Behövs för en självhostad tjänst på ditt lokala nätverk. Avstängt som standard för att förhindra förfrågningar till interna adresser." + }, + "onError": { + "stop": "Stoppa löpningen", + "continue": "Fortsätta" + } + } + } + }, + "nav": { + "automations": "Automatiseringar" + }, + "onboarding": { + "feature_automations": "Automatiseringar", + "feature_automations_desc": "Kör steg automatiskt när något händer och få aviseringar." + } +} diff --git a/plugins/automations/locales/translated/th_TH.json b/plugins/automations/locales/translated/th_TH.json new file mode 100644 index 000000000..72b00d2db --- /dev/null +++ b/plugins/automations/locales/translated/th_TH.json @@ -0,0 +1,149 @@ +{ + "newUi": { + "sidebar": { + "automations": { + "title": "ระบบอัตโนมัติ", + "tabAutomations": "ระบบอัตโนมัติ", + "tabRuns": "วิ่ง", + "tabChannels": "ช่องต่างๆ", + "createAutomation": "ระบบอัตโนมัติใหม่", + "backToAutomations": "กลับสู่ระบบอัตโนมัติ", + "createTitle": "ระบบอัตโนมัติใหม่", + "editTitle": "แก้ไขอัตโนมัติ", + "empty": "ยังไม่มีระบบอัตโนมัติใดๆ สร้างระบบอัตโนมัติเพื่อตอบสนองต่อตัวชี้วัด กำหนดการ หรือเหตุการณ์ต่างๆ", + "emptyRuns": "ยังไม่มีการทดลองใดๆ เกิดขึ้น", + "emptyChannels": "ยังไม่มีช่องทางการแจ้งเตือน เพิ่มช่องทางเพื่อส่งการแจ้งเตือนไปยังที่ใดที่หนึ่ง", + "noChannelsHint": "ยังไม่ได้ตั้งค่าช่องใดๆ เพิ่มช่องในแท็บช่องได้เลย", + "addChannel": "เพิ่มช่องทาง", + "testChannel": "ทดสอบ", + "channelTestSent": "ส่งการแจ้งเตือนการทดสอบแล้ว", + "channelTestFailed": "การแจ้งเตือนการทดสอบล้มเหลว", + "channelDeleted": "ช่องถูกลบแล้ว", + "deleteChannelConfirm": "ลบช่องทางนี้? ระบบอัตโนมัติที่ใช้ช่องทางนี้จะหยุดแจ้งเตือน", + "nameLabel": "ชื่อ", + "namePlaceholder": "เช่น ล้างข้อมูลใน /data เมื่อเต็ม", + "nameRequired": "ต้องระบุชื่อ", + "descriptionLabel": "คำอธิบาย", + "descriptionPlaceholder": "คำอธิบายเพิ่มเติม (ไม่บังคับ)", + "enabledLabel": "เปิดใช้งาน", + "concurrencyLabel": "หากกำลังทำงานอยู่แล้ว", + "concurrencyHint": "ควรทำอย่างไรเมื่อเหตุการณ์นี้เกิดขึ้นอีกครั้งก่อนที่การทำงานครั้งสุดท้ายจะเสร็จสิ้น", + "concurrency": { + "skip": "ข้ามการวิ่งรอบใหม่ไป", + "queue": "รอและวิ่งตาม", + "allow": "เรียกใช้ทั้งสองอย่างพร้อมกัน" + }, + "save": "บันทึก", + "created": "ระบบอัตโนมัติสร้างขึ้น", + "updated": "ระบบอัตโนมัติได้รับการบันทึกแล้ว", + "deleted": "ระบบอัตโนมัติลบแล้ว", + "deleteConfirm": "ลบระบบอัตโนมัตินี้แล้วใช่ไหม? ประวัติการทำงานของมันก็จะถูกลบไปด้วย", + "runNow": "วิ่งเลยตอนนี้", + "testRun": "การทดสอบการทำงาน", + "testRunHint": "ทำงานทุกขั้นตอน แต่ไม่แตะต้องสิ่งใดนอกเหนือจาก Termix", + "runStarted": "การวิ่งเริ่มต้นขึ้นแล้ว", + "runFinished": "การทำงานเสร็จสิ้น: {{status}}", + "trigger": "สิ่งกระตุ้น", + "steps": "ขั้นตอน", + "addStep": "เพิ่มขั้นตอน", + "removeStep": "ลบขั้นตอน", + "moveUp": "เลื่อนขึ้น", + "moveDown": "เลื่อนลง", + "noSteps": "ยังไม่มีขั้นตอนใดๆ เพิ่มขั้นตอนเพื่ออธิบายว่าควรเกิดอะไรขึ้น", + "webhookTokenTitle": "URL ของเว็บฮุค", + "webhookTokenDescription": "แสดงเพียงครั้งเดียว บันทึกตอนนี้ ไม่สามารถเรียกดูซ้ำได้ในภายหลัง", + "copy": "สำเนา", + "copied": "คัดลอกแล้ว", + "viewJson": "เจซอน", + "viewBuilder": "ผู้สร้าง", + "viewGraph": "กราฟ", + "lastRun": "การวิ่งครั้งสุดท้าย", + "never": "ไม่เคย", + "duration": "{{seconds}}s", + "stepOutput": "เอาต์พุต", + "stepError": "ข้อผิดพลาด", + "dryRunBadge": "การทดสอบการทำงาน", + "hostSelector": { + "trigger": "โฮสต์ทริกเกอร์", + "host": "โฮสต์เฉพาะ", + "fleet": "กองเรือ", + "all": "โฮสต์ทั้งหมด" + }, + "triggerKinds": { + "metric_threshold": "เกณฑ์เมตริก", + "host_status": "โฮสต์ขึ้นหรือลง", + "health_check": "การเปลี่ยนแปลงการตรวจสุขภาพ", + "schedule": "ตามกำหนดเวลา", + "docker_event": "เหตุการณ์คอนเทนเนอร์", + "internal_event": "กิจกรรมเทอร์มิกซ์", + "webhook": "เว็บฮุคขาเข้า" + }, + "stepTypes": { + "notify": "ส่งการแจ้งเตือน", + "http": "เรียกใช้ URL", + "run_snippet": "เรียกใช้โค้ดตัวอย่าง", + "run_command": "เรียกใช้คำสั่ง", + "docker": "ควบคุมตู้คอนเทนเนอร์", + "tunnel": "ควบคุมอุโมงค์", + "wol": "ปลุกโฮสต์", + "wait": "รอ", + "set_var": "ตั้งค่าตัวแปร", + "if": "ถ้า / มิฉะนั้น", + "run_automation": "เรียกใช้ระบบอัตโนมัติอีกครั้ง", + "stop": "หยุด" + }, + "statuses": { + "running": "วิ่ง", + "success": "ความสำเร็จ", + "failed": "ล้มเหลว", + "timeout": "หมดเวลา", + "skipped": "ข้ามไป", + "cancelled": "ยกเลิก" + }, + "fields": { + "host": "เจ้าภาพ", + "metric": "เมตริก", + "mount": "จุดยึด", + "operator": "เป็น", + "value": "ค่า", + "forSeconds": "ต่อเนื่องเป็นเวลา (วินาที)", + "cooldown": "ระยะเวลาคูลดาวน์ (นาที)", + "cron": "การแสดงออกของ Cron", + "intervalSeconds": "ทุกๆ (วินาที)", + "timezone": "เขตเวลา", + "timezoneServer": "เวลาเซิร์ฟเวอร์", + "timezoneHint": "เวลาของ Cron จะอ่านได้ในโซนนี้ ไม่สามารถใช้ได้กับตารางเวลาแบบช่วงเวลา", + "container": "คอนเทนเนอร์", + "command": "สั่งการ", + "url": "URL", + "method": "วิธี", + "body": "ร่างกาย", + "channels": "ช่องต่างๆ", + "title": "ชื่อ", + "message": "ข้อความ", + "snippet": "ส่วนหนึ่ง", + "seconds": "วินาที", + "conditionLeftPlaceholder": "ค่าที่ต้องตรวจสอบ", + "conditionRightPlaceholder": "เปรียบเทียบกับ", + "variableName": "ชื่อตัวแปร", + "variableValue": "ค่า", + "elevated": "เรียกใช้ด้วยคำสั่ง sudo", + "onError": "หากวิธีนี้ล้มเหลว", + "allowPrivateNetwork": "อนุญาตให้ใช้ที่อยู่เครือข่ายท้องถิ่น", + "allowPrivateNetworkHint": "จำเป็นสำหรับบริการที่โฮสต์เองบนเครือข่าย LAN ของคุณ โดยค่าเริ่มต้นจะปิดใช้งานเพื่อป้องกันการร้องขอไปยังที่อยู่ภายใน" + }, + "onError": { + "stop": "หยุดการวิ่ง", + "continue": "ดำเนินการต่อไป" + } + } + } + }, + "nav": { + "automations": "ระบบอัตโนมัติ" + }, + "onboarding": { + "feature_automations": "ระบบอัตโนมัติ", + "feature_automations_desc": "ดำเนินการตามขั้นตอนโดยอัตโนมัติเมื่อเกิดเหตุการณ์ใดๆ และรับการแจ้งเตือน" + } +} diff --git a/plugins/automations/locales/translated/tr_TR.json b/plugins/automations/locales/translated/tr_TR.json new file mode 100644 index 000000000..d2099477e --- /dev/null +++ b/plugins/automations/locales/translated/tr_TR.json @@ -0,0 +1,149 @@ +{ + "newUi": { + "sidebar": { + "automations": { + "title": "Otomasyonlar", + "tabAutomations": "Otomasyonlar", + "tabRuns": "Koşular", + "tabChannels": "Kanallar", + "createAutomation": "Yeni Otomasyon", + "backToAutomations": "Otomasyonlara geri dön", + "createTitle": "Yeni Otomasyon", + "editTitle": "Düzenleme Otomasyonu", + "empty": "Henüz otomasyon yok. Bir ölçüme, bir programa veya bir olaya tepki verecek bir otomasyon oluşturun.", + "emptyRuns": "Henüz hiçbir deneme yapılmadı.", + "emptyChannels": "Henüz kanal yok. Bildirim göndermek için bir kanal ekleyin.", + "noChannelsHint": "Henüz hiçbir kanal ayarlanmadı. Kanallar sekmesinden bir kanal ekleyin.", + "addChannel": "Kanal Ekle", + "testChannel": "Test", + "channelTestSent": "Test bildirimi gönderildi", + "channelTestFailed": "Test bildirimi başarısız oldu.", + "channelDeleted": "Kanal silindi", + "deleteChannelConfirm": "Bu kanalı silmek ister misiniz? Bu kanalı kullanan otomasyonlar bildirim göndermeyi durduracaktır.", + "nameLabel": "İsim", + "namePlaceholder": "Örneğin, /data klasörü dolduğunda temizle.", + "nameRequired": "İsim zorunludur.", + "descriptionLabel": "Tanım", + "descriptionPlaceholder": "İsteğe bağlı açıklama", + "enabledLabel": "Etkinleştirilmiş", + "concurrencyLabel": "Eğer zaten çalışıyorsa", + "concurrencyHint": "Son çalıştırma tamamlanmadan önce bu durum tekrar tetiklendiğinde ne yapılmalı?", + "concurrency": { + "skip": "Yeni sürümü atla", + "queue": "Bekle ve sonra koş", + "allow": "İkisini birden çalıştırın" + }, + "save": "Kaydetmek", + "created": "Otomasyon oluşturuldu", + "updated": "Otomasyon kaydedildi", + "deleted": "Otomasyon silindi", + "deleteConfirm": "Bu otomasyonu silerseniz, çalıştırma geçmişi de silinir.", + "runNow": "Şimdi çalıştır", + "testRun": "Test çalıştırması", + "testRunHint": "Her adımı çalıştırır ancak Termix dışındaki hiçbir şeye dokunmaz.", + "runStarted": "Koşu başladı", + "runFinished": "Çalıştırma tamamlandı: {{status}}", + "trigger": "Tetiklemek", + "steps": "Adımlar", + "addStep": "Adım ekle", + "removeStep": "Adımı kaldır", + "moveUp": "Yukarı çık", + "moveDown": "Aşağıya doğru hareket edin", + "noSteps": "Henüz hiçbir adım yok. Ne olması gerektiğini belirtmek için bir adım ekleyin.", + "webhookTokenTitle": "Webhook URL", + "webhookTokenDescription": "Bu yalnızca bir kez gösterilecektir. Şimdi kaydedin, daha sonra geri alınamaz.", + "copy": "Kopyala", + "copied": "Kopyalandı", + "viewJson": "JSON", + "viewBuilder": "İnşaatçı", + "viewGraph": "Grafik", + "lastRun": "Son koşu", + "never": "Asla", + "duration": "{{seconds}}s", + "stepOutput": "Çıktı", + "stepError": "Hata", + "dryRunBadge": "Test çalıştırması", + "hostSelector": { + "trigger": "Tetikleyici sunucu", + "host": "Belirli ev sahibi", + "fleet": "Filo", + "all": "Tüm ev sahipleri" + }, + "triggerKinds": { + "metric_threshold": "Metrik eşik", + "host_status": "Sunucu yukarı veya aşağı hareket eder.", + "health_check": "Sağlık kontrolü değişiklikleri", + "schedule": "Bir programa göre", + "docker_event": "Konteyner olayı", + "internal_event": "Termix etkinliği", + "webhook": "Gelen web kancası" + }, + "stepTypes": { + "notify": "Bildirim gönder", + "http": "Bir URL'yi çağırın", + "run_snippet": "Bir kod parçası çalıştırın.", + "run_command": "Bir komut çalıştır", + "docker": "Bir konteyneri kontrol edin.", + "tunnel": "Bir tüneli kontrol edin.", + "wol": "Bir ev sahibini uyandırın", + "wait": "Beklemek", + "set_var": "Bir değişken tanımlayın", + "if": "Eğer / aksi takdirde", + "run_automation": "Başka bir otomasyon çalıştırın", + "stop": "Durmak" + }, + "statuses": { + "running": "Koşma", + "success": "Başarı", + "failed": "Arızalı", + "timeout": "Süre doldu", + "skipped": "Atlandı", + "cancelled": "İptal edildi" + }, + "fields": { + "host": "Ev sahibi", + "metric": "Metrik", + "mount": "Montaj noktası", + "operator": "O", + "value": "Değer", + "forSeconds": "(Saniye) süreyle sürdürüldü", + "cooldown": "Soğuma süresi (dakika)", + "cron": "Cron ifadesi", + "intervalSeconds": "Her (saniye)", + "timezone": "Saat dilimi", + "timezoneServer": "Sunucu zamanı", + "timezoneHint": "Cron zamanlama ayarları bu bölgede okunur. Aralıklı zamanlamalar için geçerli değildir.", + "container": "Konteyner", + "command": "Emretmek", + "url": "URL", + "method": "Yöntem", + "body": "Vücut", + "channels": "Kanallar", + "title": "Başlık", + "message": "Mesaj", + "snippet": "Alıntı", + "seconds": "Saniyeler", + "conditionLeftPlaceholder": "Kontrol edilecek değer", + "conditionRightPlaceholder": "Karşılaştırın", + "variableName": "Değişken adı", + "variableValue": "Değer", + "elevated": "sudo ile çalıştır", + "onError": "Eğer bu başarısız olursa", + "allowPrivateNetwork": "Yerel ağ adreslerine izin verin.", + "allowPrivateNetworkHint": "Yerel ağınızda kendi sunucunuzda barındırdığınız bir hizmet için gereklidir. Dahili adreslere yapılan istekleri engellemek için varsayılan olarak kapalıdır." + }, + "onError": { + "stop": "Koşuyu durdurun", + "continue": "Devam edin" + } + } + } + }, + "nav": { + "automations": "Otomasyonlar" + }, + "onboarding": { + "feature_automations": "Otomasyonlar", + "feature_automations_desc": "Bir şey olduğunda adımları otomatik olarak çalıştırın ve bildirim alın." + } +} diff --git a/plugins/automations/locales/translated/uk_UA.json b/plugins/automations/locales/translated/uk_UA.json new file mode 100644 index 000000000..2fbe13446 --- /dev/null +++ b/plugins/automations/locales/translated/uk_UA.json @@ -0,0 +1,149 @@ +{ + "newUi": { + "sidebar": { + "automations": { + "title": "Автоматизація", + "tabAutomations": "Автоматизація", + "tabRuns": "Пробіжки", + "tabChannels": "Канали", + "createAutomation": "Нова автоматизація", + "backToAutomations": "Назад до автоматизації", + "createTitle": "Нова автоматизація", + "editTitle": "Редагувати автоматизацію", + "empty": "Автоматизації поки що немає. Створіть її, щоб реагувати на метрику, розклад або подію.", + "emptyRuns": "Поки що жодних пробіжок.", + "emptyChannels": "Поки що немає каналів. Додайте один, щоб надсилати сповіщення кудись.", + "noChannelsHint": "Канали ще не налаштовано. Додайте його на вкладці «Канали».", + "addChannel": "Додати канал", + "testChannel": "Тест", + "channelTestSent": "Тестове сповіщення надіслано", + "channelTestFailed": "Не вдалося виконати тестове сповіщення", + "channelDeleted": "Канал видалено", + "deleteChannelConfirm": "Видалити цей канал? Автоматизації, що його використовують, перестануть надсилати сповіщення.", + "nameLabel": "Ім'я", + "namePlaceholder": "наприклад, Очищати /дані, коли вони заповнюються", + "nameRequired": "Ім'я обов'язкове", + "descriptionLabel": "Опис", + "descriptionPlaceholder": "Додатковий опис", + "enabledLabel": "Увімкнено", + "concurrencyLabel": "Якщо воно вже працює", + "concurrencyHint": "Що робити, якщо це спрацьовує знову до завершення останнього запуску.", + "concurrency": { + "skip": "Пропустити новий пробіг", + "queue": "Чекай і біжіть за ним", + "allow": "Запустіть обидва одночасно" + }, + "save": "Зберегти", + "created": "Автоматизація створена", + "updated": "Автоматизація збережена", + "deleted": "Автоматизацію видалено", + "deleteConfirm": "Видалити цю автоматизацію? Історія її запуску також видаляється.", + "runNow": "Біжи зараз", + "testRun": "Тестовий запуск", + "testRunHint": "Виконує кожен крок, але не торкається нічого поза Termix.", + "runStarted": "Біг розпочато", + "runFinished": "Виконання завершено: {{status}}", + "trigger": "Тригер", + "steps": "Кроки", + "addStep": "Додати крок", + "removeStep": "Видалити крок", + "moveUp": "Перемістити вгору", + "moveDown": "Перемістити вниз", + "noSteps": "Кроків поки що немає. Додайте один, щоб пояснити, що має статися.", + "webhookTokenTitle": "URL-адреса вебхука", + "webhookTokenDescription": "Це відображається один раз. Збережіть це зараз, пізніше це неможливо буде отримати.", + "copy": "Копіювати", + "copied": "Скопійовано", + "viewJson": "JSON", + "viewBuilder": "Будівельник", + "viewGraph": "Графік", + "lastRun": "Останній запуск", + "never": "Ніколи", + "duration": "{{seconds}}с", + "stepOutput": "Вихід", + "stepError": "Помилка", + "dryRunBadge": "Тестовий запуск", + "hostSelector": { + "trigger": "Хост-тригер", + "host": "Конкретний хост", + "fleet": "Флот", + "all": "Усі хости" + }, + "triggerKinds": { + "metric_threshold": "Поріг показника", + "host_status": "Хост піднімається або опускається", + "health_check": "Зміни в перевірці стану здоров'я", + "schedule": "За розкладом", + "docker_event": "Подія контейнера", + "internal_event": "Подія Termix", + "webhook": "Вхідний вебхук" + }, + "stepTypes": { + "notify": "Надіслати сповіщення", + "http": "Виклик URL-адреси", + "run_snippet": "Виконати фрагмент коду", + "run_command": "Виконайте команду", + "docker": "Керування контейнером", + "tunnel": "Контролюйте тунель", + "wol": "Розбудити господаря", + "wait": "Зачекайте", + "set_var": "Встановити змінну", + "if": "Якщо / інакше", + "run_automation": "Запустіть ще одну автоматизацію", + "stop": "СТІЙ" + }, + "statuses": { + "running": "Біг", + "success": "Успіх", + "failed": "Не вдалося", + "timeout": "Час очікування минув", + "skipped": "Пропущено", + "cancelled": "Скасовано" + }, + "fields": { + "host": "Хост", + "metric": "Метрика", + "mount": "Точка монтування", + "operator": "Є", + "value": "Значення", + "forSeconds": "Триває протягом (секунд)", + "cooldown": "Охолодження (хвилини)", + "cron": "Cron-вираз", + "intervalSeconds": "Кожні (секунди)", + "timezone": "Часовий пояс", + "timezoneServer": "Час сервера", + "timezoneHint": "Час Cron зчитується в цій зоні. Не стосується інтервальних розкладів.", + "container": "Контейнер", + "command": "Команда", + "url": "URL-адреса", + "method": "Метод", + "body": "Тіло", + "channels": "Канали", + "title": "Назва", + "message": "Повідомлення", + "snippet": "Фрагмент", + "seconds": "Секунди", + "conditionLeftPlaceholder": "Значення для перевірки", + "conditionRightPlaceholder": "Порівняйте з", + "variableName": "Ім'я змінної", + "variableValue": "Значення", + "elevated": "Запустити за допомогою sudo", + "onError": "Якщо це не вдасться", + "allowPrivateNetwork": "Дозволити адреси локальної мережі", + "allowPrivateNetworkHint": "Потрібно для самостійно розміщеної служби у вашій локальній мережі. Вимкнено за замовчуванням, щоб запобігти запитам до внутрішніх адрес." + }, + "onError": { + "stop": "Зупинити біг", + "continue": "Продовжуйте" + } + } + } + }, + "nav": { + "automations": "Автоматизація" + }, + "onboarding": { + "feature_automations": "Автоматизація", + "feature_automations_desc": "Автоматично виконувати кроки, коли щось відбувається, та отримувати сповіщення." + } +} diff --git a/plugins/automations/locales/translated/vi_VN.json b/plugins/automations/locales/translated/vi_VN.json new file mode 100644 index 000000000..3b36d81cd --- /dev/null +++ b/plugins/automations/locales/translated/vi_VN.json @@ -0,0 +1,149 @@ +{ + "newUi": { + "sidebar": { + "automations": { + "title": "Tự động hóa", + "tabAutomations": "Tự động hóa", + "tabRuns": "Chạy", + "tabChannels": "Kênh", + "createAutomation": "Tự động hóa mới", + "backToAutomations": "Quay lại phần Tự động hóa", + "createTitle": "Tự động hóa mới", + "editTitle": "Tự động chỉnh sửa", + "empty": "Hiện chưa có tính năng tự động hóa nào. Hãy tạo một tính năng để phản ứng với một chỉ số, lịch trình hoặc sự kiện nào đó.", + "emptyRuns": "Chưa có lượt chạy nào.", + "emptyChannels": "Chưa có kênh nào. Thêm một kênh để gửi thông báo đến đâu đó.", + "noChannelsHint": "Chưa có kênh nào được thiết lập. Thêm một kênh trong tab Kênh.", + "addChannel": "Thêm kênh", + "testChannel": "Bài kiểm tra", + "channelTestSent": "Thông báo kiểm tra đã được gửi", + "channelTestFailed": "Thông báo kiểm tra thất bại", + "channelDeleted": "Kênh đã bị xóa", + "deleteChannelConfirm": "Xóa kênh này? Các tự động hóa sử dụng kênh này sẽ ngừng gửi thông báo.", + "nameLabel": "Tên", + "namePlaceholder": "Ví dụ: Dọn dẹp thư mục /data khi nó đầy.", + "nameRequired": "Tên là bắt buộc", + "descriptionLabel": "Sự miêu tả", + "descriptionPlaceholder": "Mô tả tùy chọn", + "enabledLabel": "Đã bật", + "concurrencyLabel": "Nếu nó đang chạy", + "concurrencyHint": "Phải làm gì khi sự cố này xảy ra lần nữa trước khi quá trình chạy cuối cùng hoàn tất?", + "concurrency": { + "skip": "Bỏ qua lần chạy mới", + "queue": "Chờ đợi và chạy theo", + "allow": "Chạy cả hai cùng một lúc" + }, + "save": "Cứu", + "created": "Tự động hóa được tạo", + "updated": "Tự động hóa đã được lưu", + "deleted": "Tự động hóa đã bị xóa", + "deleteConfirm": "Xóa tự động hóa này? Lịch sử chạy của nó cũng bị xóa.", + "runNow": "Chạy ngay", + "testRun": "Chạy thử nghiệm", + "testRunHint": "Nó chạy theo từng bước nhưng không chạm vào bất cứ thứ gì bên ngoài Termix.", + "runStarted": "Chạy bắt đầu", + "runFinished": "Quá trình chạy đã hoàn tất: {{status}}", + "trigger": "Cò súng", + "steps": "Các bước", + "addStep": "Thêm bước", + "removeStep": "Xóa bước", + "moveUp": "Tiến lên", + "moveDown": "Di chuyển xuống", + "noSteps": "Chưa có bước nào. Hãy thêm một bước để mô tả những gì cần xảy ra.", + "webhookTokenTitle": "URL Webhook", + "webhookTokenDescription": "Thông tin này chỉ hiển thị một lần. Hãy lưu lại ngay, bạn sẽ không thể khôi phục lại sau này.", + "copy": "Sao chép", + "copied": "Đã sao chép", + "viewJson": "JSON", + "viewBuilder": "Nhà xây dựng", + "viewGraph": "Đồ thị", + "lastRun": "Lần chạy cuối", + "never": "Không bao giờ", + "duration": "{{seconds}}s", + "stepOutput": "Đầu ra", + "stepError": "Lỗi", + "dryRunBadge": "Chạy thử nghiệm", + "hostSelector": { + "trigger": "Máy chủ kích hoạt", + "host": "Máy chủ cụ thể", + "fleet": "Hạm đội", + "all": "Tất cả người chủ trì" + }, + "triggerKinds": { + "metric_threshold": "Ngưỡng số liệu", + "host_status": "Máy chủ tăng hoặc giảm", + "health_check": "Thay đổi trong kiểm tra sức khỏe", + "schedule": "Theo lịch trình", + "docker_event": "Sự kiện container", + "internal_event": "Sự kiện Termix", + "webhook": "Webhook đến" + }, + "stepTypes": { + "notify": "Gửi thông báo", + "http": "Gọi một URL", + "run_snippet": "Chạy một đoạn mã", + "run_command": "Chạy một lệnh", + "docker": "Kiểm soát một container", + "tunnel": "Kiểm soát đường hầm", + "wol": "Đánh thức một chủ nhà", + "wait": "Chờ đợi", + "set_var": "Đặt một biến", + "if": "Nếu/ngược lại", + "run_automation": "Chạy một quy trình tự động hóa khác", + "stop": "Dừng lại" + }, + "statuses": { + "running": "Đang chạy", + "success": "Thành công", + "failed": "Thất bại", + "timeout": "Hết thời gian", + "skipped": "Bỏ qua", + "cancelled": "Đã hủy" + }, + "fields": { + "host": "Chủ nhà", + "metric": "Số liệu", + "mount": "Điểm gắn kết", + "operator": "Là", + "value": "Giá trị", + "forSeconds": "Duy trì trong (giây)", + "cooldown": "Thời gian hồi chiêu (phút)", + "cron": "Biểu thức Cron", + "intervalSeconds": "Mỗi (giây)", + "timezone": "Múi giờ", + "timezoneServer": "Thời gian máy chủ", + "timezoneHint": "Thời gian Cron được đọc trong vùng này. Không áp dụng cho lịch trình theo khoảng thời gian.", + "container": "Thùng chứa", + "command": "Yêu cầu", + "url": "URL", + "method": "Phương pháp", + "body": "Thân hình", + "channels": "Kênh", + "title": "Tiêu đề", + "message": "Tin nhắn", + "snippet": "Đoạn trích", + "seconds": "Giây", + "conditionLeftPlaceholder": "Giá trị cần kiểm tra", + "conditionRightPlaceholder": "So sánh với", + "variableName": "Tên biến", + "variableValue": "Giá trị", + "elevated": "Chạy với quyền sudo", + "onError": "Nếu điều này thất bại", + "allowPrivateNetwork": "Cho phép địa chỉ mạng cục bộ", + "allowPrivateNetworkHint": "Cần thiết cho dịch vụ tự lưu trữ trên mạng LAN của bạn. Mặc định là tắt để ngăn chặn các yêu cầu đến các địa chỉ nội bộ." + }, + "onError": { + "stop": "Dừng cuộc chạy", + "continue": "Tiếp tục" + } + } + } + }, + "nav": { + "automations": "Tự động hóa" + }, + "onboarding": { + "feature_automations": "Tự động hóa", + "feature_automations_desc": "Thực hiện các bước tự động khi có sự kiện xảy ra và nhận thông báo." + } +} diff --git a/plugins/automations/locales/translated/zh_CN.json b/plugins/automations/locales/translated/zh_CN.json new file mode 100644 index 000000000..f634ce3ce --- /dev/null +++ b/plugins/automations/locales/translated/zh_CN.json @@ -0,0 +1,149 @@ +{ + "newUi": { + "sidebar": { + "automations": { + "title": "自动化", + "tabAutomations": "自动化", + "tabRuns": "运行记录", + "tabChannels": "频道", + "createAutomation": "新自动化", + "backToAutomations": "返回自动化页面", + "createTitle": "新自动化", + "editTitle": "编辑自动化", + "empty": "尚未设置任何自动化流程。请创建一个自动化流程,使其能够根据指标、日程安排或事件做出反应。", + "emptyRuns": "暂无运行记录。", + "emptyChannels": "暂无频道。添加一个频道以便向某个地方发送通知。", + "noChannelsHint": "尚未设置任何频道。请在“频道”标签页中添加频道。", + "addChannel": "添加频道", + "testChannel": "测试", + "channelTestSent": "已发送测试通知", + "channelTestFailed": "测试通知失败", + "channelDeleted": "频道已删除", + "deleteChannelConfirm": "删除此频道?使用该频道的自动化功能将停止通知。", + "nameLabel": "名称", + "namePlaceholder": "例如,当 /data 目录填满时进行清理。", + "nameRequired": "名称为必填项", + "descriptionLabel": "描述", + "descriptionPlaceholder": "可选描述", + "enabledLabel": "已启用", + "concurrencyLabel": "如果它已经在运行", + "concurrencyHint": "如果在上次运行结束前再次触发此问题,该怎么办?", + "concurrency": { + "skip": "跳过新一轮", + "queue": "稍等会再运行", + "allow": "同时运行这两个程序" + }, + "save": "保存", + "created": "自动化已创建", + "updated": "自动化已保存", + "deleted": "自动化已删除", + "deleteConfirm": "删除此自动化流程?其运行历史记录也会被删除。", + "runNow": "立即运行", + "testRun": "测试运行", + "testRunHint": "执行所有步骤,但不触及 Termix 之外的任何内容。", + "runStarted": "运行已启动", + "runFinished": "运行结束: {{status}}", + "trigger": "触发器", + "steps": "步骤", + "addStep": "添加步骤", + "removeStep": "移除步骤", + "moveUp": "向上", + "moveDown": "向下", + "noSteps": "暂无步骤。请添加步骤说明应该发生什么。", + "webhookTokenTitle": "Webhook URL", + "webhookTokenDescription": "此信息仅显示一次。请立即保存,之后将无法调取。", + "copy": "复制", + "copied": "已复制", + "viewJson": "JSON", + "viewBuilder": "构建器", + "viewGraph": "图形", + "lastRun": "上次运行", + "never": "绝不", + "duration": "{{seconds}}s", + "stepOutput": "输出", + "stepError": "错误", + "dryRunBadge": "测试运行", + "hostSelector": { + "trigger": "触发主机", + "host": "特定主机", + "fleet": "舰队", + "all": "所有主机" + }, + "triggerKinds": { + "metric_threshold": "指标阈值", + "host_status": "主机上线或离线", + "health_check": "健康检查变化", + "schedule": "按计划", + "docker_event": "容器事件", + "internal_event": "Termix 事件", + "webhook": "传入的 webhook" + }, + "stepTypes": { + "notify": "发送通知", + "http": "调用 URL", + "run_snippet": "运行一段代码片段", + "run_command": "运行命令", + "docker": "控制容器", + "tunnel": "控制隧道", + "wol": "唤醒主机", + "wait": "等待", + "set_var": "设置变量", + "if": "如果/否则", + "run_automation": "运行另一个自动化程序", + "stop": "停止" + }, + "statuses": { + "running": "运行中", + "success": "成功", + "failed": "失败", + "timeout": "超时", + "skipped": "跳过", + "cancelled": "已取消" + }, + "fields": { + "host": "主机", + "metric": "指标", + "mount": "挂载点", + "operator": "是", + "value": "值", + "forSeconds": "持续(秒)", + "cooldown": "冷却时间(分钟)", + "cron": "Cron 表达式", + "intervalSeconds": "每隔(秒)", + "timezone": "时区", + "timezoneServer": "服务器时间", + "timezoneHint": "此区域读取 cron 任务的时间。不适用于间隔任务。", + "container": "容器", + "command": "命令", + "url": "URL", + "method": "方法", + "body": "请求体", + "channels": "频道", + "title": "标题", + "message": "消息", + "snippet": "片段", + "seconds": "秒", + "conditionLeftPlaceholder": "待检查的值", + "conditionRightPlaceholder": "与……比较", + "variableName": "变量名", + "variableValue": "值", + "elevated": "使用 sudo 运行", + "onError": "如果失败", + "allowPrivateNetwork": "允许本地网络地址", + "allowPrivateNetworkHint": "在局域网内运行自托管服务时需要此功能。默认情况下处于关闭状态,以防止向内部地址发送请求。" + }, + "onError": { + "stop": "停止运行", + "continue": "继续" + } + } + } + }, + "nav": { + "automations": "自动化" + }, + "onboarding": { + "feature_automations": "自动化", + "feature_automations_desc": "触发特定事件时自动执行任务,并接收通知。" + } +} diff --git a/plugins/automations/locales/translated/zh_TW.json b/plugins/automations/locales/translated/zh_TW.json new file mode 100644 index 000000000..7bc08c3d7 --- /dev/null +++ b/plugins/automations/locales/translated/zh_TW.json @@ -0,0 +1,149 @@ +{ + "newUi": { + "sidebar": { + "automations": { + "title": "自動化", + "tabAutomations": "自動化", + "tabRuns": "跑", + "tabChannels": "頻道", + "createAutomation": "新自動化", + "backToAutomations": "返回自動化頁面", + "createTitle": "新自動化", + "editTitle": "編輯自動化", + "empty": "尚未設定任何自動化流程。請建立一個自動化流程,使其能夠根據指標、日程安排或事件做出反應。", + "emptyRuns": "目前還沒有人運行。", + "emptyChannels": "暫無頻道。新增一個頻道以便向某個地方發送通知。", + "noChannelsHint": "尚未設定任何頻道。請在「頻道」標籤中新增頻道。", + "addChannel": "新增頻道", + "testChannel": "測試", + "channelTestSent": "已發送測試通知", + "channelTestFailed": "測試通知失敗", + "channelDeleted": "頻道已刪除", + "deleteChannelConfirm": "刪除此頻道?使用該頻道的自動化功能將停止通知。", + "nameLabel": "姓名", + "namePlaceholder": "例如,當 /data 目錄填滿時進行清理。", + "nameRequired": "姓名(必填)", + "descriptionLabel": "描述", + "descriptionPlaceholder": "選用描述", + "enabledLabel": "已啟用", + "concurrencyLabel": "如果它已經在運行", + "concurrencyHint": "如果在上次運行結束前再次觸發此問題,該怎麼辦?", + "concurrency": { + "skip": "跳過新一輪", + "queue": "等待並追趕", + "allow": "同時運行這兩個程序" + }, + "save": "節省", + "created": "自動化創建", + "updated": "自動化保存", + "deleted": "自動化刪除", + "deleteConfirm": "刪除此自動化流程?其運行歷史記錄也會被刪除。", + "runNow": "立即運行", + "testRun": "測試運行", + "testRunHint": "執行所有步驟,但不觸及 Termix 以外的任何內容。", + "runStarted": "運行已啟動", + "runFinished": "運轉結束: {{status}}", + "trigger": "扳機", + "steps": "步驟", + "addStep": "新增步驟", + "removeStep": "移除步驟", + "moveUp": "向上", + "moveDown": "向下", + "noSteps": "暫無步驟。請加入步驟說明應該發生什麼。", + "webhookTokenTitle": "Webhook URL", + "webhookTokenDescription": "此資訊僅顯示一次。請立即儲存,之後將無法調取。", + "copy": "複製", + "copied": "已複製", + "viewJson": "JSON", + "viewBuilder": "建造者", + "viewGraph": "圖形", + "lastRun": "最後一次運行", + "never": "絕不", + "duration": "{{seconds}}s", + "stepOutput": "輸出", + "stepError": "錯誤", + "dryRunBadge": "測試運行", + "hostSelector": { + "trigger": "觸發主機", + "host": "特定主機", + "fleet": "艦隊", + "all": "所有主持人" + }, + "triggerKinds": { + "metric_threshold": "指標閾值", + "host_status": "主機升溫或降溫", + "health_check": "健康檢查變化", + "schedule": "按計劃", + "docker_event": "容器事件", + "internal_event": "Termix 活動", + "webhook": "傳入的 webhook" + }, + "stepTypes": { + "notify": "發送通知", + "http": "呼叫 URL", + "run_snippet": "運行一段程式碼片段", + "run_command": "運行命令", + "docker": "控制容器", + "tunnel": "控制隧道", + "wol": "喚醒主機", + "wait": "等待", + "set_var": "設定變數", + "if": "如果/否則", + "run_automation": "執行另一個自動化流程", + "stop": "停止" + }, + "statuses": { + "running": "跑步", + "success": "成功", + "failed": "失敗的", + "timeout": "超時", + "skipped": "跳過", + "cancelled": "取消" + }, + "fields": { + "host": "主持人", + "metric": "指標", + "mount": "登山點", + "operator": "是", + "value": "價值", + "forSeconds": "持續(秒)", + "cooldown": "冷卻時間(分鐘)", + "cron": "複製表達式", + "intervalSeconds": "每隔(秒)", + "timezone": "時區", + "timezoneServer": "伺服器時間", + "timezoneHint": "此區域讀取 cron 任務的時間。不適用於間隔任務。", + "container": "容器", + "command": "命令", + "url": "URL", + "method": "方法", + "body": "身體", + "channels": "頻道", + "title": "標題", + "message": "訊息", + "snippet": "片段", + "seconds": "秒", + "conditionLeftPlaceholder": "待檢查的數值", + "conditionRightPlaceholder": "與…比較", + "variableName": "變數名", + "variableValue": "價值", + "elevated": "使用 sudo 運行", + "onError": "如果失敗", + "allowPrivateNetwork": "允許本地網路位址", + "allowPrivateNetworkHint": "在區域網路內執行自託管服務時需要此功能。預設為關閉狀態,以防止向內部位址發送請求。" + }, + "onError": { + "stop": "停止奔跑", + "continue": "繼續" + } + } + } + }, + "nav": { + "automations": "自動化" + }, + "onboarding": { + "feature_automations": "自動化", + "feature_automations_desc": "當發生某些事情時,自動運行步驟並接收通知。" + } +} diff --git a/plugins/automations/manifest.json b/plugins/automations/manifest.json index b972a6602..0451d5a37 100644 --- a/plugins/automations/manifest.json +++ b/plugins/automations/manifest.json @@ -27,6 +27,14 @@ "ui:surface" ], "contributes": { + "tabs": [ + { + "id": "automations", + "titleKey": "nav.automations", + "icon": "Workflow", + "openFrom": ["rail"] + } + ], "permissions": [ { "name": "view", diff --git a/plugins/automations/src/frontend/AutomationsPanel.tsx b/plugins/automations/src/frontend/AutomationsPanel.tsx index bb4d7d48b..ce5a315ef 100644 --- a/plugins/automations/src/frontend/AutomationsPanel.tsx +++ b/plugins/automations/src/frontend/AutomationsPanel.tsx @@ -1,6 +1,6 @@ import { getErrorMessage } from "@/lib/error-message.js"; import { useCallback, useEffect, useState } from "react"; -import { useTranslation } from "react-i18next"; +import { useTranslation } from "@termix/plugin-sdk/frontend"; import { toast } from "sonner"; import { ArrowLeft, @@ -35,7 +35,8 @@ import { import { NotificationChannelDialog } from "@/sidebar/NotificationChannelDialog"; import { getSnippets } from "@/api/snippets-api"; import { getSSHHosts } from "@/api/ssh-host-management-api"; -import { listFleets } from "@/api/fleets-api"; +import { invokeAction } from "@termix/plugin-sdk/frontend"; + import { AutomationEditor, emptyDraft, @@ -70,6 +71,14 @@ function timeAgo(iso: string | null): string { return `${Math.floor(hr / 24)}d ago`; } +/** Fleets from the fleets plugin, or none when it is not running. */ +async function listFleets(): Promise<{ id: number; name: string }[]> { + const result = await invokeAction("fleets.list"); + return Array.isArray(result) + ? (result as { id: number; name: string }[]) + : []; +} + export function AutomationsPanel({ active = true, onEditingChange, diff --git a/plugins/automations/src/frontend/automations/AutomationEditor.tsx b/plugins/automations/src/frontend/automations/AutomationEditor.tsx index d6715adde..b2bb53669 100644 --- a/plugins/automations/src/frontend/automations/AutomationEditor.tsx +++ b/plugins/automations/src/frontend/automations/AutomationEditor.tsx @@ -1,6 +1,6 @@ import { getErrorMessage } from "@/lib/error-message.js"; import { useState } from "react"; -import { useTranslation } from "react-i18next"; +import { useTranslation } from "@termix/plugin-sdk/frontend"; import { Plus } from "lucide-react"; import { Button } from "@/components/button"; import { Input } from "@/components/input"; diff --git a/plugins/automations/src/frontend/automations/HostSelectorField.tsx b/plugins/automations/src/frontend/automations/HostSelectorField.tsx index bd2814441..f40bd4abe 100644 --- a/plugins/automations/src/frontend/automations/HostSelectorField.tsx +++ b/plugins/automations/src/frontend/automations/HostSelectorField.tsx @@ -1,4 +1,4 @@ -import { useTranslation } from "react-i18next"; +import { useTranslation } from "@termix/plugin-sdk/frontend"; import { Label } from "@/components/label"; import { Select, diff --git a/plugins/automations/src/frontend/automations/StepBlock.tsx b/plugins/automations/src/frontend/automations/StepBlock.tsx index 923f149b0..abe35a097 100644 --- a/plugins/automations/src/frontend/automations/StepBlock.tsx +++ b/plugins/automations/src/frontend/automations/StepBlock.tsx @@ -1,4 +1,4 @@ -import { useTranslation } from "react-i18next"; +import { useTranslation } from "@termix/plugin-sdk/frontend"; import { ChevronDown, ChevronUp, Trash2 } from "lucide-react"; import { Button } from "@/components/button"; import { Input } from "@/components/input"; diff --git a/plugins/automations/src/frontend/automations/TriggerCard.tsx b/plugins/automations/src/frontend/automations/TriggerCard.tsx index bbaa558ab..ef5c285a8 100644 --- a/plugins/automations/src/frontend/automations/TriggerCard.tsx +++ b/plugins/automations/src/frontend/automations/TriggerCard.tsx @@ -1,4 +1,4 @@ -import { useTranslation } from "react-i18next"; +import { useTranslation } from "@termix/plugin-sdk/frontend"; import { Input } from "@/components/input"; import { Label } from "@/components/label"; import { diff --git a/plugins/automations/src/frontend/index.mjs b/plugins/automations/src/frontend/index.mjs deleted file mode 100644 index a80d84ba7..000000000 --- a/plugins/automations/src/frontend/index.mjs +++ /dev/null @@ -1,36 +0,0 @@ -/** - * Frontend half of the automations plugin. - * - * AutomationsPanel is a left-sidebar railView panel (opened from the rail, - * not a Tab), the same shape as FleetsPanel/HostsPanel/AiPanel. None of those - * go through registerRailItem/registerTabComponent either -- per - * src/ui/shell/pluginLoader.ts's own comment, a rail-view panel like this is - * rendered directly by AppShell.tsx rather than registered at runtime, the - * same way ai's AiPanel is. AutomationsPanel is reached today through a - * direct relative import in AppShell.tsx - * (../../plugins/automations/frontend/AutomationsPanel) and in - * src/ui/shell/tabUtils.tsx (for its promotable/dockable tab surface), not - * through register() below. - * - * register()/unregister() still follow the same shape every other plugin's - * frontend entry does, so this is ready the moment a real frontend plugin - * loader exists -- see plugins/ssh-terminal/frontend/index.mjs and - * src/ui/tests/sidebar/plugin-extension-seam.test.tsx, which says outright - * "there is no plugin loader yet". - */ - -export const id = "automations"; -export const railViewId = "automations"; - -export async function register({ registerRailItem, icons }) { - registerRailItem?.({ - id: railViewId, - icon: icons.Workflow, - labelKey: "nav.automations", - separatorAfter: true, - }); -} - -export async function unregister({ unregisterRailItem }) { - unregisterRailItem?.(railViewId); -} diff --git a/plugins/automations/src/frontend/index.tsx b/plugins/automations/src/frontend/index.tsx new file mode 100644 index 000000000..7e6181c63 --- /dev/null +++ b/plugins/automations/src/frontend/index.tsx @@ -0,0 +1,51 @@ +import { Workflow } from "lucide-react"; +import type { + PanelProps, + TabProps, + TermixApp, +} from "@termix/plugin-sdk/frontend"; +import { AutomationsPanel } from "./AutomationsPanel"; +import { listAutomations } from "./automations-api"; + +const VIEW_ID = "automations"; + +function Panel({ active, setEditing }: PanelProps) { + return ( +
+ +
+ ); +} + +function AutomationsTab({ isVisible }: TabProps) { + return ; +} + +export function activate(app: TermixApp): void { + app.registerRailItem({ + id: VIEW_ID, + icon: Workflow, + titleKey: "nav.automations", + promotable: true, + after: "macros", + order: 30, + }); + app.registerPanel(VIEW_ID, Panel); + app.registerTab(VIEW_ID, AutomationsTab, { + icon: Workflow, + titleKey: "nav.automations", + singleton: true, + hostless: true, + panelFrame: true, + }); + + // The assistant's @-mentions list automations through this. + app.registerAction("automations.list", () => listAutomations()); + + app.registerSlotContribution("onboarding.features", { + actionId: "automations.feature", + titleKey: "onboarding.feature_automations", + descriptionKey: "onboarding.feature_automations_desc", + icon: Workflow, + }); +} diff --git a/plugins/automations/tests/frontend/activate.test.tsx b/plugins/automations/tests/frontend/activate.test.tsx new file mode 100644 index 000000000..814097280 --- /dev/null +++ b/plugins/automations/tests/frontend/activate.test.tsx @@ -0,0 +1,53 @@ +import { afterEach, describe, expect, it } from "vitest"; +import { + renderWithApp, + type RenderedPluginApp, +} from "@termix/plugin-sdk/testing"; +import type { PluginManifest } from "@termix/plugin-sdk/manifest"; +import * as plugin from "../../src/frontend/index"; +import manifestJson from "../../manifest.json"; +import locales from "../../locales/en.json"; + +const manifest = manifestJson as unknown as PluginManifest; + +const declared = (views?: Array<{ id: string }>) => + (views ?? []).map((view) => view.id).sort(); + +let rendered: RenderedPluginApp | null = null; + +afterEach(async () => { + await rendered?.deactivate(); + rendered = null; +}); + +describe(`${manifest.id} activate`, () => { + it("activates and registers only views its manifest declares", async () => { + rendered = await renderWithApp(plugin, { manifest, locales }); + const contributes = manifest.contributes as unknown as Record< + string, + Array<{ id: string }> | undefined + >; + const tabs = declared(contributes.tabs); + // A rail panel may reuse one of the plugin's tab ids. + const panels = [...declared(contributes.panels), ...tabs]; + const cards = declared(contributes.dashboardCards); + for (const id of rendered.registered.tabs()) expect(tabs).toContain(id); + for (const id of rendered.registered.panels()) expect(panels).toContain(id); + for (const id of rendered.registered.dashboardCards()) { + expect(cards).toContain(id); + } + }); + + it("removes everything it registered on deactivate", async () => { + const app = await renderWithApp(plugin, { manifest, locales }); + await app.deactivate(); + expect(app.registered.tabs()).toEqual([]); + expect(app.registered.panels()).toEqual([]); + expect(app.registered.railItems()).toEqual([]); + expect(app.registered.hostActions()).toEqual([]); + expect(app.registered.hostEditorSections()).toEqual([]); + expect(app.registered.dashboardCards()).toEqual([]); + expect(app.registered.settingsComponents()).toEqual([]); + expect(app.registered.actions()).toEqual([]); + }); +}); diff --git a/plugins/docker/locales/en.json b/plugins/docker/locales/en.json index 0967ef424..20d720bea 100644 --- a/plugins/docker/locales/en.json +++ b/plugins/docker/locales/en.json @@ -1 +1,125 @@ -{} +{ + "docker": { + "notEnabled": "Docker is not enabled for this host", + "validating": "Validating Docker...", + "connecting": "Connecting...", + "error": "Error", + "version": "{{runtime}} {{version}}", + "connectionFailed": "Failed to connect to Docker", + "containerStarted": "Container {{name}} started", + "failedToStartContainer": "Failed to start container {{name}}", + "containerStopped": "Container {{name}} stopped", + "failedToStopContainer": "Failed to stop container {{name}}", + "containerRestarted": "Container {{name}} restarted", + "failedToRestartContainer": "Failed to restart container {{name}}", + "containerPaused": "Container {{name}} paused", + "containerUnpaused": "Container {{name}} unpaused", + "failedToTogglePauseContainer": "Failed to toggle pause state for container {{name}}", + "containerRemoved": "Container {{name}} removed", + "failedToRemoveContainer": "Failed to remove container {{name}}", + "image": "Image", + "ports": "Ports", + "noPorts": "No ports", + "start": "Start", + "stop": "Stop", + "status": "Status", + "actions": "Actions", + "cardView": "Card view", + "listView": "List view", + "confirmRemoveContainer": "Are you sure you want to remove the container '{{name}}'? This action cannot be undone.", + "runningContainerWarning": "Warning: This container is currently running. Removing it will stop the container first.", + "loadingContainers": "Loading containers...", + "manager": "Docker Manager", + "autoRefresh": "Auto Refresh", + "timestamps": "Timestamps", + "lines": "Lines", + "filterLogs": "Filter logs...", + "refresh": "Refresh", + "download": "Download", + "clear": "Clear", + "logsDownloaded": "Logs downloaded successfully", + "last50": "Last 50", + "last100": "Last 100", + "last500": "Last 500", + "last1000": "Last 1000", + "allLogs": "All Logs", + "noLogsMatching": "No logs matching \"{{query}}\"", + "noLogsAvailable": "No logs available", + "noContainersFound": "No containers found", + "noContainersFoundHint": "No Docker containers are available on this host", + "searchPlaceholder": "Search containers...", + "allStatuses": "All Statuses", + "stateRunning": "Running", + "statePaused": "Paused", + "stateExited": "Exited", + "stateRestarting": "Restarting", + "noContainersMatchFilters": "No containers match your filters", + "noContainersMatchFiltersHint": "Try adjusting your search or filter criteria", + "failedToFetchStats": "Failed to fetch container statistics", + "containerNotRunning": "Container not running", + "startContainerToViewStats": "Start the container to view statistics", + "loadingStats": "Loading statistics...", + "errorLoadingStats": "Error loading statistics", + "noStatsAvailable": "No statistics available", + "cpuUsage": "CPU Usage", + "current": "Current", + "memoryUsage": "Memory Usage", + "networkIo": "Network I/O", + "input": "Input", + "output": "Output", + "blockIo": "Block I/O", + "read": "Read", + "write": "Write", + "pids": "PIDs", + "containerInformation": "Container Information", + "name": "Name", + "id": "ID", + "state": "State", + "containerMustBeRunning": "Container must be running to access console", + "verificationCodePrompt": "Enter verification code", + "totpVerificationFailed": "TOTP verification failed. Please try again.", + "warpgateVerificationFailed": "Warpgate authentication failed. Please try again.", + "connectedTo": "Connected to {{containerName}}", + "disconnected": "Disconnected", + "consoleError": "Console error", + "errorMessage": "Error: {{message}}", + "failedToConnect": "Failed to connect to container", + "console": "Console", + "selectShell": "Select shell", + "bash": "Bash", + "sh": "sh", + "ash": "ash", + "connect": "Connect", + "disconnect": "Disconnect", + "notConnected": "Not connected", + "clickToConnect": "Click connect to start a shell session", + "connectingTo": "Connecting to {{containerName}}...", + "containerNotFound": "Container not found", + "backToList": "Back to List", + "logs": "Logs", + "stats": "Stats", + "consoleTab": "Console", + "startContainerToAccess": "Start the container to access the console", + "noHostSelected": "No host selected" + }, + "nav": { + "docker": "Docker" + }, + "hosts": { + "tabDocker": "Docker", + "dockerIntegration": "Docker Integration", + "enableDockerMonitor": "Enable Docker", + "enableDockerMonitorDesc": "Monitor and manage containers on this host via Docker", + "containerRuntime": "Container Runtime", + "containerRuntimeDesc": "Choose the CLI used for container management on this host", + "containerRuntimeDocker": "Docker", + "containerRuntimePodman": "Podman" + }, + "onboarding": { + "feature_docker": "Docker", + "feature_docker_desc": "See containers, read logs and watch stats on any host running Docker." + }, + "terminal": { + "retry": "Retry" + } +} diff --git a/plugins/docker/locales/translated/af_ZA.json b/plugins/docker/locales/translated/af_ZA.json new file mode 100644 index 000000000..7e8ee775a --- /dev/null +++ b/plugins/docker/locales/translated/af_ZA.json @@ -0,0 +1,116 @@ +{ + "docker": { + "notEnabled": "Docker is nie vir hierdie gasheer geaktiveer nie", + "validating": "Valideer Docker...", + "connecting": "Verbind...", + "error": "Fout", + "version": "{{runtime}} {{version}}", + "connectionFailed": "Kon nie aan Docker koppel nie", + "containerStarted": "Houer {{name}} het begin", + "failedToStartContainer": "Kon nie houer {{name}} begin nie", + "containerStopped": "Houer {{name}} gestop", + "failedToStopContainer": "Kon nie houer {{name}} stop nie", + "containerRestarted": "Houer {{name}} herbegin", + "failedToRestartContainer": "Kon nie houer {{name}} herbegin nie", + "containerPaused": "Houer {{name}} gepouseer", + "containerUnpaused": "Houer {{name}} ontpoos", + "failedToTogglePauseContainer": "Kon nie pousestatus vir houer {{name}} wissel nie", + "containerRemoved": "Houer {{name}} is verwyder", + "failedToRemoveContainer": "Kon nie houer {{name}} verwyder nie", + "image": "Beeld", + "ports": "Hawens", + "noPorts": "Geen poorte nie", + "start": "Begin", + "confirmRemoveContainer": "Is jy seker jy wil die houer '{{name}}' verwyder? Hierdie aksie kan nie ongedaan gemaak word nie.", + "runningContainerWarning": "Waarskuwing: Hierdie houer loop tans. As dit verwyder word, sal die houer eers gestop word.", + "loadingContainers": "Laai houers...", + "manager": "Docker Bestuurder", + "autoRefresh": "Outomatiese Herlaai", + "timestamps": "Tydstempels", + "lines": "Lyne", + "filterLogs": "Filtreer logboeke...", + "refresh": "Verfris", + "download": "Laai af", + "clear": "Duidelik", + "logsDownloaded": "Logboeke suksesvol afgelaai", + "last50": "Laaste 50", + "last100": "Laaste 100", + "last500": "Laaste 500", + "last1000": "Laaste 1000", + "allLogs": "Alle logboeke", + "noLogsMatching": "Geen logboeke wat ooreenstem met \"{{query}}\"", + "noLogsAvailable": "Geen logboeke beskikbaar nie", + "noContainersFound": "Geen houers gevind nie", + "noContainersFoundHint": "Geen Docker-houers is op hierdie gasheer beskikbaar nie", + "searchPlaceholder": "Soek houers...", + "allStatuses": "Alle statusse", + "stateRunning": "Hardloop", + "statePaused": "Onderbreek", + "stateExited": "Uitgegaan", + "stateRestarting": "Herbegin", + "noContainersMatchFilters": "Geen houers stem ooreen met jou filters nie", + "noContainersMatchFiltersHint": "Probeer om jou soek- of filterkriteria aan te pas", + "failedToFetchStats": "Kon nie houerstatistieke haal nie", + "containerNotRunning": "Houer loop nie", + "startContainerToViewStats": "Begin die houer om statistieke te sien", + "loadingStats": "Laai statistieke...", + "errorLoadingStats": "Fout by die laai van statistieke", + "noStatsAvailable": "Geen statistieke beskikbaar nie", + "cpuUsage": "SVE-gebruik", + "current": "Huidige", + "memoryUsage": "Geheuegebruik", + "networkIo": "Netwerk I/O", + "input": "Invoer", + "output": "Uitset", + "blockIo": "Blok I/O", + "read": "Lees", + "write": "Skryf", + "pids": "PID's", + "containerInformation": "Houerinligting", + "name": "Naam", + "id": "ID", + "state": "Staat", + "containerMustBeRunning": "Die houer moet loop om toegang tot die konsole te verkry", + "verificationCodePrompt": "Voer verifikasiekode in", + "totpVerificationFailed": "TOTP-verifikasie het misluk. Probeer asseblief weer.", + "warpgateVerificationFailed": "Warpgate-verifikasie het misluk. Probeer asseblief weer.", + "connectedTo": "Gekoppel aan {{containerName}}", + "disconnected": "Ontkoppel", + "consoleError": "Konsolefout", + "errorMessage": "Fout: {{message}}", + "failedToConnect": "Kon nie aan houer koppel nie", + "console": "Konsole", + "selectShell": "Kies dop", + "bash": "Bash", + "sh": "sj", + "ash": "as", + "connect": "Verbind", + "disconnect": "Ontkoppel", + "notConnected": "Nie gekoppel nie", + "clickToConnect": "Klik verbind om 'n dopsessie te begin", + "connectingTo": "Verbind met {{containerName}}...", + "containerNotFound": "Houer nie gevind nie", + "backToList": "Terug na lys", + "logs": "Logboeke", + "stats": "Statistiek", + "consoleTab": "Konsole", + "startContainerToAccess": "Begin die houer om toegang tot die konsole te verkry" + }, + "nav": { + "docker": "Docker" + }, + "hosts": { + "tabDocker": "Docker", + "dockerIntegration": "Docker-integrasie", + "enableDockerMonitor": "Aktiveer Docker", + "enableDockerMonitorDesc": "Monitor en bestuur houers op hierdie gasheer via Docker", + "containerRuntime": "Houerlooptyd", + "containerRuntimeDesc": "Kies die CLI wat vir houerbestuur op hierdie gasheer gebruik word", + "containerRuntimeDocker": "Docker", + "containerRuntimePodman": "Podman" + }, + "onboarding": { + "feature_docker": "Docker", + "feature_docker_desc": "Sien houers, lees logs en kyk na statistieke op enige gasheer wat Docker gebruik." + } +} diff --git a/plugins/docker/locales/translated/ar_SA.json b/plugins/docker/locales/translated/ar_SA.json new file mode 100644 index 000000000..a6d11fee5 --- /dev/null +++ b/plugins/docker/locales/translated/ar_SA.json @@ -0,0 +1,116 @@ +{ + "docker": { + "notEnabled": "Docker غير مفعّل لهذا المضيف", + "validating": "جارٍ التحقق من Docker...", + "connecting": "جارٍ الاتصال...", + "error": "خطأ", + "version": "{{runtime}} {{version}}", + "connectionFailed": "فشل الاتصال بـ Docker", + "containerStarted": "بدأت الحاوية {{name}}", + "failedToStartContainer": "فشل تشغيل الحاوية {{name}}", + "containerStopped": "توقفت الحاوية {{name}}", + "failedToStopContainer": "فشل إيقاف الحاوية {{name}}", + "containerRestarted": "أعيد تشغيل الحاوية {{name}}", + "failedToRestartContainer": "فشل إعادة تشغيل الحاوية {{name}}", + "containerPaused": "تم إيقاف الحاوية {{name}} مؤقتاً", + "containerUnpaused": "تم استئناف الحاوية {{name}}", + "failedToTogglePauseContainer": "فشل تبديل حالة الإيقاف المؤقت للحاوية {{name}}", + "containerRemoved": "تمت إزالة الحاوية {{name}}", + "failedToRemoveContainer": "فشلت إزالة الحاوية {{name}}", + "image": "صورة", + "ports": "منافذ", + "noPorts": "لا توجد منافذ", + "start": "ابدأ", + "confirmRemoveContainer": "هل أنت متأكد من رغبتك في إزالة الحاوية '{{name}}'؟ لا يمكن التراجع عن هذا الإجراء.", + "runningContainerWarning": "تحذير: هذه الحاوية قيد التشغيل حالياً. ستؤدي إزالتها إلى إيقافها أولاً.", + "loadingContainers": "جارٍ تحميل الحاويات...", + "manager": "مدير Docker", + "autoRefresh": "تحديث تلقائي", + "timestamps": "الطوابع الزمنية", + "lines": "الأسطر", + "filterLogs": "تصفية السجلات...", + "refresh": "تحديث", + "download": "تنزيل", + "clear": "مسح", + "logsDownloaded": "تم تنزيل السجلات بنجاح", + "last50": "آخر 50", + "last100": "آخر 100", + "last500": "آخر 500", + "last1000": "آخر 1000", + "allLogs": "كل السجلات", + "noLogsMatching": "لا توجد سجلات تطابق \"{{query}}\"", + "noLogsAvailable": "لا توجد سجلات متاحة", + "noContainersFound": "لا توجد حاويات", + "noContainersFoundHint": "لا توجد حاويات Docker متاحة على هذا المضيف", + "searchPlaceholder": "البحث عن حاويات...", + "allStatuses": "جميع الحالات", + "stateRunning": "قيد التشغيل", + "statePaused": "معلق", + "stateExited": "متوقف", + "stateRestarting": "إعادة التشغيل", + "noContainersMatchFilters": "لا توجد حاويات تطابق عوامل التصفية الخاصة بك", + "noContainersMatchFiltersHint": "جرّب تعديل معايير البحث أو التصفية", + "failedToFetchStats": "فشل جلب إحصائيات الحاوية", + "containerNotRunning": "الحاوية غير قيد التشغيل", + "startContainerToViewStats": "ابدأ الحاوية لعرض الإحصائيات", + "loadingStats": "جارٍ تحميل الإحصائيات...", + "errorLoadingStats": "خطأ في تحميل الإحصائيات", + "noStatsAvailable": "لا توجد إحصائيات متاحة", + "cpuUsage": "استخدام CPU", + "current": "الحالي", + "memoryUsage": "استخدام الذاكرة", + "networkIo": "الإدخال/الإخراج للشبكة", + "input": "إدخال", + "output": "المخرجات", + "blockIo": "الإدخال/الإخراج الكتلي", + "read": "قراءة", + "write": "كتابة", + "pids": "PIDs", + "containerInformation": "معلومات الحاوية", + "name": "الاسم", + "id": "المعرف", + "state": "الحالة", + "containerMustBeRunning": "يجب أن تكون الحاوية قيد التشغيل للوصول إلى وحدة التحكم", + "verificationCodePrompt": "أدخل رمز التحقق", + "totpVerificationFailed": "فشل التحقق من TOTP. يرجى المحاولة مرة أخرى.", + "warpgateVerificationFailed": "فشلت مصادقة Warpgate. يرجى المحاولة مرة أخرى.", + "connectedTo": "متصل بـ {{containerName}}", + "disconnected": "تم قطع الاتصال", + "consoleError": "خطأ في وحدة التحكم", + "errorMessage": "خطأ: {{message}}", + "failedToConnect": "فشل الاتصال بالحاوية", + "console": "وحدة التحكم", + "selectShell": "اختر الصدفة", + "bash": "Bash", + "sh": "sh", + "ash": "ash", + "connect": "اتصل", + "disconnect": "قطع الاتصال", + "notConnected": "غير متصل", + "clickToConnect": "انقر فوق 'اتصل' لبدء جلسة صدفة", + "connectingTo": "جارٍ الاتصال بـ {{containerName}}...", + "containerNotFound": "الحاوية غير موجودة", + "backToList": "عودة إلى القائمة", + "logs": "السجلات", + "stats": "الإحصائيات", + "consoleTab": "وحدة التحكم", + "startContainerToAccess": "ابدأ تشغيل الحاوية للوصول إلى وحدة التحكم" + }, + "nav": { + "docker": "Docker" + }, + "hosts": { + "tabDocker": "Docker", + "dockerIntegration": "تكامل Docker", + "enableDockerMonitor": "تمكين Docker", + "enableDockerMonitorDesc": "مراقبة وإدارة الحاويات على هذا المضيف عبر Docker", + "containerRuntime": "بيئة تشغيل الحاويات", + "containerRuntimeDesc": "اختر واجهة سطر الأوامر المستخدمة لإدارة الحاويات على هذا المضيف", + "containerRuntimeDocker": "Docker", + "containerRuntimePodman": "Podman" + }, + "onboarding": { + "feature_docker": "عامل ميناء", + "feature_docker_desc": "اطلع على الحاويات، واقرأ السجلات، وراقب الإحصائيات على أي مضيف يعمل بنظام Docker." + } +} diff --git a/plugins/docker/locales/translated/bg_BG.json b/plugins/docker/locales/translated/bg_BG.json new file mode 100644 index 000000000..a06fdfbf7 --- /dev/null +++ b/plugins/docker/locales/translated/bg_BG.json @@ -0,0 +1,116 @@ +{ + "docker": { + "notEnabled": "Docker не е активиран за този хост", + "validating": "Валидиране на Docker...", + "connecting": "Свързване...", + "error": "Грешка", + "version": "{{runtime}} {{version}}", + "connectionFailed": "Неуспешно свързване с Docker", + "containerStarted": "Контейнерът {{name}} е стартиран", + "failedToStartContainer": "Неуспешно стартиране на контейнера {{name}}", + "containerStopped": "Контейнерът {{name}} е спрян", + "failedToStopContainer": "Неуспешно спиране на контейнера {{name}}", + "containerRestarted": "Контейнерът {{name}} е рестартиран", + "failedToRestartContainer": "Рестартирането на контейнера не бе успешно {{name}}", + "containerPaused": "Контейнерът {{name}} е на пауза", + "containerUnpaused": "Контейнерът {{name}} е възстановен", + "failedToTogglePauseContainer": "Неуспешно превключване на състоянието на пауза за контейнер {{name}}", + "containerRemoved": "Контейнерът {{name}} е премахнат", + "failedToRemoveContainer": "Неуспешно премахване на контейнера {{name}}", + "image": "Изображение", + "ports": "Портове", + "noPorts": "Няма портове", + "start": "Старт", + "confirmRemoveContainer": "Сигурни ли сте, че искате да премахнете контейнера „{{name}}“? Това действие не може да бъде отменено.", + "runningContainerWarning": "Предупреждение: Този контейнер в момента работи. Премахването му първо ще спре контейнера.", + "loadingContainers": "Зареждане на контейнери...", + "manager": "Докер мениджър", + "autoRefresh": "Автоматично опресняване", + "timestamps": "Времеви печати", + "lines": "Линии", + "filterLogs": "Филтриране на лог файлове...", + "refresh": "Обновяване", + "download": "Изтегляне", + "clear": "Изчисти", + "logsDownloaded": "Дневниците са изтеглени успешно", + "last50": "Последните 50", + "last100": "Последните 100", + "last500": "Последните 500", + "last1000": "Последни 1000", + "allLogs": "Всички лог файлове", + "noLogsMatching": "Няма регистрационни файлове, съответстващи на „{{query}}“", + "noLogsAvailable": "Няма налични лог файлове", + "noContainersFound": "Не са намерени контейнери", + "noContainersFoundHint": "На този хост няма налични Docker контейнери", + "searchPlaceholder": "Търсене на контейнери...", + "allStatuses": "Всички статуси", + "stateRunning": "Бягане", + "statePaused": "Пауза", + "stateExited": "Изход", + "stateRestarting": "Рестартиране", + "noContainersMatchFilters": "Няма контейнери, които да отговарят на вашите филтри", + "noContainersMatchFiltersHint": "Опитайте да коригирате критериите си за търсене или филтриране", + "failedToFetchStats": "Извличането на статистически данни за контейнера не бе успешно", + "containerNotRunning": "Контейнерът не работи", + "startContainerToViewStats": "Стартирайте контейнера, за да видите статистиката", + "loadingStats": "Зареждане на статистика...", + "errorLoadingStats": "Грешка при зареждане на статистиката", + "noStatsAvailable": "Няма налична статистика", + "cpuUsage": "Използване на процесора", + "current": "Текущ", + "memoryUsage": "Използване на паметта", + "networkIo": "Мрежов вход/изход", + "input": "Вход", + "output": "Изход", + "blockIo": "Блокиране на входно/изходни данни", + "read": "Прочетете", + "write": "Пишете", + "pids": "PID-ове", + "containerInformation": "Информация за контейнера", + "name": "Име", + "id": "Идентификационен номер", + "state": "Щат", + "containerMustBeRunning": "Контейнерът трябва да е работещ, за да има достъп до конзолата", + "verificationCodePrompt": "Въведете код за потвърждение", + "totpVerificationFailed": "Проверката на TOTP не бе успешна. Моля, опитайте отново.", + "warpgateVerificationFailed": "Удостоверяването на Warpgate не бе успешно. Моля, опитайте отново.", + "connectedTo": "Свързано с {{containerName}}", + "disconnected": "Изключен", + "consoleError": "Грешка в конзолата", + "errorMessage": "Грешка: {{message}}", + "failedToConnect": "Неуспешно свързване с контейнера", + "console": "Конзола", + "selectShell": "Изберете черупка", + "bash": "Баш", + "sh": "ш", + "ash": "пепел", + "connect": "Свържете се", + "disconnect": "Изключване", + "notConnected": "Няма връзка", + "clickToConnect": "Щракнете върху „Свързване“, за да стартирате сесия на shell", + "connectingTo": "Свързване към {{containerName}}...", + "containerNotFound": "Контейнерът не е намерен", + "backToList": "Обратно към списъка", + "logs": "Дневници", + "stats": "Статистика", + "consoleTab": "Конзола", + "startContainerToAccess": "Стартирайте контейнера, за да получите достъп до конзолата" + }, + "nav": { + "docker": "Докер" + }, + "hosts": { + "tabDocker": "Докер", + "dockerIntegration": "Интеграция на Docker", + "enableDockerMonitor": "Активиране на Докер", + "enableDockerMonitorDesc": "Наблюдавайте и управлявайте контейнери на този хост чрез Docker", + "containerRuntime": "Изпълнение на контейнера", + "containerRuntimeDesc": "Изберете CLI, използван за управление на контейнери на този хост", + "containerRuntimeDocker": "Докер", + "containerRuntimePodman": "Подман" + }, + "onboarding": { + "feature_docker": "Докер", + "feature_docker_desc": "Вижте контейнери, прочетете лог файлове и наблюдавайте статистики на всеки хост, на който работи Docker." + } +} diff --git a/plugins/docker/locales/translated/bn_BD.json b/plugins/docker/locales/translated/bn_BD.json new file mode 100644 index 000000000..9901c6a32 --- /dev/null +++ b/plugins/docker/locales/translated/bn_BD.json @@ -0,0 +1,116 @@ +{ + "docker": { + "notEnabled": "এই হোস্টের জন্য ডকার সক্রিয় করা নেই।", + "validating": "ডকার যাচাই করা হচ্ছে...", + "connecting": "সংযোগ স্থাপন...", + "error": "ত্রুটি", + "version": "{{runtime}} {{version}}", + "connectionFailed": "ডকারের সাথে সংযোগ করতে ব্যর্থ হয়েছে", + "containerStarted": "কন্টেইনার {{name}} চালু হয়েছে", + "failedToStartContainer": "{{name}} কন্টেইনারটি শুরু করতে ব্যর্থ হয়েছে", + "containerStopped": "কন্টেইনার {{name}} থেমে গেছে", + "failedToStopContainer": "কন্টেইনার বন্ধ করতে ব্যর্থ {{name}}", + "containerRestarted": "কন্টেইনার {{name}} পুনরায় চালু হয়েছে", + "failedToRestartContainer": "কন্টেইনার পুনরায় চালু করতে ব্যর্থ {{name}}", + "containerPaused": "কন্টেইনার {{name}} থামানো হয়েছে", + "containerUnpaused": "কন্টেইনার {{name}} বিরতিহীন", + "failedToTogglePauseContainer": "কন্টেইনার {{name}} এর জন্য বিরতি অবস্থা টগল করতে ব্যর্থ হয়েছে", + "containerRemoved": "কন্টেইনার {{name}} সরানো হয়েছে", + "failedToRemoveContainer": "কন্টেইনার অপসারণ করা সম্ভব হয়নি {{name}}", + "image": "ছবি", + "ports": "বন্দর", + "noPorts": "কোন পোর্ট নেই", + "start": "শুরু করুন", + "confirmRemoveContainer": "আপনি কি '{{name}}' কন্টেইনারটি সরাতে নিশ্চিত? এই কাজটি পূর্বাবস্থায় ফেরানো যাবে না।", + "runningContainerWarning": "সতর্কীকরণ: এই কন্টেইনারটি বর্তমানে চালু আছে। এটি অপসারণ করলে প্রথমে কন্টেইনারটি বন্ধ হবে।", + "loadingContainers": "কন্টেইনার লোড করা হচ্ছে...", + "manager": "ডকার ম্যানেজার", + "autoRefresh": "স্বয়ংক্রিয় রিফ্রেশ", + "timestamps": "টাইমস্ট্যাম্প", + "lines": "লাইন", + "filterLogs": "লগ ফিল্টার করুন...", + "refresh": "রিফ্রেশ", + "download": "ডাউনলোড করুন", + "clear": "পরিষ্কার", + "logsDownloaded": "লগগুলি সফলভাবে ডাউনলোড করা হয়েছে।", + "last50": "শেষ ৫০", + "last100": "শেষ ১০০", + "last500": "শেষ ৫০০", + "last1000": "শেষ ১০০০", + "allLogs": "সমস্ত লগ", + "noLogsMatching": "\"{{query}} \" এর সাথে মেলে এমন কোনও লগ নেই", + "noLogsAvailable": "কোন লগ উপলব্ধ নেই", + "noContainersFound": "কোন কন্টেইনার পাওয়া যায়নি", + "noContainersFoundHint": "এই হোস্টে কোনো ডকার কন্টেইনার উপলব্ধ নেই।", + "searchPlaceholder": "কন্টেইনারগুলি অনুসন্ধান করুন...", + "allStatuses": "সমস্ত স্ট্যাটাস", + "stateRunning": "দৌড়ানো", + "statePaused": "বিরতি দেওয়া হয়েছে", + "stateExited": "উত্তেজিত", + "stateRestarting": "পুনরায় চালু করা", + "noContainersMatchFilters": "আপনার ফিল্টারগুলির সাথে কোনও কন্টেইনার মেলে না", + "noContainersMatchFiltersHint": "আপনার অনুসন্ধান বা ফিল্টারের শর্তাবলী পরিবর্তন করে দেখুন।", + "failedToFetchStats": "কন্টেইনার পরিসংখ্যান আনতে ব্যর্থ হয়েছে", + "containerNotRunning": "কন্টেইনারটি চলছে না", + "startContainerToViewStats": "পরিসংখ্যান দেখতে কন্টেইনারটি চালু করুন।", + "loadingStats": "পরিসংখ্যান লোড হচ্ছে...", + "errorLoadingStats": "পরিসংখ্যান লোড করতে ত্রুটি", + "noStatsAvailable": "কোন পরিসংখ্যান উপলব্ধ নেই", + "cpuUsage": "সিপিইউ ব্যবহার", + "current": "বর্তমান", + "memoryUsage": "মেমরি ব্যবহার", + "networkIo": "নেটওয়ার্ক আই/ও", + "input": "ইনপুট", + "output": "আউটপুট", + "blockIo": "ব্লক আই/ও", + "read": "পড়ুন", + "write": "লিখুন", + "pids": "পিআইডি", + "containerInformation": "কন্টেইনারের তথ্য", + "name": "নাম", + "id": "আইডি", + "state": "রাজ্য", + "containerMustBeRunning": "কনসোল অ্যাক্সেস করতে হলে কন্টেইনারটি অবশ্যই চালু থাকতে হবে।", + "verificationCodePrompt": "যাচাইকরণ কোড প্রবেশ করান", + "totpVerificationFailed": "TOTP যাচাইকরণ ব্যর্থ হয়েছে। অনুগ্রহ করে আবার চেষ্টা করুন।", + "warpgateVerificationFailed": "ওয়ার্পগেট প্রমাণীকরণ ব্যর্থ হয়েছে। অনুগ্রহ করে আবার চেষ্টা করুন।", + "connectedTo": "{{containerName}} এর সাথে সংযুক্ত", + "disconnected": "বিচ্ছিন্ন", + "consoleError": "কনসোল ত্রুটি", + "errorMessage": "ত্রুটি: {{message}}", + "failedToConnect": "কন্টেইনারের সাথে সংযোগ করতে ব্যর্থ হয়েছে", + "console": "কনসোল", + "selectShell": "শেল নির্বাচন করুন", + "bash": "ব্যাশ", + "sh": "শ", + "ash": "ছাই", + "connect": "সংযোগ করুন", + "disconnect": "সংযোগ বিচ্ছিন্ন করুন", + "notConnected": "সংযুক্ত নয়", + "clickToConnect": "শেল সেশন শুরু করতে কানেক্ট-এ ক্লিক করুন।", + "connectingTo": "{{containerName}} এর সাথে সংযোগ স্থাপন করা হচ্ছে...", + "containerNotFound": "কন্টেইনারটি খুঁজে পাওয়া যায়নি", + "backToList": "তালিকায় ফিরে যান", + "logs": "লগ", + "stats": "পরিসংখ্যান", + "consoleTab": "কনসোল", + "startContainerToAccess": "কনসোল অ্যাক্সেস করতে কন্টেইনারটি চালু করুন।" + }, + "nav": { + "docker": "ডকার" + }, + "hosts": { + "tabDocker": "ডকার", + "dockerIntegration": "ডকার ইন্টিগ্রেশন", + "enableDockerMonitor": "ডকার সক্রিয় করুন", + "enableDockerMonitorDesc": "ডকারের মাধ্যমে এই হোস্টে কন্টেইনারগুলি নিরীক্ষণ ও পরিচালনা করুন।", + "containerRuntime": "কন্টেইনার রানটাইম", + "containerRuntimeDesc": "এই হোস্টে কন্টেইনার ব্যবস্থাপনার জন্য ব্যবহৃত CLI নির্বাচন করুন", + "containerRuntimeDocker": "ডকার", + "containerRuntimePodman": "পডম্যান" + }, + "onboarding": { + "feature_docker": "ডকার", + "feature_docker_desc": "ডকার চালিত যেকোনো হোস্টে কন্টেইনার দেখুন, লগ পড়ুন এবং পরিসংখ্যান পর্যবেক্ষণ করুন।" + } +} diff --git a/plugins/docker/locales/translated/ca_ES.json b/plugins/docker/locales/translated/ca_ES.json new file mode 100644 index 000000000..9d2471510 --- /dev/null +++ b/plugins/docker/locales/translated/ca_ES.json @@ -0,0 +1,116 @@ +{ + "docker": { + "notEnabled": "Docker no està habilitat per a aquest amfitrió", + "validating": "Validant Docker...", + "connecting": "Connectant...", + "error": "Error", + "version": "{{runtime}} {{version}}", + "connectionFailed": "No s'ha pogut connectar a Docker", + "containerStarted": "Contenidor {{name}} iniciat", + "failedToStartContainer": "No s'ha pogut iniciar el contenidor {{name}}", + "containerStopped": "El contenidor {{name}} s'ha aturat", + "failedToStopContainer": "No s'ha pogut aturar el contenidor {{name}}", + "containerRestarted": "El contenidor {{name}} s'ha reiniciat", + "failedToRestartContainer": "No s'ha pogut reiniciar el contenidor {{name}}", + "containerPaused": "Contenidor {{name}} en pausa", + "containerUnpaused": "Contenidor {{name}} reactivat", + "failedToTogglePauseContainer": "No s'ha pogut activar o desactivar l'estat de pausa per al contenidor {{name}}", + "containerRemoved": "Contenidor {{name}} eliminat", + "failedToRemoveContainer": "No s'ha pogut eliminar el contenidor {{name}}", + "image": "Imatge", + "ports": "Ports", + "noPorts": "Sense ports", + "start": "Inici", + "confirmRemoveContainer": "Esteu segur que voleu eliminar el contenidor '{{name}}'? Aquesta acció no es pot desfer.", + "runningContainerWarning": "Avís: Aquest contenidor està en execució. Si el suprimiu, primer s'aturarà el contenidor.", + "loadingContainers": "Carregant contenidors...", + "manager": "Gestor de Docker", + "autoRefresh": "Actualització automàtica", + "timestamps": "Marques de temps", + "lines": "Línies", + "filterLogs": "Filtra els registres...", + "refresh": "Actualitza", + "download": "Descarrega", + "clear": "Clar", + "logsDownloaded": "Registres descarregats correctament", + "last50": "Últims 50", + "last100": "Últims 100", + "last500": "Últims 500", + "last1000": "Els últims 1000", + "allLogs": "Tots els registres", + "noLogsMatching": "No hi ha registres que coincideixin amb \"{{query}}\"", + "noLogsAvailable": "No hi ha registres disponibles", + "noContainersFound": "No s'han trobat contenidors", + "noContainersFoundHint": "No hi ha contenidors Docker disponibles en aquest amfitrió.", + "searchPlaceholder": "Cerca contenidors...", + "allStatuses": "Tots els estats", + "stateRunning": "Córrer", + "statePaused": "En pausa", + "stateExited": "Sortit", + "stateRestarting": "Reinici", + "noContainersMatchFilters": "No hi ha contenidors que coincideixin amb els vostres filtres", + "noContainersMatchFiltersHint": "Prova d'ajustar els criteris de cerca o de filtre", + "failedToFetchStats": "No s'han pogut obtenir les estadístiques del contenidor", + "containerNotRunning": "El contenidor no funciona", + "startContainerToViewStats": "Inicia el contenidor per veure les estadístiques", + "loadingStats": "S'estan carregant les estadístiques...", + "errorLoadingStats": "S'ha produït un error en carregar les estadístiques", + "noStatsAvailable": "No hi ha estadístiques disponibles", + "cpuUsage": "Ús de la CPU", + "current": "Actual", + "memoryUsage": "Ús de memòria", + "networkIo": "E/S de xarxa", + "input": "Entrada", + "output": "Sortida", + "blockIo": "Bloc d'E/S", + "read": "Llegir", + "write": "Escriure", + "pids": "PIDs", + "containerInformation": "Informació del contenidor", + "name": "Nom", + "id": "ID", + "state": "Estat", + "containerMustBeRunning": "El contenidor ha d'estar en execució per accedir a la consola.", + "verificationCodePrompt": "Introduïu el codi de verificació", + "totpVerificationFailed": "La verificació TOTP ha fallat. Torna-ho a provar.", + "warpgateVerificationFailed": "L'autenticació de Warpgate ha fallat. Torna-ho a intentar.", + "connectedTo": "Connectat a {{containerName}}", + "disconnected": "Desconnectat", + "consoleError": "Error de consola", + "errorMessage": "Error: {{message}}", + "failedToConnect": "No s'ha pogut connectar al contenidor", + "console": "Consola", + "selectShell": "Selecciona l'intèrpret d'ordres", + "bash": "Bash", + "sh": "sh", + "ash": "cendra", + "connect": "Connecta", + "disconnect": "Desconnecta", + "notConnected": "No connectat", + "clickToConnect": "Feu clic a Connecta per iniciar una sessió de shell", + "connectingTo": "Connectant a {{containerName}}...", + "containerNotFound": "No s'ha trobat el contenidor", + "backToList": "Torna a la llista", + "logs": "Registres", + "stats": "Estadístiques", + "consoleTab": "Consola", + "startContainerToAccess": "Inicieu el contenidor per accedir a la consola" + }, + "nav": { + "docker": "Docker" + }, + "hosts": { + "tabDocker": "Docker", + "dockerIntegration": "Integració de Docker", + "enableDockerMonitor": "Activa Docker", + "enableDockerMonitorDesc": "Supervisar i gestionar els contenidors d'aquest amfitrió mitjançant Docker", + "containerRuntime": "Temps d'execució del contenidor", + "containerRuntimeDesc": "Trieu la CLI utilitzada per a la gestió de contenidors en aquest amfitrió", + "containerRuntimeDocker": "Docker", + "containerRuntimePodman": "Podman" + }, + "onboarding": { + "feature_docker": "Docker", + "feature_docker_desc": "Veure contenidors, llegir registres i observar estadístiques de qualsevol host que executi Docker." + } +} diff --git a/plugins/docker/locales/translated/cs_CZ.json b/plugins/docker/locales/translated/cs_CZ.json new file mode 100644 index 000000000..96919b628 --- /dev/null +++ b/plugins/docker/locales/translated/cs_CZ.json @@ -0,0 +1,116 @@ +{ + "docker": { + "notEnabled": "Docker není pro tohoto hostitele povolen.", + "validating": "Ověřování Dockeru...", + "connecting": "Spojovací...", + "error": "Chyba", + "version": "{{runtime}} {{version}}", + "connectionFailed": "Nepodařilo se připojit k Dockeru", + "containerStarted": "Kontejner {{name}} spuštěn", + "failedToStartContainer": "Nepodařilo se spustit kontejner {{name}}", + "containerStopped": "Kontejner {{name}} zastaven", + "failedToStopContainer": "Nepodařilo se zastavit kontejner {{name}}", + "containerRestarted": "Kontejner {{name}} restartován", + "failedToRestartContainer": "Nepodařilo se restartovat kontejner {{name}}", + "containerPaused": "Kontejner {{name}} pozastaven", + "containerUnpaused": "Kontejner {{name}} pozastaven", + "failedToTogglePauseContainer": "Nepodařilo se přepnout stav pozastavení pro kontejner {{name}}", + "containerRemoved": "Kontejner {{name}} byl odstraněn", + "failedToRemoveContainer": "Nepodařilo se odstranit kontejner {{name}}", + "image": "Obraz", + "ports": "Porty", + "noPorts": "Žádné porty", + "start": "Start", + "confirmRemoveContainer": "Opravdu chcete odstranit kontejner '{{name}}'? Tuto akci nelze vrátit zpět.", + "runningContainerWarning": "Varování: Tento kontejner je aktuálně spuštěný. Jeho odstraněním se nejprve zastaví.", + "loadingContainers": "Nakládání kontejnerů...", + "manager": "Správce Dockeru", + "autoRefresh": "Automatické obnovení", + "timestamps": "Časová razítka", + "lines": "Čáry", + "filterLogs": "Filtrovat protokoly...", + "refresh": "Obnovit", + "download": "Stáhnout", + "clear": "Jasný", + "logsDownloaded": "Protokoly byly úspěšně staženy", + "last50": "Posledních 50", + "last100": "Posledních 100", + "last500": "Posledních 500", + "last1000": "Posledních 1000", + "allLogs": "Všechny protokoly", + "noLogsMatching": "Žádné protokoly neodpovídají „{{query}}“", + "noLogsAvailable": "Žádné protokoly nejsou k dispozici", + "noContainersFound": "Nenalezeny žádné kontejnery", + "noContainersFoundHint": "Na tomto hostiteli nejsou k dispozici žádné kontejnery Docker.", + "searchPlaceholder": "Hledat kontejnery...", + "allStatuses": "Všechny stavy", + "stateRunning": "Běh", + "statePaused": "Pozastaveno", + "stateExited": "Ukončeno", + "stateRestarting": "Restartování", + "noContainersMatchFilters": "Žádné kontejnery neodpovídají vašim filtrům", + "noContainersMatchFiltersHint": "Zkuste upravit kritéria vyhledávání nebo filtru", + "failedToFetchStats": "Nepodařilo se načíst statistiky kontejneru", + "containerNotRunning": "Kontejner neběží", + "startContainerToViewStats": "Spusťte kontejner pro zobrazení statistik", + "loadingStats": "Načítání statistik...", + "errorLoadingStats": "Chyba při načítání statistik", + "noStatsAvailable": "Žádné statistiky nejsou k dispozici", + "cpuUsage": "Využití CPU", + "current": "Proud", + "memoryUsage": "Využití paměti", + "networkIo": "Síťové I/O", + "input": "Vstup", + "output": "Výstup", + "blockIo": "Blok I/O", + "read": "Číst", + "write": "Napsat", + "pids": "PIDy", + "containerInformation": "Informace o kontejneru", + "name": "Jméno", + "id": "Průkaz totožnosti", + "state": "Stát", + "containerMustBeRunning": "Pro přístup ke konzoli musí být kontejner spuštěný.", + "verificationCodePrompt": "Zadejte ověřovací kód", + "totpVerificationFailed": "Ověření TOTP se nezdařilo. Zkuste to prosím znovu.", + "warpgateVerificationFailed": "Ověření Warpgate se nezdařilo. Zkuste to prosím znovu.", + "connectedTo": "Připojeno k {{containerName}}", + "disconnected": "Odpojeno", + "consoleError": "Chyba konzole", + "errorMessage": "Chyba: {{message}}", + "failedToConnect": "Nepodařilo se připojit ke kontejneru", + "console": "Utěšit", + "selectShell": "Vyberte skořápku", + "bash": "Bash", + "sh": "sh", + "ash": "popel", + "connect": "Připojit", + "disconnect": "Odpojit", + "notConnected": "Nepřipojeno", + "clickToConnect": "Kliknutím na tlačítko Připojit spusťte relaci shellu.", + "connectingTo": "Připojování k {{containerName}}...", + "containerNotFound": "Kontejner nenalezen", + "backToList": "Zpět na seznam", + "logs": "Protokoly", + "stats": "Statistiky", + "consoleTab": "Utěšit", + "startContainerToAccess": "Spusťte kontejner pro přístup ke konzoli" + }, + "nav": { + "docker": "Přístavní dělník" + }, + "hosts": { + "tabDocker": "Přístavní dělník", + "dockerIntegration": "Integrace Dockeru", + "enableDockerMonitor": "Povolit Docker", + "enableDockerMonitorDesc": "Monitorování a správa kontejnerů na tomto hostiteli pomocí Dockeru", + "containerRuntime": "Běh kontejneru", + "containerRuntimeDesc": "Vyberte rozhraní CLI používané pro správu kontejnerů na tomto hostiteli", + "containerRuntimeDocker": "Přístavní dělník", + "containerRuntimePodman": "Podman" + }, + "onboarding": { + "feature_docker": "Přístavní dělník", + "feature_docker_desc": "Zobrazujte kontejnery, čtěte protokoly a sledujte statistiky na jakémkoli hostiteli s Dockerem." + } +} diff --git a/plugins/docker/locales/translated/da_DK.json b/plugins/docker/locales/translated/da_DK.json new file mode 100644 index 000000000..5a382b61f --- /dev/null +++ b/plugins/docker/locales/translated/da_DK.json @@ -0,0 +1,116 @@ +{ + "docker": { + "notEnabled": "Docker er ikke aktiveret for denne vært", + "validating": "Validerer Docker...", + "connecting": "Forbinder...", + "error": "Fejl", + "version": "{{runtime}} {{version}}", + "connectionFailed": "Kunne ikke oprette forbindelse til Docker", + "containerStarted": "Container {{name}} startet", + "failedToStartContainer": "Kunne ikke starte containeren {{name}}", + "containerStopped": "Container {{name}} stoppet", + "failedToStopContainer": "Kunne ikke stoppe containeren {{name}}", + "containerRestarted": "Container {{name}} genstartet", + "failedToRestartContainer": "Kunne ikke genstarte containeren {{name}}", + "containerPaused": "Container {{name}} sat på pause", + "containerUnpaused": "Container {{name}} genoptaget", + "failedToTogglePauseContainer": "Kunne ikke slå pausetilstand til og fra for container {{name}}", + "containerRemoved": "Container {{name}} fjernet", + "failedToRemoveContainer": "Kunne ikke fjerne containeren {{name}}", + "image": "Billede", + "ports": "Havne", + "noPorts": "Ingen porte", + "start": "Starte", + "confirmRemoveContainer": "Er du sikker på, at du vil fjerne containeren '{{name}}'? Denne handling kan ikke fortrydes.", + "runningContainerWarning": "Advarsel: Denne container kører i øjeblikket. Fjernelse af den vil stoppe containeren først.", + "loadingContainers": "Indlæser containere...", + "manager": "Docker Manager", + "autoRefresh": "Automatisk opdatering", + "timestamps": "Tidsstempler", + "lines": "Linjer", + "filterLogs": "Filtrer logfiler...", + "refresh": "Opfriske", + "download": "Download", + "clear": "Klar", + "logsDownloaded": "Logfilerne er downloadet", + "last50": "Sidste 50", + "last100": "Sidste 100", + "last500": "Sidste 500", + "last1000": "Sidste 1000", + "allLogs": "Alle logfiler", + "noLogsMatching": "Ingen logfiler matcher \"{{query}}\"", + "noLogsAvailable": "Ingen logfiler tilgængelige", + "noContainersFound": "Ingen containere fundet", + "noContainersFoundHint": "Der er ingen Docker-containere tilgængelige på denne vært", + "searchPlaceholder": "Søg i containere...", + "allStatuses": "Alle statusser", + "stateRunning": "Løb", + "statePaused": "Pausesat", + "stateExited": "Afsluttet", + "stateRestarting": "Genstart", + "noContainersMatchFilters": "Ingen containere matcher dine filtre", + "noContainersMatchFiltersHint": "Prøv at justere dine søge- eller filterkriterier", + "failedToFetchStats": "Kunne ikke hente containerstatistik", + "containerNotRunning": "Containeren kører ikke", + "startContainerToViewStats": "Start containeren for at se statistik", + "loadingStats": "Indlæser statistik...", + "errorLoadingStats": "Fejl ved indlæsning af statistik", + "noStatsAvailable": "Ingen statistik tilgængelig", + "cpuUsage": "CPU-forbrug", + "current": "Strøm", + "memoryUsage": "Hukommelsesforbrug", + "networkIo": "Netværks-I/O", + "input": "Input", + "output": "Produktion", + "blockIo": "Blok I/O", + "read": "Læse", + "write": "Skrive", + "pids": "PID'er", + "containerInformation": "Containeroplysninger", + "name": "Navn", + "id": "ID", + "state": "Tilstand", + "containerMustBeRunning": "Containeren skal køre for at få adgang til konsollen", + "verificationCodePrompt": "Indtast bekræftelseskode", + "totpVerificationFailed": "TOTP-bekræftelse mislykkedes. Prøv igen.", + "warpgateVerificationFailed": "Warpgate-godkendelse mislykkedes. Prøv igen.", + "connectedTo": "Forbundet til {{containerName}}", + "disconnected": "Afbrudt", + "consoleError": "Konsolfejl", + "errorMessage": "Fejl: {{message}}", + "failedToConnect": "Kunne ikke oprette forbindelse til containeren", + "console": "Konsol", + "selectShell": "Vælg skal", + "bash": "Bash", + "sh": "sh", + "ash": "aske", + "connect": "Forbinde", + "disconnect": "Afbryde", + "notConnected": "Ikke forbundet", + "clickToConnect": "Klik på Opret forbindelse for at starte en shell-session", + "connectingTo": "Forbinder til {{containerName}}...", + "containerNotFound": "Beholderen blev ikke fundet", + "backToList": "Tilbage til listen", + "logs": "Logfiler", + "stats": "Statistik", + "consoleTab": "Konsol", + "startContainerToAccess": "Start containeren for at få adgang til konsollen" + }, + "nav": { + "docker": "Docker" + }, + "hosts": { + "tabDocker": "Docker", + "dockerIntegration": "Docker-integration", + "enableDockerMonitor": "Aktivér Docker", + "enableDockerMonitorDesc": "Overvåg og administrer containere på denne vært via Docker", + "containerRuntime": "Containerkørselstid", + "containerRuntimeDesc": "Vælg den CLI, der bruges til containeradministration på denne vært", + "containerRuntimeDocker": "Docker", + "containerRuntimePodman": "Podman" + }, + "onboarding": { + "feature_docker": "Docker", + "feature_docker_desc": "Se containere, læs logfiler og se statistikker på enhver vært, der kører Docker." + } +} diff --git a/plugins/docker/locales/translated/de_DE.json b/plugins/docker/locales/translated/de_DE.json new file mode 100644 index 000000000..0d020dee7 --- /dev/null +++ b/plugins/docker/locales/translated/de_DE.json @@ -0,0 +1,116 @@ +{ + "docker": { + "notEnabled": "Docker ist für diesen Host nicht aktiviert", + "validating": "Docker wird überprüft...", + "connecting": "Verbindung wird hergestellt...", + "error": "Fehler", + "version": "{{runtime}} {{version}}", + "connectionFailed": "Verbindung zu Docker fehlgeschlagen", + "containerStarted": "Container {{name}} gestartet", + "failedToStartContainer": "Starten des Containers {{name}} fehlgeschlagen", + "containerStopped": "Container {{name}} gestoppt", + "failedToStopContainer": "Stoppen des Containers {{name}} fehlgeschlagen", + "containerRestarted": "Container {{name}} neu gestartet", + "failedToRestartContainer": "Neustart des Containers {{name}} fehlgeschlagen", + "containerPaused": "Container {{name}} pausiert", + "containerUnpaused": "Container {{name}} fortgesetzt", + "failedToTogglePauseContainer": "Umschalten des Pause-Zustands für Container {{name}} fehlgeschlagen", + "containerRemoved": "Container {{name}} entfernt", + "failedToRemoveContainer": "Entfernen des Containers {{name}} fehlgeschlagen", + "image": "Image", + "ports": "Ports", + "noPorts": "Keine Ports", + "start": "Start", + "confirmRemoveContainer": "Sind Sie sicher, dass Sie den Container '{{name}}' entfernen möchten? Diese Aktion kann nicht rückgängig gemacht werden.", + "runningContainerWarning": "Warnung: Dieser Container wird gerade ausgeführt. Beim Entfernen wird der Container zuerst gestoppt.", + "loadingContainers": "Container werden geladen...", + "manager": "Docker-Manager", + "autoRefresh": "Automatische Aktualisierung", + "timestamps": "Zeitstempel", + "lines": "Zeilen", + "filterLogs": "Logs filtern...", + "refresh": "Aktualisieren", + "download": "Herunterladen", + "clear": "Löschen", + "logsDownloaded": "Logs erfolgreich heruntergeladen", + "last50": "Letzte 50", + "last100": "Letzte 100", + "last500": "Letzte 500", + "last1000": "Letzte 1000", + "allLogs": "Alle Logs", + "noLogsMatching": "Keine Logs passend zu \"{{query}}\"", + "noLogsAvailable": "Keine Logs verfügbar", + "noContainersFound": "Keine Container gefunden", + "noContainersFoundHint": "Auf diesem Host sind keine Docker-Container verfügbar", + "searchPlaceholder": "Container durchsuchen...", + "allStatuses": "Alle Status", + "stateRunning": "Läuft", + "statePaused": "Pausiert", + "stateExited": "Beendet", + "stateRestarting": "Wird neu gestartet", + "noContainersMatchFilters": "Keine Container entsprechen Ihren Filtern", + "noContainersMatchFiltersHint": "Versuchen Sie, Ihre Such- oder Filterkriterien anzupassen.", + "failedToFetchStats": "Container-Statistiken konnten nicht abgerufen werden", + "containerNotRunning": "Container läuft nicht", + "startContainerToViewStats": "Starten Sie den Container, um Statistiken anzuzeigen", + "loadingStats": "Statistiken werden geladen...", + "errorLoadingStats": "Fehler beim Laden der Statistiken", + "noStatsAvailable": "Keine Statistiken verfügbar", + "cpuUsage": "CPU-Auslastung", + "current": "Aktuell", + "memoryUsage": "Speicherauslastung", + "networkIo": "Netzwerk-I/O", + "input": "Eingabe", + "output": "Ausgabe", + "blockIo": "Block-I/O", + "read": "Lesen", + "write": "Schreiben", + "pids": "PIDs", + "containerInformation": "Container-Informationen", + "name": "Name", + "id": "ID", + "state": "Status", + "containerMustBeRunning": "Der Container muss ausgeführt werden, um auf die Konsole zuzugreifen", + "verificationCodePrompt": "Bestätigungscode eingeben", + "totpVerificationFailed": "TOTP-Überprüfung fehlgeschlagen. Bitte versuchen Sie es erneut.", + "warpgateVerificationFailed": "Warpgate-Authentifizierung fehlgeschlagen. Bitte versuchen Sie es erneut.", + "connectedTo": "Verbunden mit {{containerName}}", + "disconnected": "Getrennt", + "consoleError": "Konsolenfehler", + "errorMessage": "Fehler: {{message}}", + "failedToConnect": "Verbindung zum Container fehlgeschlagen", + "console": "Konsole", + "selectShell": "Shell auswählen", + "bash": "Bash", + "sh": "sh", + "ash": "ash", + "connect": "Verbinden", + "disconnect": "Trennen", + "notConnected": "Nicht verbunden", + "clickToConnect": "Klicken Sie auf 'Verbinden', um eine Shell-Sitzung zu starten", + "connectingTo": "Verbinden mit {{containerName}}...", + "containerNotFound": "Container nicht gefunden", + "backToList": "Zurück zur Liste", + "logs": "Protokolle", + "stats": "Statistiken", + "consoleTab": "Konsole", + "startContainerToAccess": "Starten Sie den Container, um auf die Konsole zuzugreifen" + }, + "nav": { + "docker": "Docker" + }, + "hosts": { + "tabDocker": "Docker", + "dockerIntegration": "Docker-Integration", + "enableDockerMonitor": "Docker aktivieren", + "enableDockerMonitorDesc": "Container auf diesem Host über Docker überwachen und verwalten", + "containerRuntime": "Container-Runtime", + "containerRuntimeDesc": "Wählen Sie die CLI für die Container-Verwaltung auf diesem Host", + "containerRuntimeDocker": "Docker", + "containerRuntimePodman": "Podman" + }, + "onboarding": { + "feature_docker": "Docker", + "feature_docker_desc": "Container anzeigen, Protokolle lesen und Statistiken auf jedem Host, auf dem Docker ausgeführt wird, einsehen." + } +} diff --git a/plugins/docker/locales/translated/el_GR.json b/plugins/docker/locales/translated/el_GR.json new file mode 100644 index 000000000..c51ae9939 --- /dev/null +++ b/plugins/docker/locales/translated/el_GR.json @@ -0,0 +1,116 @@ +{ + "docker": { + "notEnabled": "Το Docker δεν είναι ενεργοποιημένο για αυτόν τον κεντρικό υπολογιστή", + "validating": "Επικύρωση Docker...", + "connecting": "Συνδετικός...", + "error": "Σφάλμα", + "version": "{{runtime}} {{version}}", + "connectionFailed": "Αποτυχία σύνδεσης με το Docker", + "containerStarted": "Το κοντέινερ {{name}} ξεκίνησε", + "failedToStartContainer": "Αποτυχία εκκίνησης κοντέινερ {{name}}", + "containerStopped": "Το κοντέινερ {{name}} σταμάτησε", + "failedToStopContainer": "Αποτυχία διακοπής του κοντέινερ {{name}}", + "containerRestarted": "Το κοντέινερ {{name}} επανεκκινήθηκε", + "failedToRestartContainer": "Αποτυχία επανεκκίνησης κοντέινερ {{name}}", + "containerPaused": "Το κοντέινερ {{name}} τέθηκε σε παύση", + "containerUnpaused": "Το κοντέινερ {{name}} δεν έπαυσε να λειτουργεί", + "failedToTogglePauseContainer": "Αποτυχία εναλλαγής κατάστασης παύσης για το κοντέινερ {{name}}", + "containerRemoved": "Το κοντέινερ {{name}} αφαιρέθηκε", + "failedToRemoveContainer": "Αποτυχία κατάργησης του κοντέινερ {{name}}", + "image": "Εικών", + "ports": "Λιμάνια", + "noPorts": "Δεν υπάρχουν θύρες", + "start": "Αρχή", + "confirmRemoveContainer": "Είστε βέβαιοι ότι θέλετε να καταργήσετε το κοντέινερ '{{name}}'; Αυτή η ενέργεια δεν μπορεί να αναιρεθεί.", + "runningContainerWarning": "Προειδοποίηση: Αυτό το κοντέινερ εκτελείται αυτήν τη στιγμή. Η αφαίρεσή του θα διακόψει πρώτα τη λειτουργία του.", + "loadingContainers": "Φόρτωση κοντέινερ...", + "manager": "Διαχειριστής Docker", + "autoRefresh": "Αυτόματη Ανανέωση", + "timestamps": "Χρονικές σημάνσεις", + "lines": "Γραμμές", + "filterLogs": "Φιλτράρισμα αρχείων καταγραφής...", + "refresh": "Φρεσκάρω", + "download": "Λήψη", + "clear": "Σαφής", + "logsDownloaded": "Τα αρχεία καταγραφής λήφθηκαν με επιτυχία", + "last50": "Τελευταία 50", + "last100": "Τελευταία 100", + "last500": "Τελευταία 500", + "last1000": "Τελευταία 1000", + "allLogs": "Όλα τα αρχεία καταγραφής", + "noLogsMatching": "Δεν υπάρχουν αρχεία καταγραφής που να ταιριάζουν με το \"{{query}}\"", + "noLogsAvailable": "Δεν υπάρχουν διαθέσιμα αρχεία καταγραφής", + "noContainersFound": "Δεν βρέθηκαν κοντέινερ", + "noContainersFoundHint": "Δεν υπάρχουν διαθέσιμα κοντέινερ Docker σε αυτόν τον κεντρικό υπολογιστή", + "searchPlaceholder": "Αναζήτηση κοντέινερ...", + "allStatuses": "Όλες οι καταστάσεις", + "stateRunning": "Τρέξιμο", + "statePaused": "Σε παύση", + "stateExited": "Έξοδος", + "stateRestarting": "Επανεκκίνηση", + "noContainersMatchFilters": "Δεν υπάρχουν κοντέινερ που να αντιστοιχούν στα φίλτρα σας", + "noContainersMatchFiltersHint": "Δοκιμάστε να προσαρμόσετε τα κριτήρια αναζήτησης ή φιλτραρίσματος", + "failedToFetchStats": "Αποτυχία ανάκτησης στατιστικών στοιχείων κοντέινερ", + "containerNotRunning": "Το κοντέινερ δεν λειτουργεί", + "startContainerToViewStats": "Ξεκινήστε το κοντέινερ για να δείτε στατιστικά στοιχεία", + "loadingStats": "Φόρτωση στατιστικών στοιχείων...", + "errorLoadingStats": "Σφάλμα φόρτωσης στατιστικών στοιχείων", + "noStatsAvailable": "Δεν υπάρχουν διαθέσιμα στατιστικά στοιχεία", + "cpuUsage": "Χρήση CPU", + "current": "Ρεύμα", + "memoryUsage": "Χρήση μνήμης", + "networkIo": "Είσοδος/Έξοδος Δικτύου", + "input": "Εισαγωγή", + "output": "Παραγωγή", + "blockIo": "Είσοδος/Έξοδος μπλοκ", + "read": "Ανάγνωση", + "write": "Γράφω", + "pids": "PID", + "containerInformation": "Πληροφορίες κοντέινερ", + "name": "Ονομα", + "id": "ταυτότητα", + "state": "Κατάσταση", + "containerMustBeRunning": "Το κοντέινερ πρέπει να εκτελείται για πρόσβαση στην κονσόλα", + "verificationCodePrompt": "Εισαγάγετε τον κωδικό επαλήθευσης", + "totpVerificationFailed": "Η επαλήθευση TOTP απέτυχε. Δοκιμάστε ξανά.", + "warpgateVerificationFailed": "Ο έλεγχος ταυτότητας Warpgate απέτυχε. Δοκιμάστε ξανά.", + "connectedTo": "Συνδεδεμένο με {{containerName}}", + "disconnected": "Ασύνδετος", + "consoleError": "Σφάλμα κονσόλας", + "errorMessage": "Σφάλμα: {{message}}", + "failedToConnect": "Αποτυχία σύνδεσης με το κοντέινερ", + "console": "Κονσόλα", + "selectShell": "Επιλογή κελύφους", + "bash": "Βίαιο χτύπημα", + "sh": "σς", + "ash": "φλαμουριά", + "connect": "Συνδέω", + "disconnect": "Αποσυνδέω", + "notConnected": "Δεν είναι συνδεδεμένο", + "clickToConnect": "Κάντε κλικ στη σύνδεση για να ξεκινήσετε μια συνεδρία κελύφους", + "connectingTo": "Σύνδεση με {{containerName}}...", + "containerNotFound": "Δεν βρέθηκε κοντέινερ", + "backToList": "Επιστροφή στη λίστα", + "logs": "Αρχεία καταγραφής", + "stats": "Στατιστικά", + "consoleTab": "Κονσόλα", + "startContainerToAccess": "Ξεκινήστε το κοντέινερ για να αποκτήσετε πρόσβαση στην κονσόλα" + }, + "nav": { + "docker": "Λιμενεργάτης" + }, + "hosts": { + "tabDocker": "Λιμενεργάτης", + "dockerIntegration": "Ενσωμάτωση Docker", + "enableDockerMonitor": "Ενεργοποίηση Docker", + "enableDockerMonitorDesc": "Παρακολούθηση και διαχείριση κοντέινερ σε αυτόν τον κεντρικό υπολογιστή μέσω του Docker", + "containerRuntime": "Χρόνος εκτέλεσης κοντέινερ", + "containerRuntimeDesc": "Επιλέξτε το CLI που χρησιμοποιείται για τη διαχείριση κοντέινερ σε αυτόν τον κεντρικό υπολογιστή", + "containerRuntimeDocker": "Λιμενεργάτης", + "containerRuntimePodman": "Πόντμαν" + }, + "onboarding": { + "feature_docker": "Λιμενεργάτης", + "feature_docker_desc": "Δείτε κοντέινερ, διαβάστε αρχεία καταγραφής και παρακολουθήστε στατιστικά στοιχεία σε οποιονδήποτε κεντρικό υπολογιστή που εκτελεί Docker." + } +} diff --git a/plugins/docker/locales/translated/es_ES.json b/plugins/docker/locales/translated/es_ES.json new file mode 100644 index 000000000..057c962df --- /dev/null +++ b/plugins/docker/locales/translated/es_ES.json @@ -0,0 +1,116 @@ +{ + "docker": { + "notEnabled": "Docker no está habilitado para este host", + "validating": "Validando Docker...", + "connecting": "Conectando...", + "error": "Error", + "version": "{{runtime}} {{version}}", + "connectionFailed": "Error al conectar con Docker", + "containerStarted": "Contenedor {{name}} iniciado", + "failedToStartContainer": "Error al iniciar el contenedor {{name}}", + "containerStopped": "Contenedor {{name}} detenido", + "failedToStopContainer": "Error al detener el contenedor {{name}}", + "containerRestarted": "Contenedor {{name}} reiniciado", + "failedToRestartContainer": "Error al reiniciar el contenedor {{name}}", + "containerPaused": "Contenedor {{name}} pausado", + "containerUnpaused": "Contenedor {{name}} reanudado", + "failedToTogglePauseContainer": "Error al cambiar el estado de pausa del contenedor {{name}}", + "containerRemoved": "Contenedor {{name}} eliminado", + "failedToRemoveContainer": "Error al eliminar el contenedor {{name}}", + "image": "Imagen", + "ports": "Puertos", + "noPorts": "Sin puertos", + "start": "Iniciar", + "confirmRemoveContainer": "¿Está seguro de que desea eliminar el contenedor '{{name}}'? Esta acción no se puede deshacer.", + "runningContainerWarning": "Advertencia: Este contenedor está actualmente en ejecución. Al eliminarlo, se detendrá primero.", + "loadingContainers": "Cargando contenedores...", + "manager": "Administrador de Docker", + "autoRefresh": "Actualización automática", + "timestamps": "Marcas de tiempo", + "lines": "Líneas", + "filterLogs": "Filtrar registros...", + "refresh": "Actualizar", + "download": "Descargar", + "clear": "Limpiar", + "logsDownloaded": "Registros descargados correctamente", + "last50": "Últimos 50", + "last100": "Últimos 100", + "last500": "Últimos 500", + "last1000": "Últimos 1000", + "allLogs": "Todos los registros", + "noLogsMatching": "No hay registros que coincidan con \"{{query}}\"", + "noLogsAvailable": "No hay registros disponibles", + "noContainersFound": "No se encontraron contenedores", + "noContainersFoundHint": "No hay contenedores Docker disponibles en este host", + "searchPlaceholder": "Buscar contenedores...", + "allStatuses": "Todos los estados", + "stateRunning": "En ejecución", + "statePaused": "En pausa", + "stateExited": "Detenido", + "stateRestarting": "Reiniciando", + "noContainersMatchFilters": "Ningún contenedor coincide con los filtros", + "noContainersMatchFiltersHint": "Intente ajustar los criterios de búsqueda o filtro", + "failedToFetchStats": "Error al obtener las estadísticas del contenedor", + "containerNotRunning": "El contenedor no está en ejecución", + "startContainerToViewStats": "Inicie el contenedor para ver las estadísticas", + "loadingStats": "Cargando estadísticas...", + "errorLoadingStats": "Error al cargar las estadísticas", + "noStatsAvailable": "No hay estadísticas disponibles", + "cpuUsage": "Uso de CPU", + "current": "Actual", + "memoryUsage": "Uso de memoria", + "networkIo": "E/S de red", + "input": "Entrada", + "output": "Salida", + "blockIo": "E/S de bloques", + "read": "Lectura", + "write": "Escritura", + "pids": "PIDs", + "containerInformation": "Información del contenedor", + "name": "Nombre", + "id": "ID", + "state": "Estado", + "containerMustBeRunning": "El contenedor debe estar en ejecución para acceder a la consola", + "verificationCodePrompt": "Introduzca el código de verificación", + "totpVerificationFailed": "La verificación TOTP falló. Inténtelo de nuevo.", + "warpgateVerificationFailed": "La autenticación Warpgate falló. Inténtelo de nuevo.", + "connectedTo": "Conectado a {{containerName}}", + "disconnected": "Desconectado", + "consoleError": "Error de consola", + "errorMessage": "Error: {{message}}", + "failedToConnect": "No se pudo conectar al contenedor", + "console": "Consola", + "selectShell": "Seleccionar shell", + "bash": "Bash", + "sh": "sh", + "ash": "ash", + "connect": "Conectar", + "disconnect": "Desconectar", + "notConnected": "No conectado", + "clickToConnect": "Haga clic en conectar para iniciar una sesión de shell", + "connectingTo": "Conectando a {{containerName}}...", + "containerNotFound": "Contenedor no encontrado", + "backToList": "Volver a la lista", + "logs": "Registros", + "stats": "Estadísticas", + "consoleTab": "Consola", + "startContainerToAccess": "Inicie el contenedor para acceder a la consola" + }, + "nav": { + "docker": "Docker" + }, + "hosts": { + "tabDocker": "Docker", + "dockerIntegration": "Integración con Docker", + "enableDockerMonitor": "Activar Docker", + "enableDockerMonitorDesc": "Supervisar y gestionar contenedores en este host mediante Docker.", + "containerRuntime": "Runtime de contenedores", + "containerRuntimeDesc": "Elegir la CLI utilizada para la gestión de contenedores en este host.", + "containerRuntimeDocker": "Docker", + "containerRuntimePodman": "Podman" + }, + "onboarding": { + "feature_docker": "Estibador", + "feature_docker_desc": "Vea los contenedores, lea los registros y observe las estadísticas en cualquier host que ejecute Docker." + } +} diff --git a/plugins/docker/locales/translated/fi_FI.json b/plugins/docker/locales/translated/fi_FI.json new file mode 100644 index 000000000..e7e618b61 --- /dev/null +++ b/plugins/docker/locales/translated/fi_FI.json @@ -0,0 +1,116 @@ +{ + "docker": { + "notEnabled": "Docker ei ole käytössä tälle isännälle", + "validating": "Dockerin validointi...", + "connecting": "Yhdistetään...", + "error": "Virhe", + "version": "{{runtime}} {{version}}", + "connectionFailed": "Yhteyden muodostaminen Dockeriin epäonnistui", + "containerStarted": "Säiliö {{name}} aloitettu", + "failedToStartContainer": "Säiliön {{name}} käynnistäminen epäonnistui", + "containerStopped": "Kontti {{name}} pysäytetty", + "failedToStopContainer": "Säiliön {{name}} pysäyttäminen epäonnistui", + "containerRestarted": "Säiliö {{name}} käynnistetty uudelleen", + "failedToRestartContainer": "Säiliön uudelleenkäynnistys epäonnistui {{name}}", + "containerPaused": "Säilö {{name}} keskeytetty", + "containerUnpaused": "Säiliö {{name}} keskeytetty", + "failedToTogglePauseContainer": "Säilön {{name}} taukotilan vaihtaminen epäonnistui", + "containerRemoved": "Säiliö {{name}} poistettu", + "failedToRemoveContainer": "Säilön {{name}} poistaminen epäonnistui", + "image": "Kuva", + "ports": "Portit", + "noPorts": "Ei portteja", + "start": "Aloita", + "confirmRemoveContainer": "Haluatko varmasti poistaa säilön '{{name}}'? Tätä toimintoa ei voi perua.", + "runningContainerWarning": "Varoitus: Tämä säilö on parhaillaan käynnissä. Sen poistaminen pysäyttää säilön ensin.", + "loadingContainers": "Konttien lastaus...", + "manager": "Docker-hallinta", + "autoRefresh": "Automaattinen päivitys", + "timestamps": "Aikaleimat", + "lines": "Viivat", + "filterLogs": "Suodata lokit...", + "refresh": "Päivitä", + "download": "Lataa", + "clear": "Tyhjennä", + "logsDownloaded": "Lokien lataus onnistui", + "last50": "Viimeiset 50", + "last100": "Viimeiset 100", + "last500": "Viimeiset 500", + "last1000": "Viimeiset 1000", + "allLogs": "Kaikki lokit", + "noLogsMatching": "Ei lokeja, jotka vastaavat \"{{query}}\"", + "noLogsAvailable": "Ei lokeja saatavilla", + "noContainersFound": "Ei löytynyt säiliöitä", + "noContainersFoundHint": "Docker-kontteja ei ole saatavilla tällä isännöintipalvelimella", + "searchPlaceholder": "Hae säilöjä...", + "allStatuses": "Kaikki tilat", + "stateRunning": "Juoksu", + "statePaused": "Keskeytetty", + "stateExited": "Poistui", + "stateRestarting": "Uudelleenkäynnistys", + "noContainersMatchFilters": "Yksikään säilö ei vastaa suodattimiasi", + "noContainersMatchFiltersHint": "Kokeile muokata haku- tai suodatusehtojasi", + "failedToFetchStats": "Säilön tilastojen nouto epäonnistui", + "containerNotRunning": "Säiliö ei ole käynnissä", + "startContainerToViewStats": "Käynnistä säilö tilastojen tarkastelemiseksi", + "loadingStats": "Ladataan tilastoja...", + "errorLoadingStats": "Virhe tilastojen lataamisessa", + "noStatsAvailable": "Ei tilastoja saatavilla", + "cpuUsage": "Suorittimen käyttö", + "current": "Nykyinen", + "memoryUsage": "Muistin käyttö", + "networkIo": "Verkko-I/O", + "input": "Syöttö", + "output": "Lähtö", + "blockIo": "Estä I/O", + "read": "Lukea", + "write": "Kirjoittaa", + "pids": "PID-tunnukset", + "containerInformation": "Säiliön tiedot", + "name": "Nimi", + "id": "Henkilöllisyystodistus", + "state": "Osavaltio", + "containerMustBeRunning": "Kontin on oltava käynnissä, jotta konsoliin pääsee käsiksi.", + "verificationCodePrompt": "Syötä vahvistuskoodi", + "totpVerificationFailed": "TOTP-vahvistus epäonnistui. Yritä uudelleen.", + "warpgateVerificationFailed": "Warpgate-todennus epäonnistui. Yritä uudelleen.", + "connectedTo": "Yhdistetty kohteeseen {{containerName}}", + "disconnected": "Yhteys katkennut", + "consoleError": "Konsolivirhe", + "errorMessage": "Virhe: {{message}}", + "failedToConnect": "Yhteyden muodostaminen säilöön epäonnistui", + "console": "Konsoli", + "selectShell": "Valitse komentotulkki", + "bash": "Lyödä", + "sh": "sh", + "ash": "tuhka", + "connect": "Yhdistä", + "disconnect": "Katkaise yhteys", + "notConnected": "Ei yhdistetty", + "clickToConnect": "Aloita shell-istunto napsauttamalla Yhdistä", + "connectingTo": "Yhdistetään kohteeseen {{containerName}}...", + "containerNotFound": "Säiliötä ei löydy", + "backToList": "Takaisin listaan", + "logs": "Lokit", + "stats": "Tilastot", + "consoleTab": "Konsoli", + "startContainerToAccess": "Käynnistä säilö päästäksesi konsoliin" + }, + "nav": { + "docker": "Satamatyöläinen" + }, + "hosts": { + "tabDocker": "Satamatyöläinen", + "dockerIntegration": "Docker-integraatio", + "enableDockerMonitor": "Ota Docker käyttöön", + "enableDockerMonitorDesc": "Valvo ja hallinnoi tämän isännän säilöjä Dockerin kautta", + "containerRuntime": "Säilön suoritusaika", + "containerRuntimeDesc": "Valitse CLI, jota käytetään säilön hallintaan tässä isännässä", + "containerRuntimeDocker": "Satamatyöläinen", + "containerRuntimePodman": "Podman" + }, + "onboarding": { + "feature_docker": "Satamatyöläinen", + "feature_docker_desc": "Katso säilöjä, lue lokeja ja seuraa tilastoja millä tahansa Dockeria käyttävällä isännällä." + } +} diff --git a/plugins/docker/locales/translated/fr_FR.json b/plugins/docker/locales/translated/fr_FR.json new file mode 100644 index 000000000..1c4d2693d --- /dev/null +++ b/plugins/docker/locales/translated/fr_FR.json @@ -0,0 +1,116 @@ +{ + "docker": { + "notEnabled": "Docker n'est pas activé pour cet hôte", + "validating": "Validation de Docker...", + "connecting": "Connexion...", + "error": "Erreur", + "version": "{{runtime}} {{version}}", + "connectionFailed": "Échec de la connexion à Docker", + "containerStarted": "Conteneur {{name}} démarré", + "failedToStartContainer": "Échec du démarrage du conteneur {{name}}", + "containerStopped": "Conteneur {{name}} arrêté", + "failedToStopContainer": "Échec de l'arrêt du conteneur {{name}}", + "containerRestarted": "Conteneur {{name}} redémarré", + "failedToRestartContainer": "Échec du redémarrage du conteneur {{name}}", + "containerPaused": "Conteneur {{name}} mis en pause", + "containerUnpaused": "Conteneur {{name}} repris", + "failedToTogglePauseContainer": "Échec du basculement de l'état de pause du conteneur {{name}}", + "containerRemoved": "Conteneur {{name}} supprimé", + "failedToRemoveContainer": "Échec de la suppression du conteneur {{name}}", + "image": "Image", + "ports": "Ports", + "noPorts": "Aucun port", + "start": "Démarrer", + "confirmRemoveContainer": "Êtes-vous sûr de vouloir supprimer le conteneur '{{name}}' ? Cette action est irréversible.", + "runningContainerWarning": "Attention : Ce conteneur est en cours d'exécution. Sa suppression l'arrêtera d'abord.", + "loadingContainers": "Chargement des conteneurs...", + "manager": "Gestionnaire Docker", + "autoRefresh": "Actualisation automatique", + "timestamps": "Horodatages", + "lines": "Lignes", + "filterLogs": "Filtrer les journaux...", + "refresh": "Actualiser", + "download": "Télécharger", + "clear": "Effacer", + "logsDownloaded": "Journaux téléchargés avec succès", + "last50": "50 derniers", + "last100": "100 derniers", + "last500": "500 derniers", + "last1000": "1 000 derniers", + "allLogs": "Tous les journaux", + "noLogsMatching": "Aucun journal correspondant à \"{{query}}\"", + "noLogsAvailable": "Aucun journal disponible", + "noContainersFound": "Aucun conteneur trouvé", + "noContainersFoundHint": "Aucun conteneur Docker n’est disponible sur cet hôte", + "searchPlaceholder": "Rechercher des conteneurs...", + "allStatuses": "Tous les statuts", + "stateRunning": "En cours d’exécution", + "statePaused": "En pause", + "stateExited": "Arrêté", + "stateRestarting": "Redémarrage en cours", + "noContainersMatchFilters": "Aucun conteneur ne correspond à vos filtres", + "noContainersMatchFiltersHint": "Essayez de modifier vos critères de recherche ou de filtrage", + "failedToFetchStats": "Échec de la récupération des statistiques du conteneur", + "containerNotRunning": "Conteneur arrêté", + "startContainerToViewStats": "Démarrez le conteneur pour afficher les statistiques", + "loadingStats": "Chargement des statistiques...", + "errorLoadingStats": "Erreur lors du chargement des statistiques", + "noStatsAvailable": "Aucune statistique disponible", + "cpuUsage": "Utilisation CPU", + "current": "Actuel", + "memoryUsage": "Utilisation mémoire", + "networkIo": "E/S réseau", + "input": "Entrée", + "output": "Sortie", + "blockIo": "E/S de blocs", + "read": "Lecture", + "write": "Écriture", + "pids": "PIDs", + "containerInformation": "Informations sur le conteneur", + "name": "Nom", + "id": "ID", + "state": "État", + "containerMustBeRunning": "Le conteneur doit être en cours d'exécution pour accéder à la console", + "verificationCodePrompt": "Saisissez le code de vérification", + "totpVerificationFailed": "La vérification TOTP a échoué. Veuillez réessayer.", + "warpgateVerificationFailed": "L'authentification Warpgate a échoué. Veuillez réessayer.", + "connectedTo": "Connecté à {{containerName}}", + "disconnected": "Déconnecté", + "consoleError": "Erreur de la console", + "errorMessage": "Erreur : {{message}}", + "failedToConnect": "Échec de la connexion au conteneur", + "console": "Console", + "selectShell": "Sélectionner le shell", + "bash": "Bash", + "sh": "sh", + "ash": "ash", + "connect": "Connecter", + "disconnect": "Déconnecter", + "notConnected": "Non connecté", + "clickToConnect": "Cliquez sur Connecter pour démarrer une session shell", + "connectingTo": "Connexion à {{containerName}}…", + "containerNotFound": "Conteneur introuvable", + "backToList": "Retour à la liste", + "logs": "Journaux", + "stats": "Stats", + "consoleTab": "Console", + "startContainerToAccess": "Démarrez le conteneur pour accéder à la console" + }, + "nav": { + "docker": "Docker" + }, + "hosts": { + "tabDocker": "Docker", + "dockerIntegration": "Intégration Docker", + "enableDockerMonitor": "Activer Docker", + "enableDockerMonitorDesc": "Surveiller et gérer les conteneurs sur cet hôte via Docker", + "containerRuntime": "Moteur d'exécution de conteneurs", + "containerRuntimeDesc": "Choisissez le CLI utilisé pour la gestion des conteneurs sur cet hôte", + "containerRuntimeDocker": "Docker", + "containerRuntimePodman": "Podman" + }, + "onboarding": { + "feature_docker": "Docker", + "feature_docker_desc": "Consultez les conteneurs, lisez les journaux et surveillez les statistiques sur n'importe quel hôte exécutant Docker." + } +} diff --git a/plugins/docker/locales/translated/he_IL.json b/plugins/docker/locales/translated/he_IL.json new file mode 100644 index 000000000..50db67f46 --- /dev/null +++ b/plugins/docker/locales/translated/he_IL.json @@ -0,0 +1,116 @@ +{ + "docker": { + "notEnabled": "Docker אינו מופעל עבור מארח זה", + "validating": "מאמת את Docker...", + "connecting": "מְקַשֵׁר...", + "error": "שְׁגִיאָה", + "version": "{{runtime}} {{version}}", + "connectionFailed": "נכשלה ההתחברות ל-Docker", + "containerStarted": "מיכל {{name}} הופעל", + "failedToStartContainer": "נכשל בהפעלת המכולה {{name}}", + "containerStopped": "מיכל {{name}} נעצר", + "failedToStopContainer": "נכשלה עצירת המכולה {{name}}", + "containerRestarted": "המיכל {{name}} הופעל מחדש", + "failedToRestartContainer": "נכשלה ההפעלה מחדש של המכולה {{name}}", + "containerPaused": "מיכל {{name}} הושהה", + "containerUnpaused": "השהייתה של המיכל {{name}} בוטלה", + "failedToTogglePauseContainer": "נכשל הניסיון להחליף בין מצב השהייה עבור המכולה {{name}}", + "containerRemoved": "המיכל {{name}} הוסר", + "failedToRemoveContainer": "נכשלה הסרת המיכל {{name}}", + "image": "תְמוּנָה", + "ports": "נמלים", + "noPorts": "אין יציאות", + "start": "הַתחָלָה", + "confirmRemoveContainer": "האם אתה בטוח שברצונך להסיר את המכולה '{{name}}'? לא ניתן לבטל פעולה זו.", + "runningContainerWarning": "אזהרה: מיכל זה פועל כעת. הסרתו תעצור את המיכל תחילה.", + "loadingContainers": "טוען מכולות...", + "manager": "מנהל דוקר", + "autoRefresh": "רענון אוטומטי", + "timestamps": "חותמות זמן", + "lines": "קווים", + "filterLogs": "סנן יומני רישום...", + "refresh": "לְרַעֲנֵן", + "download": "הורדה", + "clear": "בָּרוּר", + "logsDownloaded": "יומני הרישום הורדו בהצלחה", + "last50": "50 האחרונים", + "last100": "100 האחרונים", + "last500": "500 האחרונים", + "last1000": "1000 האחרונים", + "allLogs": "כל היומנים", + "noLogsMatching": "אין יומנים התואמים ל-\"{{query}}\"", + "noLogsAvailable": "אין יומנים זמינים", + "noContainersFound": "לא נמצאו מכולות", + "noContainersFoundHint": "אין מכולות Docker זמינות במארח זה", + "searchPlaceholder": "חיפוש מכולות...", + "allStatuses": "כל הסטטוסים", + "stateRunning": "רִיצָה", + "statePaused": "מושהה", + "stateExited": "יצא", + "stateRestarting": "הפעלה מחדש", + "noContainersMatchFilters": "אין מכולות התואמות את המסננים שלך", + "noContainersMatchFiltersHint": "נסה להתאים את קריטריוני החיפוש או הסינון שלך", + "failedToFetchStats": "נכשל באחזור סטטיסטיקות המכולה", + "containerNotRunning": "המכולה לא פועלת", + "startContainerToViewStats": "הפעל את המכולה כדי להציג נתונים סטטיסטיים", + "loadingStats": "טוען סטטיסטיקות...", + "errorLoadingStats": "שגיאה בטעינת סטטיסטיקות", + "noStatsAvailable": "אין סטטיסטיקות זמינות", + "cpuUsage": "שימוש במעבד", + "current": "נוֹכְחִי", + "memoryUsage": "שימוש בזיכרון", + "networkIo": "קלט/פלט של הרשת", + "input": "קֶלֶט", + "output": "תְפוּקָה", + "blockIo": "בלוק קלט/פלט", + "read": "לִקְרוֹא", + "write": "לִכתוֹב", + "pids": "PIDs", + "containerInformation": "מידע על המכולה", + "name": "שֵׁם", + "id": "תְעוּדַת זֶהוּת", + "state": "מְדִינָה", + "containerMustBeRunning": "יש לפעול על מנת לגשת למסוף.", + "verificationCodePrompt": "הזן קוד אימות", + "totpVerificationFailed": "אימות TOTP נכשל. אנא נסה שוב.", + "warpgateVerificationFailed": "אימות Warpgate נכשל. אנא נסה שוב.", + "connectedTo": "מחובר אל {{containerName}}", + "disconnected": "מְנוּתָק", + "consoleError": "שגיאת קונסולה", + "errorMessage": "שגיאה: {{message}}", + "failedToConnect": "נכשל החיבור למכולה", + "console": "לְנַחֵם", + "selectShell": "בחר מעטפת", + "bash": "לַחֲבוֹט", + "sh": "ש", + "ash": "אֵפֶר", + "connect": "לְחַבֵּר", + "disconnect": "לְנַתֵק", + "notConnected": "לא מחובר", + "clickToConnect": "לחץ על התחבר כדי להתחיל סשן מעטפת", + "connectingTo": "מתחבר אל {{containerName}}...", + "containerNotFound": "המיכל לא נמצא", + "backToList": "חזרה לרשימה", + "logs": "יומני רישום", + "stats": "סטטיסטיקות", + "consoleTab": "לְנַחֵם", + "startContainerToAccess": "הפעל את המכולה כדי לגשת לקונסולה" + }, + "nav": { + "docker": "דוקר" + }, + "hosts": { + "tabDocker": "דוקר", + "dockerIntegration": "אינטגרציה עם Docker", + "enableDockerMonitor": "הפעל את Docker", + "enableDockerMonitorDesc": "ניטור וניהול של מכולות במארח זה באמצעות Docker", + "containerRuntime": "זמן ריצה של המכולה", + "containerRuntimeDesc": "בחר את ממשק שורת הפקודה (CLI) המשמש לניהול מכולות במארח זה", + "containerRuntimeDocker": "דוקר", + "containerRuntimePodman": "פודמן" + }, + "onboarding": { + "feature_docker": "דוקר", + "feature_docker_desc": "ראה קונטיינרים, קרא יומני רישום וצפה בסטטיסטיקות על כל מארח שמפעיל את Docker." + } +} diff --git a/plugins/docker/locales/translated/hi_IN.json b/plugins/docker/locales/translated/hi_IN.json new file mode 100644 index 000000000..2ddadfd83 --- /dev/null +++ b/plugins/docker/locales/translated/hi_IN.json @@ -0,0 +1,116 @@ +{ + "docker": { + "notEnabled": "इस होस्ट के लिए Docker सक्षम नहीं है", + "validating": "Docker सत्यापित कर रहा है...", + "connecting": "कनेक्ट हो रहा है...", + "error": "त्रुटि", + "version": "{{runtime}} {{version}}", + "connectionFailed": "Docker से कनेक्ट होने में विफल", + "containerStarted": "कंटेनर {{name}} प्रारंभ हुआ", + "failedToStartContainer": "कंटेनर {{name}} प्रारंभ करने में विफल", + "containerStopped": "कंटेनर {{name}} रुका", + "failedToStopContainer": "कंटेनर {{name}} रोकने में विफल", + "containerRestarted": "कंटेनर {{name}} पुनरारंभ हुआ", + "failedToRestartContainer": "कंटेनर {{name}} पुनरारंभ करने में विफल", + "containerPaused": "कंटेनर {{name}} विरामित", + "containerUnpaused": "कंटेनर {{name}} जारी", + "failedToTogglePauseContainer": "कंटेनर {{name}} के लिए विराम/जारी स्थिति बदलने में विफल", + "containerRemoved": "कंटेनर {{name}} हटा दिया गया", + "failedToRemoveContainer": "कंटेनर {{name}} हटाने में विफल", + "image": "इमेज", + "ports": "पोर्ट", + "noPorts": "कोई पोर्ट नहीं", + "start": "प्रारंभ करें", + "confirmRemoveContainer": "क्या आप वाकई कंटेनर '{{name}}' हटाना चाहते हैं? यह क्रिया पूर्ववत नहीं की जा सकती।", + "runningContainerWarning": "चेतावनी: यह कंटेनर वर्तमान में चल रहा है। हटाने पर पहले इसे रोका जाएगा।", + "loadingContainers": "कंटेनर लोड हो रहे हैं...", + "manager": "Docker प्रबंधक", + "autoRefresh": "स्वतः ताज़ा करें", + "timestamps": "टाइमस्टैम्प्स", + "lines": "पंक्तियाँ", + "filterLogs": "लॉग फ़िल्टर करें...", + "refresh": "ताज़ा करें", + "download": "डाउनलोड करें", + "clear": "साफ़ करें", + "logsDownloaded": "लॉग सफलतापूर्वक डाउनलोड हो गए", + "last50": "अंतिम 50", + "last100": "अंतिम 100", + "last500": "अंतिम 500", + "last1000": "अंतिम 1000", + "allLogs": "सभी लॉग", + "noLogsMatching": "\"{{query}}\" से मेल खाने वाले कोई लॉग नहीं हैं", + "noLogsAvailable": "कोई लॉग उपलब्ध नहीं", + "noContainersFound": "कोई कंटेनर नहीं मिले", + "noContainersFoundHint": "इस होस्ट पर कोई Docker कंटेनर उपलब्ध नहीं हैं", + "searchPlaceholder": "कंटेनर खोजें...", + "allStatuses": "सभी स्टेटस", + "stateRunning": "चालू", + "statePaused": "रुका हुआ", + "stateExited": "बंद", + "stateRestarting": "रीस्टार्ट हो रहा है", + "noContainersMatchFilters": "आपके फ़िल्टर से मेल खाने वाले कोई कंटेनर नहीं हैं", + "noContainersMatchFiltersHint": "अपनी खोज या फ़िल्टर मापदंड बदलकर देखें", + "failedToFetchStats": "कंटेनर के आँकड़े प्राप्त नहीं हो सके", + "containerNotRunning": "कंटेनर चालू नहीं है", + "startContainerToViewStats": "आँकड़े देखने के लिए कंटेनर चालू करें", + "loadingStats": "आँकड़े लोड हो रहे हैं...", + "errorLoadingStats": "आँकड़े लोड करने में त्रुटि", + "noStatsAvailable": "कोई आँकड़े उपलब्ध नहीं", + "cpuUsage": "CPU उपयोग", + "current": "वर्तमान", + "memoryUsage": "मेमोरी उपयोग", + "networkIo": "नेटवर्क I/O", + "input": "इनपुट", + "output": "आउटपुट", + "blockIo": "ब्लॉक I/O", + "read": "रीड", + "write": "राइट", + "pids": "PIDs", + "containerInformation": "कंटेनर जानकारी", + "name": "नाम", + "id": "आईडी", + "state": "स्थिति", + "containerMustBeRunning": "कंसोल तक पहुंचने के लिए कंटेनर चालू होना चाहिए", + "verificationCodePrompt": "सत्यापन कोड दर्ज करें", + "totpVerificationFailed": "TOTP सत्यापन विफल। कृपया पुनः प्रयास करें।", + "warpgateVerificationFailed": "Warpgate प्रमाणीकरण विफल। कृपया पुनः प्रयास करें।", + "connectedTo": "{{containerName}} से जुड़ा", + "disconnected": "डिस्कनेक्टेड", + "consoleError": "कंसोल त्रुटि", + "errorMessage": "त्रुटि: {{message}}", + "failedToConnect": "कंटेनर से जुड़ने में विफल", + "console": "कंसोल", + "selectShell": "शेल चुनें", + "bash": "Bash", + "sh": "sh", + "ash": "ash", + "connect": "कनेक्ट करें", + "disconnect": "डिस्कनेक्ट करें", + "notConnected": "कनेक्टेड नहीं", + "clickToConnect": "शेल सत्र शुरू करने के लिए कनेक्ट पर क्लिक करें", + "connectingTo": "{{containerName}} से कनेक्ट हो रहा है...", + "containerNotFound": "कंटेनर नहीं मिला", + "backToList": "सूची में वापस जाएं", + "logs": "लॉग", + "stats": "आंकड़े", + "consoleTab": "कंसोल", + "startContainerToAccess": "कंसोल तक पहुंचने के लिए कंटेनर चालू करें" + }, + "nav": { + "docker": "Docker" + }, + "hosts": { + "tabDocker": "Docker", + "dockerIntegration": "Docker एकीकरण", + "enableDockerMonitor": "Docker सक्षम करें", + "enableDockerMonitorDesc": "इस होस्ट पर Docker के माध्यम से कंटेनरों की निगरानी और प्रबंधन करें", + "containerRuntime": "कंटेनर रनटाइम", + "containerRuntimeDesc": "इस होस्ट पर कंटेनर प्रबंधन के लिए उपयोग किए जाने वाले CLI को चुनें", + "containerRuntimeDocker": "Docker", + "containerRuntimePodman": "Podman" + }, + "onboarding": { + "feature_docker": "डाक में काम करनेवाला मज़दूर", + "feature_docker_desc": "डॉकर चलाने वाले किसी भी होस्ट पर कंटेनर देखें, लॉग पढ़ें और आंकड़े देखें।" + } +} diff --git a/plugins/docker/locales/translated/hu_HU.json b/plugins/docker/locales/translated/hu_HU.json new file mode 100644 index 000000000..ec317ac09 --- /dev/null +++ b/plugins/docker/locales/translated/hu_HU.json @@ -0,0 +1,116 @@ +{ + "docker": { + "notEnabled": "A Docker nincs engedélyezve ehhez a gazdagéphez", + "validating": "Docker érvényesítése...", + "connecting": "Kapcsolódás...", + "error": "Hiba", + "version": "{{runtime}} {{version}}", + "connectionFailed": "Nem sikerült csatlakozni a Dockerhez", + "containerStarted": "{{name}} konténer elindítva", + "failedToStartContainer": "Nem sikerült elindítani a(z) {{name}} konténert", + "containerStopped": "Konténer {{name}} leállítva", + "failedToStopContainer": "Nem sikerült leállítani a(z) {{name}} konténert", + "containerRestarted": "{{name}} konténer újraindítva", + "failedToRestartContainer": "Nem sikerült újraindítani a konténert {{name}}", + "containerPaused": "{{name}} konténer szünetel", + "containerUnpaused": "{{name}} konténer szüneteltetése feloldva", + "failedToTogglePauseContainer": "Nem sikerült a szüneteltetési állapotot be- és kikapcsolni a következő konténernél: {{name}}", + "containerRemoved": "{{name}} konténer eltávolítva", + "failedToRemoveContainer": "Nem sikerült eltávolítani a(z) {{name}} konténert", + "image": "Kép", + "ports": "kikötők", + "noPorts": "Nincsenek portok", + "start": "Indul", + "confirmRemoveContainer": "Are you sure you want to remove the container '{{name}}'? This action cannot be undone.", + "runningContainerWarning": "Figyelmeztetés: Ez a konténer jelenleg fut. Eltávolítása először a konténer leállítását jelenti.", + "loadingContainers": "Konténerek betöltése...", + "manager": "Docker-kezelő", + "autoRefresh": "Automatikus frissítés", + "timestamps": "Időbélyegek", + "lines": "Vonalak", + "filterLogs": "Naplók szűrése...", + "refresh": "Frissítés", + "download": "Letöltés", + "clear": "Világos", + "logsDownloaded": "Naplók sikeresen letöltve", + "last50": "Utolsó 50", + "last100": "Utolsó 100", + "last500": "Utolsó 500", + "last1000": "Utolsó 1000", + "allLogs": "Minden napló", + "noLogsMatching": "Nincsenek a következőnek megfelelő naplók: \"{{query}}\"", + "noLogsAvailable": "Nincsenek elérhető naplók", + "noContainersFound": "Nem találhatók konténerek", + "noContainersFoundHint": "Nincsenek elérhető Docker konténerek ezen a gazdagépen", + "searchPlaceholder": "Konténerek keresése...", + "allStatuses": "Minden állapot", + "stateRunning": "Futás", + "statePaused": "Szüneteltetett", + "stateExited": "Kilépett", + "stateRestarting": "Újraindítás", + "noContainersMatchFilters": "Egyetlen tároló sem felel meg a szűrőknek", + "noContainersMatchFiltersHint": "Próbálja meg módosítani a keresési vagy szűrési feltételeket", + "failedToFetchStats": "Nem sikerült lekérni a konténer statisztikáit", + "containerNotRunning": "A konténer nem működik", + "startContainerToViewStats": "Indítsa el a konténert a statisztikák megtekintéséhez", + "loadingStats": "Statisztikák betöltése...", + "errorLoadingStats": "Hiba a statisztikák betöltése során", + "noStatsAvailable": "Nincsenek elérhető statisztikák", + "cpuUsage": "CPU-használat", + "current": "Jelenlegi", + "memoryUsage": "Memóriahasználat", + "networkIo": "Hálózati I/O", + "input": "Bemenet", + "output": "Kimenet", + "blockIo": "Blokk I/O", + "read": "Olvas", + "write": "Írás", + "pids": "PID-ek", + "containerInformation": "Konténerinformációk", + "name": "Név", + "id": "azonosító", + "state": "Állami", + "containerMustBeRunning": "A konténernek futnia kell a konzol eléréséhez", + "verificationCodePrompt": "Írja be az ellenőrző kódot", + "totpVerificationFailed": "A TOTP ellenőrzése sikertelen. Próbáld újra.", + "warpgateVerificationFailed": "A Warpgate hitelesítése sikertelen. Próbáld újra.", + "connectedTo": "Csatlakoztatva ehhez: {{containerName}}", + "disconnected": "Szétkapcsolt", + "consoleError": "Konzolhiba", + "errorMessage": "Hiba: {{message}}", + "failedToConnect": "Nem sikerült csatlakozni a konténerhez", + "console": "Konzol", + "selectShell": "Válassza ki a héjat", + "bash": "Bash", + "sh": "sh", + "ash": "hamu", + "connect": "Csatlakozás", + "disconnect": "Leválasztás", + "notConnected": "Nincs csatlakoztatva", + "clickToConnect": "Kattintson a Csatlakozás gombra a shell munkamenet elindításához", + "connectingTo": "Kapcsolódás ehhez: {{containerName}}...", + "containerNotFound": "A konténer nem található", + "backToList": "Vissza a listához", + "logs": "Naplók", + "stats": "Statisztikák", + "consoleTab": "Konzol", + "startContainerToAccess": "Indítsa el a konténert a konzol eléréséhez" + }, + "nav": { + "docker": "Dokkmunkás" + }, + "hosts": { + "tabDocker": "Dokkmunkás", + "dockerIntegration": "Docker-integráció", + "enableDockerMonitor": "Docker engedélyezése", + "enableDockerMonitorDesc": "Dockeren keresztül figyelheti és kezelheti a konténereket ezen a gazdagépen", + "containerRuntime": "Konténer futásideje", + "containerRuntimeDesc": "Válassza ki a gazdagépen a konténerkezeléshez használt parancssori felületet", + "containerRuntimeDocker": "Dokkmunkás", + "containerRuntimePodman": "Podman" + }, + "onboarding": { + "feature_docker": "Dokkmunkás", + "feature_docker_desc": "Tekintsd meg a konténereket, olvasd el a naplókat és figyeld a statisztikákat bármelyik Dockert futtató gazdagépen." + } +} diff --git a/plugins/docker/locales/translated/id_ID.json b/plugins/docker/locales/translated/id_ID.json new file mode 100644 index 000000000..8852358ec --- /dev/null +++ b/plugins/docker/locales/translated/id_ID.json @@ -0,0 +1,116 @@ +{ + "docker": { + "notEnabled": "Docker tidak diaktifkan untuk host ini.", + "validating": "Memvalidasi Docker...", + "connecting": "Menghubungkan...", + "error": "Kesalahan", + "version": "{{runtime}} {{version}}", + "connectionFailed": "Gagal terhubung ke Docker", + "containerStarted": "Kontainer {{name}} dimulai", + "failedToStartContainer": "Gagal memulai kontainer {{name}}", + "containerStopped": "Kontainer {{name}} berhenti", + "failedToStopContainer": "Gagal menghentikan kontainer {{name}}", + "containerRestarted": "Kontainer {{name}} dimulai ulang", + "failedToRestartContainer": "Gagal memulai ulang kontainer {{name}}", + "containerPaused": "Kontainer {{name}} berhenti", + "containerUnpaused": "Kontainer {{name}} tidak dijeda", + "failedToTogglePauseContainer": "Gagal mengubah status jeda untuk kontainer {{name}}", + "containerRemoved": "Kontainer {{name}} dihapus", + "failedToRemoveContainer": "Gagal menghapus kontainer {{name}}", + "image": "Gambar", + "ports": "Pelabuhan", + "noPorts": "Tidak ada port", + "start": "Awal", + "confirmRemoveContainer": "Apakah Anda yakin ingin menghapus kontainer '{{name}}'? Tindakan ini tidak dapat dibatalkan.", + "runningContainerWarning": "Peringatan: Kontainer ini sedang berjalan. Menghapusnya akan menghentikan kontainer terlebih dahulu.", + "loadingContainers": "Memuat kontainer...", + "manager": "Manajer Docker", + "autoRefresh": "Penyegaran Otomatis", + "timestamps": "Cap waktu", + "lines": "Garis", + "filterLogs": "Filter log...", + "refresh": "Menyegarkan", + "download": "Unduh", + "clear": "Jernih", + "logsDownloaded": "Log berhasil diunduh.", + "last50": "50 Terakhir", + "last100": "100 terakhir", + "last500": "500 Terakhir", + "last1000": "1000 terakhir", + "allLogs": "Semua Log", + "noLogsMatching": "Tidak ada log yang cocok dengan \"{{query}}\"", + "noLogsAvailable": "Tidak ada log yang tersedia.", + "noContainersFound": "Tidak ditemukan wadah apa pun", + "noContainersFoundHint": "Tidak ada kontainer Docker yang tersedia di host ini.", + "searchPlaceholder": "Cari kontainer...", + "allStatuses": "Semua Status", + "stateRunning": "Berlari", + "statePaused": "Dijeda", + "stateExited": "Keluar", + "stateRestarting": "Memulai ulang", + "noContainersMatchFilters": "Tidak ada wadah yang sesuai dengan filter Anda.", + "noContainersMatchFiltersHint": "Cobalah menyesuaikan kriteria pencarian atau filter Anda.", + "failedToFetchStats": "Gagal mengambil statistik kontainer", + "containerNotRunning": "Kontainer tidak berjalan", + "startContainerToViewStats": "Jalankan kontainer untuk melihat statistik.", + "loadingStats": "Memuat statistik...", + "errorLoadingStats": "Terjadi kesalahan saat memuat statistik.", + "noStatsAvailable": "Tidak ada statistik yang tersedia.", + "cpuUsage": "Penggunaan CPU", + "current": "Saat ini", + "memoryUsage": "Penggunaan Memori", + "networkIo": "Input/Output Jaringan", + "input": "Masukan", + "output": "Keluaran", + "blockIo": "Blok I/O", + "read": "Membaca", + "write": "Menulis", + "pids": "PID", + "containerInformation": "Informasi Kontainer", + "name": "Nama", + "id": "PENGENAL", + "state": "Negara", + "containerMustBeRunning": "Kontainer harus berjalan agar dapat mengakses konsol.", + "verificationCodePrompt": "Masukkan kode verifikasi", + "totpVerificationFailed": "Verifikasi TOTP gagal. Silakan coba lagi.", + "warpgateVerificationFailed": "Autentikasi Warpgate gagal. Silakan coba lagi.", + "connectedTo": "Terhubung ke {{containerName}}", + "disconnected": "Terputus", + "consoleError": "Kesalahan konsol", + "errorMessage": "Kesalahan: {{message}}", + "failedToConnect": "Gagal terhubung ke kontainer", + "console": "Menghibur", + "selectShell": "Pilih cangkang", + "bash": "Pesta", + "sh": "sh", + "ash": "abu", + "connect": "Menghubungkan", + "disconnect": "Memutuskan", + "notConnected": "Tidak terhubung", + "clickToConnect": "Klik sambungkan untuk memulai sesi shell.", + "connectingTo": "Menghubungkan ke {{containerName}}...", + "containerNotFound": "Kontainer tidak ditemukan", + "backToList": "Kembali ke Daftar", + "logs": "Log", + "stats": "Statistik", + "consoleTab": "Menghibur", + "startContainerToAccess": "Jalankan kontainer untuk mengakses konsol." + }, + "nav": { + "docker": "Buruh pelabuhan" + }, + "hosts": { + "tabDocker": "Buruh pelabuhan", + "dockerIntegration": "Integrasi Docker", + "enableDockerMonitor": "Aktifkan Docker", + "enableDockerMonitorDesc": "Pantau dan kelola kontainer di host ini melalui Docker.", + "containerRuntime": "Lingkungan Eksekusi Kontainer", + "containerRuntimeDesc": "Pilih CLI yang digunakan untuk manajemen kontainer pada host ini.", + "containerRuntimeDocker": "Buruh pelabuhan", + "containerRuntimePodman": "Podman" + }, + "onboarding": { + "feature_docker": "Buruh pelabuhan", + "feature_docker_desc": "Lihat kontainer, baca log, dan pantau statistik pada host mana pun yang menjalankan Docker." + } +} diff --git a/plugins/docker/locales/translated/it_IT.json b/plugins/docker/locales/translated/it_IT.json new file mode 100644 index 000000000..e8cdb6be1 --- /dev/null +++ b/plugins/docker/locales/translated/it_IT.json @@ -0,0 +1,116 @@ +{ + "docker": { + "notEnabled": "Docker non è abilitato per questo host", + "validating": "Convalida Docker in corso...", + "connecting": "Connessione in corso...", + "error": "Errore", + "version": "{{runtime}} {{version}}", + "connectionFailed": "Connessione a Docker non riuscita", + "containerStarted": "Container {{name}} avviato", + "failedToStartContainer": "Impossibile avviare il container {{name}}", + "containerStopped": "Container {{name}} arrestato", + "failedToStopContainer": "Impossibile arrestare il container {{name}}", + "containerRestarted": "Container {{name}} riavviato", + "failedToRestartContainer": "Impossibile riavviare il container {{name}}", + "containerPaused": "Container {{name}} in pausa", + "containerUnpaused": "Container {{name}} riattivato", + "failedToTogglePauseContainer": "Impossibile cambiare lo stato di pausa del container {{name}}", + "containerRemoved": "Container {{name}} rimosso", + "failedToRemoveContainer": "Impossibile rimuovere il container {{name}}", + "image": "Immagine", + "ports": "Porte", + "noPorts": "Nessuna porta", + "start": "Avvia", + "confirmRemoveContainer": "Sei sicuro di voler rimuovere il container '{{name}}'? Questa azione non può essere annullata.", + "runningContainerWarning": "Attenzione: questo container è attualmente in esecuzione. La rimozione lo arresterà prima.", + "loadingContainers": "Caricamento container in corso...", + "manager": "Gestore Docker", + "autoRefresh": "Aggiornamento automatico", + "timestamps": "Timestamp", + "lines": "Righe", + "filterLogs": "Filtra log...", + "refresh": "Aggiorna", + "download": "Scarica", + "clear": "Pulisci", + "logsDownloaded": "Log scaricati con successo", + "last50": "Ultime 50", + "last100": "Ultime 100", + "last500": "Ultime 500", + "last1000": "Ultime 1000", + "allLogs": "Tutti i log", + "noLogsMatching": "Nessun log corrispondente a \"{{query}}\"", + "noLogsAvailable": "Nessun log disponibile", + "noContainersFound": "Nessun contenitore trovato", + "noContainersFoundHint": "Nessun contenitore Docker disponibile su questo host", + "searchPlaceholder": "Cerca contenitori...", + "allStatuses": "Tutti gli stati", + "stateRunning": "In esecuzione", + "statePaused": "In pausa", + "stateExited": "Terminato", + "stateRestarting": "In riavvio", + "noContainersMatchFilters": "Nessun contenitore corrisponde ai filtri", + "noContainersMatchFiltersHint": "Prova a modificare i criteri di ricerca o di filtro", + "failedToFetchStats": "Impossibile recuperare le statistiche del contenitore", + "containerNotRunning": "Contenitore non in esecuzione", + "startContainerToViewStats": "Avvia il contenitore per visualizzare le statistiche", + "loadingStats": "Caricamento statistiche...", + "errorLoadingStats": "Errore nel caricamento delle statistiche", + "noStatsAvailable": "Nessuna statistica disponibile", + "cpuUsage": "Utilizzo CPU", + "current": "Corrente", + "memoryUsage": "Utilizzo memoria", + "networkIo": "I/O di rete", + "input": "Input", + "output": "Output", + "blockIo": "Block I/O", + "read": "Lettura", + "write": "Scrittura", + "pids": "PIDs", + "containerInformation": "Informazioni sul container", + "name": "Nome", + "id": "ID", + "state": "Stato", + "containerMustBeRunning": "Il container deve essere in esecuzione per accedere alla console", + "verificationCodePrompt": "Inserisci il codice di verifica", + "totpVerificationFailed": "Verifica TOTP fallita. Riprova.", + "warpgateVerificationFailed": "Autenticazione Warpgate fallita. Riprova.", + "connectedTo": "Connesso a {{containerName}}", + "disconnected": "Disconnesso", + "consoleError": "Errore console", + "errorMessage": "Errore: {{message}}", + "failedToConnect": "Connessione al container fallita", + "console": "Console", + "selectShell": "Seleziona shell", + "bash": "Bash", + "sh": "sh", + "ash": "ash", + "connect": "Connetti", + "disconnect": "Disconnetti", + "notConnected": "Non connesso", + "clickToConnect": "Clicca Connetti per avviare una sessione shell", + "connectingTo": "Connessione a {{containerName}} in corso...", + "containerNotFound": "Container non trovato", + "backToList": "Torna all'elenco", + "logs": "Log", + "stats": "Statistiche", + "consoleTab": "Console", + "startContainerToAccess": "Avvia il container per accedere alla console" + }, + "nav": { + "docker": "Docker" + }, + "hosts": { + "tabDocker": "Docker", + "dockerIntegration": "Integrazione Docker", + "enableDockerMonitor": "Abilita Docker", + "enableDockerMonitorDesc": "Monitora e gestisci i container su questo host tramite Docker", + "containerRuntime": "Runtime container", + "containerRuntimeDesc": "Scegli la CLI utilizzata per la gestione dei container su questo host", + "containerRuntimeDocker": "Docker", + "containerRuntimePodman": "Podman" + }, + "onboarding": { + "feature_docker": "Docker", + "feature_docker_desc": "Visualizza i container, leggi i log e controlla le statistiche su qualsiasi host che esegue Docker." + } +} diff --git a/plugins/docker/locales/translated/ja_JP.json b/plugins/docker/locales/translated/ja_JP.json new file mode 100644 index 000000000..191baff1b --- /dev/null +++ b/plugins/docker/locales/translated/ja_JP.json @@ -0,0 +1,116 @@ +{ + "docker": { + "notEnabled": "このホストではDockerが有効になっていません", + "validating": "Dockerを検証中...", + "connecting": "接続中...", + "error": "エラー", + "version": "{{runtime}} {{version}}", + "connectionFailed": "Dockerへの接続に失敗しました", + "containerStarted": "コンテナ {{name}} が起動しました", + "failedToStartContainer": "コンテナ {{name}} の起動に失敗しました", + "containerStopped": "コンテナ {{name}} が停止しました", + "failedToStopContainer": "コンテナ {{name}} の停止に失敗しました", + "containerRestarted": "コンテナ {{name}} が再起動しました", + "failedToRestartContainer": "コンテナ {{name}} の再起動に失敗しました", + "containerPaused": "コンテナ {{name}} が一時停止しました", + "containerUnpaused": "コンテナ {{name}} の一時停止が解除されました", + "failedToTogglePauseContainer": "コンテナ {{name}} の一時停止状態の切り替えに失敗しました", + "containerRemoved": "コンテナ {{name}} が削除されました", + "failedToRemoveContainer": "コンテナ {{name}} の削除に失敗しました", + "image": "イメージ", + "ports": "ポート", + "noPorts": "ポートなし", + "start": "起動", + "confirmRemoveContainer": "コンテナ '{{name}}' を削除してもよろしいですか? この操作は元に戻せません。", + "runningContainerWarning": "警告: このコンテナは現在実行中です。削除すると、まずコンテナが停止されます。", + "loadingContainers": "コンテナを読み込み中...", + "manager": "Docker マネージャー", + "autoRefresh": "自動更新", + "timestamps": "タイムスタンプ", + "lines": "行数", + "filterLogs": "ログをフィルター...", + "refresh": "再読み込み", + "download": "ダウンロード", + "clear": "クリア", + "logsDownloaded": "ログのダウンロードに成功しました", + "last50": "直近50件", + "last100": "直近100件", + "last500": "直近500件", + "last1000": "直近1000件", + "allLogs": "すべてのログ", + "noLogsMatching": "検索条件 \"{{query}}\" に一致するログはありません", + "noLogsAvailable": "利用可能なログはありません", + "noContainersFound": "コンテナが見つかりません", + "noContainersFoundHint": "このホストには利用可能なDockerコンテナがありません", + "searchPlaceholder": "コンテナを検索...", + "allStatuses": "すべての状態", + "stateRunning": "実行中", + "statePaused": "一時停止中", + "stateExited": "終了済み", + "stateRestarting": "再起動中", + "noContainersMatchFilters": "条件に一致するコンテナはありません", + "noContainersMatchFiltersHint": "検索条件またはフィルター条件を調整してください", + "failedToFetchStats": "コンテナの統計情報の取得に失敗しました", + "containerNotRunning": "コンテナが実行されていません", + "startContainerToViewStats": "統計情報を表示するにはコンテナを起動してください", + "loadingStats": "統計情報を読み込み中...", + "errorLoadingStats": "統計情報の読み込みエラー", + "noStatsAvailable": "利用可能な統計情報はありません", + "cpuUsage": "CPU使用率", + "current": "現在", + "memoryUsage": "メモリ使用量", + "networkIo": "ネットワークI/O", + "input": "受信", + "output": "出力", + "blockIo": "ブロック I/O", + "read": "読み取り", + "write": "書き込み", + "pids": "PIDs", + "containerInformation": "コンテナ情報", + "name": "名前", + "id": "ID", + "state": "状態", + "containerMustBeRunning": "コンソールにアクセスするにはコンテナが実行中である必要があります", + "verificationCodePrompt": "認証コードを入力してください", + "totpVerificationFailed": "TOTP認証に失敗しました。もう一度お試しください。", + "warpgateVerificationFailed": "Warpgate認証に失敗しました。もう一度お試しください。", + "connectedTo": "{{containerName}}に接続しました", + "disconnected": "切断されました", + "consoleError": "コンソールエラー", + "errorMessage": "エラー: {{message}}", + "failedToConnect": "コンテナに接続できませんでした", + "console": "コンソール", + "selectShell": "シェルを選択", + "bash": "Bash", + "sh": "sh", + "ash": "ash", + "connect": "接続", + "disconnect": "切断", + "notConnected": "未接続", + "clickToConnect": "接続ボタンをクリックしてシェルセッションを開始", + "connectingTo": "{{containerName}}に接続中...", + "containerNotFound": "コンテナが見つかりません", + "backToList": "一覧に戻る", + "logs": "ログ", + "stats": "統計", + "consoleTab": "コンソール", + "startContainerToAccess": "コンテナを起動してコンソールにアクセスしてください" + }, + "nav": { + "docker": "Docker" + }, + "hosts": { + "tabDocker": "Docker", + "dockerIntegration": "Docker統合", + "enableDockerMonitor": "Docker有効化", + "enableDockerMonitorDesc": "Docker経由でこのホスト上のコンテナを監視・管理します。", + "containerRuntime": "コンテナランタイム", + "containerRuntimeDesc": "このホストのコンテナ管理に使用するCLIを選択します。", + "containerRuntimeDocker": "Docker", + "containerRuntimePodman": "Podman" + }, + "onboarding": { + "feature_docker": "ドッカー", + "feature_docker_desc": "Dockerを実行している任意のホスト上で、コンテナの表示、ログの読み取り、統計情報の監視が可能です。" + } +} diff --git a/plugins/docker/locales/translated/ko_KR.json b/plugins/docker/locales/translated/ko_KR.json new file mode 100644 index 000000000..164c2b24b --- /dev/null +++ b/plugins/docker/locales/translated/ko_KR.json @@ -0,0 +1,116 @@ +{ + "docker": { + "notEnabled": "이 호스트에서 Docker가 활성화되지 않았습니다", + "validating": "Docker 확인 중...", + "connecting": "연결 중...", + "error": "오류", + "version": "{{runtime}} {{version}}", + "connectionFailed": "Docker에 연결하지 못했습니다", + "containerStarted": "컨테이너 {{name}} 시작됨", + "failedToStartContainer": "컨테이너 {{name}} 시작에 실패했습니다", + "containerStopped": "컨테이너 {{name}} 중지됨", + "failedToStopContainer": "컨테이너 {{name}} 중지에 실패했습니다", + "containerRestarted": "컨테이너 {{name}} 재시작됨", + "failedToRestartContainer": "컨테이너 {{name}} 재시작에 실패했습니다", + "containerPaused": "컨테이너 {{name}} 일시 정지됨", + "containerUnpaused": "컨테이너 {{name}} 일시 정지 해제됨", + "failedToTogglePauseContainer": "컨테이너 {{name}}의 일시 정지 상태 전환에 실패했습니다", + "containerRemoved": "컨테이너 {{name}} 제거됨", + "failedToRemoveContainer": "컨테이너 {{name}} 제거에 실패했습니다", + "image": "이미지", + "ports": "포트", + "noPorts": "포트 없음", + "start": "시작", + "confirmRemoveContainer": "컨테이너 '{{name}}'을(를) 제거하시겠습니까? 이 작업은 되돌릴 수 없습니다.", + "runningContainerWarning": "경고: 이 컨테이너는 현재 실행 중입니다. 제거하면 먼저 컨테이너가 중지됩니다.", + "loadingContainers": "컨테이너 로딩 중...", + "manager": "Docker 관리자", + "autoRefresh": "자동 새로고침", + "timestamps": "타임스탬프", + "lines": "라인", + "filterLogs": "로그 필터...", + "refresh": "새로고침", + "download": "다운로드", + "clear": "지우기", + "logsDownloaded": "로그가 성공적으로 다운로드되었습니다.", + "last50": "최근 50개", + "last100": "최근 100개", + "last500": "최근 500개", + "last1000": "최근 1000개", + "allLogs": "전체 로그", + "noLogsMatching": "\"{{query}}\"와 일치하는 로그가 없습니다.", + "noLogsAvailable": "사용 가능한 로그가 없습니다.", + "noContainersFound": "컨테이너를 찾을 수 없습니다.", + "noContainersFoundHint": "이 호스트에 Docker 컨테이너가 없습니다.", + "searchPlaceholder": "컨테이너 검색...", + "allStatuses": "모든 상태", + "stateRunning": "실행 중", + "statePaused": "일시 중지", + "stateExited": "종료됨", + "stateRestarting": "다시 시작 중", + "noContainersMatchFilters": "필터와 일치하는 컨테이너가 없습니다.", + "noContainersMatchFiltersHint": "검색 또는 필터 조건을 조정해 보세요.", + "failedToFetchStats": "컨테이너 통계를 가져오지 못했습니다.", + "containerNotRunning": "컨테이너가 실행 중이 아닙니다.", + "startContainerToViewStats": "통계를 보려면 컨테이너를 시작하세요.", + "loadingStats": "통계 로딩 중...", + "errorLoadingStats": "통계 로딩 오류", + "noStatsAvailable": "사용 가능한 통계가 없습니다.", + "cpuUsage": "CPU 사용량", + "current": "현재", + "memoryUsage": "메모리 사용량", + "networkIo": "네트워크 I/O", + "input": "입력", + "output": "출력", + "blockIo": "블록 I/O", + "read": "읽기", + "write": "쓰기", + "pids": "PID", + "containerInformation": "컨테이너 정보", + "name": "이름", + "id": "ID", + "state": "상태", + "containerMustBeRunning": "컨테이너가 실행 중이어야 콘솔에 접근할 수 있습니다", + "verificationCodePrompt": "인증 코드를 입력하세요", + "totpVerificationFailed": "TOTP 인증에 실패했습니다. 다시 시도하세요.", + "warpgateVerificationFailed": "Warpgate 인증에 실패했습니다. 다시 시도하세요.", + "connectedTo": "{{containerName}}에 연결됨", + "disconnected": "연결 끊김", + "consoleError": "콘솔 오류", + "errorMessage": "오류: {{message}}", + "failedToConnect": "컨테이너에 연결하지 못했습니다", + "console": "콘솔", + "selectShell": "셸 선택", + "bash": "Bash", + "sh": "sh", + "ash": "ash", + "connect": "연결", + "disconnect": "연결 해제", + "notConnected": "연결되지 않음", + "clickToConnect": "연결을 클릭하여 셸 세션을 시작하세요", + "connectingTo": "{{containerName}}에 연결 중...", + "containerNotFound": "컨테이너를 찾을 수 없음", + "backToList": "목록으로 돌아가기", + "logs": "로그", + "stats": "통계", + "consoleTab": "콘솔", + "startContainerToAccess": "컨테이너를 시작하여 콘솔에 접근하세요" + }, + "nav": { + "docker": "Docker" + }, + "hosts": { + "tabDocker": "Docker", + "dockerIntegration": "Docker 통합", + "enableDockerMonitor": "Docker 활성화", + "enableDockerMonitorDesc": "Docker를 통해 이 호스트의 컨테이너를 모니터링하고 관리합니다.", + "containerRuntime": "컨테이너 런타임", + "containerRuntimeDesc": "이 호스트에서 컨테이너 관리에 사용할 CLI를 선택합니다.", + "containerRuntimeDocker": "Docker", + "containerRuntimePodman": "Podman" + }, + "onboarding": { + "feature_docker": "도커", + "feature_docker_desc": "Docker가 실행 중인 모든 호스트에서 컨테이너를 확인하고, 로그를 읽고, 통계를 볼 수 있습니다." + } +} diff --git a/plugins/docker/locales/translated/nl_NL.json b/plugins/docker/locales/translated/nl_NL.json new file mode 100644 index 000000000..8c8abbf4a --- /dev/null +++ b/plugins/docker/locales/translated/nl_NL.json @@ -0,0 +1,116 @@ +{ + "docker": { + "notEnabled": "Docker is niet ingeschakeld voor deze host.", + "validating": "Docker valideren...", + "connecting": "Verbinden...", + "error": "Fout", + "version": "{{runtime}} {{version}}", + "connectionFailed": "Verbinding met Docker mislukt.", + "containerStarted": "Container {{name}} gestart", + "failedToStartContainer": "Het starten van de container is mislukt {{name}}", + "containerStopped": "Container {{name}} is gestopt", + "failedToStopContainer": "Het is niet gelukt om de container {{name}} te stoppen.", + "containerRestarted": "Container {{name}} opnieuw opgestart", + "failedToRestartContainer": "Het opnieuw opstarten van de container is mislukt {{name}}", + "containerPaused": "Container {{name}} gepauzeerd", + "containerUnpaused": "Container {{name}} is niet langer gepauzeerd", + "failedToTogglePauseContainer": "Het is niet gelukt om de pauzestatus voor container {{name}} te wijzigen.", + "containerRemoved": "Container {{name}} verwijderd", + "failedToRemoveContainer": "Het verwijderen van de container is mislukt {{name}}", + "image": "Afbeelding", + "ports": "Havens", + "noPorts": "Geen poorten", + "start": "Begin", + "confirmRemoveContainer": "Weet je zeker dat je de container '{{name}}' wilt verwijderen? Deze actie kan niet ongedaan worden gemaakt.", + "runningContainerWarning": "Waarschuwing: Deze container is momenteel actief. Als u deze verwijdert, wordt de container eerst gestopt.", + "loadingContainers": "Containers laden...", + "manager": "Docker Manager", + "autoRefresh": "Automatisch vernieuwen", + "timestamps": "Tijdstempels", + "lines": "Lijnen", + "filterLogs": "Filterlogboeken...", + "refresh": "Vernieuwen", + "download": "Download", + "clear": "Duidelijk", + "logsDownloaded": "Logbestanden succesvol gedownload.", + "last50": "Laatste 50", + "last100": "Laatste 100", + "last500": "Laatste 500", + "last1000": "Laatste 1000", + "allLogs": "Alle logboeken", + "noLogsMatching": "Geen logbestanden gevonden die overeenkomen met \"{{query}}\"", + "noLogsAvailable": "Geen logbestanden beschikbaar", + "noContainersFound": "Geen containers gevonden", + "noContainersFoundHint": "Er zijn geen Docker-containers beschikbaar op deze host.", + "searchPlaceholder": "Containers doorzoeken...", + "allStatuses": "Alle statussen", + "stateRunning": "Rennen", + "statePaused": "Gepauzeerd", + "stateExited": "Uitgang", + "stateRestarting": "Opnieuw opstarten", + "noContainersMatchFilters": "Geen containers komen overeen met uw filters.", + "noContainersMatchFiltersHint": "Probeer je zoek- of filtercriteria aan te passen.", + "failedToFetchStats": "Het ophalen van containerstatistieken is mislukt.", + "containerNotRunning": "Container draait niet", + "startContainerToViewStats": "Start de container om de statistieken te bekijken.", + "loadingStats": "Statistieken laden...", + "errorLoadingStats": "Fout bij het laden van statistieken", + "noStatsAvailable": "Geen statistieken beschikbaar", + "cpuUsage": "CPU-gebruik", + "current": "Huidig", + "memoryUsage": "Geheugengebruik", + "networkIo": "Netwerk I/O", + "input": "Invoer", + "output": "Uitvoer", + "blockIo": "Blok I/O", + "read": "Lezen", + "write": "Schrijven", + "pids": "PID's", + "containerInformation": "Containerinformatie", + "name": "Naam", + "id": "ID", + "state": "Staat", + "containerMustBeRunning": "De container moet actief zijn om toegang te krijgen tot de console.", + "verificationCodePrompt": "Voer de verificatiecode in.", + "totpVerificationFailed": "TOTP-verificatie mislukt. Probeer het opnieuw.", + "warpgateVerificationFailed": "Authenticatie via Warpgate is mislukt. Probeer het opnieuw.", + "connectedTo": "Verbonden met {{containerName}}", + "disconnected": "Verbinding verbroken", + "consoleError": "Consolefout", + "errorMessage": "Fout: {{message}}", + "failedToConnect": "Verbinding met de container mislukt.", + "console": "Troosten", + "selectShell": "Selecteer shell", + "bash": "Knal", + "sh": "sh", + "ash": "as", + "connect": "Verbinden", + "disconnect": "Verbinding verbreken", + "notConnected": "Niet verbonden", + "clickToConnect": "Klik op 'Verbinden' om een shellsessie te starten.", + "connectingTo": "Verbinding maken met {{containerName}}...", + "containerNotFound": "Container niet gevonden", + "backToList": "Terug naar de lijst", + "logs": "Logboeken", + "stats": "Statistieken", + "consoleTab": "Troosten", + "startContainerToAccess": "Start de container om toegang te krijgen tot de console." + }, + "nav": { + "docker": "Docker" + }, + "hosts": { + "tabDocker": "Docker", + "dockerIntegration": "Docker-integratie", + "enableDockerMonitor": "Docker inschakelen", + "enableDockerMonitorDesc": "Containers op deze host bewaken en beheren via Docker.", + "containerRuntime": "Container Runtime", + "containerRuntimeDesc": "Kies de CLI die op deze host wordt gebruikt voor containerbeheer.", + "containerRuntimeDocker": "Docker", + "containerRuntimePodman": "Podman" + }, + "onboarding": { + "feature_docker": "Docker", + "feature_docker_desc": "Bekijk containers, lees logboeken en bekijk statistieken op elke host waarop Docker draait." + } +} diff --git a/plugins/docker/locales/translated/no_NO.json b/plugins/docker/locales/translated/no_NO.json new file mode 100644 index 000000000..3fdb7f2f1 --- /dev/null +++ b/plugins/docker/locales/translated/no_NO.json @@ -0,0 +1,116 @@ +{ + "docker": { + "notEnabled": "Docker er ikke aktivert for denne verten", + "validating": "Validerer Docker...", + "connecting": "Kobler til...", + "error": "Feil", + "version": "{{runtime}} {{version}}", + "connectionFailed": "Kunne ikke koble til Docker", + "containerStarted": "Container {{name}} startet", + "failedToStartContainer": "Kunne ikke starte containeren {{name}}", + "containerStopped": "Container {{name}} stoppet", + "failedToStopContainer": "Klarte ikke å stoppe containeren {{name}}", + "containerRestarted": "Beholder {{name}} startet på nytt", + "failedToRestartContainer": "Kunne ikke starte beholderen {{name}} på nytt", + "containerPaused": "Beholder {{name}} satt på pause", + "containerUnpaused": "Beholder {{name}} er ikke satt på pause lenger", + "failedToTogglePauseContainer": "Kunne ikke slå av/på pausetilstand for container {{name}}", + "containerRemoved": "Beholder {{name}} fjernet", + "failedToRemoveContainer": "Kunne ikke fjerne beholderen {{name}}", + "image": "Bilde", + "ports": "Porter", + "noPorts": "Ingen porter", + "start": "Start", + "confirmRemoveContainer": "Er du sikker på at du vil fjerne beholderen '{{name}}'? Denne handlingen kan ikke angres.", + "runningContainerWarning": "Advarsel: Denne beholderen kjører for øyeblikket. Hvis du fjerner den, stoppes beholderen først.", + "loadingContainers": "Laster containere ...", + "manager": "Docker Manager", + "autoRefresh": "Automatisk oppdatering", + "timestamps": "Tidsstempler", + "lines": "Linjer", + "filterLogs": "Filtrer logger...", + "refresh": "Forfriske", + "download": "Last ned", + "clear": "Klar", + "logsDownloaded": "Loggene er lastet ned", + "last50": "Siste 50", + "last100": "Siste 100", + "last500": "Siste 500", + "last1000": "Siste 1000", + "allLogs": "Alle logger", + "noLogsMatching": "Ingen logger som samsvarer med «{{query}}»", + "noLogsAvailable": "Ingen logger tilgjengelig", + "noContainersFound": "Ingen containere funnet", + "noContainersFoundHint": "Ingen Docker-containere er tilgjengelige på denne verten", + "searchPlaceholder": "Søk i containere...", + "allStatuses": "Alle statuser", + "stateRunning": "Løping", + "statePaused": "Pauset", + "stateExited": "Avsluttet", + "stateRestarting": "Starter på nytt", + "noContainersMatchFilters": "Ingen beholdere samsvarer med filtrene dine", + "noContainersMatchFiltersHint": "Prøv å justere søke- eller filterkriteriene dine", + "failedToFetchStats": "Kunne ikke hente containerstatistikk", + "containerNotRunning": "Beholderen kjører ikke", + "startContainerToViewStats": "Start beholderen for å se statistikk", + "loadingStats": "Laster inn statistikk ...", + "errorLoadingStats": "Feil ved lasting av statistikk", + "noStatsAvailable": "Ingen statistikk tilgjengelig", + "cpuUsage": "CPU-bruk", + "current": "Nåværende", + "memoryUsage": "Minnebruk", + "networkIo": "Nettverk I/O", + "input": "Inndata", + "output": "Produksjon", + "blockIo": "Blokk I/O", + "read": "Lese", + "write": "Skrive", + "pids": "PID-er", + "containerInformation": "Containerinformasjon", + "name": "Navn", + "id": "ID", + "state": "Tilstand", + "containerMustBeRunning": "Containeren må kjøre for å få tilgang til konsollen", + "verificationCodePrompt": "Skriv inn bekreftelseskoden", + "totpVerificationFailed": "TOTP-verifisering mislyktes. Prøv på nytt.", + "warpgateVerificationFailed": "Warpgate-autentisering mislyktes. Prøv på nytt.", + "connectedTo": "Koblet til {{containerName}}", + "disconnected": "Frakoblet", + "consoleError": "Konsollfeil", + "errorMessage": "Feil: {{message}}", + "failedToConnect": "Kunne ikke koble til beholderen", + "console": "Konsoll", + "selectShell": "Velg skall", + "bash": "Bash", + "sh": "sh", + "ash": "aske", + "connect": "Koble til", + "disconnect": "Frakople", + "notConnected": "Ikke tilkoblet", + "clickToConnect": "Klikk på koble til for å starte en skalløkt", + "connectingTo": "Kobler til {{containerName}}...", + "containerNotFound": "Beholderen ble ikke funnet", + "backToList": "Tilbake til listen", + "logs": "Logger", + "stats": "Statistikk", + "consoleTab": "Konsoll", + "startContainerToAccess": "Start containeren for å få tilgang til konsollen" + }, + "nav": { + "docker": "Dokker" + }, + "hosts": { + "tabDocker": "Dokker", + "dockerIntegration": "Docker-integrasjon", + "enableDockerMonitor": "Aktiver Docker", + "enableDockerMonitorDesc": "Overvåk og administrer containere på denne verten via Docker", + "containerRuntime": "Containerkjøringstid", + "containerRuntimeDesc": "Velg CRI-et som brukes for containeradministrasjon på denne verten", + "containerRuntimeDocker": "Dokker", + "containerRuntimePodman": "Podman" + }, + "onboarding": { + "feature_docker": "Dokker", + "feature_docker_desc": "Se containere, les logger og se statistikk på alle verter som kjører Docker." + } +} diff --git a/plugins/docker/locales/translated/pl_PL.json b/plugins/docker/locales/translated/pl_PL.json new file mode 100644 index 000000000..54e3bde21 --- /dev/null +++ b/plugins/docker/locales/translated/pl_PL.json @@ -0,0 +1,116 @@ +{ + "docker": { + "notEnabled": "Docker nie jest włączony dla tego hosta", + "validating": "Sprawdzanie poprawności Dockera...", + "connecting": "Łączenie...", + "error": "Błąd", + "version": "{{runtime}} {{version}}", + "connectionFailed": "Nie udało się połączyć z Dockerem", + "containerStarted": "Kontener {{name}} został uruchomiony", + "failedToStartContainer": "Nie udało się uruchomić kontenera {{name}}", + "containerStopped": "Kontener {{name}} zatrzymany", + "failedToStopContainer": "Nie udało się zatrzymać kontenera {{name}}", + "containerRestarted": "Kontener {{name}} został ponownie uruchomiony", + "failedToRestartContainer": "Nie udało się ponownie uruchomić kontenera {{name}}", + "containerPaused": "Kontener {{name}} wstrzymany", + "containerUnpaused": "Kontener {{name}} wznowiony", + "failedToTogglePauseContainer": "Nie udało się przełączyć stanu pauzy dla kontenera {{name}}", + "containerRemoved": "Kontener {{name}} został usunięty", + "failedToRemoveContainer": "Nie udało się usunąć kontenera {{name}}", + "image": "Obraz", + "ports": "Porty", + "noPorts": "Brak portów", + "start": "Start", + "confirmRemoveContainer": "Czy na pewno chcesz usunąć kontener „{{name}}”? Tej czynności nie można cofnąć.", + "runningContainerWarning": "Ostrzeżenie: Ten kontener jest obecnie uruchomiony. Jego usunięcie spowoduje najpierw jego zatrzymanie.", + "loadingContainers": "Ładowanie kontenerów...", + "manager": "Menedżer Dockera", + "autoRefresh": "Automatyczne odświeżanie", + "timestamps": "Znaczniki czasu", + "lines": "Wiersze", + "filterLogs": "Filtruj logi...", + "refresh": "Odśwież", + "download": "Pobierz", + "clear": "Wyczyść", + "logsDownloaded": "Pomyślnie pobrano logi", + "last50": "Ostatnie 50", + "last100": "Ostatnie 100", + "last500": "Ostatnie 500", + "last1000": "Ostatnie 1000", + "allLogs": "Wszystkie logi", + "noLogsMatching": "Brak logów pasujących do „{{query}}”", + "noLogsAvailable": "Brak dostępnych logów", + "noContainersFound": "Nie znaleziono kontenerów", + "noContainersFoundHint": "Na tym hoście nie ma dostępnych kontenerów Docker", + "searchPlaceholder": "Przeszukaj kontenery...", + "allStatuses": "Wszystkie statusy", + "stateRunning": "Działa", + "statePaused": "Wstrzymano", + "stateExited": "Zakończony", + "stateRestarting": "Restartuje się", + "noContainersMatchFilters": "Brak kontenerów pasujących do filtrów", + "noContainersMatchFiltersHint": "Spróbuj dostosować kryteria wyszukiwania lub filtrowania", + "failedToFetchStats": "Nie udało się pobrać statystyk kontenera", + "containerNotRunning": "Kontener nie działa", + "startContainerToViewStats": "Uruchom kontener, aby wyświetlić statystyki", + "loadingStats": "Ładowanie statystyk...", + "errorLoadingStats": "Błąd ładowania statystyk", + "noStatsAvailable": "Brak dostępnych statystyk", + "cpuUsage": "Wykorzystanie procesora", + "current": "Bieżące", + "memoryUsage": "Wykorzystanie pamięci", + "networkIo": "Wejście/wyjście sieciowe", + "input": "Wejście", + "output": "Wyjście", + "blockIo": "Blokowe I/O", + "read": "Odczyt", + "write": "Zapis", + "pids": "PID-y", + "containerInformation": "Informacje o kontenerze", + "name": "Nazwa", + "id": "ID", + "state": "Stan", + "containerMustBeRunning": "Aby uzyskać dostęp do konsoli, kontener musi być uruchomiony", + "verificationCodePrompt": "Wprowadź kod weryfikacyjny", + "totpVerificationFailed": "Weryfikacja TOTP nie powiodła się. Spróbuj ponownie.", + "warpgateVerificationFailed": "Uwierzytelnianie Warpgate nie powiodło się. Spróbuj ponownie.", + "connectedTo": "Połączono z {{containerName}}", + "disconnected": "Rozłączono", + "consoleError": "Błąd konsoli", + "errorMessage": "Błąd: {{message}}", + "failedToConnect": "Nie udało się połączyć z kontenerem", + "console": "Konsola", + "selectShell": "Wybierz powłokę", + "bash": "Bash", + "sh": "sh", + "ash": "ash", + "connect": "Połącz", + "disconnect": "Odłącz", + "notConnected": "Nie połączono", + "clickToConnect": "Kliknij „Połącz”, aby rozpocząć sesję powłoki", + "connectingTo": "Łączenie z {{containerName}}...", + "containerNotFound": "Nie znaleziono kontenera", + "backToList": "Powrót do listy", + "logs": "Logi", + "stats": "Statystyki", + "consoleTab": "Konsola", + "startContainerToAccess": "Uruchom kontener, aby uzyskać dostęp do konsoli" + }, + "nav": { + "docker": "Docker" + }, + "hosts": { + "tabDocker": "Docker", + "dockerIntegration": "Integracja z Dockerem", + "enableDockerMonitor": "Włącz Docker", + "enableDockerMonitorDesc": "Monitoruj i zarządzaj kontenerami na tym hoście za pomocą Dockera", + "containerRuntime": "Środowisko wykonawcze kontenera", + "containerRuntimeDesc": "Wybierz CLI używane do zarządzania kontenerami na tym hoście", + "containerRuntimeDocker": "Docker", + "containerRuntimePodman": "Podman" + }, + "onboarding": { + "feature_docker": "Docker", + "feature_docker_desc": "Przeglądaj kontenery, czytaj logi i śledź statystyki na dowolnym hoście, na którym działa Docker." + } +} diff --git a/plugins/docker/locales/translated/pt_BR.json b/plugins/docker/locales/translated/pt_BR.json new file mode 100644 index 000000000..e4d3eb899 --- /dev/null +++ b/plugins/docker/locales/translated/pt_BR.json @@ -0,0 +1,116 @@ +{ + "docker": { + "notEnabled": "O Docker não está habilitado para este host.", + "validating": "Validando o Docker...", + "connecting": "Conectando...", + "error": "Erro", + "version": "{{runtime}} {{version}}", + "connectionFailed": "Falha ao conectar ao Docker", + "containerStarted": "Contêiner {{name}} iniciado", + "failedToStartContainer": "Falha ao iniciar o contêiner {{name}}", + "containerStopped": "Contêiner {{name}} parado", + "failedToStopContainer": "Falha ao parar o contêiner {{name}}", + "containerRestarted": "Contêiner {{name}} reiniciado", + "failedToRestartContainer": "Falha ao reiniciar o contêiner {{name}}", + "containerPaused": "Contêiner {{name}} pausado", + "containerUnpaused": "Contêiner {{name}} despausado", + "failedToTogglePauseContainer": "Falha ao alternar o estado de pausa para o contêiner {{name}}", + "containerRemoved": "Contêiner {{name}} removido", + "failedToRemoveContainer": "Falha ao remover o contêiner {{name}}", + "image": "Imagem", + "ports": "Portos", + "noPorts": "Sem portas", + "start": "Começar", + "confirmRemoveContainer": "Tem certeza de que deseja remover o contêiner '{{name}}'? Esta ação não pode ser desfeita.", + "runningContainerWarning": "Aviso: Este contêiner está em execução. Removê-lo interromperá o contêiner primeiro.", + "loadingContainers": "Carregando contêineres...", + "manager": "Gerenciador de Docker", + "autoRefresh": "Atualização automática", + "timestamps": "Carimbos de data/hora", + "lines": "Linhas", + "filterLogs": "Filtrar registros...", + "refresh": "Atualizar", + "download": "Download", + "clear": "Claro", + "logsDownloaded": "Registros baixados com sucesso", + "last50": "Últimos 50", + "last100": "Últimos 100", + "last500": "Últimos 500", + "last1000": "Últimos 1000", + "allLogs": "Todos os registros", + "noLogsMatching": "Nenhum registro correspondente a \"{{query}}\"", + "noLogsAvailable": "Nenhum registro disponível", + "noContainersFound": "Nenhum contêiner encontrado", + "noContainersFoundHint": "Não há contêineres Docker disponíveis neste host.", + "searchPlaceholder": "Contêineres de pesquisa...", + "allStatuses": "Todos os status", + "stateRunning": "Correndo", + "statePaused": "Em pausa", + "stateExited": "Saiu", + "stateRestarting": "Reiniciando", + "noContainersMatchFilters": "Nenhum recipiente corresponde aos seus filtros.", + "noContainersMatchFiltersHint": "Tente ajustar seus critérios de pesquisa ou filtro.", + "failedToFetchStats": "Falha ao obter as estatísticas do contêiner.", + "containerNotRunning": "Contêiner não está em execução", + "startContainerToViewStats": "Inicie o contêiner para visualizar as estatísticas.", + "loadingStats": "Carregando estatísticas...", + "errorLoadingStats": "Estatísticas de carregamento de erros", + "noStatsAvailable": "Não há estatísticas disponíveis.", + "cpuUsage": "Utilização da CPU", + "current": "Atual", + "memoryUsage": "Uso de memória", + "networkIo": "E/S de rede", + "input": "Entrada", + "output": "Saída", + "blockIo": "Bloco de E/S", + "read": "Ler", + "write": "Escrever", + "pids": "PIDs", + "containerInformation": "Informações do contêiner", + "name": "Nome", + "id": "EU IA", + "state": "Estado", + "containerMustBeRunning": "O contêiner precisa estar em execução para acessar o console.", + "verificationCodePrompt": "Insira o código de verificação", + "totpVerificationFailed": "A verificação TOTP falhou. Tente novamente.", + "warpgateVerificationFailed": "A autenticação no portal de guerra falhou. Por favor, tente novamente.", + "connectedTo": "Conectado a {{containerName}}", + "disconnected": "Desconectado", + "consoleError": "Erro no console", + "errorMessage": "Erro: {{message}}", + "failedToConnect": "Falha ao conectar ao contêiner", + "console": "Console", + "selectShell": "Selecione shell", + "bash": "Bash", + "sh": "sh", + "ash": "cinzas", + "connect": "Conectar", + "disconnect": "Desconectar", + "notConnected": "Não conectado", + "clickToConnect": "Clique em conectar para iniciar uma sessão de shell.", + "connectingTo": "Conectando a {{containerName}}...", + "containerNotFound": "Contêiner não encontrado", + "backToList": "Voltar à lista", + "logs": "Registros", + "stats": "Estatísticas", + "consoleTab": "Console", + "startContainerToAccess": "Inicie o contêiner para acessar o console." + }, + "nav": { + "docker": "Docker" + }, + "hosts": { + "tabDocker": "Docker", + "dockerIntegration": "Integração do Docker", + "enableDockerMonitor": "Habilitar Docker", + "enableDockerMonitorDesc": "Monitore e gerencie contêineres neste host via Docker.", + "containerRuntime": "Tempo de execução do contêiner", + "containerRuntimeDesc": "Escolha a CLI usada para gerenciamento de contêineres neste host.", + "containerRuntimeDocker": "Docker", + "containerRuntimePodman": "Podman" + }, + "onboarding": { + "feature_docker": "Docker", + "feature_docker_desc": "Visualize contêineres, leia registros e acompanhe as estatísticas em qualquer host que execute o Docker." + } +} diff --git a/plugins/docker/locales/translated/pt_PT.json b/plugins/docker/locales/translated/pt_PT.json new file mode 100644 index 000000000..138d379e1 --- /dev/null +++ b/plugins/docker/locales/translated/pt_PT.json @@ -0,0 +1,116 @@ +{ + "docker": { + "notEnabled": "Docker não está ativado para este host", + "validating": "A validar o Docker...", + "connecting": "A ligar...", + "error": "Erro", + "version": "{{runtime}} {{version}}", + "connectionFailed": "Falha ao ligar ao Docker", + "containerStarted": "Contentor {{name}} iniciado", + "failedToStartContainer": "Falha ao iniciar o contentor {{name}}", + "containerStopped": "Contentor {{name}} parado", + "failedToStopContainer": "Falha ao parar o contentor {{name}}", + "containerRestarted": "Contentor {{name}} reiniciado", + "failedToRestartContainer": "Falha ao reiniciar o contentor {{name}}", + "containerPaused": "Contentor {{name}} suspenso", + "containerUnpaused": "Contentor {{name}} retomado", + "failedToTogglePauseContainer": "Falha ao alternar estado de pausa do contentor {{name}}", + "containerRemoved": "Contentor {{name}} removido", + "failedToRemoveContainer": "Falha ao remover o contentor {{name}}", + "image": "Imagem", + "ports": "Portas", + "noPorts": "Sem portas", + "start": "Iniciar", + "confirmRemoveContainer": "Tem a certeza de que pretende remover o contentor '{{name}}'? Esta ação não pode ser desfeita.", + "runningContainerWarning": "Aviso: Este contentor está em execução. Removê-lo irá pará-lo primeiro.", + "loadingContainers": "A carregar contentores...", + "manager": "Gestor Docker", + "autoRefresh": "Atualização automática", + "timestamps": "Marcas de tempo", + "lines": "Linhas", + "filterLogs": "Filtrar registos...", + "refresh": "Atualizar", + "download": "Transferir", + "clear": "Limpar", + "logsDownloaded": "Registos transferidos com sucesso", + "last50": "Últimos 50", + "last100": "Últimos 100", + "last500": "Últimos 500", + "last1000": "Últimos 1000", + "allLogs": "Todos os registos", + "noLogsMatching": "Nenhum registo corresponde a \"{{query}}\"", + "noLogsAvailable": "Nenhum registo disponível", + "noContainersFound": "Nenhum contentor encontrado", + "noContainersFoundHint": "Não existem contentores Docker disponíveis neste host", + "searchPlaceholder": "Pesquisar contentores...", + "allStatuses": "Todos os estados", + "stateRunning": "Em execução", + "statePaused": "Em pausa", + "stateExited": "Terminado", + "stateRestarting": "A reiniciar", + "noContainersMatchFilters": "Nenhum contentor corresponde aos seus filtros", + "noContainersMatchFiltersHint": "Tente ajustar os seus critérios de pesquisa ou filtro", + "failedToFetchStats": "Falha ao obter estatísticas do contentor", + "containerNotRunning": "O contentor não está em execução", + "startContainerToViewStats": "Inicie o contentor para ver as estatísticas", + "loadingStats": "A carregar estatísticas...", + "errorLoadingStats": "Erro ao carregar estatísticas", + "noStatsAvailable": "Nenhuma estatística disponível", + "cpuUsage": "Utilização da CPU", + "current": "Atual", + "memoryUsage": "Utilização da memória", + "networkIo": "I/O de rede", + "input": "Entrada", + "output": "Saída", + "blockIo": "E/S de blocos", + "read": "Leitura", + "write": "Escrita", + "pids": "PIDs", + "containerInformation": "Informações do contentor", + "name": "Nome", + "id": "ID", + "state": "Estado", + "containerMustBeRunning": "O contentor tem de estar em execução para aceder à consola", + "verificationCodePrompt": "Introduza o código de verificação", + "totpVerificationFailed": "A verificação TOTP falhou. Por favor, tente novamente.", + "warpgateVerificationFailed": "A autenticação Warpgate falhou. Por favor, tente novamente.", + "connectedTo": "Ligado a {{containerName}}", + "disconnected": "Desligado", + "consoleError": "Erro da consola", + "errorMessage": "Erro: {{message}}", + "failedToConnect": "Falha ao ligar ao contentor", + "console": "Consola", + "selectShell": "Selecionar shell", + "bash": "Bash", + "sh": "sh", + "ash": "ash", + "connect": "Ligar", + "disconnect": "Desligar", + "notConnected": "Não ligado", + "clickToConnect": "Clique em Ligar para iniciar uma sessão shell", + "connectingTo": "A ligar a {{containerName}}...", + "containerNotFound": "Contentor não encontrado", + "backToList": "Voltar à lista", + "logs": "Registos", + "stats": "Estatísticas", + "consoleTab": "Consola", + "startContainerToAccess": "Inicie o contentor para aceder à consola" + }, + "nav": { + "docker": "Docker" + }, + "hosts": { + "tabDocker": "Docker", + "dockerIntegration": "Integração com Docker", + "enableDockerMonitor": "Ativar Docker", + "enableDockerMonitorDesc": "Monitorizar e gerir contentores neste host via Docker", + "containerRuntime": "Runtime de Contentores", + "containerRuntimeDesc": "Escolha a CLI usada para a gestão de contentores neste host", + "containerRuntimeDocker": "Docker", + "containerRuntimePodman": "Podman" + }, + "onboarding": { + "feature_docker": "Docker", + "feature_docker_desc": "Visualize contentores, leia registos e acompanhe as estatísticas em qualquer host que execute o Docker." + } +} diff --git a/plugins/docker/locales/translated/ro_RO.json b/plugins/docker/locales/translated/ro_RO.json new file mode 100644 index 000000000..f81deceb9 --- /dev/null +++ b/plugins/docker/locales/translated/ro_RO.json @@ -0,0 +1,116 @@ +{ + "docker": { + "notEnabled": "Docker nu este activat pentru această gazdă", + "validating": "Se validează Docker...", + "connecting": "Se conectează...", + "error": "Eroare", + "version": "{{runtime}} {{version}}", + "connectionFailed": "Conectarea la Docker nu a reușit", + "containerStarted": "Containerul {{name}} a fost pornit", + "failedToStartContainer": "Containerul {{name}} nu a putut fi pornit", + "containerStopped": "Containerul {{name}} s-a oprit", + "failedToStopContainer": "Containerul {{name}} nu a putut fi oprit.", + "containerRestarted": "Containerul {{name}} a fost repornit", + "failedToRestartContainer": "Repornirea containerului {{name}} a eșuat.", + "containerPaused": "Containerul {{name}} a fost întrerupt", + "containerUnpaused": "Containerul {{name}} a fost reluat", + "failedToTogglePauseContainer": "Nu s-a putut comuta starea de pauză pentru containerul {{name}}", + "containerRemoved": "Containerul {{name}} a fost eliminat", + "failedToRemoveContainer": "Nu s-a putut elimina containerul {{name}}", + "image": "Imagine", + "ports": "Porturi", + "noPorts": "Fără porturi", + "start": "Început", + "confirmRemoveContainer": "Sigur doriți să eliminați containerul „{{name}}”? Această acțiune nu poate fi anulată.", + "runningContainerWarning": "Avertisment: Acest container rulează în prezent. Eliminarea sa va opri mai întâi containerul.", + "loadingContainers": "Se încarcă containerele...", + "manager": "Manager Docker", + "autoRefresh": "Reîmprospătare automată", + "timestamps": "Marcaje temporale", + "lines": "Linii", + "filterLogs": "Filtrare jurnale...", + "refresh": "Reîmprospăta", + "download": "Descărcare", + "clear": "Clar", + "logsDownloaded": "Jurnalele au fost descărcate cu succes", + "last50": "Ultimii 50", + "last100": "Ultimele 100", + "last500": "Ultimii 500", + "last1000": "Ultimele 1000", + "allLogs": "Toate jurnalele", + "noLogsMatching": "Niciun jurnal care să corespundă cu „{{query}}”", + "noLogsAvailable": "Nu sunt disponibile jurnale", + "noContainersFound": "Nu s-au găsit containere", + "noContainersFoundHint": "Nu există containere Docker disponibile pe această gazdă.", + "searchPlaceholder": "Căutați containere...", + "allStatuses": "Toate stările", + "stateRunning": "Funcţionare", + "statePaused": "Întrerupt", + "stateExited": "Ieșit", + "stateRestarting": "Repornire", + "noContainersMatchFilters": "Niciun container nu corespunde filtrelor dvs.", + "noContainersMatchFiltersHint": "Încercați să ajustați criteriile de căutare sau de filtrare", + "failedToFetchStats": "Nu s-au putut prelua statisticile containerului", + "containerNotRunning": "Containerul nu rulează", + "startContainerToViewStats": "Porniți containerul pentru a vizualiza statisticile", + "loadingStats": "Se încarcă statisticile...", + "errorLoadingStats": "Eroare la încărcarea statisticilor", + "noStatsAvailable": "Nu sunt disponibile statistici", + "cpuUsage": "Utilizarea procesorului", + "current": "Actual", + "memoryUsage": "Utilizarea memoriei", + "networkIo": "I/O de rețea", + "input": "Intrare", + "output": "Ieșire", + "blockIo": "Bloc I/O", + "read": "Citire", + "write": "Scrie", + "pids": "PID-uri", + "containerInformation": "Informații despre container", + "name": "Nume", + "id": "ID-ul", + "state": "Stat", + "containerMustBeRunning": "Containerul trebuie să ruleze pentru a accesa consola.", + "verificationCodePrompt": "Introduceți codul de verificare", + "totpVerificationFailed": "Verificarea TOTP a eșuat. Vă rugăm să încercați din nou.", + "warpgateVerificationFailed": "Autentificarea Warpgate a eșuat. Vă rugăm să încercați din nou.", + "connectedTo": "Conectat la {{containerName}}", + "disconnected": "Deconectat", + "consoleError": "Eroare consolă", + "errorMessage": "Eroare: {{message}}", + "failedToConnect": "Conectarea la container nu a reușit", + "console": "Consolă", + "selectShell": "Selectați shell-ul", + "bash": "Bash", + "sh": "sh", + "ash": "frasin", + "connect": "Conectează-te", + "disconnect": "Deconecta", + "notConnected": "Neconectat", + "clickToConnect": "Faceți clic pe conectare pentru a începe o sesiune shell", + "connectingTo": "Conectare la {{containerName}}...", + "containerNotFound": "Container negăsit", + "backToList": "Înapoi la listă", + "logs": "Jurnalele", + "stats": "Statistici", + "consoleTab": "Consolă", + "startContainerToAccess": "Porniți containerul pentru a accesa consola" + }, + "nav": { + "docker": "Docher" + }, + "hosts": { + "tabDocker": "Docher", + "dockerIntegration": "Integrare Docker", + "enableDockerMonitor": "Activează Docker", + "enableDockerMonitorDesc": "Monitorizați și gestionați containerele de pe această gazdă prin Docker", + "containerRuntime": "Runtime de container", + "containerRuntimeDesc": "Alegeți interfața CLI utilizată pentru gestionarea containerelor pe această gazdă", + "containerRuntimeDocker": "Docher", + "containerRuntimePodman": "Podman" + }, + "onboarding": { + "feature_docker": "Docher", + "feature_docker_desc": "Vizualizați containere, citiți jurnale și urmăriți statistici pe orice gazdă care rulează Docker." + } +} diff --git a/plugins/docker/locales/translated/ru_RU.json b/plugins/docker/locales/translated/ru_RU.json new file mode 100644 index 000000000..671411170 --- /dev/null +++ b/plugins/docker/locales/translated/ru_RU.json @@ -0,0 +1,116 @@ +{ + "docker": { + "notEnabled": "Docker не включен для этого хоста", + "validating": "Проверка Docker...", + "connecting": "Подключение...", + "error": "Ошибка", + "version": "{{runtime}} {{version}}", + "connectionFailed": "Не удалось подключиться к Docker", + "containerStarted": "Контейнер {{name}} запущен", + "failedToStartContainer": "Не удалось запустить контейнер {{name}}", + "containerStopped": "Контейнер {{name}} остановлен", + "failedToStopContainer": "Не удалось остановить контейнер {{name}}", + "containerRestarted": "Контейнер {{name}} перезапущен", + "failedToRestartContainer": "Не удалось перезапустить контейнер {{name}}", + "containerPaused": "Контейнер {{name}} приостановлен", + "containerUnpaused": "Контейнер {{name}} возобновлён", + "failedToTogglePauseContainer": "Не удалось изменить состояние приостановки для контейнера {{name}}", + "containerRemoved": "Контейнер {{name}} удалён", + "failedToRemoveContainer": "Не удалось удалить контейнер {{name}}", + "image": "Образ", + "ports": "Порты", + "noPorts": "Нет портов", + "start": "Запустить", + "confirmRemoveContainer": "Вы уверены, что хотите удалить контейнер «{{name}}»? Это действие нельзя отменить.", + "runningContainerWarning": "Предупреждение: этот контейнер в настоящее время работает. При удалении он будет сначала остановлен.", + "loadingContainers": "Загрузка контейнеров...", + "manager": "Менеджер Docker", + "autoRefresh": "Автообновление", + "timestamps": "Отметки времени", + "lines": "Строки", + "filterLogs": "Фильтровать логи...", + "refresh": "Обновить", + "download": "Скачать", + "clear": "Очистить", + "logsDownloaded": "Логи успешно скачаны", + "last50": "Последние 50", + "last100": "Последние 100", + "last500": "Последние 500", + "last1000": "Последние 1000", + "allLogs": "Все логи", + "noLogsMatching": "Нет логов, соответствующих \"{{query}}\"", + "noLogsAvailable": "Логи отсутствуют", + "noContainersFound": "Контейнеры не найдены", + "noContainersFoundHint": "На этом хосте нет Docker-контейнеров", + "searchPlaceholder": "Поиск контейнеров...", + "allStatuses": "Все состояния", + "stateRunning": "Запущен", + "statePaused": "Приостановлен", + "stateExited": "Завершён", + "stateRestarting": "Перезапускается", + "noContainersMatchFilters": "Нет контейнеров, соответствующих фильтрам", + "noContainersMatchFiltersHint": "Попробуйте изменить параметры поиска или фильтры", + "failedToFetchStats": "Не удалось получить статистику контейнера", + "containerNotRunning": "Контейнер не запущен", + "startContainerToViewStats": "Запустите контейнер, чтобы посмотреть статистику", + "loadingStats": "Загрузка статистики...", + "errorLoadingStats": "Ошибка загрузки статистики", + "noStatsAvailable": "Статистика недоступна", + "cpuUsage": "Использование ЦП", + "current": "Текущий", + "memoryUsage": "Использование памяти", + "networkIo": "Сетевой ввод-вывод", + "input": "Ввод", + "output": "Вывод", + "blockIo": "Блочный ввод-вывод", + "read": "Чтение", + "write": "Запись", + "pids": "PID", + "containerInformation": "Информация о контейнере", + "name": "Имя", + "id": "ID", + "state": "Состояние", + "containerMustBeRunning": "Для доступа к консоли контейнер должен быть запущен", + "verificationCodePrompt": "Введите код подтверждения", + "totpVerificationFailed": "Ошибка проверки TOTP. Попробуйте еще раз.", + "warpgateVerificationFailed": "Ошибка аутентификации Warpgate. Попробуйте еще раз.", + "connectedTo": "Подключено к {{containerName}}", + "disconnected": "Отключено", + "consoleError": "Ошибка консоли", + "errorMessage": "Ошибка: {{message}}", + "failedToConnect": "Не удалось подключиться к контейнеру", + "console": "Консоль", + "selectShell": "Выберите оболочку", + "bash": "Bash", + "sh": "sh", + "ash": "ash", + "connect": "Подключиться", + "disconnect": "Отключиться", + "notConnected": "Не подключено", + "clickToConnect": "Нажмите «Подключиться», чтобы запустить сеанс оболочки", + "connectingTo": "Подключение к {{containerName}}...", + "containerNotFound": "Контейнер не найден", + "backToList": "Вернуться к списку", + "logs": "Логи", + "stats": "Статистика", + "consoleTab": "Консоль", + "startContainerToAccess": "Запустите контейнер, чтобы получить доступ к консоли" + }, + "nav": { + "docker": "Docker" + }, + "hosts": { + "tabDocker": "Docker", + "dockerIntegration": "Интеграция Docker", + "enableDockerMonitor": "Включить Docker", + "enableDockerMonitorDesc": "Отслеживать и управлять контейнерами на этом хосте через Docker", + "containerRuntime": "Среда выполнения контейнеров", + "containerRuntimeDesc": "Выберите CLI, используемый для управления контейнерами на этом хосте", + "containerRuntimeDocker": "Docker", + "containerRuntimePodman": "Podman" + }, + "onboarding": { + "feature_docker": "Docker", + "feature_docker_desc": "Просматривайте контейнеры, читайте журналы и отслеживайте статистику на любом хосте, где запущен Docker." + } +} diff --git a/plugins/docker/locales/translated/sr_SP.json b/plugins/docker/locales/translated/sr_SP.json new file mode 100644 index 000000000..00a2ee5f3 --- /dev/null +++ b/plugins/docker/locales/translated/sr_SP.json @@ -0,0 +1,116 @@ +{ + "docker": { + "notEnabled": "Докер није омогућен за овај хост", + "validating": "Валидација Докера...", + "connecting": "Повезивање...", + "error": "Грешка", + "version": "{{runtime}} {{version}}", + "connectionFailed": "Повезивање са Докером није успело", + "containerStarted": "Контејнер {{name}} је покренут", + "failedToStartContainer": "Покретање контејнера {{name}} није успело", + "containerStopped": "Контејнер {{name}} је заустављен", + "failedToStopContainer": "Заустављање контејнера {{name}} није успело", + "containerRestarted": "Контејнер {{name}} поново покренут", + "failedToRestartContainer": "Поновно покретање контејнера није успело {{name}}", + "containerPaused": "Контејнер {{name}} је паузиран", + "containerUnpaused": "Паузирање контејнера {{name}} је прекинуто", + "failedToTogglePauseContainer": "Није успело пребацивање стања паузе за контејнер {{name}}", + "containerRemoved": "Контејнер {{name}} је уклоњен", + "failedToRemoveContainer": "Није успело уклањање контејнера {{name}}", + "image": "Слика", + "ports": "Портови", + "noPorts": "Нема портова", + "start": "Почетак", + "confirmRemoveContainer": "Да ли сте сигурни да желите да уклоните контејнер „{{name}}“? Ова радња се не може поништити.", + "runningContainerWarning": "Упозорење: Овај контејнер је тренутно покренут. Његово уклањање ће прво зауставити рад контејнера.", + "loadingContainers": "Учитавање контејнера...", + "manager": "Докер менаџер", + "autoRefresh": "Аутоматско освежавање", + "timestamps": "Временске ознаке", + "lines": "Линије", + "filterLogs": "Филтрирај логове...", + "refresh": "Освежи", + "download": "Преузми", + "clear": "Јасно", + "logsDownloaded": "Дневници су успешно преузети", + "last50": "Последњих 50", + "last100": "Последњих 100", + "last500": "Последњих 500", + "last1000": "Последњих 1000", + "allLogs": "Сви дневници", + "noLogsMatching": "Нема логова који одговарају „{{query}}“", + "noLogsAvailable": "Нема доступних логова", + "noContainersFound": "Нису пронађени контејнери", + "noContainersFoundHint": "На овом хосту нису доступни Docker контејнери", + "searchPlaceholder": "Претражи контејнере...", + "allStatuses": "Сви статуси", + "stateRunning": "Трчање", + "statePaused": "Паузирано", + "stateExited": "Изашао/ла", + "stateRestarting": "Поновно покретање", + "noContainersMatchFilters": "Ниједан контејнер не одговара вашим филтерима", + "noContainersMatchFiltersHint": "Покушајте да прилагодите критеријуме претраге или филтрирања", + "failedToFetchStats": "Није успело преузимање статистике контејнера", + "containerNotRunning": "Контејнер се не покреће", + "startContainerToViewStats": "Покрените контејнер да бисте видели статистику", + "loadingStats": "Учитавање статистике...", + "errorLoadingStats": "Грешка при учитавању статистике", + "noStatsAvailable": "Нема доступних статистика", + "cpuUsage": "Искоришћеност процесора", + "current": "Тренутни", + "memoryUsage": "Коришћење меморије", + "networkIo": "Мрежни улаз/излаз", + "input": "Унос", + "output": "Излаз", + "blockIo": "Блок У/И", + "read": "Читај", + "write": "Пиши", + "pids": "ПИД-ови", + "containerInformation": "Информације о контејнеру", + "name": "Име", + "id": "ИД", + "state": "Држава", + "containerMustBeRunning": "Контејнер мора бити покренут да би се приступило конзоли", + "verificationCodePrompt": "Унесите верификациони код", + "totpVerificationFailed": "Верификација TOTP-а није успела. Молимо покушајте поново.", + "warpgateVerificationFailed": "Аутентификација преко Ворпгејта није успела. Молимо покушајте поново.", + "connectedTo": "Повезано са {{containerName}}", + "disconnected": "Искључено", + "consoleError": "Грешка конзоле", + "errorMessage": "Грешка: {{message}}", + "failedToConnect": "Повезивање са контејнером није успело", + "console": "Конзола", + "selectShell": "Изаберите љуску", + "bash": "Баш", + "sh": "ш", + "ash": "пепео", + "connect": "Повежи се", + "disconnect": "Прекини везу", + "notConnected": "Није повезано", + "clickToConnect": "Кликните на повезивање да бисте покренули сесију шкољке", + "connectingTo": "Повезивање са {{containerName}}...", + "containerNotFound": "Контејнер није пронађен", + "backToList": "Назад на листу", + "logs": "Дневници", + "stats": "Статистика", + "consoleTab": "Конзола", + "startContainerToAccess": "Покрените контејнер да бисте приступили конзоли" + }, + "nav": { + "docker": "Докер" + }, + "hosts": { + "tabDocker": "Докер", + "dockerIntegration": "Интеграција Докера", + "enableDockerMonitor": "Омогући Докер", + "enableDockerMonitorDesc": "Пратите и управљајте контејнерима на овом хосту путем Докера", + "containerRuntime": "Време извршавања контејнера", + "containerRuntimeDesc": "Изаберите CLI који се користи за управљање контејнерима на овом хосту", + "containerRuntimeDocker": "Докер", + "containerRuntimePodman": "Подман" + }, + "onboarding": { + "feature_docker": "Докер", + "feature_docker_desc": "Погледајте контејнере, читајте логове и пратите статистику на било ком хосту који користи Docker." + } +} diff --git a/plugins/docker/locales/translated/sv_SE.json b/plugins/docker/locales/translated/sv_SE.json new file mode 100644 index 000000000..a49891e02 --- /dev/null +++ b/plugins/docker/locales/translated/sv_SE.json @@ -0,0 +1,116 @@ +{ + "docker": { + "notEnabled": "Docker är inte aktiverat för den här värden", + "validating": "Validerar Docker...", + "connecting": "Ansluter...", + "error": "Fel", + "version": "{{runtime}} {{version}}", + "connectionFailed": "Misslyckades med att ansluta till Docker", + "containerStarted": "Behållaren {{name}} startad", + "failedToStartContainer": "Misslyckades med att starta containern {{name}}", + "containerStopped": "Behållaren {{name}} har stoppats", + "failedToStopContainer": "Misslyckades med att stoppa containern {{name}}", + "containerRestarted": "Behållaren {{name}} har startats om", + "failedToRestartContainer": "Misslyckades med att starta om behållaren {{name}}", + "containerPaused": "Behållaren {{name}} pausad", + "containerUnpaused": "Behållaren {{name}} har återupptagits", + "failedToTogglePauseContainer": "Misslyckades med att växla pausläge för container {{name}}", + "containerRemoved": "Behållaren {{name}} har tagits bort", + "failedToRemoveContainer": "Misslyckades med att ta bort behållaren {{name}}", + "image": "Bild", + "ports": "Hamnar", + "noPorts": "Inga portar", + "start": "Start", + "confirmRemoveContainer": "Är du säker på att du vill ta bort behållaren '{{name}}'? Den här åtgärden kan inte ångras.", + "runningContainerWarning": "Varning: Den här behållaren körs för närvarande. Om du tar bort den stoppas behållaren först.", + "loadingContainers": "Lastar containrar...", + "manager": "Docker Manager", + "autoRefresh": "Automatisk uppdatering", + "timestamps": "Tidsstämplar", + "lines": "Rader", + "filterLogs": "Filtrera loggar...", + "refresh": "Uppdatera", + "download": "Ladda ner", + "clear": "Rensa", + "logsDownloaded": "Loggarna har laddats ner", + "last50": "Senaste 50", + "last100": "Senaste 100", + "last500": "Senaste 500", + "last1000": "Senaste 1000", + "allLogs": "Alla loggar", + "noLogsMatching": "Inga loggar som matchar \"{{query}}\"", + "noLogsAvailable": "Inga loggar tillgängliga", + "noContainersFound": "Inga containrar hittades", + "noContainersFoundHint": "Inga Docker-containrar är tillgängliga på den här värden", + "searchPlaceholder": "Sök behållare...", + "allStatuses": "Alla statusar", + "stateRunning": "Spring", + "statePaused": "Pausad", + "stateExited": "Avslutad", + "stateRestarting": "Omstart", + "noContainersMatchFilters": "Inga behållare matchar dina filter", + "noContainersMatchFiltersHint": "Försök att justera dina sök- eller filterkriterier", + "failedToFetchStats": "Misslyckades med att hämta containerstatistik", + "containerNotRunning": "Behållaren körs inte", + "startContainerToViewStats": "Starta containern för att visa statistik", + "loadingStats": "Laddar statistik...", + "errorLoadingStats": "Fel vid inläsning av statistik", + "noStatsAvailable": "Ingen statistik tillgänglig", + "cpuUsage": "CPU-användning", + "current": "Nuvarande", + "memoryUsage": "Minnesanvändning", + "networkIo": "Nätverks-I/O", + "input": "Input", + "output": "Produktion", + "blockIo": "Blockera I/O", + "read": "Läsa", + "write": "Skriva", + "pids": "PID:er", + "containerInformation": "Containerinformation", + "name": "Namn", + "id": "ID", + "state": "Ange", + "containerMustBeRunning": "Behållaren måste köras för att komma åt konsolen", + "verificationCodePrompt": "Ange verifieringskod", + "totpVerificationFailed": "TOTP-verifieringen misslyckades. Försök igen.", + "warpgateVerificationFailed": "Warpgate-autentiseringen misslyckades. Försök igen.", + "connectedTo": "Ansluten till {{containerName}}", + "disconnected": "Osammanhängande", + "consoleError": "Konsolfel", + "errorMessage": "Fel: {{message}}", + "failedToConnect": "Misslyckades med att ansluta till containern", + "console": "Trösta", + "selectShell": "Välj skal", + "bash": "Våldsamt slag", + "sh": "sh", + "ash": "aska", + "connect": "Ansluta", + "disconnect": "Koppla från", + "notConnected": "Inte ansluten", + "clickToConnect": "Klicka på Anslut för att starta en shell-session", + "connectingTo": "Ansluter till {{containerName}}...", + "containerNotFound": "Behållaren hittades inte", + "backToList": "Tillbaka till listan", + "logs": "Loggar", + "stats": "Statistik", + "consoleTab": "Trösta", + "startContainerToAccess": "Starta containern för att komma åt konsolen" + }, + "nav": { + "docker": "Hamnarbetare" + }, + "hosts": { + "tabDocker": "Hamnarbetare", + "dockerIntegration": "Docker-integration", + "enableDockerMonitor": "Aktivera Docker", + "enableDockerMonitorDesc": "Övervaka och hantera containrar på den här värden via Docker", + "containerRuntime": "Containerkörningstid", + "containerRuntimeDesc": "Välj det CRI som används för containerhantering på den här värden", + "containerRuntimeDocker": "Hamnarbetare", + "containerRuntimePodman": "Podman" + }, + "onboarding": { + "feature_docker": "Hamnarbetare", + "feature_docker_desc": "Se containrar, läs loggar och titta på statistik för alla värdar som kör Docker." + } +} diff --git a/plugins/docker/locales/translated/th_TH.json b/plugins/docker/locales/translated/th_TH.json new file mode 100644 index 000000000..bdea9fc5f --- /dev/null +++ b/plugins/docker/locales/translated/th_TH.json @@ -0,0 +1,116 @@ +{ + "docker": { + "notEnabled": "Docker ไม่ได้เปิดใช้งานสำหรับโฮสต์นี้", + "validating": "กำลังตรวจสอบความถูกต้องของ Docker...", + "connecting": "กำลังเชื่อมต่อ...", + "error": "ข้อผิดพลาด", + "version": "{{runtime}} {{version}}", + "connectionFailed": "ไม่สามารถเชื่อมต่อกับ Docker ได้", + "containerStarted": "คอนเทนเนอร์ {{name}} เริ่มทำงานแล้ว", + "failedToStartContainer": "ไม่สามารถเริ่มต้นคอนเทนเนอร์ได้ {{name}}", + "containerStopped": "คอนเทนเนอร์ {{name}} หยุดทำงานแล้ว", + "failedToStopContainer": "ไม่สามารถหยุดคอนเทนเนอร์ได้ {{name}}", + "containerRestarted": "คอนเทนเนอร์ {{name}} รีสตาร์ทแล้ว", + "failedToRestartContainer": "ไม่สามารถรีสตาร์ทคอนเทนเนอร์ได้ {{name}}", + "containerPaused": "คอนเทนเนอร์ {{name}} หยุดชั่วคราว", + "containerUnpaused": "คอนเทนเนอร์ {{name}} ยกเลิกการหยุดชั่วคราว", + "failedToTogglePauseContainer": "ไม่สามารถสลับสถานะหยุดชั่วคราวสำหรับคอนเทนเนอร์ {{name}} ได้", + "containerRemoved": "คอนเทนเนอร์ {{name}} ถูกลบออกแล้ว", + "failedToRemoveContainer": "ไม่สามารถลบคอนเทนเนอร์ {{name}} ได้", + "image": "ภาพ", + "ports": "ท่าเรือ", + "noPorts": "ไม่มีพอร์ต", + "start": "เริ่ม", + "confirmRemoveContainer": "คุณแน่ใจหรือไม่ว่าต้องการลบคอนเทนเนอร์ '{{name}}'? การกระทำนี้ไม่สามารถย้อนกลับได้", + "runningContainerWarning": "คำเตือน: ขณะนี้คอนเทนเนอร์นี้กำลังทำงานอยู่ การลบคอนเทนเนอร์นี้จะหยุดการทำงานของคอนเทนเนอร์ก่อน", + "loadingContainers": "กำลังขนถ่ายตู้คอนเทนเนอร์...", + "manager": "ตัวจัดการ Docker", + "autoRefresh": "รีเฟรชอัตโนมัติ", + "timestamps": "ไทม์สแตมป์", + "lines": "เส้น", + "filterLogs": "กรองบันทึก...", + "refresh": "รีเฟรช", + "download": "ดาวน์โหลด", + "clear": "ชัดเจน", + "logsDownloaded": "ดาวน์โหลดบันทึกข้อมูลสำเร็จแล้ว", + "last50": "50 ครั้งสุดท้าย", + "last100": "100 ปีที่แล้ว", + "last500": "500 ครั้งสุดท้าย", + "last1000": "1000 ครั้งสุดท้าย", + "allLogs": "บันทึกทั้งหมด", + "noLogsMatching": "ไม่พบบันทึกใดที่ตรงกับ \"{{query}}\"", + "noLogsAvailable": "ไม่มีบันทึกข้อมูล", + "noContainersFound": "ไม่พบภาชนะบรรจุใดๆ", + "noContainersFoundHint": "ไม่มีคอนเทนเนอร์ Docker ให้บริการบนโฮสต์นี้", + "searchPlaceholder": "ค้นหาตู้คอนเทนเนอร์...", + "allStatuses": "สถานะทั้งหมด", + "stateRunning": "วิ่ง", + "statePaused": "หยุดชั่วคราว", + "stateExited": "ออกแล้ว", + "stateRestarting": "เริ่มใหม่อีกครั้ง", + "noContainersMatchFilters": "ไม่มีภาชนะใดตรงกับตัวกรองของคุณ", + "noContainersMatchFiltersHint": "ลองปรับเกณฑ์การค้นหาหรือตัวกรองของคุณดู", + "failedToFetchStats": "ไม่สามารถดึงข้อมูลสถิติของคอนเทนเนอร์ได้", + "containerNotRunning": "คอนเทนเนอร์ไม่ทำงาน", + "startContainerToViewStats": "เริ่มคอนเทนเนอร์เพื่อดูสถิติ", + "loadingStats": "กำลังโหลดสถิติ...", + "errorLoadingStats": "ข้อผิดพลาดในการโหลดสถิติ", + "noStatsAvailable": "ไม่มีสถิติให้ดู", + "cpuUsage": "การใช้งาน CPU", + "current": "ปัจจุบัน", + "memoryUsage": "การใช้งานหน่วยความจำ", + "networkIo": "อินพุต/เอาต์พุตเครือข่าย", + "input": "ป้อนข้อมูล", + "output": "เอาต์พุต", + "blockIo": "บล็อก I/O", + "read": "อ่าน", + "write": "เขียน", + "pids": "PIDs", + "containerInformation": "ข้อมูลเกี่ยวกับตู้คอนเทนเนอร์", + "name": "ชื่อ", + "id": "รหัสประจำตัว", + "state": "สถานะ", + "containerMustBeRunning": "ต้องเปิดใช้งานคอนเทนเนอร์ก่อนจึงจะสามารถเข้าถึงคอนโซลได้", + "verificationCodePrompt": "ป้อนรหัสยืนยัน", + "totpVerificationFailed": "การตรวจสอบ TOTP ล้มเหลว โปรดลองอีกครั้ง", + "warpgateVerificationFailed": "การตรวจสอบสิทธิ์ผ่านวาร์ปไม่สำเร็จ โปรดลองอีกครั้ง", + "connectedTo": "เชื่อมต่อกับ {{containerName}}", + "disconnected": "ตัดการเชื่อมต่อ", + "consoleError": "ข้อผิดพลาดของคอนโซล", + "errorMessage": "ข้อผิดพลาด: {{message}}", + "failedToConnect": "ไม่สามารถเชื่อมต่อกับคอนเทนเนอร์ได้", + "console": "คอนโซล", + "selectShell": "เลือกเปลือกหอย", + "bash": "ทุบตี", + "sh": "ช", + "ash": "เถ้า", + "connect": "เชื่อมต่อ", + "disconnect": "ตัดการเชื่อมต่อ", + "notConnected": "ไม่ได้เชื่อมต่อ", + "clickToConnect": "คลิกเชื่อมต่อเพื่อเริ่มเซสชันเชลล์", + "connectingTo": "กำลังเชื่อมต่อกับ {{containerName}}...", + "containerNotFound": "ไม่พบคอนเทนเนอร์", + "backToList": "กลับสู่รายการ", + "logs": "บันทึก", + "stats": "สถิติ", + "consoleTab": "คอนโซล", + "startContainerToAccess": "เริ่มคอนเทนเนอร์เพื่อเข้าถึงคอนโซล" + }, + "nav": { + "docker": "ด็อกเกอร์" + }, + "hosts": { + "tabDocker": "ด็อกเกอร์", + "dockerIntegration": "การผสานรวม Docker", + "enableDockerMonitor": "เปิดใช้งาน Docker", + "enableDockerMonitorDesc": "ตรวจสอบและจัดการคอนเทนเนอร์บนโฮสต์นี้ผ่าน Docker", + "containerRuntime": "รันไทม์คอนเทนเนอร์", + "containerRuntimeDesc": "เลือก CLI ที่ใช้สำหรับการจัดการคอนเทนเนอร์บนโฮสต์นี้", + "containerRuntimeDocker": "ด็อกเกอร์", + "containerRuntimePodman": "พอดแมน" + }, + "onboarding": { + "feature_docker": "ด็อกเกอร์", + "feature_docker_desc": "ดูคอนเทนเนอร์ อ่านบันทึก และตรวจสอบสถิติบนโฮสต์ใดก็ได้ที่ใช้งาน Docker" + } +} diff --git a/plugins/docker/locales/translated/tr_TR.json b/plugins/docker/locales/translated/tr_TR.json new file mode 100644 index 000000000..5b0e444ea --- /dev/null +++ b/plugins/docker/locales/translated/tr_TR.json @@ -0,0 +1,116 @@ +{ + "docker": { + "notEnabled": "Bu sunucu için Docker etkinleştirilmemiş", + "validating": "Docker doğrulanıyor...", + "connecting": "Bağlanıyor...", + "error": "Hata", + "version": "{{runtime}} {{version}}", + "connectionFailed": "Docker'a bağlanılamadı", + "containerStarted": "{{name}} konteyneri başlatıldı", + "failedToStartContainer": "{{name}} konteyneri başlatılamadı", + "containerStopped": "{{name}} konteyneri durduruldu", + "failedToStopContainer": "{{name}} konteyneri durdurulamadı", + "containerRestarted": "{{name}} konteyneri yeniden başlatıldı", + "failedToRestartContainer": "{{name}} konteyneri yeniden başlatılamadı", + "containerPaused": "{{name}} konteyneri duraklatıldı", + "containerUnpaused": "{{name}} konteyneri devam ettirildi", + "failedToTogglePauseContainer": "{{name}} konteyneri için duraklatma durumu değiştirilemedi", + "containerRemoved": "{{name}} konteyneri kaldırıldı", + "failedToRemoveContainer": "{{name}} konteyneri kaldırılamadı", + "image": "İmaj", + "ports": "Portlar", + "noPorts": "Port yok", + "start": "Başlat", + "confirmRemoveContainer": "'{{name}}' konteynerini kaldırmak istediğinizden emin misiniz? Bu işlem geri alınamaz.", + "runningContainerWarning": "Uyarı: Bu konteyner şu anda çalışıyor. Kaldırma işlemi önce konteyneri durduracak.", + "loadingContainers": "Konteynerler yükleniyor...", + "manager": "Docker Yöneticisi", + "autoRefresh": "Otomatik Yenile", + "timestamps": "Zaman Damgaları", + "lines": "Satırlar", + "filterLogs": "Günlükleri filtrele...", + "refresh": "Yenile", + "download": "İndir", + "clear": "Temizle", + "logsDownloaded": "Günlükler başarıyla indirildi", + "last50": "Son 50", + "last100": "Son 100", + "last500": "Son 500", + "last1000": "Son 1000", + "allLogs": "Tüm Günlükler", + "noLogsMatching": "\"{{query}}\" ile eşleşen günlük yok", + "noLogsAvailable": "Günlükler mevcut değil", + "noContainersFound": "Konteyner bulunamadı", + "noContainersFoundHint": "Bu ana bilgisayarda Docker konteyneri bulunmuyor", + "searchPlaceholder": "Konteyner ara...", + "allStatuses": "Tüm Durumlar", + "stateRunning": "Çalışıyor", + "statePaused": "Duraklatıldı", + "stateExited": "Durduruldu", + "stateRestarting": "Yeniden başlatılıyor", + "noContainersMatchFilters": "Filtrelere uyan konteyner yok", + "noContainersMatchFiltersHint": "Aramanızı veya filtre ölçütlerinizi değiştirmeyi deneyin", + "failedToFetchStats": "Konteyner istatistikleri alınamadı", + "containerNotRunning": "Konteyner çalışmıyor", + "startContainerToViewStats": "İstatistikleri görüntülemek için konteyneri başlatın", + "loadingStats": "İstatistikler yükleniyor...", + "errorLoadingStats": "İstatistikler yüklenirken hata oluştu", + "noStatsAvailable": "İstatistikler mevcut değil", + "cpuUsage": "CPU Kullanımı", + "current": "Anlık", + "memoryUsage": "Bellek Kullanımı", + "networkIo": "Ağ G/Ç", + "input": "Giriş", + "output": "Çıktı", + "blockIo": "Blok G/Ç", + "read": "Okuma", + "write": "Yazma", + "pids": "PID'ler", + "containerInformation": "Konteyner Bilgileri", + "name": "Ad", + "id": "ID", + "state": "Durum", + "containerMustBeRunning": "Konsola erişmek için konteyner çalışıyor olmalıdır", + "verificationCodePrompt": "Doğrulama kodunu girin", + "totpVerificationFailed": "TOTP doğrulaması başarısız oldu. Lütfen tekrar deneyin.", + "warpgateVerificationFailed": "Warpgate kimlik doğrulaması başarısız oldu. Lütfen tekrar deneyin.", + "connectedTo": "{{containerName}} ile bağlantı kuruldu", + "disconnected": "Bağlantı kesildi", + "consoleError": "Konsol hatası", + "errorMessage": "Hata: {{message}}", + "failedToConnect": "Konteynere bağlanılamadı", + "console": "Konsol", + "selectShell": "Kabuk seç", + "bash": "Bash", + "sh": "sh", + "ash": "ash", + "connect": "Bağlan", + "disconnect": "Bağlantıyı kes", + "notConnected": "Bağlı değil", + "clickToConnect": "Kabuk oturumu başlatmak için bağlan düğmesine tıklayın", + "connectingTo": "{{containerName}} konteynerine bağlanılıyor...", + "containerNotFound": "Konteyner bulunamadı", + "backToList": "Listeye Dön", + "logs": "Günlükler", + "stats": "İstatistikler", + "consoleTab": "Konsol", + "startContainerToAccess": "Konsola erişmek için konteyneri başlatın" + }, + "nav": { + "docker": "Docker" + }, + "hosts": { + "tabDocker": "Docker", + "dockerIntegration": "Docker Entegrasyonu", + "enableDockerMonitor": "Docker'ı Etkinleştir", + "enableDockerMonitorDesc": "Docker aracılığıyla bu ana bilgisayardaki kapsayıcıları izle ve yönet", + "containerRuntime": "Kapsayıcı Çalışma Zamanı", + "containerRuntimeDesc": "Bu ana bilgisayarda kapsayıcı yönetimi için kullanılan CLI'yi seçin", + "containerRuntimeDocker": "Docker", + "containerRuntimePodman": "Podman" + }, + "onboarding": { + "feature_docker": "Liman işçisi", + "feature_docker_desc": "Docker çalıştıran herhangi bir sunucudaki konteynerleri görüntüleyin, günlükleri okuyun ve istatistikleri izleyin." + } +} diff --git a/plugins/docker/locales/translated/uk_UA.json b/plugins/docker/locales/translated/uk_UA.json new file mode 100644 index 000000000..2a7c7bc7f --- /dev/null +++ b/plugins/docker/locales/translated/uk_UA.json @@ -0,0 +1,116 @@ +{ + "docker": { + "notEnabled": "Docker не ввімкнено для цього хоста", + "validating": "Перевірка Docker...", + "connecting": "Підключення...", + "error": "Помилка", + "version": "{{runtime}} {{version}}", + "connectionFailed": "Не вдалося підключитися до Docker", + "containerStarted": "Контейнер {{name}} запущено", + "failedToStartContainer": "Не вдалося запустити контейнер {{name}}", + "containerStopped": "Контейнер {{name}} зупинено", + "failedToStopContainer": "Не вдалося зупинити контейнер {{name}}", + "containerRestarted": "Контейнер {{name}} перезапущено", + "failedToRestartContainer": "Не вдалося перезапустити контейнер {{name}}", + "containerPaused": "Контейнер {{name}} призупинено", + "containerUnpaused": "Контейнер {{name}} відновлено", + "failedToTogglePauseContainer": "Не вдалося перемкнути стан паузи для контейнера {{name}}", + "containerRemoved": "Контейнер {{name}} видалено", + "failedToRemoveContainer": "Не вдалося видалити контейнер {{name}}", + "image": "Зображення", + "ports": "Порти", + "noPorts": "Без портів", + "start": "Початок", + "confirmRemoveContainer": "Ви впевнені, що хочете видалити контейнер '{{name}}'? Цю дію неможливо скасувати.", + "runningContainerWarning": "Попередження: Цей контейнер зараз працює. Його видалення спочатку зупинить його роботу.", + "loadingContainers": "Завантаження контейнерів...", + "manager": "Менеджер Докера", + "autoRefresh": "Автоматичне оновлення", + "timestamps": "Позначки часу", + "lines": "Лінії", + "filterLogs": "Фільтрувати журнали...", + "refresh": "Оновити", + "download": "Завантажити", + "clear": "Очистити", + "logsDownloaded": "Журнали успішно завантажено", + "last50": "Останні 50", + "last100": "Останні 100", + "last500": "Останні 500", + "last1000": "Останні 1000", + "allLogs": "Усі журнали", + "noLogsMatching": "Немає журналів, що відповідають \"{{query}}\"", + "noLogsAvailable": "Журнали недоступні", + "noContainersFound": "Контейнерів не знайдено", + "noContainersFoundHint": "На цьому хості немає доступних контейнерів Docker", + "searchPlaceholder": "Пошук контейнерів...", + "allStatuses": "Усі статуси", + "stateRunning": "Біг", + "statePaused": "Призупинено", + "stateExited": "Вихід", + "stateRestarting": "Перезапуск", + "noContainersMatchFilters": "Немає контейнерів, що відповідають вашим фільтрам", + "noContainersMatchFiltersHint": "Спробуйте змінити критерії пошуку або фільтра", + "failedToFetchStats": "Не вдалося отримати статистику контейнера", + "containerNotRunning": "Контейнер не працює", + "startContainerToViewStats": "Запустіть контейнер для перегляду статистики", + "loadingStats": "Завантаження статистики...", + "errorLoadingStats": "Помилка завантаження статистики", + "noStatsAvailable": "Статистика недоступна", + "cpuUsage": "Використання процесора", + "current": "Поточний", + "memoryUsage": "Використання пам'яті", + "networkIo": "Мережевий ввід/вивід", + "input": "Вхід", + "output": "Вихід", + "blockIo": "Блок вводу/виводу", + "read": "Читати", + "write": "Написати", + "pids": "PID-ідентифікатори", + "containerInformation": "Інформація про контейнер", + "name": "Ім'я", + "id": "Ідентифікатор", + "state": "Штат", + "containerMustBeRunning": "Для доступу до консолі контейнер має бути запущений", + "verificationCodePrompt": "Введіть код підтвердження", + "totpVerificationFailed": "Не вдалося перевірити TOTP. Спробуйте ще раз.", + "warpgateVerificationFailed": "Помилка автентифікації Warpgate. Будь ласка, спробуйте ще раз.", + "connectedTo": "Підключено до {{containerName}}", + "disconnected": "Відключено", + "consoleError": "Помилка консолі", + "errorMessage": "Помилка: {{message}}", + "failedToConnect": "Не вдалося підключитися до контейнера", + "console": "Консоль", + "selectShell": "Виберіть оболонку", + "bash": "Баш", + "sh": "ш", + "ash": "попіл", + "connect": "Підключитися", + "disconnect": "Відключитися", + "notConnected": "Не підключено", + "clickToConnect": "Натисніть кнопку «Підключитися», щоб розпочати сеанс оболонки", + "connectingTo": "Підключення до {{containerName}}...", + "containerNotFound": "Контейнер не знайдено", + "backToList": "Назад до списку", + "logs": "Журнали", + "stats": "Статистика", + "consoleTab": "Консоль", + "startContainerToAccess": "Запустіть контейнер для доступу до консолі" + }, + "nav": { + "docker": "Докер" + }, + "hosts": { + "tabDocker": "Докер", + "dockerIntegration": "Інтеграція Docker", + "enableDockerMonitor": "Увімкнути Докер", + "enableDockerMonitorDesc": "Моніторинг та керування контейнерами на цьому хості через Docker", + "containerRuntime": "Середовище виконання контейнера", + "containerRuntimeDesc": "Виберіть інтерфейс командного рядка, який використовується для керування контейнерами на цьому хості", + "containerRuntimeDocker": "Докер", + "containerRuntimePodman": "Подман" + }, + "onboarding": { + "feature_docker": "Докер", + "feature_docker_desc": "Переглядайте контейнери, читайте журнали та переглядайте статистику на будь-якому хості, на якому працює Docker." + } +} diff --git a/plugins/docker/locales/translated/vi_VN.json b/plugins/docker/locales/translated/vi_VN.json new file mode 100644 index 000000000..d4ca5f532 --- /dev/null +++ b/plugins/docker/locales/translated/vi_VN.json @@ -0,0 +1,116 @@ +{ + "docker": { + "notEnabled": "Docker chưa được kích hoạt cho máy chủ này", + "validating": "Đang kiểm tra Docker...", + "connecting": "Đang kết nối...", + "error": "Lỗi", + "version": "{{runtime}} {{version}}", + "connectionFailed": "Kết nối Docker thất bại", + "containerStarted": "Container {{name}} đã khởi động", + "failedToStartContainer": "Khởi động container {{name}} thất bại", + "containerStopped": "Container {{name}} đã dừng", + "failedToStopContainer": "Dừng container {{name}} thất bại", + "containerRestarted": "Container {{name}} đã khởi động lại", + "failedToRestartContainer": "Khởi động lại container {{name}} thất bại", + "containerPaused": "Container {{name}} đã tạm dừng", + "containerUnpaused": "Container {{name}} đã tiếp tục", + "failedToTogglePauseContainer": "Chuyển đổi trạng thái tạm dừng cho container {{name}} thất bại", + "containerRemoved": "Container {{name}} đã bị xóa", + "failedToRemoveContainer": "Xóa container {{name}} thất bại", + "image": "Image", + "ports": "Cổng", + "noPorts": "Không có cổng nào", + "start": "Khởi động", + "confirmRemoveContainer": "Bạn có chắc chắn muốn xóa container '{{name}}' không? Hành động này không thể hoàn tác.", + "runningContainerWarning": "Cảnh báo: Container này đang chạy. Xóa nó sẽ dừng container trước.", + "loadingContainers": "Đang tải danh sách container...", + "manager": "Quản lý Docker", + "autoRefresh": "Tự động làm mới", + "timestamps": "Dấu thời gian", + "lines": "Dòng", + "filterLogs": "Lọc nhật ký...", + "refresh": "Làm mới", + "download": "Tải xuống", + "clear": "Xóa", + "logsDownloaded": "Đã tải xuống nhật ký thành công", + "last50": "50 cuối cùng", + "last100": "100 cuối cùng", + "last500": "500 cuối cùng", + "last1000": "1000 cuối cùng", + "allLogs": "Tất cả nhật ký", + "noLogsMatching": "Không có nhật ký nào khớp với \"{{query}}\"", + "noLogsAvailable": "Không có nhật ký khả dụng", + "noContainersFound": "Không tìm thấy container", + "noContainersFoundHint": "Không có container Docker nào trên máy chủ này", + "searchPlaceholder": "Tìm kiếm container...", + "allStatuses": "Tất cả trạng thái", + "stateRunning": "Đang chạy", + "statePaused": "Tạm dừng", + "stateExited": "Đã thoát", + "stateRestarting": "Đang khởi động lại", + "noContainersMatchFilters": "Không có container nào khớp bộ lọc của bạn", + "noContainersMatchFiltersHint": "Hãy thử điều chỉnh tiêu chí tìm kiếm hoặc lọc", + "failedToFetchStats": "Không thể lấy số liệu thống kê container", + "containerNotRunning": "Container không chạy", + "startContainerToViewStats": "Khởi động container để xem số liệu thống kê", + "loadingStats": "Đang tải số liệu thống kê...", + "errorLoadingStats": "Lỗi khi tải số liệu thống kê", + "noStatsAvailable": "Không có số liệu thống kê", + "cpuUsage": "Sử dụng CPU", + "current": "Hiện tại", + "memoryUsage": "Sử dụng bộ nhớ", + "networkIo": "I/O mạng", + "input": "Nhập", + "output": "Đầu ra", + "blockIo": "I/O khối", + "read": "Đọc", + "write": "Ghi", + "pids": "PIDs", + "containerInformation": "Thông tin container", + "name": "Tên", + "id": "ID", + "state": "Trạng thái", + "containerMustBeRunning": "Container phải đang chạy để truy cập bảng điều khiển", + "verificationCodePrompt": "Nhập mã xác minh", + "totpVerificationFailed": "Xác minh TOTP thất bại. Vui lòng thử lại.", + "warpgateVerificationFailed": "Xác thực Warpgate thất bại. Vui lòng thử lại.", + "connectedTo": "Đã kết nối đến {{containerName}}", + "disconnected": "Đã ngắt kết nối", + "consoleError": "Lỗi bảng điều khiển", + "errorMessage": "Lỗi: {{message}}", + "failedToConnect": "Không thể kết nối đến container", + "console": "Bảng điều khiển", + "selectShell": "Chọn shell", + "bash": "Bash", + "sh": "sh", + "ash": "ash", + "connect": "Kết nối", + "disconnect": "Ngắt kết nối", + "notConnected": "Chưa kết nối", + "clickToConnect": "Nhấn Kết nối để bắt đầu phiên shell", + "connectingTo": "Đang kết nối đến {{containerName}}...", + "containerNotFound": "Không tìm thấy container", + "backToList": "Quay lại danh sách", + "logs": "Nhật ký", + "stats": "Thống kê", + "consoleTab": "Bảng điều khiển", + "startContainerToAccess": "Khởi động container để truy cập bảng điều khiển" + }, + "nav": { + "docker": "Docker" + }, + "hosts": { + "tabDocker": "Docker", + "dockerIntegration": "Tích hợp Docker", + "enableDockerMonitor": "Bật Docker", + "enableDockerMonitorDesc": "Giám sát và quản lý container trên máy chủ này qua Docker", + "containerRuntime": "Môi trường chạy container", + "containerRuntimeDesc": "Chọn CLI dùng để quản lý container trên máy chủ này", + "containerRuntimeDocker": "Docker", + "containerRuntimePodman": "Podman" + }, + "onboarding": { + "feature_docker": "Docker", + "feature_docker_desc": "Xem các container, đọc nhật ký và theo dõi số liệu thống kê trên bất kỳ máy chủ nào đang chạy Docker." + } +} diff --git a/plugins/docker/locales/translated/zh_CN.json b/plugins/docker/locales/translated/zh_CN.json new file mode 100644 index 000000000..eb8e7e431 --- /dev/null +++ b/plugins/docker/locales/translated/zh_CN.json @@ -0,0 +1,116 @@ +{ + "docker": { + "notEnabled": "此主机未启用 Docker", + "validating": "验证 Docker 中...", + "connecting": "连接中...", + "error": "错误", + "version": "{{runtime}} {{version}}", + "connectionFailed": "连接 Docker 失败", + "containerStarted": "容器 {{name}} 已启动", + "failedToStartContainer": "启动容器 {{name}} 失败", + "containerStopped": "容器 {{name}} 已停止", + "failedToStopContainer": "停止容器 {{name}} 失败", + "containerRestarted": "容器 {{name}} 已重启", + "failedToRestartContainer": "重启容器 {{name}} 失败", + "containerPaused": "容器 {{name}} 已暂停", + "containerUnpaused": "容器 {{name}} 已恢复", + "failedToTogglePauseContainer": "切换容器 {{name}} 暂停状态失败", + "containerRemoved": "容器 {{name}} 已移除", + "failedToRemoveContainer": "移除容器 {{name}} 失败", + "image": "镜像", + "ports": "端口", + "noPorts": "无端口", + "start": "启动", + "confirmRemoveContainer": "确定要移除容器 '{{name}}' 吗?此操作无法撤销。", + "runningContainerWarning": "警告:此容器正在运行。移除操作将先停止容器。", + "loadingContainers": "正在加载容器...", + "manager": "Docker 管理器", + "autoRefresh": "自动刷新", + "timestamps": "时间戳", + "lines": "行数", + "filterLogs": "筛选日志...", + "refresh": "刷新", + "download": "下载", + "clear": "清除", + "logsDownloaded": "日志下载成功", + "last50": "最近 50 条", + "last100": "最近 100 条", + "last500": "最近 500 条", + "last1000": "最近 1000 条", + "allLogs": "全部日志", + "noLogsMatching": "未找到匹配 \"{{query}}\" 的日志", + "noLogsAvailable": "暂无日志", + "noContainersFound": "未找到容器", + "noContainersFoundHint": "此主机上没有可用的 Docker 容器", + "searchPlaceholder": "搜索容器...", + "allStatuses": "所有状态", + "stateRunning": "运行中", + "statePaused": "已暂停", + "stateExited": "已退出", + "stateRestarting": "重启中", + "noContainersMatchFilters": "没有容器符合筛选条件", + "noContainersMatchFiltersHint": "请尝试调整搜索或筛选条件", + "failedToFetchStats": "获取容器统计信息失败", + "containerNotRunning": "容器未运行", + "startContainerToViewStats": "启动容器以查看统计信息", + "loadingStats": "加载统计信息...", + "errorLoadingStats": "加载统计信息时出错", + "noStatsAvailable": "无可用统计信息", + "cpuUsage": "CPU 使用率", + "current": "当前", + "memoryUsage": "内存使用量", + "networkIo": "网络 I/O", + "input": "输入", + "output": "输出", + "blockIo": "块 I/O", + "read": "读取", + "write": "写入", + "pids": "PIDs", + "containerInformation": "容器信息", + "name": "名称", + "id": "ID", + "state": "状态", + "containerMustBeRunning": "访问控制台需要容器处于运行状态", + "verificationCodePrompt": "输入验证码", + "totpVerificationFailed": "TOTP 验证失败,请重试。", + "warpgateVerificationFailed": "Warpgate 认证失败,请重试。", + "connectedTo": "已连接到 {{containerName}}", + "disconnected": "已断开连接", + "consoleError": "控制台错误", + "errorMessage": "错误:{{message}}", + "failedToConnect": "连接到容器失败", + "console": "控制台", + "selectShell": "选择 shell", + "bash": "Bash", + "sh": "sh", + "ash": "ash", + "connect": "连接", + "disconnect": "断开连接", + "notConnected": "未连接", + "clickToConnect": "点击“连接”启动 shell 会话", + "connectingTo": "正在连接到 {{containerName}}...", + "containerNotFound": "未找到容器", + "backToList": "返回列表", + "logs": "日志", + "stats": "统计", + "consoleTab": "控制台", + "startContainerToAccess": "启动容器以访问控制台" + }, + "nav": { + "docker": "Docker" + }, + "hosts": { + "tabDocker": "Docker", + "dockerIntegration": "Docker 集成", + "enableDockerMonitor": "启用 Docker", + "enableDockerMonitorDesc": "通过 Docker 监控和管理此主机上的容器", + "containerRuntime": "容器运行时", + "containerRuntimeDesc": "选择此主机上用于容器管理的 CLI", + "containerRuntimeDocker": "Docker", + "containerRuntimePodman": "Podman" + }, + "onboarding": { + "feature_docker": "Docker", + "feature_docker_desc": "在任何运行 Docker 的主机上查看容器、读取日志及监控运行状态。" + } +} diff --git a/plugins/docker/locales/translated/zh_TW.json b/plugins/docker/locales/translated/zh_TW.json new file mode 100644 index 000000000..92ff524fd --- /dev/null +++ b/plugins/docker/locales/translated/zh_TW.json @@ -0,0 +1,116 @@ +{ + "docker": { + "notEnabled": "此主機未啟用 Docker", + "validating": "正在驗證 Docker...", + "connecting": "連線中...", + "error": "錯誤", + "version": "{{runtime}} {{version}}", + "connectionFailed": "無法連線至 Docker", + "containerStarted": "容器 {{name}} 已啟動", + "failedToStartContainer": "無法啟動容器 {{name}}", + "containerStopped": "容器 {{name}} 已停止", + "failedToStopContainer": "無法停止容器 {{name}}", + "containerRestarted": "容器 {{name}} 已重新啟動", + "failedToRestartContainer": "無法重新啟動容器 {{name}}", + "containerPaused": "容器 {{name}} 已暫停", + "containerUnpaused": "容器 {{name}} 已取消暫停", + "failedToTogglePauseContainer": "無法切換容器 {{name}} 的暫停狀態", + "containerRemoved": "容器 {{name}} 已移除", + "failedToRemoveContainer": "無法移除容器 {{name}}", + "image": "映像", + "ports": "連接埠", + "noPorts": "無連接埠", + "start": "啟動", + "confirmRemoveContainer": "確定要移除容器 '{{name}}' 嗎?此動作無法復原。", + "runningContainerWarning": "警告:此容器正在執行中。移除時會先將其停止。", + "loadingContainers": "正在載入容器...", + "manager": "Docker 管理", + "autoRefresh": "自動重新整理", + "timestamps": "時間戳記", + "lines": "行", + "filterLogs": "篩選日誌...", + "refresh": "重新整理", + "download": "下載", + "clear": "清除", + "logsDownloaded": "日誌下載成功", + "last50": "最後 50 筆", + "last100": "最後 100 筆", + "last500": "最後 500 筆", + "last1000": "最後 1000 筆", + "allLogs": "所有日誌", + "noLogsMatching": "沒有符合 \"{{query}}\" 的日誌", + "noLogsAvailable": "無可用日誌", + "noContainersFound": "找不到容器", + "noContainersFoundHint": "此主機上沒有可用的 Docker 容器", + "searchPlaceholder": "搜尋容器...", + "allStatuses": "所有狀態", + "stateRunning": "執行中", + "statePaused": "已暫停", + "stateExited": "已退出", + "stateRestarting": "正在重新啟動", + "noContainersMatchFilters": "沒有符合篩選條件的容器", + "noContainersMatchFiltersHint": "請嘗試調整搜尋或篩選條件", + "failedToFetchStats": "無法取得容器統計資料", + "containerNotRunning": "容器未執行", + "startContainerToViewStats": "啟動容器以檢視統計資料", + "loadingStats": "正在載入統計資料...", + "errorLoadingStats": "載入統計資料時發生錯誤", + "noStatsAvailable": "無可用統計資料", + "cpuUsage": "CPU 使用率", + "current": "目前", + "memoryUsage": "記憶體使用量", + "networkIo": "網路 I/O", + "input": "輸入", + "output": "輸出", + "blockIo": "區塊 I/O", + "read": "讀取", + "write": "寫入", + "pids": "PID", + "containerInformation": "容器資訊", + "name": "名稱", + "id": "ID", + "state": "狀態", + "containerMustBeRunning": "容器必須在執行中才能存取主控台", + "verificationCodePrompt": "請輸入驗證碼", + "totpVerificationFailed": "TOTP 驗證失敗,請再試一次。", + "warpgateVerificationFailed": "Warpgate 驗證失敗,請再試一次。", + "connectedTo": "已連線至 {{containerName}}", + "disconnected": "已中斷連線", + "consoleError": "主控台錯誤", + "errorMessage": "錯誤:{{message}}", + "failedToConnect": "無法連線至容器", + "console": "主控台", + "selectShell": "選取 shell", + "bash": "Bash", + "sh": "sh", + "ash": "ash", + "connect": "連線", + "disconnect": "中斷連線", + "notConnected": "未連線", + "clickToConnect": "點擊連線以啟動 shell 工作階段", + "connectingTo": "正在連線至 {{containerName}}...", + "containerNotFound": "找不到容器", + "backToList": "返回列表", + "logs": "記錄", + "stats": "統計資料", + "consoleTab": "主控台", + "startContainerToAccess": "啟動容器以存取主控台" + }, + "nav": { + "docker": "Docker" + }, + "hosts": { + "tabDocker": "Docker", + "dockerIntegration": "Docker 整合", + "enableDockerMonitor": "啟用 Docker", + "enableDockerMonitorDesc": "透過 Docker 監控及管理此主機上的容器", + "containerRuntime": "容器執行環境", + "containerRuntimeDesc": "選擇用於此主機容器管理的 CLI", + "containerRuntimeDocker": "Docker", + "containerRuntimePodman": "Podman" + }, + "onboarding": { + "feature_docker": "Docker", + "feature_docker_desc": "查看執行 Docker 的任何主機上的容器、讀取日誌和查看統計資料。" + } +} diff --git a/plugins/docker/src/frontend/DockerApp.tsx b/plugins/docker/src/frontend/DockerApp.tsx index 40e74e0f2..b2bd1a650 100644 --- a/plugins/docker/src/frontend/DockerApp.tsx +++ b/plugins/docker/src/frontend/DockerApp.tsx @@ -1,5 +1,5 @@ import React from "react"; -import { useTranslation } from "react-i18next"; +import { useTranslation } from "@termix/plugin-sdk/frontend"; import { DockerManager } from "./DockerManager.tsx"; import { FullScreenAppWrapper } from "@/features/FullScreenAppWrapper.tsx"; import { ConnectionScreen } from "@/components/connection/ConnectionScreen.tsx"; diff --git a/plugins/docker/src/frontend/DockerManager.tsx b/plugins/docker/src/frontend/DockerManager.tsx index 328b98e65..b5fb68991 100644 --- a/plugins/docker/src/frontend/DockerManager.tsx +++ b/plugins/docker/src/frontend/DockerManager.tsx @@ -15,8 +15,9 @@ import { Search, } from "lucide-react"; -import { useTranslation } from "react-i18next"; +import { useTranslation } from "@termix/plugin-sdk/frontend"; import type { SSHHost, DockerContainer, DockerValidation } from "@/types"; +import { logActivity, getSSHHosts } from "@/main-axios"; import { connectDockerSession, disconnectDockerSession, @@ -25,9 +26,7 @@ import { keepaliveDockerSession, verifyDockerTOTP, verifyDockerWarpgate, - logActivity, - getSSHHosts, -} from "@/main-axios.ts"; +} from "./docker-api"; import { ContainerList } from "./components/ContainerList.tsx"; import { ContainerTable } from "./components/ContainerTable.tsx"; import { ContainerDetail } from "./components/ContainerDetail.tsx"; diff --git a/src/ui/features/homepage/widgets/DockerWidget.tsx b/plugins/docker/src/frontend/DockerWidget.tsx similarity index 85% rename from src/ui/features/homepage/widgets/DockerWidget.tsx rename to plugins/docker/src/frontend/DockerWidget.tsx index 68348fe87..5c8bcd006 100644 --- a/src/ui/features/homepage/widgets/DockerWidget.tsx +++ b/plugins/docker/src/frontend/DockerWidget.tsx @@ -1,17 +1,18 @@ import { useState, useEffect } from "react"; import { Box } from "lucide-react"; -import { useTranslation } from "react-i18next"; -import { registerWidget } from "./WidgetRegistry"; +import { useTranslation } from "@termix/plugin-sdk/frontend"; +import { DockerWidgetEditForm } from "./DockerWidgetEditForm"; import type { DockerWidgetConfig, WidgetComponentProps, + WidgetTypeDefinition, } from "@/types/homepage-types"; import { GRID_SIZE } from "@/types/homepage-types"; import { getSSHHosts } from "@/api/ssh-host-management-api"; import type { SSHHostWithStatus } from "@/main-axios"; -import { DockerManager } from "../../../../../plugins/docker/src/frontend/DockerManager"; +import { DockerManager } from "./DockerManager"; import type { SSHHost } from "@/types/index"; -import { WidgetTitle } from "./WidgetTitle"; +import { WidgetTitle } from "@/features/homepage/widgets/WidgetTitle"; function DockerWidget({ widget, @@ -81,7 +82,8 @@ function DockerWidget({ ); } -registerWidget({ +/** Registered by the plugin while it runs. */ +export const dockerWidget: WidgetTypeDefinition = { id: "docker_widget", name: "Docker Manager", description: "Embedded Docker container manager for a configured host", @@ -91,4 +93,5 @@ registerWidget({ defaultSize: { w: GRID_SIZE * 20, h: GRID_SIZE * 14 }, minSize: { w: GRID_SIZE * 10, h: GRID_SIZE * 8 }, component: DockerWidget, -}); + editFormComponent: DockerWidgetEditForm, +}; diff --git a/src/ui/features/homepage/dialogs/DockerWidgetEditForm.tsx b/plugins/docker/src/frontend/DockerWidgetEditForm.tsx similarity index 82% rename from src/ui/features/homepage/dialogs/DockerWidgetEditForm.tsx rename to plugins/docker/src/frontend/DockerWidgetEditForm.tsx index bbe779ee4..d8e57086a 100644 --- a/src/ui/features/homepage/dialogs/DockerWidgetEditForm.tsx +++ b/plugins/docker/src/frontend/DockerWidgetEditForm.tsx @@ -2,7 +2,7 @@ import type { DockerWidgetConfig, WidgetEditFormProps, } from "@/types/homepage-types"; -import { SingleHostEditForm } from "./SingleHostEditForm"; +import { SingleHostEditForm } from "@/features/homepage/dialogs/SingleHostEditForm"; export function DockerWidgetEditForm({ config, diff --git a/plugins/docker/src/frontend/HostDockerTab.tsx b/plugins/docker/src/frontend/HostDockerTab.tsx new file mode 100644 index 000000000..e59572637 --- /dev/null +++ b/plugins/docker/src/frontend/HostDockerTab.tsx @@ -0,0 +1,68 @@ +import { useTranslation } from "@termix/plugin-sdk/frontend"; +import { Box } from "lucide-react"; +import { Select2 } from "@/components/select2"; +import { SectionCard, SettingRow, FakeSwitch } from "@/components/section-card"; +import type { HostEditorForm } from "@/sidebar/HostEditorData"; + +type SetHostField = ( + key: K, + value: HostEditorForm[K], +) => void; + +export function HostDockerTab({ + form, + setField, +}: { + form: HostEditorForm; + setField: SetHostField; +}) { + const { t } = useTranslation(); + const dockerConfig = form.dockerConfig ?? { runtime: "docker" as const }; + const runtime = + dockerConfig.runtime === "podman" + ? ("podman" as const) + : ("docker" as const); + + return ( + } + > +
+ + setField("enableDocker", v)} + /> + + {form.enableDocker && ( + + + setField("dockerConfig", { + ...dockerConfig, + runtime: e.target.value as "docker" | "podman", + }) + } + className="h-7 w-44 text-xs border border-border bg-background px-2 outline-none focus:ring-1 focus:ring-ring" + > + + + + + )} +
+
+ ); +} diff --git a/plugins/docker/src/frontend/components/ConsoleTerminal.tsx b/plugins/docker/src/frontend/components/ConsoleTerminal.tsx index 431affe97..366376482 100644 --- a/plugins/docker/src/frontend/components/ConsoleTerminal.tsx +++ b/plugins/docker/src/frontend/components/ConsoleTerminal.tsx @@ -15,7 +15,7 @@ import { Terminal as TerminalIcon, Power, PowerOff } from "lucide-react"; import { toast } from "sonner"; import type { SSHHost } from "@/types"; import { isElectron } from "@/main-axios.ts"; -import { useTranslation } from "react-i18next"; +import { useTranslation } from "@termix/plugin-sdk/frontend"; import { resolveTermixThemeColors } from "@/features/terminal/terminal-theme"; import { DEFAULT_TERMINAL_CONFIG, TERMINAL_FONTS } from "@/lib/terminal-themes"; import { ensureTerminalFontsLoaded } from "@/features/terminal/terminal-global-styles"; diff --git a/plugins/docker/src/frontend/components/ContainerCard.tsx b/plugins/docker/src/frontend/components/ContainerCard.tsx index 1b3b32bbb..c5cdc3b08 100644 --- a/plugins/docker/src/frontend/components/ContainerCard.tsx +++ b/plugins/docker/src/frontend/components/ContainerCard.tsx @@ -13,7 +13,7 @@ import { RefreshCw, } from "lucide-react"; import { toast } from "sonner"; -import { useTranslation } from "react-i18next"; +import { useTranslation } from "@termix/plugin-sdk/frontend"; import type { DockerContainer } from "@/types"; import { startDockerContainer, @@ -22,7 +22,7 @@ import { pauseDockerContainer, unpauseDockerContainer, removeDockerContainer, -} from "@/main-axios.ts"; +} from "../docker-api"; import { useConfirmation } from "@/hooks/use-confirmation.ts"; interface ContainerCardProps { diff --git a/plugins/docker/src/frontend/components/ContainerDetail.tsx b/plugins/docker/src/frontend/components/ContainerDetail.tsx index 46ff43a64..3d77c8552 100644 --- a/plugins/docker/src/frontend/components/ContainerDetail.tsx +++ b/plugins/docker/src/frontend/components/ContainerDetail.tsx @@ -10,7 +10,7 @@ import { Settings, Terminal, } from "lucide-react"; -import { useTranslation } from "react-i18next"; +import { useTranslation } from "@termix/plugin-sdk/frontend"; import type { DockerContainer, SSHHost } from "@/types"; import { LogViewer } from "./LogViewer.tsx"; import { ContainerStats } from "./ContainerStats.tsx"; diff --git a/plugins/docker/src/frontend/components/ContainerList.tsx b/plugins/docker/src/frontend/components/ContainerList.tsx index e6886838a..29a4bed3d 100644 --- a/plugins/docker/src/frontend/components/ContainerList.tsx +++ b/plugins/docker/src/frontend/components/ContainerList.tsx @@ -1,6 +1,6 @@ import React from "react"; import { Box } from "lucide-react"; -import { useTranslation } from "react-i18next"; +import { useTranslation } from "@termix/plugin-sdk/frontend"; import type { DockerContainer } from "@/types"; import { ContainerCard } from "./ContainerCard.tsx"; diff --git a/plugins/docker/src/frontend/components/ContainerStats.tsx b/plugins/docker/src/frontend/components/ContainerStats.tsx index b30334088..e3c4297e5 100644 --- a/plugins/docker/src/frontend/components/ContainerStats.tsx +++ b/plugins/docker/src/frontend/components/ContainerStats.tsx @@ -10,8 +10,8 @@ import { RefreshCw, } from "lucide-react"; import type { DockerStats } from "@/types"; -import { getContainerStats } from "@/main-axios.ts"; -import { useTranslation } from "react-i18next"; +import { getContainerStats } from "../docker-api"; +import { useTranslation } from "@termix/plugin-sdk/frontend"; import { SectionCard } from "@/components/section-card"; import { DockerBadge } from "./ContainerCard.tsx"; import { useAdaptivePolling } from "@/hooks/use-adaptive-polling.ts"; diff --git a/plugins/docker/src/frontend/components/ContainerTable.tsx b/plugins/docker/src/frontend/components/ContainerTable.tsx index cfb873d0e..4196e7ec8 100644 --- a/plugins/docker/src/frontend/components/ContainerTable.tsx +++ b/plugins/docker/src/frontend/components/ContainerTable.tsx @@ -2,10 +2,10 @@ import { getErrorMessage } from "@/lib/error-message.js"; import React from "react"; import { Box, List, Play, RefreshCw, Square, Terminal } from "lucide-react"; import { toast } from "sonner"; -import { useTranslation } from "react-i18next"; +import { useTranslation } from "@termix/plugin-sdk/frontend"; import { Button } from "@/components/button.tsx"; import type { DockerContainer } from "@/types"; -import { startDockerContainer, stopDockerContainer } from "@/main-axios.ts"; +import { startDockerContainer, stopDockerContainer } from "../docker-api"; import { DockerBadge } from "./ContainerCard.tsx"; type DetailTab = "logs" | "stats" | "console"; diff --git a/plugins/docker/src/frontend/components/LogViewer.tsx b/plugins/docker/src/frontend/components/LogViewer.tsx index 54e489146..1804d4446 100644 --- a/plugins/docker/src/frontend/components/LogViewer.tsx +++ b/plugins/docker/src/frontend/components/LogViewer.tsx @@ -5,9 +5,9 @@ import { Input } from "@/components/input.tsx"; import { Separator } from "@/components/separator.tsx"; import { Download, RefreshCw, Search, Trash2 } from "lucide-react"; import { toast } from "sonner"; -import { useTranslation } from "react-i18next"; +import { useTranslation } from "@termix/plugin-sdk/frontend"; import type { DockerLogOptions } from "@/types"; -import { getContainerLogs, downloadContainerLogs } from "@/main-axios.ts"; +import { getContainerLogs, downloadContainerLogs } from "../docker-api"; import { useAdaptivePolling } from "@/hooks/use-adaptive-polling.ts"; import { Select2 } from "@/components/select2"; diff --git a/src/ui/api/docker-api.ts b/plugins/docker/src/frontend/docker-api.ts similarity index 100% rename from src/ui/api/docker-api.ts rename to plugins/docker/src/frontend/docker-api.ts diff --git a/plugins/docker/src/frontend/index.mjs b/plugins/docker/src/frontend/index.mjs deleted file mode 100644 index 08529b956..000000000 --- a/plugins/docker/src/frontend/index.mjs +++ /dev/null @@ -1,67 +0,0 @@ -/** - * Frontend half of the docker plugin. - * - * Registers the container-management tab through the existing extension - * seams (registerRailItem / registerTabComponent) the same way - * ssh-terminal's frontend does, and the host-editor Docker tab through the - * new registerHostEditorTab seam built for this plugin. - * - * HostDockerTab itself stays in src/ui/sidebar/HostEditorFeatureTabs.tsx - * rather than moving into this plugin: it takes the same {form, setField} - * pair every other host editor tab does, and those types (HostEditorForm, - * the setField signature) are core types HostEditor.tsx owns, the same - * reason ssh-terminal leaves session-manager.ts in core rather than copying - * it here. - * - * register() is called when the plugin is enabled, unregister() when it is - * disabled. As of this change neither is actually invoked anywhere yet -- - * see plugins/ssh-terminal/frontend/index.mjs and - * src/ui/tests/sidebar/plugin-extension-seam.test.tsx, which says outright - * "there is no plugin loader yet" for the frontend half. This file follows - * the same shape so it is ready the moment that loader exists. - */ - -export const id = "docker"; -export const tabId = "docker"; -export const hostEditorTabId = "docker"; - -export async function register({ - registerRailItem, - registerTabComponent, - registerHostEditorTab, - icons, -}) { - registerTabComponent(tabId, () => - import("./DockerManager.tsx").then((m) => ({ - default: m.DockerManager, - })), - ); - - registerRailItem({ - id: tabId, - icon: icons.Box, - labelKey: "nav.docker", - kind: "tab", - }); - - if (registerHostEditorTab) { - const { HostDockerTab } = - await import("../../../../src/ui/sidebar/HostEditorFeatureTabs.tsx"); - registerHostEditorTab({ - id: hostEditorTabId, - labelKey: "hosts.tabDocker", - icon: icons.Box, - component: HostDockerTab, - }); - } -} - -export async function unregister({ - unregisterRailItem, - unregisterTabComponent, - unregisterHostEditorTab, -}) { - unregisterRailItem(tabId); - unregisterTabComponent(tabId); - unregisterHostEditorTab?.(hostEditorTabId); -} diff --git a/plugins/docker/src/frontend/index.tsx b/plugins/docker/src/frontend/index.tsx new file mode 100644 index 000000000..1319fd295 --- /dev/null +++ b/plugins/docker/src/frontend/index.tsx @@ -0,0 +1,83 @@ +import type { ComponentType } from "react"; +import { Box } from "lucide-react"; +import type { + HomepageWidgetContribution, + HostEditorSectionProps, + StandaloneViewProps, + TabProps, + TermixApp, +} from "@termix/plugin-sdk/frontend"; +import type { SSHHost } from "@/types"; +import { DockerManager } from "./DockerManager"; +import DockerApp from "./DockerApp"; +import { HostDockerTab } from "./HostDockerTab"; +import { dockerWidget } from "./DockerWidget"; + +function DockerTab({ sshHost, label, isVisible }: TabProps) { + return ( + + ); +} + +function DockerStandalone({ hostId }: StandaloneViewProps) { + return ; +} + +function DockerHostSection({ form, setField }: HostEditorSectionProps) { + return ( + [0]["setField"]} + /> + ); +} + +export function activate(app: TermixApp): void { + app.registerTab("docker", DockerTab, { + icon: Box, + titleKey: "nav.docker", + requiresHost: true, + noHostMessageKey: "docker.noHostSelected", + persistent: true, + activityTypes: ["docker"], + standalone: DockerStandalone, + preload: () => import("./DockerManager"), + }); + + app.registerHostAction({ + id: "docker", + titleKey: "nav.docker", + icon: Box, + kind: "open", + order: 30, + tabType: "docker", + copyUrlView: "docker", + when: (host) => !!host.enableSsh && !!host.enableDocker, + }); + + app.registerHostEditorSection({ + id: "docker", + group: "ssh", + titleKey: "hosts.tabDocker", + icon: Box, + order: 30, + component: DockerHostSection, + }); + + app.registerHomepageWidget( + dockerWidget as unknown as HomepageWidgetContribution, + ); + + app.registerSlotContribution("onboarding.features", { + actionId: "docker.feature", + titleKey: "onboarding.feature_docker", + descriptionKey: "onboarding.feature_docker_desc", + icon: Box as ComponentType<{ className?: string }>, + }); +} diff --git a/plugins/docker/tests/frontend/activate.test.tsx b/plugins/docker/tests/frontend/activate.test.tsx new file mode 100644 index 000000000..814097280 --- /dev/null +++ b/plugins/docker/tests/frontend/activate.test.tsx @@ -0,0 +1,53 @@ +import { afterEach, describe, expect, it } from "vitest"; +import { + renderWithApp, + type RenderedPluginApp, +} from "@termix/plugin-sdk/testing"; +import type { PluginManifest } from "@termix/plugin-sdk/manifest"; +import * as plugin from "../../src/frontend/index"; +import manifestJson from "../../manifest.json"; +import locales from "../../locales/en.json"; + +const manifest = manifestJson as unknown as PluginManifest; + +const declared = (views?: Array<{ id: string }>) => + (views ?? []).map((view) => view.id).sort(); + +let rendered: RenderedPluginApp | null = null; + +afterEach(async () => { + await rendered?.deactivate(); + rendered = null; +}); + +describe(`${manifest.id} activate`, () => { + it("activates and registers only views its manifest declares", async () => { + rendered = await renderWithApp(plugin, { manifest, locales }); + const contributes = manifest.contributes as unknown as Record< + string, + Array<{ id: string }> | undefined + >; + const tabs = declared(contributes.tabs); + // A rail panel may reuse one of the plugin's tab ids. + const panels = [...declared(contributes.panels), ...tabs]; + const cards = declared(contributes.dashboardCards); + for (const id of rendered.registered.tabs()) expect(tabs).toContain(id); + for (const id of rendered.registered.panels()) expect(panels).toContain(id); + for (const id of rendered.registered.dashboardCards()) { + expect(cards).toContain(id); + } + }); + + it("removes everything it registered on deactivate", async () => { + const app = await renderWithApp(plugin, { manifest, locales }); + await app.deactivate(); + expect(app.registered.tabs()).toEqual([]); + expect(app.registered.panels()).toEqual([]); + expect(app.registered.railItems()).toEqual([]); + expect(app.registered.hostActions()).toEqual([]); + expect(app.registered.hostEditorSections()).toEqual([]); + expect(app.registered.dashboardCards()).toEqual([]); + expect(app.registered.settingsComponents()).toEqual([]); + expect(app.registered.actions()).toEqual([]); + }); +}); diff --git a/plugins/fleets/locales/en.json b/plugins/fleets/locales/en.json index 0967ef424..3b7aeddda 100644 --- a/plugins/fleets/locales/en.json +++ b/plugins/fleets/locales/en.json @@ -1 +1,96 @@ -{} +{ + "newUi": { + "sidebar": { + "fleets": { + "title": "Fleets", + "createFleet": "Create Fleet", + "createFleetTitle": "Create Fleet", + "editFleetTitle": "Edit Fleet", + "createFleetDescription": "A fleet is a named group of hosts you can run actions against as a unit.", + "nameLabel": "Name", + "namePlaceholder": "e.g., Web Servers", + "nameRequired": "Fleet name is required", + "descriptionLabel": "Description", + "descriptionPlaceholder": "Optional description", + "colorLabel": "Color", + "tagRulesLabel": "Tag rules", + "tagRulesPlaceholder": "prod-web, edge", + "tagRulesHint": "Hosts with any of these tags are automatically included, in addition to hosts added manually.", + "fleetCreated": "Fleet created", + "fleetUpdated": "Fleet updated", + "fleetDeleted": "Fleet deleted", + "saveFailed": "Failed to save fleet", + "deleteFailed": "Failed to delete fleet", + "loadFailed": "Failed to load fleets", + "deleteFleetTitle": "Delete Fleet", + "deleteFleetDescription": "Are you sure you want to delete \"{{name}}\"? This does not delete the member hosts themselves.", + "searchFleets": "Search fleets...", + "noFleets": "No fleets yet. Create one to get started.", + "memberCount": "{{count}} host", + "memberCount_other": "{{count}} hosts", + "manageMembers": "Manage Members", + "manageMembersTitle": "Manage Fleet Members", + "manageMembersDescription": "Toggle hosts in or out of this fleet's static membership. Hosts matched by tag rules are always included.", + "searchHosts": "Search hosts...", + "noHostsFound": "No hosts found", + "noMembers": "This fleet has no members yet. Add hosts or set a tag rule.", + "membersLoadFailed": "Failed to load fleet members", + "memberUpdateFailed": "Failed to update fleet membership", + "tabRun": "Run Command", + "tabTransfer": "Transfer Files", + "tabInventory": "Inventory", + "openInventoryTab": "Open in full tab", + "tabPackages": "Packages", + "runOnFleet": "Run on Fleet", + "commandPlaceholder": "uptime && df -h", + "commandRequired": "A command is required", + "commandInputsLabel": "Command inputs", + "commandSucceeded": "Command succeeded on all hosts", + "commandPartialFailure": "{{failed}} of {{total}} hosts failed", + "commandFailed": "Failed to run command", + "resultSuccess": "Success", + "resultFailed": "Failed", + "push": "Push", + "pull": "Pull", + "remotePathLabel": "Remote path", + "remotePathRequired": "A remote path is required", + "fileLabel": "File", + "fileRequired": "A file is required", + "pushHint": "The selected file is written to this exact path on every host in the fleet.", + "pullHint": "The file at this path is read from every host and downloaded as a single zip, one folder per host.", + "transferComplete": "Transfer complete", + "transferFailed": "Transfer failed", + "refreshInventory": "Refresh Inventory", + "inventoryLoadFailed": "Failed to load inventory", + "inventoryRefreshed": "Inventory refreshed", + "inventoryRefreshFailed": "Failed to refresh inventory", + "inventoryNoData": "No inventory data yet - refresh to collect it.", + "inventoryHost": "Host", + "inventoryCollectedCount": "{{count}}/{{total}} collected", + "inventoryOs": "OS", + "inventoryKernel": "Kernel", + "inventoryArch": "Arch", + "inventoryUptime": "Uptime", + "inventoryPackageManager": "Package manager", + "inventoryCollectedAt": "Collected", + "packageActionLabel": "Action", + "packageInstall": "Install", + "packageRemove": "Remove", + "packageUpgradeAll": "Upgrade all packages", + "packageNameLabel": "Package name", + "packageNameRequired": "A package name is required", + "packageHint": "Requires manage-level access per host and elevates using the host's stored sudo password.", + "shareFleet": "Share Fleet", + "shareFleetTitle": "Share \"{{name}}\"", + "shareFleetDescription": "Shares this fleet's current member hosts with the selected users or roles. Hosts added to the fleet later are not shared automatically - share again to include them.", + "shareSelectionRequired": "Select at least one user or role", + "fleetSharedSuccessfully": "Shared {{shared}} of {{total}} host(s) in this fleet", + "failedToShareFleet": "Failed to share fleet", + "noMembersToShare": "This fleet has no member hosts to share yet." + } + } + }, + "nav": { + "fleets": "Fleets" + } +} diff --git a/plugins/fleets/locales/translated/af_ZA.json b/plugins/fleets/locales/translated/af_ZA.json new file mode 100644 index 000000000..e0d6d4904 --- /dev/null +++ b/plugins/fleets/locales/translated/af_ZA.json @@ -0,0 +1,89 @@ +{ + "newUi": { + "sidebar": { + "fleets": { + "title": "Vlote", + "createFleet": "Skep Vloot", + "createFleetTitle": "Skep Vloot", + "editFleetTitle": "Wysig vloot", + "createFleetDescription": "'n Vloot is 'n benoemde groep gashere teen wie jy as 'n eenheid aksies kan uitvoer.", + "nameLabel": "Naam", + "namePlaceholder": "bv. webbedieners", + "nameRequired": "Vlootnaam word vereis", + "descriptionLabel": "Beskrywing", + "descriptionPlaceholder": "Opsionele beskrywing", + "colorLabel": "Kleur", + "tagRulesLabel": "Etiketreëls", + "tagRulesPlaceholder": "prod-web, rand", + "tagRulesHint": "Gashere met enige van hierdie etikette word outomaties ingesluit, benewens gashere wat handmatig bygevoeg word.", + "fleetCreated": "Vloot geskep", + "fleetUpdated": "Vloot opgedateer", + "fleetDeleted": "Vloot uitgevee", + "saveFailed": "Kon nie vloot stoor nie", + "deleteFailed": "Kon nie vloot uitvee nie", + "loadFailed": "Kon nie vlote laai nie", + "deleteFleetTitle": "Vee vloot uit", + "deleteFleetDescription": "Is jy seker jy wil \"{{name}}\" verwyder? Dit verwyder nie die lidgashere self nie.", + "searchFleets": "Soek vlote...", + "noFleets": "Geen vlote nog nie. Skep een om te begin.", + "memberCount": "{{count}} gasheer", + "memberCount_other": "{{count}} gashere", + "manageMembers": "Bestuur Lede", + "manageMembersTitle": "Bestuur Vlootlede", + "manageMembersDescription": "Wissel gashere in of uit hierdie vloot se statiese lidmaatskap. Gashere wat ooreenstem met etiketreëls word altyd ingesluit.", + "searchHosts": "Soek gashere...", + "noHostsFound": "Geen gashere gevind nie", + "noMembers": "Hierdie vloot het nog geen lede nie. Voeg gashere by of stel 'n etiketreël.", + "membersLoadFailed": "Kon nie vlootlede laai nie", + "memberUpdateFailed": "Kon nie vlootlidmaatskap opdateer nie", + "tabRun": "Voer die opdrag uit", + "tabTransfer": "Dra lêers oor", + "tabInventory": "Voorraad", + "openInventoryTab": "Maak oop in volle oortjie", + "tabPackages": "Pakkette", + "runOnFleet": "Hardloop op Vloot", + "commandPlaceholder": "optyd && df -h", + "commandRequired": "'n Opdrag word vereis", + "commandInputsLabel": "Opdraginvoere", + "commandSucceeded": "Opdrag het op alle gashere geslaag", + "commandPartialFailure": "{{failed}} van {{total}} gashere het misluk", + "commandFailed": "Kon nie die opdrag uitvoer nie", + "resultSuccess": "Sukses", + "resultFailed": "Misluk", + "push": "Stoot", + "pull": "Trek", + "remotePathLabel": "Afgeleë pad", + "remotePathRequired": "'n Afgeleë pad word benodig", + "fileLabel": "Lêer", + "fileRequired": "'n Lêer word vereis", + "pushHint": "Die gekose lêer word na hierdie presiese pad op elke gasheer in die vloot geskryf.", + "pullHint": "Die lêer op hierdie pad word van elke gasheer gelees en as 'n enkele zip-lêer afgelaai, een lêergids per gasheer.", + "transferComplete": "Oordrag voltooi", + "transferFailed": "Oordrag het misluk", + "refreshInventory": "Verfris voorraad", + "inventoryLoadFailed": "Kon nie voorraad laai nie", + "inventoryRefreshed": "Voorraad verfris", + "inventoryRefreshFailed": "Kon nie voorraad verfris nie", + "inventoryNoData": "Geen voorraaddata nog nie - verfris om dit te versamel.", + "inventoryHost": "Gasheer", + "inventoryCollectedCount": "{{count}}/{{total}} versamel", + "inventoryOs": "OS", + "inventoryKernel": "Kern", + "inventoryArch": "Boog", + "inventoryUptime": "Optyd", + "inventoryPackageManager": "Pakketbestuurder", + "inventoryCollectedAt": "Versamel", + "packageActionLabel": "Aksie", + "packageInstall": "Installeer", + "packageRemove": "Verwyder", + "packageUpgradeAll": "Gradeer alle pakkette op", + "packageNameLabel": "Pakketnaam", + "packageNameRequired": "'n Pakketnaam word vereis", + "packageHint": "Vereis bestuursvlaktoegang per gasheer en verhoog met behulp van die gasheer se gestoorde sudo-wagwoord." + } + } + }, + "nav": { + "fleets": "Vlote" + } +} diff --git a/plugins/fleets/locales/translated/ar_SA.json b/plugins/fleets/locales/translated/ar_SA.json new file mode 100644 index 000000000..9a941645e --- /dev/null +++ b/plugins/fleets/locales/translated/ar_SA.json @@ -0,0 +1,89 @@ +{ + "newUi": { + "sidebar": { + "fleets": { + "title": "الأساطيل", + "createFleet": "إنشاء أسطول", + "createFleetTitle": "إنشاء أسطول", + "editFleetTitle": "تعديل الأسطول", + "createFleetDescription": "الأسطول عبارة عن مجموعة محددة من المضيفين يمكنك شنّ عمليات ضدهم كوحدة واحدة.", + "nameLabel": "اسم", + "namePlaceholder": "مثال: خوادم الويب", + "nameRequired": "اسم الأسطول مطلوب", + "descriptionLabel": "وصف", + "descriptionPlaceholder": "وصف اختياري", + "colorLabel": "لون", + "tagRulesLabel": "قواعد الوسوم", + "tagRulesPlaceholder": "موقع الإنتاج، الحافة", + "tagRulesHint": "يتم تضمين المضيفين الذين يحملون أيًا من هذه العلامات تلقائيًا، بالإضافة إلى المضيفين الذين تمت إضافتهم يدويًا.", + "fleetCreated": "تم إنشاء الأسطول", + "fleetUpdated": "تحديث الأسطول", + "fleetDeleted": "تم حذف الأسطول", + "saveFailed": "فشل في إنقاذ الأسطول", + "deleteFailed": "فشل حذف الأسطول", + "loadFailed": "فشل تحميل الأساطيل", + "deleteFleetTitle": "حذف الأسطول", + "deleteFleetDescription": "هل أنت متأكد من رغبتك في حذف \"{{name}}\"؟ هذا لا يحذف المضيفين الأعضاء أنفسهم.", + "searchFleets": "أساطيل البحث...", + "noFleets": "لا توجد أساطيل حتى الآن. أنشئ أسطولاً للبدء.", + "memberCount": "{{count}} المضيف", + "memberCount_other": "{{count}} المضيفون", + "manageMembers": "إدارة الأعضاء", + "manageMembersTitle": "إدارة أعضاء الأسطول", + "manageMembersDescription": "قم بتفعيل أو تعطيل عضوية المضيفين في هذه المجموعة الثابتة. يتم تضمين المضيفين الذين تتطابق قواعد الوسوم معهم دائمًا.", + "searchHosts": "ابحث عن المضيفين...", + "noHostsFound": "لم يتم العثور على مضيفين", + "noMembers": "لا يوجد أعضاء في هذا الأسطول حتى الآن. أضف مضيفين أو حدد قاعدة للوسوم.", + "membersLoadFailed": "فشل تحميل أعضاء الأسطول", + "memberUpdateFailed": "فشل تحديث عضوية الأسطول", + "tabRun": "تشغيل الأمر", + "tabTransfer": "نقل الملفات", + "tabInventory": "جرد", + "openInventoryTab": "افتح في علامة تبويب كاملة", + "tabPackages": "الطرود", + "runOnFleet": "انطلق على الأسطول", + "commandPlaceholder": "وقت التشغيل && df -h", + "commandRequired": "يلزم إصدار أمر", + "commandInputsLabel": "إدخالات الأوامر", + "commandSucceeded": "تم تنفيذ الأمر بنجاح على جميع الأجهزة المضيفة", + "commandPartialFailure": "فشل {{failed}} من أصل {{total}} مضيف", + "commandFailed": "فشل تنفيذ الأمر", + "resultSuccess": "نجاح", + "resultFailed": "فشل", + "push": "يدفع", + "pull": "يحذب", + "remotePathLabel": "مسار بعيد", + "remotePathRequired": "يلزم وجود مسار بعيد", + "fileLabel": "ملف", + "fileRequired": "الملف مطلوب", + "pushHint": "يتم كتابة الملف المحدد في هذا المسار المحدد على كل مضيف في الأسطول.", + "pullHint": "يتم قراءة الملف الموجود في هذا المسار من كل مضيف وتنزيله كملف مضغوط واحد، مجلد واحد لكل مضيف.", + "transferComplete": "اكتملت عملية النقل", + "transferFailed": "فشلت عملية النقل", + "refreshInventory": "تحديث المخزون", + "inventoryLoadFailed": "فشل تحميل المخزون", + "inventoryRefreshed": "تم تحديث المخزون", + "inventoryRefreshFailed": "فشل تحديث المخزون", + "inventoryNoData": "لا توجد بيانات جرد حتى الآن - قم بتحديث الصفحة لجمعها.", + "inventoryHost": "يستضيف", + "inventoryCollectedCount": "تم جمع {{count}}/{{total}}", + "inventoryOs": "نظام التشغيل", + "inventoryKernel": "النواة", + "inventoryArch": "قوس", + "inventoryUptime": "وقت التشغيل", + "inventoryPackageManager": "مدير الحزم", + "inventoryCollectedAt": "تم جمعها", + "packageActionLabel": "فعل", + "packageInstall": "ثَبَّتَ", + "packageRemove": "يزيل", + "packageUpgradeAll": "قم بترقية جميع الحزم", + "packageNameLabel": "اسم الحزمة", + "packageNameRequired": "اسم الحزمة مطلوب", + "packageHint": "يتطلب الوصول على مستوى الإدارة لكل مضيف ويتم رفعه باستخدام كلمة مرور sudo المخزنة للمضيف." + } + } + }, + "nav": { + "fleets": "الأساطيل" + } +} diff --git a/plugins/fleets/locales/translated/bg_BG.json b/plugins/fleets/locales/translated/bg_BG.json new file mode 100644 index 000000000..204400954 --- /dev/null +++ b/plugins/fleets/locales/translated/bg_BG.json @@ -0,0 +1,89 @@ +{ + "newUi": { + "sidebar": { + "fleets": { + "title": "Флотили", + "createFleet": "Създаване на флот", + "createFleetTitle": "Създаване на флот", + "editFleetTitle": "Редактиране на флота", + "createFleetDescription": "Флотът е именувана група от хостове, срещу които можете да изпълнявате действия като единица.", + "nameLabel": "Име", + "namePlaceholder": "напр. уеб сървъри", + "nameRequired": "Името на флота е задължително", + "descriptionLabel": "Описание", + "descriptionPlaceholder": "Незадължително описание", + "colorLabel": "Цвят", + "tagRulesLabel": "Правила за етикети", + "tagRulesPlaceholder": "prod-web, ръб", + "tagRulesHint": "Хостовете с някой от тези етикети се включват автоматично, в допълнение към хостовете, добавени ръчно.", + "fleetCreated": "Създаден флот", + "fleetUpdated": "Актуализиран автопарк", + "fleetDeleted": "Флотът е изтрит", + "saveFailed": "Запазването на флота не бе успешно", + "deleteFailed": "Изтриването на автопарка не бе успешно", + "loadFailed": "Зареждането на автопарковете не бе успешно", + "deleteFleetTitle": "Изтриване на флота", + "deleteFleetDescription": "Сигурни ли сте, че искате да изтриете „{{name}}“? Това не изтрива самите хостове-членове.", + "searchFleets": "Търсене на автопаркове...", + "noFleets": "Все още няма автопаркове. Създайте такъв, за да започнете.", + "memberCount": "{{count}} хост", + "memberCount_other": "{{count}} хостове", + "manageMembers": "Управление на членовете", + "manageMembersTitle": "Управление на членовете на автопарка", + "manageMembersDescription": "Включване/изключване на хостове от статичното членство на този флот. Хостовете, съответстващи на правилата за тагове, винаги са включени.", + "searchHosts": "Търсене на хостове...", + "noHostsFound": "Не са намерени хостове", + "noMembers": "Тази флотилия все още няма членове. Добавете хостове или задайте правило за етикетиране.", + "membersLoadFailed": "Зареждането на членовете на автопарка не бе успешно", + "memberUpdateFailed": "Актуализирането на членството в автопарка не бе успешно", + "tabRun": "Изпълнете командата", + "tabTransfer": "Прехвърляне на файлове", + "tabInventory": "Инвентар", + "openInventoryTab": "Отвори в цял раздел", + "tabPackages": "Пакети", + "runOnFleet": "Работи на флота", + "commandPlaceholder": "време на работа && df -h", + "commandRequired": "Изисква се команда", + "commandInputsLabel": "Входни команди", + "commandSucceeded": "Командата е успешна на всички хостове", + "commandPartialFailure": "{{failed}} от {{total}} хостове неуспешно", + "commandFailed": "Неуспешно изпълнение на командата", + "resultSuccess": "Успех", + "resultFailed": "Неуспешно", + "push": "Натиснете", + "pull": "Дръпнете", + "remotePathLabel": "Отдалечен път", + "remotePathRequired": "Изисква се отдалечен път", + "fileLabel": "Файл", + "fileRequired": "Изисква се файл", + "pushHint": "Избраният файл се записва точно по този път на всеки хост във флота.", + "pullHint": "Файлът по този път се чете от всеки хост и се изтегля като един zip архив, по една папка на хост.", + "transferComplete": "Прехвърлянето е завършено", + "transferFailed": "Прехвърлянето не бе успешно", + "refreshInventory": "Обновяване на инвентара", + "inventoryLoadFailed": "Зареждането на инвентара не бе успешно", + "inventoryRefreshed": "Инвентаризацията е обновена", + "inventoryRefreshFailed": "Неуспешно обновяване на инвентара", + "inventoryNoData": "Все още няма данни за инвентара - обновете страницата, за да ги съберете.", + "inventoryHost": "Домакин", + "inventoryCollectedCount": "{{count}}/{{total}} събрани", + "inventoryOs": "ОС", + "inventoryKernel": "Ядро", + "inventoryArch": "Арка", + "inventoryUptime": "Време на работа", + "inventoryPackageManager": "Мениджър на пакети", + "inventoryCollectedAt": "Събрани", + "packageActionLabel": "Действие", + "packageInstall": "Инсталиране", + "packageRemove": "Премахване", + "packageUpgradeAll": "Надстройте всички пакети", + "packageNameLabel": "Име на пакета", + "packageNameRequired": "Изисква се име на пакета", + "packageHint": "Изисква достъп на ниво управление за всеки хост и повишава правата, използвайки съхранената парола за sudo на хоста." + } + } + }, + "nav": { + "fleets": "Флотили" + } +} diff --git a/plugins/fleets/locales/translated/bn_BD.json b/plugins/fleets/locales/translated/bn_BD.json new file mode 100644 index 000000000..98b071fbc --- /dev/null +++ b/plugins/fleets/locales/translated/bn_BD.json @@ -0,0 +1,89 @@ +{ + "newUi": { + "sidebar": { + "fleets": { + "title": "ফ্লিট", + "createFleet": "ফ্লিট তৈরি করুন", + "createFleetTitle": "ফ্লিট তৈরি করুন", + "editFleetTitle": "ফ্লিট সম্পাদনা করুন", + "createFleetDescription": "ফ্লিট হলো নামযুক্ত হোস্টদের একটি দল, যাদের বিরুদ্ধে আপনি একটি ইউনিট হিসেবে বিভিন্ন অ্যাকশন চালাতে পারেন।", + "nameLabel": "নাম", + "namePlaceholder": "যেমন, ওয়েব সার্ভার", + "nameRequired": "ফ্লিটের নাম প্রয়োজন", + "descriptionLabel": "বর্ণনা", + "descriptionPlaceholder": "ঐচ্ছিক বিবরণ", + "colorLabel": "রঙ", + "tagRulesLabel": "ট্যাগ নিয়ম", + "tagRulesPlaceholder": "প্রোড-ওয়েব, এজ", + "tagRulesHint": "ম্যানুয়ালি যোগ করা হোস্টগুলোর পাশাপাশি, এই ট্যাগগুলোর যেকোনো একটি থাকা হোস্টগুলো স্বয়ংক্রিয়ভাবে অন্তর্ভুক্ত হয়ে যায়।", + "fleetCreated": "ফ্লিট তৈরি করা হয়েছে", + "fleetUpdated": "ফ্লিট আপডেট করা হয়েছে", + "fleetDeleted": "ফ্লিট মুছে ফেলা হয়েছে", + "saveFailed": "বহর সংরক্ষণ করতে ব্যর্থ হয়েছে", + "deleteFailed": "ফ্লিট মুছে ফেলতে ব্যর্থ হয়েছে", + "loadFailed": "ফ্লিট লোড করতে ব্যর্থ হয়েছে", + "deleteFleetTitle": "ফ্লিট মুছুন", + "deleteFleetDescription": "আপনি কি \"{{name}}\" মুছে ফেলতে নিশ্চিত? এটি সদস্য হোস্টদেরকে মুছে ফেলে না।", + "searchFleets": "নৌবহর অনুসন্ধান করুন...", + "noFleets": "এখনো কোনো ফ্লিট নেই। শুরু করার জন্য একটি তৈরি করুন।", + "memberCount": "{{count}} হোস্ট", + "memberCount_other": "{{count}} হোস্ট", + "manageMembers": "সদস্যদের পরিচালনা করুন", + "manageMembersTitle": "ফ্লিট সদস্যদের পরিচালনা করুন", + "manageMembersDescription": "এই ফ্লিটের স্ট্যাটিক সদস্যপদে হোস্টদের অন্তর্ভুক্ত বা বহির্ভূত করুন। ট্যাগ নিয়ম দ্বারা মেলানো হোস্টরা সর্বদা অন্তর্ভুক্ত থাকে।", + "searchHosts": "হোস্ট অনুসন্ধান করুন...", + "noHostsFound": "কোন হোস্ট খুঁজে পাওয়া যায়নি", + "noMembers": "এই ফ্লিটে এখনও কোনো সদস্য নেই। হোস্ট যোগ করুন অথবা একটি ট্যাগ নিয়ম সেট করুন।", + "membersLoadFailed": "ফ্লিট সদস্যদের লোড করতে ব্যর্থ হয়েছে", + "memberUpdateFailed": "ফ্লিট সদস্যপদ আপডেট করতে ব্যর্থ হয়েছে", + "tabRun": "রান কমান্ড", + "tabTransfer": "ফাইল স্থানান্তর করুন", + "tabInventory": "ইনভেন্টরি", + "openInventoryTab": "সম্পূর্ণ ট্যাবে খুলুন", + "tabPackages": "প্যাকেজ", + "runOnFleet": "ফ্লিটে চালান", + "commandPlaceholder": "আপটাইম && df -h", + "commandRequired": "একটি কমান্ড প্রয়োজন", + "commandInputsLabel": "কমান্ড ইনপুট", + "commandSucceeded": "সকল হোস্টে কমান্ড সফল হয়েছে।", + "commandPartialFailure": "{{failed}} এর {{total}} হোস্ট ব্যর্থ হয়েছে", + "commandFailed": "কমান্ড চালাতে ব্যর্থ হয়েছে", + "resultSuccess": "সাফল্য", + "resultFailed": "ব্যর্থ", + "push": "ধাক্কা দিন", + "pull": "টান", + "remotePathLabel": "দূরবর্তী পথ", + "remotePathRequired": "একটি দূরবর্তী পথের প্রয়োজন", + "fileLabel": "ফাইল", + "fileRequired": "একটি ফাইল প্রয়োজন", + "pushHint": "নির্বাচিত ফাইলটি ফ্লিটের প্রতিটি হোস্টের এই নির্দিষ্ট পাথে লেখা হয়।", + "pullHint": "এই পাথের ফাইলটি প্রতিটি হোস্ট থেকে পড়া হয় এবং একটি একক জিপ ফাইল হিসেবে ডাউনলোড করা হয়, যা প্রতি হোস্টে একটি করে ফোল্ডারে বিভক্ত থাকে।", + "transferComplete": "স্থানান্তর সম্পন্ন হয়েছে", + "transferFailed": "স্থানান্তর ব্যর্থ হয়েছে", + "refreshInventory": "ইনভেন্টরি রিফ্রেশ করুন", + "inventoryLoadFailed": "ইনভেন্টরি লোড করতে ব্যর্থ হয়েছে", + "inventoryRefreshed": "ইনভেন্টরি রিফ্রেশ করা হয়েছে", + "inventoryRefreshFailed": "ইনভেন্টরি রিফ্রেশ করতে ব্যর্থ হয়েছে", + "inventoryNoData": "এখনও কোনো ইনভেন্টরি ডেটা নেই - এটি সংগ্রহ করতে রিফ্রেশ করুন।", + "inventoryHost": "হোস্ট", + "inventoryCollectedCount": "{{count}}/{{total}} সংগৃহীত", + "inventoryOs": "ওএস", + "inventoryKernel": "কার্নেল", + "inventoryArch": "খিলান", + "inventoryUptime": "আপটাইম", + "inventoryPackageManager": "প্যাকেজ ম্যানেজার", + "inventoryCollectedAt": "সংগৃহীত", + "packageActionLabel": "পদক্ষেপ", + "packageInstall": "ইনস্টল করুন", + "packageRemove": "অপসারণ করুন", + "packageUpgradeAll": "সমস্ত প্যাকেজ আপগ্রেড করুন", + "packageNameLabel": "প্যাকেজের নাম", + "packageNameRequired": "একটি প্যাকেজের নাম প্রয়োজন", + "packageHint": "প্রতিটি হোস্টের জন্য ম্যানেজ-লেভেল অ্যাক্সেস প্রয়োজন এবং হোস্টের সংরক্ষিত sudo পাসওয়ার্ড ব্যবহার করে অ্যাক্সেস উন্নত করা হয়।" + } + } + }, + "nav": { + "fleets": "ফ্লিট" + } +} diff --git a/plugins/fleets/locales/translated/ca_ES.json b/plugins/fleets/locales/translated/ca_ES.json new file mode 100644 index 000000000..895227ddb --- /dev/null +++ b/plugins/fleets/locales/translated/ca_ES.json @@ -0,0 +1,89 @@ +{ + "newUi": { + "sidebar": { + "fleets": { + "title": "Flotes", + "createFleet": "Crear flota", + "createFleetTitle": "Crear flota", + "editFleetTitle": "Edita la flota", + "createFleetDescription": "Una flota és un grup d'amfitrions amb nom contra els quals podeu executar accions com una unitat.", + "nameLabel": "Nom", + "namePlaceholder": "p. ex., servidors web", + "nameRequired": "El nom de la flota és obligatori", + "descriptionLabel": "Descripció", + "descriptionPlaceholder": "Descripció opcional", + "colorLabel": "Color", + "tagRulesLabel": "Regles d'etiquetes", + "tagRulesPlaceholder": "prod-web, vora", + "tagRulesHint": "Els amfitrions amb qualsevol d'aquestes etiquetes s'inclouen automàticament, a més dels amfitrions afegits manualment.", + "fleetCreated": "Flota creada", + "fleetUpdated": "Flota actualitzada", + "fleetDeleted": "Flota suprimida", + "saveFailed": "No s'ha pogut desar la flota", + "deleteFailed": "No s'ha pogut suprimir la flota", + "loadFailed": "No s'han pogut carregar les flotes", + "deleteFleetTitle": "Suprimeix la flota", + "deleteFleetDescription": "Esteu segur que voleu suprimir \"{{name}}\"? Això no suprimeix els amfitrions membres en si.", + "searchFleets": "Cerca flotes...", + "noFleets": "Encara no hi ha cap flota. Crea'n una per començar.", + "memberCount": "amfitrió {{count}}", + "memberCount_other": "amfitrions {{count}}", + "manageMembers": "Gestiona els membres", + "manageMembersTitle": "Gestionar els membres de la flota", + "manageMembersDescription": "Activa o desactiva la pertinença estàtica dels hosts a aquesta flota. Els hosts que coincideixen amb les regles d'etiqueta sempre s'hi inclouen.", + "searchHosts": "Cerca amfitrions...", + "noHostsFound": "No s'han trobat amfitrions", + "noMembers": "Aquesta flota encara no té membres. Afegeix amfitrions o defineix una regla d'etiqueta.", + "membersLoadFailed": "No s'han pogut carregar els membres de la flota", + "memberUpdateFailed": "No s'ha pogut actualitzar la pertinença a la flota", + "tabRun": "Executa l'ordre", + "tabTransfer": "Transferir fitxers", + "tabInventory": "Inventari", + "openInventoryTab": "Obre en una pestanya completa", + "tabPackages": "Paquets", + "runOnFleet": "Funciona amb Flota", + "commandPlaceholder": "temps de funcionament && df -h", + "commandRequired": "Cal una comanda", + "commandInputsLabel": "Entrades de comandament", + "commandSucceeded": "L'ordre ha tingut èxit en tots els hosts", + "commandPartialFailure": "Els hosts han fallat {{failed}} de {{total}}", + "commandFailed": "No s'ha pogut executar l'ordre", + "resultSuccess": "Èxit", + "resultFailed": "Fallat", + "push": "Empènyer", + "pull": "Estirar", + "remotePathLabel": "Camí remot", + "remotePathRequired": "Cal una ruta remota", + "fileLabel": "Fitxer", + "fileRequired": "Es requereix un fitxer", + "pushHint": "El fitxer seleccionat s'escriu a aquesta ruta exacta a tots els hosts de la flota.", + "pullHint": "El fitxer d'aquesta ruta es llegeix des de tots els hosts i es descarrega com un únic zip, una carpeta per host.", + "transferComplete": "Transferència completada", + "transferFailed": "La transferència ha fallat", + "refreshInventory": "Actualitza l'inventari", + "inventoryLoadFailed": "No s'ha pogut carregar l'inventari", + "inventoryRefreshed": "Inventari actualitzat", + "inventoryRefreshFailed": "No s'ha pogut actualitzar l'inventari", + "inventoryNoData": "Encara no hi ha dades d'inventari; actualitza la pàgina per recopilar-les.", + "inventoryHost": "Amfitrió", + "inventoryCollectedCount": "{{count}}/{{total}} recollit", + "inventoryOs": "Sistema operatiu", + "inventoryKernel": "Nucli", + "inventoryArch": "Arc", + "inventoryUptime": "Temps de funcionament", + "inventoryPackageManager": "Gestor de paquets", + "inventoryCollectedAt": "Recollit", + "packageActionLabel": "Acció", + "packageInstall": "Instal·la", + "packageRemove": "Elimina", + "packageUpgradeAll": "Actualitza tots els paquets", + "packageNameLabel": "Nom del paquet", + "packageNameRequired": "Cal un nom de paquet", + "packageHint": "Requereix accés de nivell d'administració per host i eleva els privilegis mitjançant la contrasenya sudo emmagatzemada per l'host." + } + } + }, + "nav": { + "fleets": "Flotes" + } +} diff --git a/plugins/fleets/locales/translated/cs_CZ.json b/plugins/fleets/locales/translated/cs_CZ.json new file mode 100644 index 000000000..3e440db53 --- /dev/null +++ b/plugins/fleets/locales/translated/cs_CZ.json @@ -0,0 +1,89 @@ +{ + "newUi": { + "sidebar": { + "fleets": { + "title": "Flotily", + "createFleet": "Vytvořit flotilu", + "createFleetTitle": "Vytvořit flotilu", + "editFleetTitle": "Upravit flotilu", + "createFleetDescription": "Flotila je pojmenovaná skupina hostitelů, proti kterým můžete jako jednotce spouštět akce.", + "nameLabel": "Jméno", + "namePlaceholder": "např. webové servery", + "nameRequired": "Název flotily je povinný", + "descriptionLabel": "Popis", + "descriptionPlaceholder": "Volitelný popis", + "colorLabel": "Barva", + "tagRulesLabel": "Pravidla pro tagy", + "tagRulesPlaceholder": "prod-web, okraj", + "tagRulesHint": "Hostitelé s některým z těchto tagů jsou zahrnuti automaticky, kromě hostitelů přidaných ručně.", + "fleetCreated": "Vytvořená flotila", + "fleetUpdated": "Aktualizace vozového parku", + "fleetDeleted": "Flotila smazána", + "saveFailed": "Uložení flotily se nezdařilo", + "deleteFailed": "Nepodařilo se smazat flotilu", + "loadFailed": "Načtení flotil se nezdařilo", + "deleteFleetTitle": "Smazat flotilu", + "deleteFleetDescription": "Opravdu chcete smazat „{{name}}“? Tímto se neodstraní samotní hostitelé členů.", + "searchFleets": "Hledat flotily...", + "noFleets": "Zatím žádné flotily. Vytvořte si jednu a začněte.", + "memberCount": "{{count}} hostitel", + "memberCount_other": "{{count}} hostitelé", + "manageMembers": "Spravovat členy", + "manageMembersTitle": "Správa členů vozového parku", + "manageMembersDescription": "Přepíná hostitele do statického členství této flotily nebo z něj. Hostitelé odpovídající pravidlům tagů jsou vždy zahrnuti.", + "searchHosts": "Hledat hostitele...", + "noHostsFound": "Nenalezeny žádné hostitele", + "noMembers": "Tato flotila zatím nemá žádné členy. Přidejte hostitele nebo nastavte pravidlo pro tagy.", + "membersLoadFailed": "Nepodařilo se načíst členy flotily", + "memberUpdateFailed": "Nepodařilo se aktualizovat členství ve flotile", + "tabRun": "Spustit příkaz", + "tabTransfer": "Přenos souborů", + "tabInventory": "Inventář", + "openInventoryTab": "Otevřít na celou kartu", + "tabPackages": "Balíčky", + "runOnFleet": "Běh na flotile", + "commandPlaceholder": "doba provozuschopnosti && df -h", + "commandRequired": "Je vyžadován příkaz", + "commandInputsLabel": "Vstupy příkazů", + "commandSucceeded": "Příkaz byl úspěšný na všech hostitelích", + "commandPartialFailure": "{{failed}} z {{total}} hostitelů selhalo", + "commandFailed": "Nepodařilo se spustit příkaz", + "resultSuccess": "Úspěch", + "resultFailed": "Selhalo", + "push": "TAM", + "pull": "SEM", + "remotePathLabel": "Vzdálená cesta", + "remotePathRequired": "Je vyžadována vzdálená cesta.", + "fileLabel": "Soubor", + "fileRequired": "Je vyžadován soubor", + "pushHint": "Vybraný soubor se zapíše do této přesné cesty na každém hostiteli ve flotile.", + "pullHint": "Soubor v této cestě je načten z každého hostitele a stažen jako jeden zip soubor, jedna složka na hostitele.", + "transferComplete": "Převod dokončen", + "transferFailed": "Přenos se nezdařil", + "refreshInventory": "Obnovit inventář", + "inventoryLoadFailed": "Nepodařilo se načíst inventář", + "inventoryRefreshed": "Obnovení zásob", + "inventoryRefreshFailed": "Nepodařilo se aktualizovat inventář", + "inventoryNoData": "Zatím nejsou k dispozici žádná data o zásobách – obnovte stránku pro jejich shromažďování.", + "inventoryHost": "Hostitel", + "inventoryCollectedCount": "{{count}}/{{total}} shromážděno", + "inventoryOs": "OS", + "inventoryKernel": "Jádro", + "inventoryArch": "Oblouk", + "inventoryUptime": "Doba provozuschopnosti", + "inventoryPackageManager": "Správce balíčků", + "inventoryCollectedAt": "Sebrané", + "packageActionLabel": "Akce", + "packageInstall": "Instalovat", + "packageRemove": "Odstranit", + "packageUpgradeAll": "Aktualizujte všechny balíčky", + "packageNameLabel": "Název balíčku", + "packageNameRequired": "Je vyžadován název balíčku.", + "packageHint": "Vyžaduje přístup na úrovni správy pro každého hostitele a zvyšuje oprávnění pomocí uloženého hesla sudo hostitele." + } + } + }, + "nav": { + "fleets": "Flotily" + } +} diff --git a/plugins/fleets/locales/translated/da_DK.json b/plugins/fleets/locales/translated/da_DK.json new file mode 100644 index 000000000..c5d65e1a1 --- /dev/null +++ b/plugins/fleets/locales/translated/da_DK.json @@ -0,0 +1,89 @@ +{ + "newUi": { + "sidebar": { + "fleets": { + "title": "Flåder", + "createFleet": "Opret flåde", + "createFleetTitle": "Opret flåde", + "editFleetTitle": "Rediger flåde", + "createFleetDescription": "En flåde er en navngiven gruppe af værter, som du kan udføre handlinger mod som en enhed.", + "nameLabel": "Navn", + "namePlaceholder": "f.eks. webservere", + "nameRequired": "Flådenavn er påkrævet", + "descriptionLabel": "Beskrivelse", + "descriptionPlaceholder": "Valgfri beskrivelse", + "colorLabel": "Farve", + "tagRulesLabel": "Tagregler", + "tagRulesPlaceholder": "prod-web, kant", + "tagRulesHint": "Værter med et af disse tags inkluderes automatisk, udover værter, der tilføjes manuelt.", + "fleetCreated": "Flåde oprettet", + "fleetUpdated": "Flåden er opdateret", + "fleetDeleted": "Flåden slettet", + "saveFailed": "Kunne ikke redde flåden", + "deleteFailed": "Kunne ikke slette flåden", + "loadFailed": "Kunne ikke indlæse flåder", + "deleteFleetTitle": "Slet flåde", + "deleteFleetDescription": "Er du sikker på, at du vil slette \"{{name}}\"? Dette sletter ikke selve medlemsværterne.", + "searchFleets": "Søg efter flåder...", + "noFleets": "Ingen flåder endnu. Opret en for at komme i gang.", + "memberCount": "{{count}} vært", + "memberCount_other": "{{count}} værter", + "manageMembers": "Administrer medlemmer", + "manageMembersTitle": "Administrer flådemedlemmer", + "manageMembersDescription": "Slå værter til eller fra af denne flådes statiske medlemskab. Værter, der matches af tagregler, er altid inkluderet.", + "searchHosts": "Søg efter værter...", + "noHostsFound": "Ingen værter fundet", + "noMembers": "Denne flåde har endnu ingen medlemmer. Tilføj værter eller angiv en tagregel.", + "membersLoadFailed": "Kunne ikke indlæse flådemedlemmer", + "memberUpdateFailed": "Kunne ikke opdatere flådemedlemskab", + "tabRun": "Kør kommando", + "tabTransfer": "Overfør filer", + "tabInventory": "Inventar", + "openInventoryTab": "Åbn i fuld fane", + "tabPackages": "Pakker", + "runOnFleet": "Kør på flåden", + "commandPlaceholder": "oppetid && df -h", + "commandRequired": "En kommando er påkrævet", + "commandInputsLabel": "Kommandoindgange", + "commandSucceeded": "Kommandoen lykkedes på alle værter", + "commandPartialFailure": "{{failed}} af {{total}} værter mislykkedes", + "commandFailed": "Kunne ikke køre kommandoen", + "resultSuccess": "Succes", + "resultFailed": "Mislykkedes", + "push": "Skubbe", + "pull": "Træk", + "remotePathLabel": "Fjernsti", + "remotePathRequired": "En fjernsti er påkrævet", + "fileLabel": "Fil", + "fileRequired": "En fil er påkrævet", + "pushHint": "Den valgte fil skrives til præcis denne sti på alle værter i flåden.", + "pullHint": "Filen på denne sti læses fra hver vært og downloades som en enkelt zip-fil, én mappe pr. vært.", + "transferComplete": "Overførsel fuldført", + "transferFailed": "Overførslen mislykkedes", + "refreshInventory": "Opdater lagerbeholdning", + "inventoryLoadFailed": "Kunne ikke indlæse lagerbeholdningen", + "inventoryRefreshed": "Opdateret lagerbeholdning", + "inventoryRefreshFailed": "Kunne ikke opdatere lagerbeholdningen", + "inventoryNoData": "Ingen lagerdata endnu - opdater for at indsamle dem.", + "inventoryHost": "Vært", + "inventoryCollectedCount": "{{count}}/{{total}} indsamlet", + "inventoryOs": "OS", + "inventoryKernel": "Kernen", + "inventoryArch": "Buen", + "inventoryUptime": "Oppetid", + "inventoryPackageManager": "Pakkehåndtering", + "inventoryCollectedAt": "Indsamlet", + "packageActionLabel": "Handling", + "packageInstall": "Installere", + "packageRemove": "Fjerne", + "packageUpgradeAll": "Opgrader alle pakker", + "packageNameLabel": "Pakkenavn", + "packageNameRequired": "Et pakkenavn er påkrævet", + "packageHint": "Kræver adgang på administratorniveau pr. vært og hæver ved hjælp af værtens gemte sudo-adgangskode." + } + } + }, + "nav": { + "fleets": "Flåder" + } +} diff --git a/plugins/fleets/locales/translated/de_DE.json b/plugins/fleets/locales/translated/de_DE.json new file mode 100644 index 000000000..7fa332345 --- /dev/null +++ b/plugins/fleets/locales/translated/de_DE.json @@ -0,0 +1,89 @@ +{ + "newUi": { + "sidebar": { + "fleets": { + "title": "Flotten", + "createFleet": "Flotte erstellen", + "createFleetTitle": "Flotte erstellen", + "editFleetTitle": "Flotte bearbeiten", + "createFleetDescription": "Eine Flotte ist eine benannte Gruppe von Hosts, gegen die Sie als Einheit Aktionen ausführen können.", + "nameLabel": "Name", + "namePlaceholder": "z.B. Webserver", + "nameRequired": "Flottenname erforderlich", + "descriptionLabel": "Beschreibung", + "descriptionPlaceholder": "Optionale Beschreibung", + "colorLabel": "Farbe", + "tagRulesLabel": "Tag-Regeln", + "tagRulesPlaceholder": "Produktweb, Rand", + "tagRulesHint": "Hosts, die über eines dieser Tags verfügen, werden automatisch mit einbezogen, ebenso wie manuell hinzugefügte Hosts.", + "fleetCreated": "Flotte erstellt", + "fleetUpdated": "Flotte aktualisiert", + "fleetDeleted": "Flotte gelöscht", + "saveFailed": "Es gelang nicht, die Flotte zu retten.", + "deleteFailed": "Flotte konnte nicht gelöscht werden", + "loadFailed": "Flotten konnten nicht geladen werden", + "deleteFleetTitle": "Flotte löschen", + "deleteFleetDescription": "Möchten Sie wirklich \"{{name}}\" löschen? Dadurch werden die Mitgliedshosts selbst nicht gelöscht.", + "searchFleets": "Flotten durchsuchen...", + "noFleets": "Noch keine Flotten vorhanden. Erstellen Sie eine, um loszulegen.", + "memberCount": "{{count}} Host", + "memberCount_other": "{{count}} Hosts", + "manageMembers": "Mitglieder verwalten", + "manageMembersTitle": "Flottenmitglieder verwalten", + "manageMembersDescription": "Hosts können der statischen Mitgliedschaft dieser Flotte hinzugefügt oder daraus entfernt werden. Hosts, die den Tag-Regeln entsprechen, sind immer enthalten.", + "searchHosts": "Hosts suchen...", + "noHostsFound": "Keine Hosts gefunden", + "noMembers": "Diese Flotte hat noch keine Mitglieder. Füge Hosts hinzu oder lege eine Tag-Regel fest.", + "membersLoadFailed": "Flottenmitglieder konnten nicht geladen werden", + "memberUpdateFailed": "Aktualisierung der Flottenmitgliedschaft fehlgeschlagen", + "tabRun": "Befehl ausführen", + "tabTransfer": "Dateien übertragen", + "tabInventory": "Inventar", + "openInventoryTab": "Im vollständigen Tab öffnen", + "tabPackages": "Pakete", + "runOnFleet": "Run on Fleet", + "commandPlaceholder": "uptime && df -h", + "commandRequired": "Ein Befehl ist erforderlich", + "commandInputsLabel": "Befehlseingaben", + "commandSucceeded": "Der Befehl wurde auf allen Hosts erfolgreich ausgeführt.", + "commandPartialFailure": "{{failed}} von {{total}} Hosts fehlgeschlagen", + "commandFailed": "Befehl konnte nicht ausgeführt werden", + "resultSuccess": "Erfolg", + "resultFailed": "Fehlgeschlagen", + "push": "Drücken", + "pull": "Ziehen", + "remotePathLabel": "Remote-Pfad", + "remotePathRequired": "Ein Remote-Pfad ist erforderlich", + "fileLabel": "Datei", + "fileRequired": "Eine Datei wird benötigt", + "pushHint": "Die ausgewählte Datei wird auf jedem Host der Flotte unter genau diesem Pfad gespeichert.", + "pullHint": "Die Datei unter diesem Pfad wird von jedem Host gelesen und als einzelne ZIP-Datei heruntergeladen, ein Ordner pro Host.", + "transferComplete": "Übertragung abgeschlossen", + "transferFailed": "Übertragung fehlgeschlagen", + "refreshInventory": "Inventar aktualisieren", + "inventoryLoadFailed": "Fehler beim Laden des Inventars", + "inventoryRefreshed": "Bestand aktualisiert", + "inventoryRefreshFailed": "Fehler beim Aktualisieren des Inventars", + "inventoryNoData": "Noch keine Bestandsdaten vorhanden – aktualisieren Sie die Seite, um sie abzurufen.", + "inventoryHost": "Gastgeber", + "inventoryCollectedCount": "{{count}}/{{total}} gesammelt", + "inventoryOs": "Betriebssystem", + "inventoryKernel": "Kernel", + "inventoryArch": "Bogen", + "inventoryUptime": "Betriebszeit", + "inventoryPackageManager": "Paketmanager", + "inventoryCollectedAt": "Gesammelt", + "packageActionLabel": "Aktion", + "packageInstall": "Installieren", + "packageRemove": "Entfernen", + "packageUpgradeAll": "Alle Pakete aktualisieren", + "packageNameLabel": "Paketname", + "packageNameRequired": "Ein Paketname ist erforderlich.", + "packageHint": "Erfordert Administratorrechte pro Host und verwendet das gespeicherte sudo-Passwort des Hosts für die Rechteerweiterung." + } + } + }, + "nav": { + "fleets": "Flotten" + } +} diff --git a/plugins/fleets/locales/translated/el_GR.json b/plugins/fleets/locales/translated/el_GR.json new file mode 100644 index 000000000..2c822690f --- /dev/null +++ b/plugins/fleets/locales/translated/el_GR.json @@ -0,0 +1,89 @@ +{ + "newUi": { + "sidebar": { + "fleets": { + "title": "Στόλοι", + "createFleet": "Δημιουργία στόλου", + "createFleetTitle": "Δημιουργία στόλου", + "editFleetTitle": "Επεξεργασία στόλου", + "createFleetDescription": "Ένας στόλος είναι μια ονομαστική ομάδα οικοδεσποτών εναντίον των οποίων μπορείτε να εκτελέσετε ενέργειες ως μονάδα.", + "nameLabel": "Ονομα", + "namePlaceholder": "π.χ., Διακομιστές Ιστού", + "nameRequired": "Απαιτείται το όνομα του στόλου", + "descriptionLabel": "Περιγραφή", + "descriptionPlaceholder": "Προαιρετική περιγραφή", + "colorLabel": "Χρώμα", + "tagRulesLabel": "Κανόνες ετικετών", + "tagRulesPlaceholder": "product-web, edge", + "tagRulesHint": "Οι κεντρικοί υπολογιστές με οποιαδήποτε από αυτές τις ετικέτες περιλαμβάνονται αυτόματα, εκτός από τους κεντρικούς υπολογιστές που προστίθενται χειροκίνητα.", + "fleetCreated": "Στόλος δημιουργήθηκε", + "fleetUpdated": "Ενημερώθηκε ο στόλος", + "fleetDeleted": "Ο στόλος διαγράφηκε", + "saveFailed": "Αποτυχία αποθήκευσης στόλου", + "deleteFailed": "Η διαγραφή του στόλου απέτυχε", + "loadFailed": "Αποτυχία φόρτωσης στόλων", + "deleteFleetTitle": "Διαγραφή στόλου", + "deleteFleetDescription": "Είστε βέβαιοι ότι θέλετε να διαγράψετε το \"{{name}}\"; Αυτό δεν διαγράφει τους ίδιους τους κεντρικούς υπολογιστές-μέλη.", + "searchFleets": "Αναζήτηση στόλων...", + "noFleets": "Δεν υπάρχουν ακόμη στόλοι. Δημιουργήστε έναν για να ξεκινήσετε.", + "memberCount": "{{count}} κεντρικός υπολογιστής", + "memberCount_other": "{{count}} κεντρικοί υπολογιστές", + "manageMembers": "Διαχείριση μελών", + "manageMembersTitle": "Διαχείριση Μελών Στόλου", + "manageMembersDescription": "Εναλλαγή ή διακοπή της στατικής ιδιότητας μέλους αυτού του στόλου. Οι κεντρικοί υπολογιστές που αντιστοιχούν σε κανόνες ετικέτας περιλαμβάνονται πάντα.", + "searchHosts": "Αναζήτηση κεντρικών υπολογιστών...", + "noHostsFound": "Δεν βρέθηκαν κεντρικοί υπολογιστές", + "noMembers": "Αυτός ο στόλος δεν έχει ακόμη μέλη. Προσθέστε κεντρικούς υπολογιστές ή ορίστε έναν κανόνα ετικέτας.", + "membersLoadFailed": "Αποτυχία φόρτωσης μελών στόλου", + "memberUpdateFailed": "Η ενημέρωση της ιδιότητας μέλους του στόλου απέτυχε", + "tabRun": "Εκτέλεση εντολής", + "tabTransfer": "Μεταφορά αρχείων", + "tabInventory": "Καταγραφή εμπορευμάτων", + "openInventoryTab": "Άνοιγμα σε πλήρη καρτέλα", + "tabPackages": "Πακέτα", + "runOnFleet": "Εκτέλεση σε στόλο", + "commandPlaceholder": "χρόνος λειτουργίας && df -h", + "commandRequired": "Απαιτείται εντολή", + "commandInputsLabel": "Είσοδοι εντολών", + "commandSucceeded": "Η εντολή ήταν επιτυχής σε όλους τους κεντρικούς υπολογιστές", + "commandPartialFailure": "{{failed}} από {{total}} κεντρικούς υπολογιστές απέτυχαν", + "commandFailed": "Αποτυχία εκτέλεσης εντολής", + "resultSuccess": "Επιτυχία", + "resultFailed": "Αποτυχημένος", + "push": "Σπρώξτε", + "pull": "Τραβήξτε", + "remotePathLabel": "Απομακρυσμένη διαδρομή", + "remotePathRequired": "Απαιτείται μια απομακρυσμένη διαδρομή", + "fileLabel": "Αρχείο", + "fileRequired": "Απαιτείται ένα αρχείο", + "pushHint": "Το επιλεγμένο αρχείο εγγράφεται σε αυτήν ακριβώς τη διαδρομή σε κάθε κεντρικό υπολογιστή του στόλου.", + "pullHint": "Το αρχείο σε αυτήν τη διαδρομή διαβάζεται από κάθε κεντρικό υπολογιστή και λαμβάνεται ως ενιαίο αρχείο zip, ένας φάκελος ανά κεντρικό υπολογιστή.", + "transferComplete": "Η μεταφορά ολοκληρώθηκε", + "transferFailed": "Η μεταφορά απέτυχε", + "refreshInventory": "Ανανέωση Αποθέματος", + "inventoryLoadFailed": "Αποτυχία φόρτωσης αποθέματος", + "inventoryRefreshed": "Το απόθεμα ανανεώθηκε", + "inventoryRefreshFailed": "Η ανανέωση του αποθέματος απέτυχε", + "inventoryNoData": "Δεν υπάρχουν ακόμη δεδομένα αποθέματος - κάντε ανανέωση για να τα συλλέξετε.", + "inventoryHost": "Πλήθος", + "inventoryCollectedCount": "{{count}}/{{total}} συλλέχθηκαν", + "inventoryOs": "Λειτουργικό σύστημα", + "inventoryKernel": "Πυρήνας", + "inventoryArch": "Αψίδα", + "inventoryUptime": "Χρόνος λειτουργίας", + "inventoryPackageManager": "Διαχειριστής πακέτων", + "inventoryCollectedAt": "Συγκεντρωμένος", + "packageActionLabel": "Δράση", + "packageInstall": "Εγκαθιστώ", + "packageRemove": "Αφαιρώ", + "packageUpgradeAll": "Αναβάθμιση όλων των πακέτων", + "packageNameLabel": "Όνομα πακέτου", + "packageNameRequired": "Απαιτείται όνομα πακέτου", + "packageHint": "Απαιτείται πρόσβαση σε επίπεδο διαχείρισης ανά κεντρικό υπολογιστή και αναβαθμίζεται χρησιμοποιώντας τον αποθηκευμένο κωδικό πρόσβασης sudo του κεντρικού υπολογιστή." + } + } + }, + "nav": { + "fleets": "Στόλοι" + } +} diff --git a/plugins/fleets/locales/translated/es_ES.json b/plugins/fleets/locales/translated/es_ES.json new file mode 100644 index 000000000..5f7439657 --- /dev/null +++ b/plugins/fleets/locales/translated/es_ES.json @@ -0,0 +1,89 @@ +{ + "newUi": { + "sidebar": { + "fleets": { + "title": "Flotas", + "createFleet": "Crear flota", + "createFleetTitle": "Crear flota", + "editFleetTitle": "Editar flota", + "createFleetDescription": "Una flota es un grupo con nombre de anfitriones contra los que puedes ejecutar acciones como una unidad.", + "nameLabel": "Nombre", + "namePlaceholder": "p. ej., servidores web", + "nameRequired": "Se requiere el nombre de la flota.", + "descriptionLabel": "Descripción", + "descriptionPlaceholder": "Descripción opcional", + "colorLabel": "Color", + "tagRulesLabel": "Reglas de etiquetas", + "tagRulesPlaceholder": "web de producción, borde", + "tagRulesHint": "Los hosts que tengan cualquiera de estas etiquetas se incluyen automáticamente, además de los hosts añadidos manualmente.", + "fleetCreated": "Flota creada", + "fleetUpdated": "Flota actualizada", + "fleetDeleted": "Flota eliminada", + "saveFailed": "No se logró salvar la flota.", + "deleteFailed": "No se pudo eliminar la flota", + "loadFailed": "No se pudieron cargar las flotas.", + "deleteFleetTitle": "Eliminar flota", + "deleteFleetDescription": "¿Estás seguro de que quieres eliminar \"{{name}}\"? Esto no elimina los hosts miembros en sí.", + "searchFleets": "Buscar flotas...", + "noFleets": "Aún no hay flotas. Crea una para empezar.", + "memberCount": "{{count}} anfitrión", + "memberCount_other": "{{count}} anfitriones", + "manageMembers": "Gestionar miembros", + "manageMembersTitle": "Gestionar los miembros de la flota", + "manageMembersDescription": "Activa o desactiva la pertenencia estática de esta flota a hosts. Los hosts que coincidan con las reglas de etiquetas siempre se incluirán.", + "searchHosts": "Buscar hosts...", + "noHostsFound": "No se encontraron hosts", + "noMembers": "Esta flota aún no tiene miembros. Añade anfitriones o establece una regla de etiquetas.", + "membersLoadFailed": "No se pudo cargar a los miembros de la flota.", + "memberUpdateFailed": "No se pudo actualizar la membresía de la flota.", + "tabRun": "Ejecutar comando", + "tabTransfer": "Transferir archivos", + "tabInventory": "Inventario", + "openInventoryTab": "Abrir en pestaña completa", + "tabPackages": "Paquetes", + "runOnFleet": "Operar en Fleet", + "commandPlaceholder": "tiempo de actividad && df -h", + "commandRequired": "Se requiere un comando", + "commandInputsLabel": "Entradas de comandos", + "commandSucceeded": "El comando se ejecutó correctamente en todos los hosts.", + "commandPartialFailure": "{{failed}} de {{total}} hosts fallaron", + "commandFailed": "Error al ejecutar el comando", + "resultSuccess": "Éxito", + "resultFailed": "Fallido", + "push": "Empujar", + "pull": "Jalar", + "remotePathLabel": "Ruta remota", + "remotePathRequired": "Se requiere una ruta remota", + "fileLabel": "Archivo", + "fileRequired": "Se requiere un archivo", + "pushHint": "El archivo seleccionado se escribe en esta ruta exacta en cada host de la flota.", + "pullHint": "El archivo ubicado en esta ruta se lee desde cada host y se descarga como un único archivo zip, una carpeta por host.", + "transferComplete": "Transferencia completada", + "transferFailed": "La transferencia falló.", + "refreshInventory": "Actualizar inventario", + "inventoryLoadFailed": "No se pudo cargar el inventario.", + "inventoryRefreshed": "Inventario actualizado", + "inventoryRefreshFailed": "No se pudo actualizar el inventario.", + "inventoryNoData": "Aún no hay datos de inventario; actualice la página para recopilarlos.", + "inventoryHost": "Anfitrión", + "inventoryCollectedCount": "{{count}}/{{total}} recopilado", + "inventoryOs": "Sistema operativo", + "inventoryKernel": "Núcleo", + "inventoryArch": "Arco", + "inventoryUptime": "Tiempo de actividad", + "inventoryPackageManager": "gestor de paquetes", + "inventoryCollectedAt": "Coleccionado", + "packageActionLabel": "Acción", + "packageInstall": "Instalar", + "packageRemove": "Eliminar", + "packageUpgradeAll": "Actualizar todos los paquetes", + "packageNameLabel": "Nombre del paquete", + "packageNameRequired": "Se requiere un nombre de paquete.", + "packageHint": "Requiere acceso de nivel de administrador por host y eleva los privilegios utilizando la contraseña sudo almacenada en el host." + } + } + }, + "nav": { + "fleets": "Flotas" + } +} diff --git a/plugins/fleets/locales/translated/fi_FI.json b/plugins/fleets/locales/translated/fi_FI.json new file mode 100644 index 000000000..5992f0469 --- /dev/null +++ b/plugins/fleets/locales/translated/fi_FI.json @@ -0,0 +1,89 @@ +{ + "newUi": { + "sidebar": { + "fleets": { + "title": "Laivastot", + "createFleet": "Luo laivasto", + "createFleetTitle": "Luo laivasto", + "editFleetTitle": "Muokkaa kalustoa", + "createFleetDescription": "Laivasto on nimetty joukko isäntäjoukkoja, joita vastaan voit suorittaa toimintoja yksikkönä.", + "nameLabel": "Nimi", + "namePlaceholder": "esim. web-palvelimet", + "nameRequired": "Laivaston nimi on pakollinen", + "descriptionLabel": "Kuvaus", + "descriptionPlaceholder": "Valinnainen kuvaus", + "colorLabel": "Väri", + "tagRulesLabel": "Tagisäännöt", + "tagRulesPlaceholder": "prod-web, reuna", + "tagRulesHint": "Näillä tunnisteilla varustetut isännät sisällytetään automaattisesti manuaalisesti lisättyjen isäntien lisäksi.", + "fleetCreated": "Laivasto luotu", + "fleetUpdated": "Kalustoa päivitetty", + "fleetDeleted": "Kalusto poistettu", + "saveFailed": "Laivaston tallentaminen epäonnistui", + "deleteFailed": "Kaluston poistaminen epäonnistui", + "loadFailed": "Kalustojen lataus epäonnistui", + "deleteFleetTitle": "Poista kalusto", + "deleteFleetDescription": "Oletko varma, että haluat poistaa \"{{name}}\"? Tämä ei poista itse jäsenpalvelimia.", + "searchFleets": "Hae laivastoja...", + "noFleets": "Ei vielä laivastoja. Luo yksi aloittaaksesi.", + "memberCount": "{{count}} isäntä", + "memberCount_other": "{{count}} isännät", + "manageMembers": "Hallinnoi jäseniä", + "manageMembersTitle": "Hallinnoi laivaston jäseniä", + "manageMembersDescription": "Lisää isännät tämän laivaston staattiseen jäsenyyteen tai poista ne siitä. Tunnistesääntöjen mukaiset isännät sisällytetään aina.", + "searchHosts": "Hae isäntiä...", + "noHostsFound": "Ei isäntiä", + "noMembers": "Tässä laivastossa ei ole vielä jäseniä. Lisää isäntiä tai aseta tunnistesääntö.", + "membersLoadFailed": "Laivaston jäsenten lataaminen epäonnistui", + "memberUpdateFailed": "Laivaston jäsenyyden päivittäminen epäonnistui", + "tabRun": "Suorita komento", + "tabTransfer": "Tiedostojen siirto", + "tabInventory": "Varasto", + "openInventoryTab": "Avaa koko välilehdessä", + "tabPackages": "Paketit", + "runOnFleet": "Suorita laivastolla", + "commandPlaceholder": "käyttöaika && df -h", + "commandRequired": "Komento vaaditaan", + "commandInputsLabel": "Komentotulot", + "commandSucceeded": "Komento onnistui kaikissa isännissä", + "commandPartialFailure": "{{failed}} / {{total}} isäntäkoneesta epäonnistui", + "commandFailed": "Komennon suorittaminen epäonnistui", + "resultSuccess": "Menestys", + "resultFailed": "Epäonnistui", + "push": "Työnnä", + "pull": "Vedä", + "remotePathLabel": "Etäpolku", + "remotePathRequired": "Etäpolku vaaditaan", + "fileLabel": "Tiedosto", + "fileRequired": "Tiedosto vaaditaan", + "pushHint": "Valittu tiedosto kirjoitetaan täsmälleen tälle polulle jokaisella laivaston isännällä.", + "pullHint": "Tämän polun tiedosto luetaan jokaiselta isännältä ja ladataan yhtenä zip-tiedostona, yksi kansio isäntää kohden.", + "transferComplete": "Siirto valmis", + "transferFailed": "Siirto epäonnistui", + "refreshInventory": "Päivitä varasto", + "inventoryLoadFailed": "Varaston lataaminen epäonnistui", + "inventoryRefreshed": "Varasto päivitetty", + "inventoryRefreshFailed": "Varaston päivittäminen epäonnistui", + "inventoryNoData": "Ei vielä varastotietoja – päivitä kerätäksesi ne.", + "inventoryHost": "Isäntä", + "inventoryCollectedCount": "{{count}}/{{total}} kerätty", + "inventoryOs": "Käyttöjärjestelmä", + "inventoryKernel": "Ydin", + "inventoryArch": "Kaari", + "inventoryUptime": "Käyttöaika", + "inventoryPackageManager": "Pakettien hallinta", + "inventoryCollectedAt": "Kerätty", + "packageActionLabel": "Toiminta", + "packageInstall": "Asentaa", + "packageRemove": "Poistaa", + "packageUpgradeAll": "Päivitä kaikki paketit", + "packageNameLabel": "Paketin nimi", + "packageNameRequired": "Paketin nimi on pakollinen", + "packageHint": "Vaatii hallintatason käyttöoikeudet isäntäkohtaisesti ja nostaa käyttöoikeuksia isännän tallennetulla sudo-salasanalla." + } + } + }, + "nav": { + "fleets": "Laivastot" + } +} diff --git a/plugins/fleets/locales/translated/fr_FR.json b/plugins/fleets/locales/translated/fr_FR.json new file mode 100644 index 000000000..a79e7a324 --- /dev/null +++ b/plugins/fleets/locales/translated/fr_FR.json @@ -0,0 +1,89 @@ +{ + "newUi": { + "sidebar": { + "fleets": { + "title": "Flottes", + "createFleet": "Créer une flotte", + "createFleetTitle": "Créer une flotte", + "editFleetTitle": "Modifier la flotte", + "createFleetDescription": "Une flotte est un groupe nommé d'hôtes contre lesquels vous pouvez mener des actions en tant qu'unité.", + "nameLabel": "Nom", + "namePlaceholder": "par exemple, les serveurs Web", + "nameRequired": "Le nom de la flotte est requis.", + "descriptionLabel": "Description", + "descriptionPlaceholder": "Description facultative", + "colorLabel": "Couleur", + "tagRulesLabel": "Règles de balisage", + "tagRulesPlaceholder": "prod-web, bord", + "tagRulesHint": "Les hôtes possédant l'une de ces étiquettes sont automatiquement inclus, en plus des hôtes ajoutés manuellement.", + "fleetCreated": "Flotte créée", + "fleetUpdated": "Flotte mise à jour", + "fleetDeleted": "Flotte supprimée", + "saveFailed": "Échec de la sauvegarde de la flotte", + "deleteFailed": "Échec de la suppression de la flotte", + "loadFailed": "Échec du chargement des flottes", + "deleteFleetTitle": "Supprimer la flotte", + "deleteFleetDescription": "Êtes-vous sûr de vouloir supprimer «{{name}}» ? Cela ne supprime pas les hôtes membres eux-mêmes.", + "searchFleets": "Rechercher des flottes...", + "noFleets": "Aucune flotte pour le moment. Créez-en une pour commencer.", + "memberCount": "{{count}} hôte", + "memberCount_other": "{{count}} hôtes", + "manageMembers": "Gérer les membres", + "manageMembersTitle": "Gérer les membres de la flotte", + "manageMembersDescription": "Activez ou désactivez l'appartenance statique des hôtes à cette flotte. Les hôtes correspondant aux règles de balisage sont toujours inclus.", + "searchHosts": "Rechercher des hôtes...", + "noHostsFound": "Aucun hôte trouvé", + "noMembers": "Cette flotte est vide pour le moment. Ajoutez des hôtes ou définissez une règle de balisage.", + "membersLoadFailed": "Échec du chargement des membres de la flotte", + "memberUpdateFailed": "Échec de la mise à jour de l'adhésion à la flotte", + "tabRun": "Exécuter la commande", + "tabTransfer": "Transférer des fichiers", + "tabInventory": "Inventaire", + "openInventoryTab": "Ouvrir dans l'onglet complet", + "tabPackages": "Colis", + "runOnFleet": "Exécuter sur la flotte", + "commandPlaceholder": "disponibilité && df -h", + "commandRequired": "Une commande est requise", + "commandInputsLabel": "Entrées de commande", + "commandSucceeded": "La commande a réussi sur tous les hôtes.", + "commandPartialFailure": "{{failed}} des hôtes {{total}} ont échoué", + "commandFailed": "Échec de l'exécution de la commande", + "resultSuccess": "Succès", + "resultFailed": "Échoué", + "push": "Pousser", + "pull": "Tirer", + "remotePathLabel": "Chemin distant", + "remotePathRequired": "Un chemin distant est nécessaire", + "fileLabel": "Déposer", + "fileRequired": "Un fichier est requis", + "pushHint": "Le fichier sélectionné est enregistré à cet emplacement précis sur chaque hôte du parc.", + "pullHint": "Le fichier situé à cet emplacement est lu depuis chaque hôte et téléchargé sous forme d'un seul fichier zip, un dossier par hôte.", + "transferComplete": "Transfert terminé", + "transferFailed": "Échec du transfert", + "refreshInventory": "Actualiser l'inventaire", + "inventoryLoadFailed": "Échec du chargement de l'inventaire", + "inventoryRefreshed": "Inventaire mis à jour", + "inventoryRefreshFailed": "Échec de la mise à jour de l'inventaire", + "inventoryNoData": "Aucune donnée d'inventaire pour le moment - actualisez la page pour la récupérer.", + "inventoryHost": "Hôte", + "inventoryCollectedCount": "{{count}}/{{total}} collecté", + "inventoryOs": "Système d'exploitation", + "inventoryKernel": "Noyau", + "inventoryArch": "Cambre", + "inventoryUptime": "Disponibilité", + "inventoryPackageManager": "Gestionnaire de paquets", + "inventoryCollectedAt": "Collecté", + "packageActionLabel": "Action", + "packageInstall": "Installer", + "packageRemove": "Retirer", + "packageUpgradeAll": "Mettez à niveau tous les forfaits", + "packageNameLabel": "Nom du paquet", + "packageNameRequired": "Un nom de paquet est requis.", + "packageHint": "Nécessite un accès de niveau administrateur par hôte et élève les privilèges à l'aide du mot de passe sudo stocké sur l'hôte." + } + } + }, + "nav": { + "fleets": "Flottes" + } +} diff --git a/plugins/fleets/locales/translated/he_IL.json b/plugins/fleets/locales/translated/he_IL.json new file mode 100644 index 000000000..aacc267c5 --- /dev/null +++ b/plugins/fleets/locales/translated/he_IL.json @@ -0,0 +1,89 @@ +{ + "newUi": { + "sidebar": { + "fleets": { + "title": "ציי רכב", + "createFleet": "צור צי", + "createFleetTitle": "צור צי", + "editFleetTitle": "עריכת צי", + "createFleetDescription": "צי הוא קבוצה בעלת שם של מארחים שניתן להפעיל פעולות נגדם כיחידה.", + "nameLabel": "שֵׁם", + "namePlaceholder": "לדוגמה, שרתי אינטרנט", + "nameRequired": "נדרש שם צי", + "descriptionLabel": "תֵאוּר", + "descriptionPlaceholder": "תיאור אופציונלי", + "colorLabel": "צֶבַע", + "tagRulesLabel": "כללי תגיות", + "tagRulesPlaceholder": "רשת דחיפה, קצה", + "tagRulesHint": "מארחים עם אחד מהתגים הללו נכללים אוטומטית, בנוסף למארחים שנוספו ידנית.", + "fleetCreated": "צי נוצר", + "fleetUpdated": "הצי עודכן", + "fleetDeleted": "הצי נמחק", + "saveFailed": "נכשלה הצלת הצי", + "deleteFailed": "מחיקת הצי נכשלה", + "loadFailed": "טעינת ציי רכב נכשלה", + "deleteFleetTitle": "מחיקת צי", + "deleteFleetDescription": "האם אתה בטוח שברצונך למחוק את \"{{name}}\"? פעולה זו אינה מוחקת את המארחים החברים עצמם.", + "searchFleets": "חיפוש ציי רכב...", + "noFleets": "אין עדיין ציי רכב. צור אחד כדי להתחיל.", + "memberCount": "מארח {{count}}", + "memberCount_other": "{{count}} hosts", + "manageMembers": "ניהול חברים", + "manageMembersTitle": "ניהול חברי צי", + "manageMembersDescription": "פתח או הסר מארחים מהחברות הסטטית של צי זה. מארחים שתואמים לפי כללי תג תמיד כלולים.", + "searchHosts": "חיפוש מארחים...", + "noHostsFound": "לא נמצאו מארחים", + "noMembers": "לצי הזה עדיין אין חברים. הוסף מארחים או הגדר כלל תגיות.", + "membersLoadFailed": "טעינת חברי הצי נכשלה", + "memberUpdateFailed": "נכשל עדכון חברות הצי", + "tabRun": "הפעל את הפקודה", + "tabTransfer": "העברת קבצים", + "tabInventory": "מְלַאי", + "openInventoryTab": "פתח בכרטיסייה המלאה", + "tabPackages": "חבילות", + "runOnFleet": "רוץ על הצי", + "commandPlaceholder": "זמן פעולה ו-df -h", + "commandRequired": "נדרשת פקודה", + "commandInputsLabel": "קלטי פקודה", + "commandSucceeded": "הפקודה הצליחה בכל המארחים", + "commandPartialFailure": "{{failed}} מתוך {{total}} מארחים נכשלו", + "commandFailed": "נכשל בהפעלת הפקודה", + "resultSuccess": "הַצלָחָה", + "resultFailed": "נִכשָׁל", + "push": "לִדחוֹף", + "pull": "מְשׁוֹך", + "remotePathLabel": "נתיב מרוחק", + "remotePathRequired": "נדרש נתיב מרוחק", + "fileLabel": "קוֹבֶץ", + "fileRequired": "נדרש קובץ", + "pushHint": "הקובץ שנבחר נכתב בדיוק לנתיב הזה בכל מחשב מארח בצי.", + "pullHint": "הקובץ בנתיב זה נקרא מכל מארח ומורד כקובץ zip יחיד, תיקייה אחת לכל מארח.", + "transferComplete": "ההעברה הושלמה", + "transferFailed": "ההעברה נכשלה", + "refreshInventory": "רענון המלאי", + "inventoryLoadFailed": "טעינת המלאי נכשלה", + "inventoryRefreshed": "רענון המלאי", + "inventoryRefreshFailed": "רענון המלאי נכשל", + "inventoryNoData": "אין עדיין נתוני מלאי - רענן כדי לאסוף אותם.", + "inventoryHost": "מְאָרֵחַ", + "inventoryCollectedCount": "נאסף {{count}}/{{total}}", + "inventoryOs": "מערכת הפעלה", + "inventoryKernel": "גַרעִין", + "inventoryArch": "קֶשֶׁת", + "inventoryUptime": "זמן פעולה", + "inventoryPackageManager": "מנהל החבילות", + "inventoryCollectedAt": "נאסף", + "packageActionLabel": "פְּעוּלָה", + "packageInstall": "לְהַתְקִין", + "packageRemove": "לְהַסִיר", + "packageUpgradeAll": "שדרגו את כל החבילות", + "packageNameLabel": "שם החבילה", + "packageNameRequired": "נדרש שם חבילה", + "packageHint": "דורש גישת ניהול לכל מחשב מארח ועולה באמצעות סיסמת ה-sudo המאוחסנת של המארח." + } + } + }, + "nav": { + "fleets": "ציי רכב" + } +} diff --git a/plugins/fleets/locales/translated/hi_IN.json b/plugins/fleets/locales/translated/hi_IN.json new file mode 100644 index 000000000..1b9e94e18 --- /dev/null +++ b/plugins/fleets/locales/translated/hi_IN.json @@ -0,0 +1,89 @@ +{ + "newUi": { + "sidebar": { + "fleets": { + "title": "बेड़े", + "createFleet": "बेड़ा बनाएं", + "createFleetTitle": "बेड़ा बनाएं", + "editFleetTitle": "बेड़े को संपादित करें", + "createFleetDescription": "फ्लीट होस्ट का एक नामित समूह है जिसके विरुद्ध आप एक इकाई के रूप में कार्रवाई कर सकते हैं।", + "nameLabel": "नाम", + "namePlaceholder": "उदाहरण के लिए, वेब सर्वर", + "nameRequired": "बेड़े का नाम आवश्यक है", + "descriptionLabel": "विवरण", + "descriptionPlaceholder": "वैकल्पिक विवरण", + "colorLabel": "रंग", + "tagRulesLabel": "टैग नियम", + "tagRulesPlaceholder": "प्रोड-वेब, एज", + "tagRulesHint": "मैन्युअल रूप से जोड़े गए होस्ट के अतिरिक्त, इनमें से किसी भी टैग वाले होस्ट स्वचालित रूप से शामिल हो जाते हैं।", + "fleetCreated": "बेड़ा बनाया गया", + "fleetUpdated": "बेड़े को अपडेट किया गया", + "fleetDeleted": "बेड़ा हटा दिया गया", + "saveFailed": "बेड़े को बचाने में विफल", + "deleteFailed": "बेड़ा हटाने में विफल", + "loadFailed": "फ्लीट लोड करने में विफल", + "deleteFleetTitle": "बेड़ा हटाएं", + "deleteFleetDescription": "क्या आप वाकई \"{{name}}\" को हटाना चाहते हैं? इससे सदस्य होस्ट स्वयं नहीं हटेंगे।", + "searchFleets": "खोज बेड़े...", + "noFleets": "अभी तक कोई बेड़ा नहीं है। शुरुआत करने के लिए एक बेड़ा बनाएं।", + "memberCount": "{{count}} होस्ट", + "memberCount_other": "{{count}} मेजबान", + "manageMembers": "सदस्यों का प्रबंधन करें", + "manageMembersTitle": "बेड़े के सदस्यों का प्रबंधन करें", + "manageMembersDescription": "इस फ्लीट की स्थायी सदस्यता में होस्ट को शामिल या बाहर करें। टैग नियमों द्वारा मेल खाने वाले होस्ट हमेशा शामिल होते हैं।", + "searchHosts": "होस्ट खोजें...", + "noHostsFound": "कोई होस्ट नहीं मिला", + "noMembers": "इस फ्लीट में अभी कोई सदस्य नहीं है। होस्ट जोड़ें या टैग नियम सेट करें।", + "membersLoadFailed": "फ्लीट सदस्यों को लोड करने में विफल", + "memberUpdateFailed": "फ्लीट सदस्यता को अपडेट करने में विफल", + "tabRun": "कमांड चलाएँ", + "tabTransfer": "फ़ाइलें स्थानांतरित करें", + "tabInventory": "भंडार", + "openInventoryTab": "पूरे टैब में खोलें", + "tabPackages": "संकुल", + "runOnFleet": "फ्लीट पर चलाएँ", + "commandPlaceholder": "अपटाइम && df -h", + "commandRequired": "एक आदेश आवश्यक है", + "commandInputsLabel": "कमांड इनपुट", + "commandSucceeded": "सभी होस्ट पर कमांड सफलतापूर्वक संचालित हुई।", + "commandPartialFailure": "{{failed}} में से {{total}} होस्ट विफल हो गए", + "commandFailed": "कमांड चलाने में विफल", + "resultSuccess": "सफलता", + "resultFailed": "असफल", + "push": "धकेलना", + "pull": "खींचो", + "remotePathLabel": "दूरस्थ पथ", + "remotePathRequired": "एक दूरस्थ मार्ग आवश्यक है", + "fileLabel": "फ़ाइल", + "fileRequired": "एक फ़ाइल आवश्यक है", + "pushHint": "चयनित फ़ाइल को फ्लीट में मौजूद प्रत्येक होस्ट पर ठीक इसी पथ पर लिखा जाता है।", + "pullHint": "इस पथ पर स्थित फ़ाइल को प्रत्येक होस्ट से पढ़ा जाता है और एक ही ज़िप फ़ाइल के रूप में डाउनलोड किया जाता है, जिसमें प्रत्येक होस्ट के लिए एक फ़ोल्डर होता है।", + "transferComplete": "स्थानांतरण पूरा हुआ", + "transferFailed": "स्थानांतरण विफल", + "refreshInventory": "इन्वेंट्री रीफ़्रेश करें", + "inventoryLoadFailed": "इन्वेंट्री लोड करने में विफल", + "inventoryRefreshed": "इन्वेंट्री अपडेट हो गई", + "inventoryRefreshFailed": "इन्वेंट्री को रीफ़्रेश करने में विफल", + "inventoryNoData": "अभी तक कोई इन्वेंट्री डेटा उपलब्ध नहीं है - इसे प्राप्त करने के लिए पेज को रिफ्रेश करें।", + "inventoryHost": "मेज़बान", + "inventoryCollectedCount": "{{count}}/{{total}} एकत्रित", + "inventoryOs": "ओएस", + "inventoryKernel": "गुठली", + "inventoryArch": "मेहराब", + "inventoryUptime": "अपटाइम", + "inventoryPackageManager": "पैकेज प्रबंधक", + "inventoryCollectedAt": "एकत्र किया हुआ", + "packageActionLabel": "कार्रवाई", + "packageInstall": "स्थापित करना", + "packageRemove": "निकालना", + "packageUpgradeAll": "सभी पैकेजों को अपग्रेड करें", + "packageNameLabel": "पैकेज का नाम", + "packageNameRequired": "पैकेज का नाम आवश्यक है", + "packageHint": "प्रत्येक होस्ट के लिए प्रबंधन-स्तर की पहुँच आवश्यक है और होस्ट के संग्रहीत सूडो पासवर्ड का उपयोग करके पहुँच को बढ़ाया जा सकता है।" + } + } + }, + "nav": { + "fleets": "बेड़े" + } +} diff --git a/plugins/fleets/locales/translated/hu_HU.json b/plugins/fleets/locales/translated/hu_HU.json new file mode 100644 index 000000000..100656064 --- /dev/null +++ b/plugins/fleets/locales/translated/hu_HU.json @@ -0,0 +1,89 @@ +{ + "newUi": { + "sidebar": { + "fleets": { + "title": "Flották", + "createFleet": "Flotta létrehozása", + "createFleetTitle": "Flotta létrehozása", + "editFleetTitle": "Flotta szerkesztése", + "createFleetDescription": "A flotta egy elnevezett hosztcsoport, amely ellen egységként műveleteket lehet végrehajtani.", + "nameLabel": "Név", + "namePlaceholder": "pl. webszerverek", + "nameRequired": "A flotta nevének megadása kötelező", + "descriptionLabel": "Leírás", + "descriptionPlaceholder": "Opcionális leírás", + "colorLabel": "Szín", + "tagRulesLabel": "Címkeszabályok", + "tagRulesPlaceholder": "prod-web, él", + "tagRulesHint": "Az ezen címkék bármelyikével rendelkező hosztok automatikusan bele lesznek foglalva, a manuálisan hozzáadott hosztok mellett.", + "fleetCreated": "Flotta létrehozva", + "fleetUpdated": "Flotta frissítve", + "fleetDeleted": "Flotta törölve", + "saveFailed": "Nem sikerült menteni a flottát", + "deleteFailed": "Nem sikerült törölni a flottát", + "loadFailed": "Nem sikerült betölteni a flottákat", + "deleteFleetTitle": "Flotta törlése", + "deleteFleetDescription": "Biztosan törölni szeretnéd a(z) \"{{name}}\" fájlt? Ez nem törli a taghosztokat.", + "searchFleets": "Flották keresése...", + "noFleets": "Még nincsenek flották. Hozz létre egyet a kezdéshez.", + "memberCount": "{{count}} gazdagép", + "memberCount_other": "{{count}} gazdagépek", + "manageMembers": "Tagok kezelése", + "manageMembersTitle": "Flottatagok kezelése", + "manageMembersDescription": "Hosztok be- és kikapcsolása a flotta statikus tagságába. A címkeszabályoknak megfelelő hosztok mindig szerepelnek.", + "searchHosts": "Gazdagépek keresése...", + "noHostsFound": "Nem találhatók hostok", + "noMembers": "Ennek a flottának még nincsenek tagjai. Adjon hozzá hosztokat, vagy állítson be címkézési szabályt.", + "membersLoadFailed": "Nem sikerült betölteni a flotta tagjait", + "memberUpdateFailed": "Nem sikerült frissíteni a flottatagságot", + "tabRun": "Parancs futtatása", + "tabTransfer": "Fájlok átvitele", + "tabInventory": "Leltár", + "openInventoryTab": "Megnyitás teljes lapon", + "tabPackages": "Csomagok", + "runOnFleet": "Fleet Run", + "commandPlaceholder": "üzemidő && df -h", + "commandRequired": "Parancsra van szükség", + "commandInputsLabel": "Parancsbemenetek", + "commandSucceeded": "A parancs minden gépen sikeresen lefutott", + "commandPartialFailure": "{{failed}} / {{total}} gazdagépből {{total}} hibát jelzett", + "commandFailed": "Nem sikerült futtatni a parancsot", + "resultSuccess": "Siker", + "resultFailed": "Sikertelen", + "push": "Nyomás", + "pull": "Húzni", + "remotePathLabel": "Távoli útvonal", + "remotePathRequired": "Távoli elérési út szükséges", + "fileLabel": "Fájl", + "fileRequired": "Fájl megadása szükséges", + "pushHint": "A kiválasztott fájl pontosan erre az elérési útra kerül a flotta minden egyes gépén.", + "pullHint": "Az ezen az elérési úton található fájlt minden hosztról beolvassa a rendszer, és egyetlen zip fájlként tölti le, hosztonként egy mappában.", + "transferComplete": "Átvitel befejezve", + "transferFailed": "Átvitel sikertelen", + "refreshInventory": "Készlet frissítése", + "inventoryLoadFailed": "Nem sikerült betölteni a készletet", + "inventoryRefreshed": "Készlet frissítve", + "inventoryRefreshFailed": "Nem sikerült frissíteni a készletet", + "inventoryNoData": "Még nincsenek készletadatok – frissítse az oldalt az összegyűjtéséhez.", + "inventoryHost": "Házigazda", + "inventoryCollectedCount": "{{count}}/{{total}} begyűjtött", + "inventoryOs": "Operációs rendszer", + "inventoryKernel": "Kernel", + "inventoryArch": "Boltív", + "inventoryUptime": "Üzemidő", + "inventoryPackageManager": "Csomagkezelő", + "inventoryCollectedAt": "Összegyűjtött", + "packageActionLabel": "Akció", + "packageInstall": "Telepítés", + "packageRemove": "Eltávolítás", + "packageUpgradeAll": "Az összes csomag frissítése", + "packageNameLabel": "Csomag neve", + "packageNameRequired": "Csomagnév megadása kötelező", + "packageHint": "Gazdagépenként felügyeleti szintű hozzáférést igényel, és a gazdagép tárolt sudo jelszavával emeli ki a jogosultságokat." + } + } + }, + "nav": { + "fleets": "Flották" + } +} diff --git a/plugins/fleets/locales/translated/id_ID.json b/plugins/fleets/locales/translated/id_ID.json new file mode 100644 index 000000000..fcc949634 --- /dev/null +++ b/plugins/fleets/locales/translated/id_ID.json @@ -0,0 +1,89 @@ +{ + "newUi": { + "sidebar": { + "fleets": { + "title": "Armada", + "createFleet": "Buat Armada", + "createFleetTitle": "Buat Armada", + "editFleetTitle": "Edit Armada", + "createFleetDescription": "Armada adalah kelompok host bernama yang dapat Anda serang sebagai satu unit.", + "nameLabel": "Nama", + "namePlaceholder": "misalnya, Server Web", + "nameRequired": "Nama armada wajib diisi.", + "descriptionLabel": "Keterangan", + "descriptionPlaceholder": "Deskripsi opsional", + "colorLabel": "Warna", + "tagRulesLabel": "Aturan tag", + "tagRulesPlaceholder": "prod-web, tepi", + "tagRulesHint": "Host yang memiliki salah satu tag ini akan disertakan secara otomatis, di samping host yang ditambahkan secara manual.", + "fleetCreated": "Armada yang dibuat", + "fleetUpdated": "Armada diperbarui", + "fleetDeleted": "Armada dihapus", + "saveFailed": "Gagal menyelamatkan armada.", + "deleteFailed": "Gagal menghapus armada", + "loadFailed": "Gagal memuat armada", + "deleteFleetTitle": "Hapus Armada", + "deleteFleetDescription": "Apakah Anda yakin ingin menghapus \"{{name}}\"? Ini tidak menghapus host anggota itu sendiri.", + "searchFleets": "Armada pencarian...", + "noFleets": "Belum ada armada. Buat satu untuk memulai.", + "memberCount": "{{count}} tuan rumah", + "memberCount_other": "{{count}} tuan rumah", + "manageMembers": "Kelola Anggota", + "manageMembersTitle": "Mengelola Anggota Armada", + "manageMembersDescription": "Aktifkan atau nonaktifkan keanggotaan statis host dalam armada ini. Host yang cocok dengan aturan tag akan selalu disertakan.", + "searchHosts": "Cari host...", + "noHostsFound": "Tidak ada host yang ditemukan.", + "noMembers": "Armada ini belum memiliki anggota. Tambahkan host atau tetapkan aturan tag.", + "membersLoadFailed": "Gagal memuat anggota armada", + "memberUpdateFailed": "Gagal memperbarui keanggotaan armada.", + "tabRun": "Jalankan Perintah", + "tabTransfer": "Transfer File", + "tabInventory": "Inventaris", + "openInventoryTab": "Buka di tab penuh", + "tabPackages": "Paket", + "runOnFleet": "Lari di Armada", + "commandPlaceholder": "waktu aktif && df -h", + "commandRequired": "Diperlukan sebuah perintah.", + "commandInputsLabel": "Masukan perintah", + "commandSucceeded": "Perintah berhasil dijalankan di semua host.", + "commandPartialFailure": "{{failed}} dari {{total}} host gagal", + "commandFailed": "Perintah gagal dijalankan.", + "resultSuccess": "Kesuksesan", + "resultFailed": "Gagal", + "push": "Dorongan", + "pull": "Menarik", + "remotePathLabel": "Jalur jarak jauh", + "remotePathRequired": "Diperlukan jalur jarak jauh.", + "fileLabel": "Mengajukan", + "fileRequired": "Diperlukan sebuah berkas.", + "pushHint": "File yang dipilih akan ditulis ke jalur persis ini di setiap host dalam armada.", + "pullHint": "Berkas di jalur ini dibaca dari setiap host dan diunduh sebagai satu file zip, satu folder per host.", + "transferComplete": "Transfer selesai", + "transferFailed": "Transfer gagal", + "refreshInventory": "Perbarui Inventaris", + "inventoryLoadFailed": "Gagal memuat inventaris", + "inventoryRefreshed": "Persediaan diperbarui", + "inventoryRefreshFailed": "Gagal memperbarui inventaris", + "inventoryNoData": "Belum ada data inventaris - segarkan halaman untuk mengumpulkannya.", + "inventoryHost": "Tuan rumah", + "inventoryCollectedCount": "{{count}}/{{total}} dikumpulkan", + "inventoryOs": "Sistem Operasi", + "inventoryKernel": "Inti", + "inventoryArch": "Lengkungan", + "inventoryUptime": "Waktu aktif", + "inventoryPackageManager": "Pengelola paket", + "inventoryCollectedAt": "Dikumpulkan", + "packageActionLabel": "Tindakan", + "packageInstall": "Memasang", + "packageRemove": "Menghapus", + "packageUpgradeAll": "Tingkatkan semua paket", + "packageNameLabel": "Nama paket", + "packageNameRequired": "Nama paket wajib diisi.", + "packageHint": "Membutuhkan akses tingkat pengelola per host dan ditingkatkan menggunakan kata sandi sudo yang tersimpan di host tersebut." + } + } + }, + "nav": { + "fleets": "Armada" + } +} diff --git a/plugins/fleets/locales/translated/it_IT.json b/plugins/fleets/locales/translated/it_IT.json new file mode 100644 index 000000000..e5a2a6319 --- /dev/null +++ b/plugins/fleets/locales/translated/it_IT.json @@ -0,0 +1,89 @@ +{ + "newUi": { + "sidebar": { + "fleets": { + "title": "Flotte", + "createFleet": "Crea flotta", + "createFleetTitle": "Crea flotta", + "editFleetTitle": "Modifica flotta", + "createFleetDescription": "Una flotta è un gruppo denominato di host su cui è possibile eseguire azioni come un'unica unità.", + "nameLabel": "Nome", + "namePlaceholder": "ad esempio, server web", + "nameRequired": "Il nome della flotta è obbligatorio", + "descriptionLabel": "Descrizione", + "descriptionPlaceholder": "Descrizione facoltativa", + "colorLabel": "Colore", + "tagRulesLabel": "Regole dei tag", + "tagRulesPlaceholder": "prod-web, edge", + "tagRulesHint": "Oltre agli host aggiunti manualmente, vengono inclusi automaticamente anche quelli che presentano uno qualsiasi di questi tag.", + "fleetCreated": "Flotta creata", + "fleetUpdated": "Flotta aggiornata", + "fleetDeleted": "Flotta eliminata", + "saveFailed": "Impossibile salvare la flotta", + "deleteFailed": "Impossibile eliminare la flotta", + "loadFailed": "Impossibile caricare le flotte", + "deleteFleetTitle": "Elimina flotta", + "deleteFleetDescription": "Sei sicuro di voler eliminare \"{{name}}\"? Questa operazione non elimina gli host membri stessi.", + "searchFleets": "Cerca flotte...", + "noFleets": "Nessuna flotta ancora. Creane una per iniziare.", + "memberCount": "{{count}} host", + "memberCount_other": "{{count}} host", + "manageMembers": "Gestisci i membri", + "manageMembersTitle": "Gestisci i membri della flotta", + "manageMembersDescription": "Attiva o disattiva l'inclusione degli host nell'elenco statico di questa flotta. Gli host corrispondenti alle regole dei tag sono sempre inclusi.", + "searchHosts": "Cerca host...", + "noHostsFound": "Nessun host trovato", + "noMembers": "Questa flotta non ha ancora membri. Aggiungi host o imposta una regola di tag.", + "membersLoadFailed": "Impossibile caricare i membri della flotta", + "memberUpdateFailed": "Impossibile aggiornare l'appartenenza alla flotta", + "tabRun": "Comando di esecuzione", + "tabTransfer": "Trasferimento file", + "tabInventory": "Inventario", + "openInventoryTab": "Apri in una scheda completa", + "tabPackages": "Pacchetti", + "runOnFleet": "Run on Fleet", + "commandPlaceholder": "uptime && df -h", + "commandRequired": "È richiesto un comando", + "commandInputsLabel": "Input di comando", + "commandSucceeded": "Comando eseguito correttamente su tutti gli host", + "commandPartialFailure": "{{failed}} di {{total}} host non sono riusciti", + "commandFailed": "Impossibile eseguire il comando", + "resultSuccess": "Successo", + "resultFailed": "Fallito", + "push": "Spingere", + "pull": "Tiro", + "remotePathLabel": "Percorso remoto", + "remotePathRequired": "È necessario un percorso remoto", + "fileLabel": "File", + "fileRequired": "È necessario un file", + "pushHint": "Il file selezionato viene scritto esattamente in questo percorso su ogni host della flotta.", + "pullHint": "Il file presente in questo percorso viene letto da ogni host e scaricato come un singolo file zip, una cartella per ogni host.", + "transferComplete": "Trasferimento completato", + "transferFailed": "Trasferimento non riuscito", + "refreshInventory": "Aggiorna l'inventario", + "inventoryLoadFailed": "Impossibile caricare l'inventario", + "inventoryRefreshed": "Inventario aggiornato", + "inventoryRefreshFailed": "Impossibile aggiornare l'inventario", + "inventoryNoData": "Nessun dato di inventario disponibile al momento: aggiorna la pagina per visualizzarlo.", + "inventoryHost": "Ospite", + "inventoryCollectedCount": "{{count}}/{{total}} raccolto", + "inventoryOs": "Sistema operativo", + "inventoryKernel": "Kernel", + "inventoryArch": "Arco", + "inventoryUptime": "Tempo di attività", + "inventoryPackageManager": "Responsabile del pacchetto", + "inventoryCollectedAt": "Raccolto", + "packageActionLabel": "Azione", + "packageInstall": "Installare", + "packageRemove": "Rimuovere", + "packageUpgradeAll": "Aggiorna tutti i pacchetti", + "packageNameLabel": "Nome del pacchetto", + "packageNameRequired": "È richiesto un nome per il pacchetto", + "packageHint": "Richiede l'accesso a livello di gestione per host ed eleva i privilegi utilizzando la password sudo memorizzata sull'host." + } + } + }, + "nav": { + "fleets": "Flotte" + } +} diff --git a/plugins/fleets/locales/translated/ja_JP.json b/plugins/fleets/locales/translated/ja_JP.json new file mode 100644 index 000000000..cde1ead7b --- /dev/null +++ b/plugins/fleets/locales/translated/ja_JP.json @@ -0,0 +1,89 @@ +{ + "newUi": { + "sidebar": { + "fleets": { + "title": "艦隊", + "createFleet": "艦隊を作成する", + "createFleetTitle": "艦隊を作成する", + "editFleetTitle": "艦隊を編集", + "createFleetDescription": "フリートとは、複数のホストをまとめてグループ化し、それらを一つの単位としてアクションを実行できるグループです。", + "nameLabel": "名前", + "namePlaceholder": "例:Webサーバー", + "nameRequired": "艦隊名は必須です", + "descriptionLabel": "説明", + "descriptionPlaceholder": "オプションの説明", + "colorLabel": "色", + "tagRulesLabel": "タグルール", + "tagRulesPlaceholder": "プロダクションウェブ、エッジ", + "tagRulesHint": "これらのタグのいずれかが付いているホストは、手動で追加されたホストに加えて、自動的に含まれます。", + "fleetCreated": "艦隊が創設されました", + "fleetUpdated": "艦隊情報更新", + "fleetDeleted": "艦隊削除", + "saveFailed": "艦隊の救出に失敗しました", + "deleteFailed": "艦隊の削除に失敗しました", + "loadFailed": "艦隊の読み込みに失敗しました", + "deleteFleetTitle": "艦隊を削除", + "deleteFleetDescription": "「{{name}}」を削除してもよろしいですか?これはメンバーホスト自体を削除するものではありません。", + "searchFleets": "艦隊を検索...", + "noFleets": "まだ艦隊がありません。まずは艦隊を作成してください。", + "memberCount": "{{count}} ホスト", + "memberCount_other": "{{count}} ホスト", + "manageMembers": "メンバーの管理", + "manageMembersTitle": "フリートメンバーの管理", + "manageMembersDescription": "このフリートの静的メンバーシップにホストを追加または削除する切り替えを行います。タグルールに一致するホストは常に含まれます。", + "searchHosts": "ホストを検索...", + "noHostsFound": "ホストが見つかりませんでした", + "noMembers": "この艦隊にはまだメンバーがいません。ホストを追加するか、タグルールを設定してください。", + "membersLoadFailed": "艦隊メンバーの読み込みに失敗しました", + "memberUpdateFailed": "艦隊メンバーシップの更新に失敗しました", + "tabRun": "コマンドを実行する", + "tabTransfer": "ファイルの転送", + "tabInventory": "在庫", + "openInventoryTab": "全画面表示", + "tabPackages": "パッケージ", + "runOnFleet": "ラン・オン・フリート", + "commandPlaceholder": "uptime && df -h", + "commandRequired": "コマンドが必要です", + "commandInputsLabel": "コマンド入力", + "commandSucceeded": "コマンドはすべてのホストで正常に実行されました。", + "commandPartialFailure": "{{failed}} の {{total}} ホストが失敗しました", + "commandFailed": "コマンドの実行に失敗しました", + "resultSuccess": "成功", + "resultFailed": "失敗した", + "push": "押す", + "pull": "引く", + "remotePathLabel": "リモートパス", + "remotePathRequired": "遠隔経路が必要です", + "fileLabel": "ファイル", + "fileRequired": "ファイルが必要です", + "pushHint": "選択されたファイルは、艦隊内のすべてのホスト上のこの正確なパスに書き込まれます。", + "pullHint": "このパスにあるファイルは、すべてのホストから読み込まれ、ホストごとに1つのフォルダ、つまり単一のzipファイルとしてダウンロードされます。", + "transferComplete": "転送完了", + "transferFailed": "転送に失敗しました", + "refreshInventory": "在庫を更新", + "inventoryLoadFailed": "在庫の読み込みに失敗しました", + "inventoryRefreshed": "在庫が更新されました", + "inventoryRefreshFailed": "在庫の更新に失敗しました", + "inventoryNoData": "在庫データがまだありません。更新して取得してください。", + "inventoryHost": "ホスト", + "inventoryCollectedCount": "{{count}}/{{total}} が収集されました", + "inventoryOs": "OS", + "inventoryKernel": "カーネル", + "inventoryArch": "アーチ", + "inventoryUptime": "稼働時間", + "inventoryPackageManager": "パッケージマネージャー", + "inventoryCollectedAt": "収集済み", + "packageActionLabel": "アクション", + "packageInstall": "インストール", + "packageRemove": "取り除く", + "packageUpgradeAll": "すべてのパッケージをアップグレードする", + "packageNameLabel": "パッケージ名", + "packageNameRequired": "パッケージ名は必須です。", + "packageHint": "ホストごとに管理者レベルのアクセス権限が必要で、ホストに保存されているsudoパスワードを使用して権限を昇格します。" + } + } + }, + "nav": { + "fleets": "艦隊" + } +} diff --git a/plugins/fleets/locales/translated/ko_KR.json b/plugins/fleets/locales/translated/ko_KR.json new file mode 100644 index 000000000..5c6015ac5 --- /dev/null +++ b/plugins/fleets/locales/translated/ko_KR.json @@ -0,0 +1,89 @@ +{ + "newUi": { + "sidebar": { + "fleets": { + "title": "함대", + "createFleet": "함대 생성", + "createFleetTitle": "함대 생성", + "editFleetTitle": "함대 편집", + "createFleetDescription": "함대는 여러 호스트를 하나의 그룹으로 묶어 작업을 수행할 수 있도록 명명된 그룹입니다.", + "nameLabel": "이름", + "namePlaceholder": "예: 웹 서버", + "nameRequired": "함대 이름은 필수 입력 사항입니다.", + "descriptionLabel": "설명", + "descriptionPlaceholder": "선택적 설명", + "colorLabel": "색상", + "tagRulesLabel": "태그 규칙", + "tagRulesPlaceholder": "프로드웹, 엣지", + "tagRulesHint": "이러한 태그 중 하나라도 있는 호스트는 수동으로 추가된 호스트 외에도 자동으로 포함됩니다.", + "fleetCreated": "함대 생성됨", + "fleetUpdated": "함대 업데이트됨", + "fleetDeleted": "함대 삭제됨", + "saveFailed": "함대를 구하는 데 실패했습니다", + "deleteFailed": "함대 삭제에 실패했습니다", + "loadFailed": "함대를 로드하는 데 실패했습니다.", + "deleteFleetTitle": "함대 삭제", + "deleteFleetDescription": "\"{{name}}\"을 삭제하시겠습니까? 삭제해도 멤버 호스트 자체는 삭제되지 않습니다.", + "searchFleets": "함대를 검색하세요...", + "noFleets": "아직 함대가 없습니다. 시작하려면 함대를 생성하세요.", + "memberCount": "{{count}} 호스트", + "memberCount_other": "{{count}} 호스트", + "manageMembers": "회원 관리", + "manageMembersTitle": "함대 구성원 관리", + "manageMembersDescription": "호스트를 이 함대의 고정 멤버십에 추가하거나 제외할 수 있습니다. 태그 규칙에 따라 일치하는 호스트는 항상 포함됩니다.", + "searchHosts": "호스트를 검색하세요...", + "noHostsFound": "호스트를 찾을 수 없습니다.", + "noMembers": "이 함대에는 아직 멤버가 없습니다. 호스트를 추가하거나 태그 규칙을 설정하세요.", + "membersLoadFailed": "함대 구성원을 불러오는 데 실패했습니다.", + "memberUpdateFailed": "함대 구성원 정보 업데이트에 실패했습니다.", + "tabRun": "명령 실행", + "tabTransfer": "파일 전송", + "tabInventory": "목록", + "openInventoryTab": "전체 화면에서 열기", + "tabPackages": "패키지", + "runOnFleet": "Fleet에서 실행", + "commandPlaceholder": "uptime && df -h", + "commandRequired": "명령어가 필요합니다", + "commandInputsLabel": "명령 입력", + "commandSucceeded": "모든 호스트에서 명령이 성공했습니다.", + "commandPartialFailure": "{{failed}} 의 {{total}} 호스트가 실패했습니다.", + "commandFailed": "명령 실행에 실패했습니다.", + "resultSuccess": "성공", + "resultFailed": "실패한", + "push": "푸시", + "pull": "당기다", + "remotePathLabel": "원격 경로", + "remotePathRequired": "원격 경로가 필요합니다", + "fileLabel": "파일", + "fileRequired": "파일이 필요합니다", + "pushHint": "선택한 파일은 전체 호스트의 정확히 이 경로에 기록됩니다.", + "pullHint": "이 경로에 있는 파일은 모든 호스트에서 읽어와 호스트당 하나의 폴더로 구성된 단일 zip 파일로 다운로드됩니다.", + "transferComplete": "이체 완료", + "transferFailed": "전송 실패", + "refreshInventory": "재고 새로 고침", + "inventoryLoadFailed": "재고 불러오기에 실패했습니다", + "inventoryRefreshed": "재고가 갱신되었습니다", + "inventoryRefreshFailed": "재고 새로 고침에 실패했습니다.", + "inventoryNoData": "아직 재고 데이터가 없습니다. 새로 고침하여 데이터를 수집하세요.", + "inventoryHost": "주인", + "inventoryCollectedCount": "{{count}}/{{total}} 수집됨", + "inventoryOs": "OS", + "inventoryKernel": "핵심", + "inventoryArch": "아치", + "inventoryUptime": "가동 시간", + "inventoryPackageManager": "패키지 관리자", + "inventoryCollectedAt": "모은", + "packageActionLabel": "행동", + "packageInstall": "설치하다", + "packageRemove": "제거하다", + "packageUpgradeAll": "모든 패키지 업그레이드", + "packageNameLabel": "패키지 이름", + "packageNameRequired": "패키지 이름은 필수 입력 사항입니다.", + "packageHint": "호스트별 관리자 권한 접근이 필요하며, 호스트에 저장된 sudo 암호를 사용하여 권한을 상승시킵니다." + } + } + }, + "nav": { + "fleets": "함대" + } +} diff --git a/plugins/fleets/locales/translated/nl_NL.json b/plugins/fleets/locales/translated/nl_NL.json new file mode 100644 index 000000000..7c8f4311f --- /dev/null +++ b/plugins/fleets/locales/translated/nl_NL.json @@ -0,0 +1,89 @@ +{ + "newUi": { + "sidebar": { + "fleets": { + "title": "Vloten", + "createFleet": "Vloot creëren", + "createFleetTitle": "Vloot creëren", + "editFleetTitle": "Vloot bewerken", + "createFleetDescription": "Een vloot is een benoemde groep hosts waartegen je als eenheid acties kunt uitvoeren.", + "nameLabel": "Naam", + "namePlaceholder": "bijvoorbeeld webservers", + "nameRequired": "Vlootnaam is verplicht", + "descriptionLabel": "Beschrijving", + "descriptionPlaceholder": "Optionele beschrijving", + "colorLabel": "Kleur", + "tagRulesLabel": "Tagregels", + "tagRulesPlaceholder": "prod-web, edge", + "tagRulesHint": "Hosts met een van deze tags worden automatisch opgenomen, naast hosts die handmatig zijn toegevoegd.", + "fleetCreated": "Vloot gecreëerd", + "fleetUpdated": "Vloot bijgewerkt", + "fleetDeleted": "Vloot verwijderd", + "saveFailed": "Vloot kon niet worden gered", + "deleteFailed": "Het verwijderen van de vloot is mislukt.", + "loadFailed": "Het laden van de vloot is mislukt.", + "deleteFleetTitle": "Vloot verwijderen", + "deleteFleetDescription": "Weet je zeker dat je \"{{name}}\" wilt verwijderen? Hiermee worden de lidhosts zelf niet verwijderd.", + "searchFleets": "Zoekvloten...", + "noFleets": "Nog geen vloten. Maak er een aan om te beginnen.", + "memberCount": "{{count}} host", + "memberCount_other": "{{count}} hosts", + "manageMembers": "Leden beheren", + "manageMembersTitle": "Vlootleden beheren", + "manageMembersDescription": "Voeg hosts toe aan of verwijder ze uit het statische lidmaatschap van deze vloot. Hosts die overeenkomen met tagregels zijn altijd inbegrepen.", + "searchHosts": "Zoek hosts...", + "noHostsFound": "Geen hosts gevonden", + "noMembers": "Deze vloot heeft nog geen leden. Voeg hosts toe of stel een tagregel in.", + "membersLoadFailed": "Het laden van de vlootleden is mislukt.", + "memberUpdateFailed": "Het bijwerken van het vlootlidmaatschap is mislukt.", + "tabRun": "Voer het commando uit", + "tabTransfer": "Bestanden overdragen", + "tabInventory": "Inventaris", + "openInventoryTab": "Openen in een volledig tabblad", + "tabPackages": "Pakketten", + "runOnFleet": "Run on Fleet", + "commandPlaceholder": "uptime && df -h", + "commandRequired": "Een opdracht is vereist.", + "commandInputsLabel": "Commando-invoer", + "commandSucceeded": "De opdracht is op alle hosts succesvol uitgevoerd.", + "commandPartialFailure": "{{failed}} van {{total}} hosts mislukt", + "commandFailed": "Het uitvoeren van de opdracht is mislukt.", + "resultSuccess": "Succes", + "resultFailed": "Mislukt", + "push": "Duw", + "pull": "Trekken", + "remotePathLabel": "Externe route", + "remotePathRequired": "Een externe verbinding is vereist.", + "fileLabel": "Bestand", + "fileRequired": "Een bestand is vereist.", + "pushHint": "Het geselecteerde bestand wordt op elke host in de vloot naar precies dit pad geschreven.", + "pullHint": "Het bestand op dit pad wordt van elke host gelezen en gedownload als één zip-bestand, één map per host.", + "transferComplete": "Overdracht voltooid", + "transferFailed": "Overdracht mislukt", + "refreshInventory": "Voorraad vernieuwen", + "inventoryLoadFailed": "Het laden van de inventaris is mislukt.", + "inventoryRefreshed": "Voorraad bijgewerkt", + "inventoryRefreshFailed": "Het vernieuwen van de inventaris is mislukt.", + "inventoryNoData": "Er zijn nog geen voorraadgegevens beschikbaar - vernieuw de pagina om ze te verzamelen.", + "inventoryHost": "Gastheer", + "inventoryCollectedCount": "{{count}}/{{total}} verzameld", + "inventoryOs": "OS", + "inventoryKernel": "Kernel", + "inventoryArch": "Boog", + "inventoryUptime": "Beschikbaarheid", + "inventoryPackageManager": "Pakketbeheerder", + "inventoryCollectedAt": "Verzameld", + "packageActionLabel": "Actie", + "packageInstall": "Installeren", + "packageRemove": "Verwijderen", + "packageUpgradeAll": "Upgrade alle pakketten", + "packageNameLabel": "Pakketnaam", + "packageNameRequired": "Een pakketnaam is vereist.", + "packageHint": "Vereist beheerrechten per host en verhoogt deze rechten met behulp van het opgeslagen sudo-wachtwoord van de host." + } + } + }, + "nav": { + "fleets": "Vloten" + } +} diff --git a/plugins/fleets/locales/translated/no_NO.json b/plugins/fleets/locales/translated/no_NO.json new file mode 100644 index 000000000..a5e77e726 --- /dev/null +++ b/plugins/fleets/locales/translated/no_NO.json @@ -0,0 +1,89 @@ +{ + "newUi": { + "sidebar": { + "fleets": { + "title": "Flåter", + "createFleet": "Opprett flåte", + "createFleetTitle": "Opprett flåte", + "editFleetTitle": "Rediger flåte", + "createFleetDescription": "En flåte er en navngitt gruppe verter du kan kjøre handlinger mot som en enhet.", + "nameLabel": "Navn", + "namePlaceholder": "f.eks. webservere", + "nameRequired": "Flåtenavn er obligatorisk", + "descriptionLabel": "Beskrivelse", + "descriptionPlaceholder": "Valgfri beskrivelse", + "colorLabel": "Farge", + "tagRulesLabel": "Taggregler", + "tagRulesPlaceholder": "prod-web, kant", + "tagRulesHint": "Verter med noen av disse taggene inkluderes automatisk, i tillegg til verter som legges til manuelt.", + "fleetCreated": "Flåte opprettet", + "fleetUpdated": "Flåten er oppdatert", + "fleetDeleted": "Flåten er slettet", + "saveFailed": "Kunne ikke lagre flåten", + "deleteFailed": "Kunne ikke slette flåten", + "loadFailed": "Kunne ikke laste inn flåter", + "deleteFleetTitle": "Slett flåte", + "deleteFleetDescription": "Er du sikker på at du vil slette «{{name}}»? Dette sletter ikke selve medlemsvertene.", + "searchFleets": "Søk etter flåter...", + "noFleets": "Ingen flåter ennå. Opprett en for å komme i gang.", + "memberCount": "{{count}} vert", + "memberCount_other": "{{count}} verter", + "manageMembers": "Administrer medlemmer", + "manageMembersTitle": "Administrer flåtemedlemmer", + "manageMembersDescription": "Veksle verter inn eller ut av denne flåtens statiske medlemskap. Verter som samsvarer med tagregler er alltid inkludert.", + "searchHosts": "Søk etter verter...", + "noHostsFound": "Ingen verter funnet", + "noMembers": "Denne flåten har ingen medlemmer ennå. Legg til verter eller angi en tagregel.", + "membersLoadFailed": "Kunne ikke laste inn flåtemedlemmer", + "memberUpdateFailed": "Kunne ikke oppdatere flåtemedlemskapet", + "tabRun": "Kjør kommando", + "tabTransfer": "Overfør filer", + "tabInventory": "Inventar", + "openInventoryTab": "Åpne i full fane", + "tabPackages": "Pakker", + "runOnFleet": "Kjør på flåten", + "commandPlaceholder": "oppetid og df -h", + "commandRequired": "En kommando er nødvendig", + "commandInputsLabel": "Kommandoinnganger", + "commandSucceeded": "Kommandoen lyktes på alle verter", + "commandPartialFailure": "{{failed}} av {{total}} verter mislyktes", + "commandFailed": "Kunne ikke kjøre kommandoen", + "resultSuccess": "Suksess", + "resultFailed": "Mislyktes", + "push": "Trykk", + "pull": "Dra", + "remotePathLabel": "Fjernbane", + "remotePathRequired": "En ekstern sti er nødvendig", + "fileLabel": "Fil", + "fileRequired": "En fil er nødvendig", + "pushHint": "Den valgte filen skrives til denne nøyaktige banen på alle verter i flåten.", + "pullHint": "Filen på denne banen leses fra hver vert og lastes ned som en enkelt zip-fil, én mappe per vert.", + "transferComplete": "Overføringen er fullført", + "transferFailed": "Overføringen mislyktes", + "refreshInventory": "Oppdater beholdningen", + "inventoryLoadFailed": "Kunne ikke laste inn beholdningen", + "inventoryRefreshed": "Lagerbeholdningen er oppdatert", + "inventoryRefreshFailed": "Kunne ikke oppdatere beholdningen", + "inventoryNoData": "Ingen lagerdata ennå – oppdater for å samle dem inn.", + "inventoryHost": "Vert", + "inventoryCollectedCount": "{{count}}/{{total}} samlet", + "inventoryOs": "OS", + "inventoryKernel": "Kjerne", + "inventoryArch": "Buen", + "inventoryUptime": "Oppetid", + "inventoryPackageManager": "Pakkebehandler", + "inventoryCollectedAt": "Samlet", + "packageActionLabel": "Handling", + "packageInstall": "Installer", + "packageRemove": "Fjerne", + "packageUpgradeAll": "Oppgrader alle pakker", + "packageNameLabel": "Pakkenavn", + "packageNameRequired": "Et pakkenavn er obligatorisk", + "packageHint": "Krever tilgang på administratornivå per vert og heves ved hjelp av vertens lagrede sudo-passord." + } + } + }, + "nav": { + "fleets": "Flåter" + } +} diff --git a/plugins/fleets/locales/translated/pl_PL.json b/plugins/fleets/locales/translated/pl_PL.json new file mode 100644 index 000000000..8ad196328 --- /dev/null +++ b/plugins/fleets/locales/translated/pl_PL.json @@ -0,0 +1,89 @@ +{ + "newUi": { + "sidebar": { + "fleets": { + "title": "Floty", + "createFleet": "Utwórz flotę", + "createFleetTitle": "Utwórz flotę", + "editFleetTitle": "Edytuj flotę", + "createFleetDescription": "Flota to nazwana grupa hostów, na której możesz wykonywać akcje jak na jednym obiekcie.", + "nameLabel": "Nazwa", + "namePlaceholder": "np. Serwery WWW", + "nameRequired": "Nazwa floty jest wymagana", + "descriptionLabel": "Opis", + "descriptionPlaceholder": "Opis opcjonalny", + "colorLabel": "Kolor", + "tagRulesLabel": "Reguły tagów", + "tagRulesPlaceholder": "prod-web, edge", + "tagRulesHint": "Hosty z dowolnym z tych tagów są dołączane automatycznie, obok hostów dodanych ręcznie.", + "fleetCreated": "Utworzono flotę", + "fleetUpdated": "Zaktualizowano flotę", + "fleetDeleted": "Usunięto flotę", + "saveFailed": "Nie udało się zapisać floty", + "deleteFailed": "Nie udało się usunąć floty", + "loadFailed": "Nie udało się załadować flot", + "deleteFleetTitle": "Usuń flotę", + "deleteFleetDescription": "Czy na pewno chcesz usunąć „{{name}}”? Nie spowoduje to usunięcia samych hostów należących do floty.", + "searchFleets": "Przeszukaj floty...", + "noFleets": "Brak flot. Utwórz pierwszą, aby zacząć.", + "memberCount": "{{count}} host", + "memberCount_other": "{{count}} hostów", + "manageMembers": "Zarządzaj członkami", + "manageMembersTitle": "Zarządzaj członkami floty", + "manageMembersDescription": "Przełączaj hosty do lub z członkostwa statycznego tej floty. Hosty dopasowane według reguł tagów są zawsze uwzględniane.", + "searchHosts": "Wyszukaj hosty...", + "noHostsFound": "Nie znaleziono żadnych hostów", + "noMembers": "Ta flota nie ma jeszcze członków. Dodaj hosty lub ustaw regułę tagów.", + "membersLoadFailed": "Nie udało się załadować członków floty", + "memberUpdateFailed": "Nie udało się zaktualizować członkostwa we flocie", + "tabRun": "Uruchom polecenie", + "tabTransfer": "Przesyłanie plików", + "tabInventory": "Inwentarz", + "openInventoryTab": "Otwórz w pełnej karcie", + "tabPackages": "Pakiety", + "runOnFleet": "Uruchom na flocie", + "commandPlaceholder": "uptime && df -h", + "commandRequired": "Wymagane jest polecenie", + "commandInputsLabel": "Dane wejściowe polecenia", + "commandSucceeded": "Polecenie powiodło się na wszystkich hostach", + "commandPartialFailure": "Na {{failed}} z {{total}} hostów wystąpił błąd", + "commandFailed": "Nie udało się uruchomić polecenia", + "resultSuccess": "Powodzenie", + "resultFailed": "Niepowodzenie", + "push": "Wyślij", + "pull": "Pobierz", + "remotePathLabel": "Ścieżka zdalna", + "remotePathRequired": "Wymagana jest ścieżka zdalna", + "fileLabel": "Plik", + "fileRequired": "Wymagany jest plik", + "pushHint": "Wybrany plik zostanie zapisany dokładnie pod tą ścieżką na każdym hoście we flocie.", + "pullHint": "Plik znajdujący się pod tą ścieżką jest odczytywany z każdego hosta i pobierany jako pojedynczy plik zip, jeden folder na hosta.", + "transferComplete": "Transfer zakończony", + "transferFailed": "Transfer nie powiódł się", + "refreshInventory": "Odśwież inwentarz", + "inventoryLoadFailed": "Nie udało się załadować inwentarza", + "inventoryRefreshed": "Odświeżono inwentarz", + "inventoryRefreshFailed": "Nie udało się odświeżyć inwentarza", + "inventoryNoData": "Brak danych inwentarza. Odśwież, aby je zebrać.", + "inventoryHost": "Host", + "inventoryCollectedCount": "{{count}}/{{total}} zebrano", + "inventoryOs": "System operacyjny", + "inventoryKernel": "Jądro", + "inventoryArch": "Architektura", + "inventoryUptime": "Czas działania", + "inventoryPackageManager": "Menedżer pakietów", + "inventoryCollectedAt": "Zebrano", + "packageActionLabel": "Akcja", + "packageInstall": "Zainstaluj", + "packageRemove": "Usuń", + "packageUpgradeAll": "Uaktualnij wszystkie pakiety", + "packageNameLabel": "Nazwa pakietu", + "packageNameRequired": "Wymagana jest nazwa pakietu", + "packageHint": "Wymaga dostępu na poziomie zarządzania na każdym hoście i podnosi uprawnienia zapisanym hasłem sudo hosta." + } + } + }, + "nav": { + "fleets": "Floty" + } +} diff --git a/plugins/fleets/locales/translated/pt_BR.json b/plugins/fleets/locales/translated/pt_BR.json new file mode 100644 index 000000000..700850bc1 --- /dev/null +++ b/plugins/fleets/locales/translated/pt_BR.json @@ -0,0 +1,89 @@ +{ + "newUi": { + "sidebar": { + "fleets": { + "title": "Frotas", + "createFleet": "Criar Frota", + "createFleetTitle": "Criar Frota", + "editFleetTitle": "Editar frota", + "createFleetDescription": "Uma frota é um grupo nomeado de hosts contra os quais você pode executar ações como uma unidade.", + "nameLabel": "Nome", + "namePlaceholder": "Por exemplo, servidores web", + "nameRequired": "É necessário nomear a frota.", + "descriptionLabel": "Descrição", + "descriptionPlaceholder": "Descrição opcional", + "colorLabel": "Cor", + "tagRulesLabel": "Regras de etiqueta", + "tagRulesPlaceholder": "prod-web, edge", + "tagRulesHint": "Os hosts com qualquer uma dessas tags são incluídos automaticamente, além dos hosts adicionados manualmente.", + "fleetCreated": "Frota criada", + "fleetUpdated": "Frota atualizada", + "fleetDeleted": "Frota excluída", + "saveFailed": "Não conseguiram salvar a frota.", + "deleteFailed": "Falha ao excluir a frota", + "loadFailed": "Falha ao carregar as frotas", + "deleteFleetTitle": "Excluir frota", + "deleteFleetDescription": "Tem certeza de que deseja excluir \"{{name}}\"? Isso não exclui os próprios hosts membros.", + "searchFleets": "Pesquisar frotas...", + "noFleets": "Ainda não há frotas. Crie uma para começar.", + "memberCount": "{{count}} anfitrião", + "memberCount_other": "{{count}} anfitriões", + "manageMembers": "Gerenciar membros", + "manageMembersTitle": "Gerenciar membros da frota", + "manageMembersDescription": "Ative ou desative a inclusão de hosts nesta frota estática. Os hosts que corresponderem às regras de tags serão sempre incluídos.", + "searchHosts": "Pesquisar hosts...", + "noHostsFound": "Nenhum host encontrado", + "noMembers": "Esta frota ainda não tem membros. Adicione anfitriões ou defina uma regra de etiqueta.", + "membersLoadFailed": "Falha ao carregar membros da frota", + "memberUpdateFailed": "Falha na atualização da associação à frota", + "tabRun": "Executar comando", + "tabTransfer": "Transferir arquivos", + "tabInventory": "Inventário", + "openInventoryTab": "Abrir em aba inteira", + "tabPackages": "Pacotes", + "runOnFleet": "Executar na frota", + "commandPlaceholder": "tempo de atividade e df -h", + "commandRequired": "É necessário um comando.", + "commandInputsLabel": "Entradas de comando", + "commandSucceeded": "O comando foi executado com sucesso em todos os hosts.", + "commandPartialFailure": "{{failed}} de {{total}} hosts falharam", + "commandFailed": "Falha ao executar o comando", + "resultSuccess": "Sucesso", + "resultFailed": "Fracassado", + "push": "Empurrar", + "pull": "Puxar", + "remotePathLabel": "Caminho remoto", + "remotePathRequired": "É necessário um caminho remoto.", + "fileLabel": "Arquivo", + "fileRequired": "É necessário um arquivo.", + "pushHint": "O arquivo selecionado é gravado exatamente nesse caminho em todos os hosts da frota.", + "pullHint": "O arquivo neste caminho é lido de cada host e baixado como um único arquivo zip, uma pasta por host.", + "transferComplete": "Transferência concluída", + "transferFailed": "A transferência falhou", + "refreshInventory": "Atualizar inventário", + "inventoryLoadFailed": "Falha ao carregar o inventário", + "inventoryRefreshed": "Inventário atualizado", + "inventoryRefreshFailed": "Falha ao atualizar o inventário", + "inventoryNoData": "Ainda não há dados de estoque - atualize a página para coletá-los.", + "inventoryHost": "Hospedar", + "inventoryCollectedCount": "{{count}}/{{total}} coletado", + "inventoryOs": "SO", + "inventoryKernel": "Kernel", + "inventoryArch": "Arco", + "inventoryUptime": "Tempo de atividade", + "inventoryPackageManager": "Gerenciador de pacotes", + "inventoryCollectedAt": "Coletado", + "packageActionLabel": "Ação", + "packageInstall": "Instalar", + "packageRemove": "Remover", + "packageUpgradeAll": "Atualize todos os pacotes", + "packageNameLabel": "Nome do pacote", + "packageNameRequired": "É necessário informar o nome do pacote.", + "packageHint": "Requer acesso de nível de gerenciamento por host e eleva os privilégios usando a senha sudo armazenada no host." + } + } + }, + "nav": { + "fleets": "Frotas" + } +} diff --git a/plugins/fleets/locales/translated/pt_PT.json b/plugins/fleets/locales/translated/pt_PT.json new file mode 100644 index 000000000..f2b8a7050 --- /dev/null +++ b/plugins/fleets/locales/translated/pt_PT.json @@ -0,0 +1,89 @@ +{ + "newUi": { + "sidebar": { + "fleets": { + "title": "Frotas", + "createFleet": "Criar Frota", + "createFleetTitle": "Criar Frota", + "editFleetTitle": "Editar frota", + "createFleetDescription": "Uma frota é um grupo nomeado de hosts contra os quais pode executar ações como uma unidade.", + "nameLabel": "Nome", + "namePlaceholder": "Por exemplo, os servidores web", + "nameRequired": "É necessário dar um nome à frota.", + "descriptionLabel": "Descrição", + "descriptionPlaceholder": "Descrição opcional", + "colorLabel": "Cor", + "tagRulesLabel": "Regras de etiqueta", + "tagRulesPlaceholder": "prod-web, edge", + "tagRulesHint": "Os hosts com qualquer uma destas etiquetas são incluídos automaticamente, para além dos hosts adicionados manualmente.", + "fleetCreated": "Frota criada", + "fleetUpdated": "Frota atualizada", + "fleetDeleted": "Frota excluída", + "saveFailed": "Não conseguiram salvar a frota.", + "deleteFailed": "Falha ao eliminar a frota", + "loadFailed": "Falha ao carregar as frotas", + "deleteFleetTitle": "Excluir frota", + "deleteFleetDescription": "Tem a certeza que pretende eliminar \"{{name}}\"? Isto não exclui os próprios hosts membros.", + "searchFleets": "Pesquisar frotas...", + "noFleets": "Ainda não há frotas. Crie uma para começar.", + "memberCount": "{{count}} anfitrião", + "memberCount_other": "{{count}} anfitriões", + "manageMembers": "Gerir membros", + "manageMembersTitle": "Gerir membros da frota", + "manageMembersDescription": "Ative ou desative a inclusão de hosts nesta frota estática. Os hosts que corresponderem às regras das tags serão sempre incluídos.", + "searchHosts": "Pesquisar hosts...", + "noHostsFound": "Nenhum host encontrado", + "noMembers": "Esta frota ainda não tem membros. Adicione anfitriões ou defina uma regra de etiqueta.", + "membersLoadFailed": "Falha ao carregar membros da frota", + "memberUpdateFailed": "Falha na atualização da adesão à frota", + "tabRun": "Executar comando", + "tabTransfer": "Transferir ficheiros", + "tabInventory": "Inventário", + "openInventoryTab": "Abrir em separador inteiro", + "tabPackages": "Pacotes", + "runOnFleet": "Executar na frota", + "commandPlaceholder": "tempo de atividade e df -h", + "commandRequired": "É necessário um comando.", + "commandInputsLabel": "Entradas de comando", + "commandSucceeded": "O comando foi executado com sucesso em todos os hosts.", + "commandPartialFailure": "{{failed}} de {{total}} os hosts falharam", + "commandFailed": "Falha ao executar o comando", + "resultSuccess": "Sucesso", + "resultFailed": "Falhou", + "push": "Pressionar", + "pull": "Puxar", + "remotePathLabel": "Caminho remoto", + "remotePathRequired": "É necessário um caminho remoto.", + "fileLabel": "Ficheiro", + "fileRequired": "É necessário um ficheiro.", + "pushHint": "O ficheiro selecionado é gravado exatamente nesse caminho em todos os hosts da frota.", + "pullHint": "O ficheiro neste caminho é lido de cada host e descarregado como um único ficheiro zip, uma pasta por host.", + "transferComplete": "Transferência concluída", + "transferFailed": "A transferência falhou", + "refreshInventory": "Atualizar inventário", + "inventoryLoadFailed": "Falha ao carregar o inventário", + "inventoryRefreshed": "Inventário atualizado", + "inventoryRefreshFailed": "Falha ao atualizar o inventário", + "inventoryNoData": "Ainda não há dados de stock - atualize a página para os recolher.", + "inventoryHost": "Anfitrião", + "inventoryCollectedCount": "{{count}}/{{total}} recolhido", + "inventoryOs": "SO", + "inventoryKernel": "Kernel", + "inventoryArch": "Arco", + "inventoryUptime": "Tempo de atividade", + "inventoryPackageManager": "Gestor de pacotes", + "inventoryCollectedAt": "Coletado", + "packageActionLabel": "Ação", + "packageInstall": "Instalar", + "packageRemove": "Remover", + "packageUpgradeAll": "Atualize todos os pacotes", + "packageNameLabel": "Nome do pacote", + "packageNameRequired": "É necessário informar o nome do pacote.", + "packageHint": "Requer acesso de nível de gestão por host e eleva os privilégios utilizando a palavra-passe sudo armazenada no host." + } + } + }, + "nav": { + "fleets": "Frotas" + } +} diff --git a/plugins/fleets/locales/translated/ro_RO.json b/plugins/fleets/locales/translated/ro_RO.json new file mode 100644 index 000000000..66a220f01 --- /dev/null +++ b/plugins/fleets/locales/translated/ro_RO.json @@ -0,0 +1,89 @@ +{ + "newUi": { + "sidebar": { + "fleets": { + "title": "Flote", + "createFleet": "Creați o flotă", + "createFleetTitle": "Creați o flotă", + "editFleetTitle": "Editare flotă", + "createFleetDescription": "O flotă este un grup denumit de gazde împotriva cărora puteți rula acțiuni ca o unitate.", + "nameLabel": "Nume", + "namePlaceholder": "de exemplu, servere web", + "nameRequired": "Numele flotei este obligatoriu", + "descriptionLabel": "Descriere", + "descriptionPlaceholder": "Descriere opțională", + "colorLabel": "Culoare", + "tagRulesLabel": "Reguli de etichetare", + "tagRulesPlaceholder": "prod-web, margine", + "tagRulesHint": "Gazdele cu oricare dintre aceste etichete sunt incluse automat, pe lângă gazdele adăugate manual.", + "fleetCreated": "Flotă creată", + "fleetUpdated": "Flota actualizată", + "fleetDeleted": "Flota a fost ștearsă", + "saveFailed": "Nu s-a putut salva flota", + "deleteFailed": "Nu s-a putut șterge flota", + "loadFailed": "Nu s-au putut încărca flotele", + "deleteFleetTitle": "Ștergeți flota", + "deleteFleetDescription": "Sigur vrei să ștergi „{{name}}”? Această acțiune nu șterge gazdele membre în sine.", + "searchFleets": "Căutați flote...", + "noFleets": "Încă nu există flote. Creați una pentru a începe.", + "memberCount": "gazdă {{count}}", + "memberCount_other": "gazde {{count}}", + "manageMembers": "Gestionați membrii", + "manageMembersTitle": "Gestionați membrii flotei", + "manageMembersDescription": "Activează sau dezactivează includerea sau dezactivarea gazdelor în calitate de membru static al acestei flote. Gazdele care corespund regulilor de etichetare sunt întotdeauna incluse.", + "searchHosts": "Căutați gazde...", + "noHostsFound": "Nu s-au găsit gazde", + "noMembers": "Această flotă nu are încă membri. Adăugați gazde sau setați o regulă de etichetare.", + "membersLoadFailed": "Nu s-au putut încărca membrii flotei", + "memberUpdateFailed": "Nu s-a putut actualiza calitatea de membru al flotei", + "tabRun": "Comandă de rulare", + "tabTransfer": "Transfer fișiere", + "tabInventory": "Inventar", + "openInventoryTab": "Deschideți în fila completă", + "tabPackages": "Pachete", + "runOnFleet": "Rulați pe flotă", + "commandPlaceholder": "timp de funcționare && df -h", + "commandRequired": "Este necesară o comandă", + "commandInputsLabel": "Intrări de comandă", + "commandSucceeded": "Comanda a reușit pe toate gazdele", + "commandPartialFailure": "{{failed}} din {{total}} gazde au eșuat", + "commandFailed": "Comanda nu a putut fi executată", + "resultSuccess": "Succes", + "resultFailed": "Eșuat", + "push": "Apăsaţi", + "pull": "Trage", + "remotePathLabel": "Cale la distanță", + "remotePathRequired": "Este necesară o cale la distanță", + "fileLabel": "Fişier", + "fileRequired": "Este necesar un fișier", + "pushHint": "Fișierul selectat este scris exact pe această cale pe fiecare gazdă din flotă.", + "pullHint": "Fișierul de pe această cale este citit de pe fiecare gazdă și descărcat ca un singur fișier zip, câte un folder per gazdă.", + "transferComplete": "Transfer finalizat", + "transferFailed": "Transferul a eșuat", + "refreshInventory": "Reîmprospătați inventarul", + "inventoryLoadFailed": "Nu s-a putut încărca inventarul", + "inventoryRefreshed": "Inventarul a fost actualizat", + "inventoryRefreshFailed": "Nu s-a putut actualiza inventarul", + "inventoryNoData": "Nu există încă date despre inventar - actualizați pagina pentru a le colecta.", + "inventoryHost": "Gazdă", + "inventoryCollectedCount": "{{count}}/{{total}} colectate", + "inventoryOs": "Sistem de operare", + "inventoryKernel": "Nucleu", + "inventoryArch": "Arc", + "inventoryUptime": "Timp de funcționare", + "inventoryPackageManager": "Manager de pachete", + "inventoryCollectedAt": "Colectate", + "packageActionLabel": "Acţiune", + "packageInstall": "Instala", + "packageRemove": "Elimina", + "packageUpgradeAll": "Actualizați toate pachetele", + "packageNameLabel": "Numele pachetului", + "packageNameRequired": "Este necesar un nume de pachet", + "packageHint": "Necesită acces la nivel de administrare per gazdă și ridică privilegiile folosind parola sudo stocată a gazdei." + } + } + }, + "nav": { + "fleets": "Flote" + } +} diff --git a/plugins/fleets/locales/translated/ru_RU.json b/plugins/fleets/locales/translated/ru_RU.json new file mode 100644 index 000000000..1fcb75998 --- /dev/null +++ b/plugins/fleets/locales/translated/ru_RU.json @@ -0,0 +1,89 @@ +{ + "newUi": { + "sidebar": { + "fleets": { + "title": "Флоты", + "createFleet": "Создать флот", + "createFleetTitle": "Создать флот", + "editFleetTitle": "Редактировать флот", + "createFleetDescription": "Флот — это именованная группа хостов, против которых можно выполнять действия как единое целое.", + "nameLabel": "Имя", + "namePlaceholder": "например, веб-серверы", + "nameRequired": "Название флота обязательно.", + "descriptionLabel": "Описание", + "descriptionPlaceholder": "Дополнительное описание", + "colorLabel": "Цвет", + "tagRulesLabel": "Правила тегирования", + "tagRulesPlaceholder": "прод-веб, граничный", + "tagRulesHint": "В дополнение к хостам, добавленным вручную, автоматически включаются хосты, имеющие любой из этих тегов.", + "fleetCreated": "Создан флот", + "fleetUpdated": "Обновление флота", + "fleetDeleted": "Флот уничтожен", + "saveFailed": "Не удалось спасти флот", + "deleteFailed": "Не удалось удалить флот", + "loadFailed": "Не удалось загрузить флот.", + "deleteFleetTitle": "Удалить флот", + "deleteFleetDescription": "Вы уверены, что хотите удалить \"{{name}}\"? Это не удалит сами хосты-участники.", + "searchFleets": "Поиск флотов...", + "noFleets": "Пока нет флотов. Создайте свой, чтобы начать.", + "memberCount": "{{count}} хост", + "memberCount_other": "{{count}} хосты", + "manageMembers": "Управление участниками", + "manageMembersTitle": "Управление членами автопарка", + "manageMembersDescription": "Добавляйте или исключайте хосты из статического членства в этом флоте. Хосты, соответствующие правилам тегов, всегда включаются.", + "searchHosts": "Поиск хостов...", + "noHostsFound": "Хосты не найдены", + "noMembers": "В этом флоте пока нет участников. Добавьте хостов или установите правило тегов.", + "membersLoadFailed": "Не удалось загрузить членов флота.", + "memberUpdateFailed": "Не удалось обновить данные о членстве в автопарке.", + "tabRun": "Выполнить команду", + "tabTransfer": "Передача файлов", + "tabInventory": "Инвентаризация", + "openInventoryTab": "Открыть в полноэкранном режиме", + "tabPackages": "Пакеты", + "runOnFleet": "Run on Fleet", + "commandPlaceholder": "uptime && df -h", + "commandRequired": "Требуется команда", + "commandInputsLabel": "Ввод команд", + "commandSucceeded": "Команда успешно выполнена на всех хостах.", + "commandPartialFailure": "{{failed}} из {{total}} хостов не удалось", + "commandFailed": "Не удалось выполнить команду.", + "resultSuccess": "Успех", + "resultFailed": "Неуспешный", + "push": "Толкать", + "pull": "Тянуть", + "remotePathLabel": "Удаленный путь", + "remotePathRequired": "Требуется удаленный путь", + "fileLabel": "Файл", + "fileRequired": "Требуется файл", + "pushHint": "Выбранный файл записывается точно по этому пути на каждом хосте в сети.", + "pullHint": "Файл по этому пути считывается с каждого хоста и загружается в виде единого ZIP-архива, по одной папке на каждый хост.", + "transferComplete": "Передача завершена", + "transferFailed": "Перевод не удался", + "refreshInventory": "Обновить инвентарь", + "inventoryLoadFailed": "Не удалось загрузить товарные запасы.", + "inventoryRefreshed": "Инвентарь обновлен", + "inventoryRefreshFailed": "Не удалось обновить данные об остатках на складе.", + "inventoryNoData": "Данные об остатках товара пока отсутствуют — обновите страницу, чтобы получить их.", + "inventoryHost": "Хозяин", + "inventoryCollectedCount": "{{count}}/{{total}} собрано", + "inventoryOs": "ОС", + "inventoryKernel": "Ядро", + "inventoryArch": "Арка", + "inventoryUptime": "Время безотказной работы", + "inventoryPackageManager": "Менеджер пакетов", + "inventoryCollectedAt": "Собрано", + "packageActionLabel": "Действие", + "packageInstall": "Установить", + "packageRemove": "Удалять", + "packageUpgradeAll": "Обновить все пакеты", + "packageNameLabel": "Название пакета", + "packageNameRequired": "Требуется указать имя пакета.", + "packageHint": "Для работы требуется доступ уровня администратора для каждого хоста, повышение прав осуществляется с помощью сохраненного пароля sudo для данного хоста." + } + } + }, + "nav": { + "fleets": "Флоты" + } +} diff --git a/plugins/fleets/locales/translated/sr_SP.json b/plugins/fleets/locales/translated/sr_SP.json new file mode 100644 index 000000000..8578f48aa --- /dev/null +++ b/plugins/fleets/locales/translated/sr_SP.json @@ -0,0 +1,89 @@ +{ + "newUi": { + "sidebar": { + "fleets": { + "title": "Флоте", + "createFleet": "Креирај флоту", + "createFleetTitle": "Креирај флоту", + "editFleetTitle": "Уреди флоту", + "createFleetDescription": "Флота је именована група хостова против којих можете извршавати акције као јединицу.", + "nameLabel": "Име", + "namePlaceholder": "нпр. веб сервери", + "nameRequired": "Назив флоте је обавезан", + "descriptionLabel": "Опис", + "descriptionPlaceholder": "Опциони опис", + "colorLabel": "Боја", + "tagRulesLabel": "Правила за ознаке", + "tagRulesPlaceholder": "prod-web, edge", + "tagRulesHint": "Домаћини са било којом од ових ознака се аутоматски укључују, поред домаћина додатих ручно.", + "fleetCreated": "Флота је створена", + "fleetUpdated": "Ажурирана флота", + "fleetDeleted": "Флота је обрисана", + "saveFailed": "Чување флоте није успело", + "deleteFailed": "Брисање флоте није успело", + "loadFailed": "Учитавање возних паркова није успело", + "deleteFleetTitle": "Обриши флоту", + "deleteFleetDescription": "Да ли сте сигурни да желите да обришете „{{name}}“? Овим се не бришу сами чланови хостови.", + "searchFleets": "Претражи флоте...", + "noFleets": "Још нема флота. Направите једну да бисте започели.", + "memberCount": "{{count}} домаћин", + "memberCount_other": "{{count}} домаћини", + "manageMembers": "Управљање члановима", + "manageMembersTitle": "Управљајте члановима флоте", + "manageMembersDescription": "Укључите или искључите хостове из статичког чланства ове флоте. Хостови који се подударају са правилима ознака су увек укључени.", + "searchHosts": "Претражи хостове...", + "noHostsFound": "Нису пронађени хостови", + "noMembers": "Ова флота још нема чланова. Додајте хостове или поставите правило за ознаке.", + "membersLoadFailed": "Учитавање чланова флоте није успело", + "memberUpdateFailed": "Ажурирање чланства у флоти није успело", + "tabRun": "Покрени команду", + "tabTransfer": "Пренос датотека", + "tabInventory": "Инвентар", + "openInventoryTab": "Отвори у целој картици", + "tabPackages": "Пакети", + "runOnFleet": "Трчи на флоти", + "commandPlaceholder": "време непрекидног рада && df -h", + "commandRequired": "Потребна је команда", + "commandInputsLabel": "Уноси команди", + "commandSucceeded": "Команда је успела на свим хостовима", + "commandPartialFailure": "{{failed}} од {{total}} хостова није успело", + "commandFailed": "Није успело покретање команде", + "resultSuccess": "Успех", + "resultFailed": "Неуспешно", + "push": "Гурај", + "pull": "Повуци", + "remotePathLabel": "Удаљена путања", + "remotePathRequired": "Потребна је удаљена путања", + "fileLabel": "Датотека", + "fileRequired": "Потребна је датотека", + "pushHint": "Изабрана датотека се уписује на ову тачну путању на сваком хосту у флоти.", + "pullHint": "Датотека на овој путањи се чита са сваког хоста и преузима као један zip фасцикла, једна фасцикла по хосту.", + "transferComplete": "Пренос завршен", + "transferFailed": "Пренос није успео", + "refreshInventory": "Освежи инвентар", + "inventoryLoadFailed": "Учитавање инвентара није успело", + "inventoryRefreshed": "Инвентар освежен", + "inventoryRefreshFailed": "Освежавање инвентара није успело", + "inventoryNoData": "Још нема података о залихама - освежите да бисте их прикупили.", + "inventoryHost": "Домаћин", + "inventoryCollectedCount": "{{count}}/{{total}} сакупљено", + "inventoryOs": "ОС", + "inventoryKernel": "Језгро", + "inventoryArch": "Лук", + "inventoryUptime": "Време непрекидног рада", + "inventoryPackageManager": "Менаџер пакета", + "inventoryCollectedAt": "Сакупљено", + "packageActionLabel": "Акција", + "packageInstall": "Инсталирај", + "packageRemove": "Уклони", + "packageUpgradeAll": "Надоградите све пакете", + "packageNameLabel": "Назив пакета", + "packageNameRequired": "Потребно је име пакета", + "packageHint": "Захтева приступ на нивоу управљања по хосту и подиже привилегије користећи сачувану sudo лозинку хоста." + } + } + }, + "nav": { + "fleets": "Флоте" + } +} diff --git a/plugins/fleets/locales/translated/sv_SE.json b/plugins/fleets/locales/translated/sv_SE.json new file mode 100644 index 000000000..5542f9ba3 --- /dev/null +++ b/plugins/fleets/locales/translated/sv_SE.json @@ -0,0 +1,89 @@ +{ + "newUi": { + "sidebar": { + "fleets": { + "title": "Flottor", + "createFleet": "Skapa flotta", + "createFleetTitle": "Skapa flotta", + "editFleetTitle": "Redigera flotta", + "createFleetDescription": "En flotta är en namngiven grupp av värdar som du kan köra åtgärder mot som en enhet.", + "nameLabel": "Namn", + "namePlaceholder": "t.ex. webbservrar", + "nameRequired": "Flottans namn krävs", + "descriptionLabel": "Beskrivning", + "descriptionPlaceholder": "Valfri beskrivning", + "colorLabel": "Färg", + "tagRulesLabel": "Taggregler", + "tagRulesPlaceholder": "prod-web, kant", + "tagRulesHint": "Värdar med någon av dessa taggar inkluderas automatiskt, utöver värdar som läggs till manuellt.", + "fleetCreated": "Flotta skapad", + "fleetUpdated": "Flottan uppdaterad", + "fleetDeleted": "Flottan raderad", + "saveFailed": "Misslyckades med att spara flottan", + "deleteFailed": "Misslyckades med att ta bort flottan", + "loadFailed": "Misslyckades med att ladda flottor", + "deleteFleetTitle": "Ta bort flotta", + "deleteFleetDescription": "Är du säker på att du vill ta bort \"{{name}}\"? Detta tar inte bort själva medlemsvärdarna.", + "searchFleets": "Sök flottor...", + "noFleets": "Inga flottor ännu. Skapa en för att komma igång.", + "memberCount": "{{count}} värd", + "memberCount_other": "{{count}} värdar", + "manageMembers": "Hantera medlemmar", + "manageMembersTitle": "Hantera flottmedlemmar", + "manageMembersDescription": "Växla mellan att visa eller avaktivera värdar i flottans statiska medlemskap. Värdar som matchas av taggregler inkluderas alltid.", + "searchHosts": "Sök värdar...", + "noHostsFound": "Inga värdar hittades", + "noMembers": "Den här flottan har inga medlemmar ännu. Lägg till värdar eller ange en taggregel.", + "membersLoadFailed": "Misslyckades med att ladda flottmedlemmar", + "memberUpdateFailed": "Misslyckades med att uppdatera flottmedlemskapet", + "tabRun": "Kör kommando", + "tabTransfer": "Överför filer", + "tabInventory": "Lager", + "openInventoryTab": "Öppna i hela fliken", + "tabPackages": "Paket", + "runOnFleet": "Kör på flottan", + "commandPlaceholder": "drifttid && df -h", + "commandRequired": "Ett kommando krävs", + "commandInputsLabel": "Kommandoingångar", + "commandSucceeded": "Kommandot lyckades på alla värdar", + "commandPartialFailure": "{{failed}} av {{total}} värdar misslyckades", + "commandFailed": "Misslyckades med att köra kommandot", + "resultSuccess": "Framgång", + "resultFailed": "Misslyckades", + "push": "Tryck", + "pull": "Dra", + "remotePathLabel": "Fjärrväg", + "remotePathRequired": "En fjärrsökväg krävs", + "fileLabel": "Fil", + "fileRequired": "En fil krävs", + "pushHint": "Den valda filen skrivs till exakt denna sökväg på varje värd i flottan.", + "pullHint": "Filen på den här sökvägen läses från varje värd och laddas ner som en enda zip-fil, en mapp per värd.", + "transferComplete": "Överföringen är klar", + "transferFailed": "Överföringen misslyckades", + "refreshInventory": "Uppdatera lagret", + "inventoryLoadFailed": "Misslyckades med att ladda lagret", + "inventoryRefreshed": "Inventariet uppdaterat", + "inventoryRefreshFailed": "Misslyckades med att uppdatera lagret", + "inventoryNoData": "Ingen lagerdata ännu – uppdatera för att samla in den.", + "inventoryHost": "Värd", + "inventoryCollectedCount": "{{count}}/{{total}} samlade", + "inventoryOs": "operativsystem", + "inventoryKernel": "Kärna", + "inventoryArch": "Båge", + "inventoryUptime": "Drifttid", + "inventoryPackageManager": "Pakethanterare", + "inventoryCollectedAt": "Insamlad", + "packageActionLabel": "Handling", + "packageInstall": "Installera", + "packageRemove": "Ta bort", + "packageUpgradeAll": "Uppgradera alla paket", + "packageNameLabel": "Paketnamn", + "packageNameRequired": "Ett paketnamn krävs", + "packageHint": "Kräver åtkomst på hanteringsnivå per värd och höjs med hjälp av värdens lagrade sudo-lösenord." + } + } + }, + "nav": { + "fleets": "Flottor" + } +} diff --git a/plugins/fleets/locales/translated/th_TH.json b/plugins/fleets/locales/translated/th_TH.json new file mode 100644 index 000000000..6171c8f9d --- /dev/null +++ b/plugins/fleets/locales/translated/th_TH.json @@ -0,0 +1,89 @@ +{ + "newUi": { + "sidebar": { + "fleets": { + "title": "กองเรือ", + "createFleet": "สร้างกลุ่มยานพาหนะ", + "createFleetTitle": "สร้างกลุ่มยานพาหนะ", + "editFleetTitle": "แก้ไขข้อมูลกองเรือ", + "createFleetDescription": "กลุ่มโฮสต์ (Fleet) คือกลุ่มของโฮสต์ที่มีชื่อ ซึ่งคุณสามารถเรียกใช้คำสั่งต่างๆ กับกลุ่มนั้นได้ในฐานะหน่วยเดียวกัน", + "nameLabel": "ชื่อ", + "namePlaceholder": "เช่น เว็บเซิร์ฟเวอร์", + "nameRequired": "ต้องระบุชื่อกองเรือ", + "descriptionLabel": "คำอธิบาย", + "descriptionPlaceholder": "คำอธิบายเพิ่มเติม (ไม่บังคับ)", + "colorLabel": "สี", + "tagRulesLabel": "กฎการติดแท็ก", + "tagRulesPlaceholder": "โปรด-เว็บ, เอดจ์", + "tagRulesHint": "โฮสต์ที่มีแท็กใดแท็กหนึ่งเหล่านี้จะถูกรวมไว้โดยอัตโนมัติ นอกเหนือจากโฮสต์ที่เพิ่มเข้ามาด้วยตนเอง", + "fleetCreated": "กองเรือสร้าง", + "fleetUpdated": "อัปเดตฝูงบินแล้ว", + "fleetDeleted": "กองเรือถูกลบ", + "saveFailed": "ไม่สามารถช่วยกองเรือได้", + "deleteFailed": "ไม่สามารถลบกลุ่มยานพาหนะได้", + "loadFailed": "ไม่สามารถโหลดข้อมูลยานพาหนะได้", + "deleteFleetTitle": "ลบกลุ่มยานพาหนะ", + "deleteFleetDescription": "คุณแน่ใจหรือไม่ว่าต้องการลบ \"{{name}}\"? การดำเนินการนี้ไม่ได้ลบโฮสต์สมาชิกเอง", + "searchFleets": "ค้นหากองเรือ...", + "noFleets": "ยังไม่มีกลุ่มเรือ สร้างกลุ่มเรือเพื่อเริ่มต้นใช้งานได้เลย", + "memberCount": "{{count}} โฮสต์", + "memberCount_other": "{{count}} โฮสต์", + "manageMembers": "จัดการสมาชิก", + "manageMembersTitle": "จัดการสมาชิกกลุ่มยานพาหนะ", + "manageMembersDescription": "สลับการเพิ่มหรือลบโฮสต์ออกจากการเป็นสมาชิกแบบคงที่ของกลุ่มโฮสต์นี้ โฮสต์ที่ตรงกับกฎแท็กจะถูกรวมอยู่เสมอ", + "searchHosts": "ค้นหาโฮสต์...", + "noHostsFound": "ไม่พบโฮสต์", + "noMembers": "กลุ่มเรือนี้ยังไม่มีสมาชิก เพิ่มโฮสต์หรือตั้งค่ากฎแท็ก", + "membersLoadFailed": "ไม่สามารถโหลดสมาชิกกองเรือได้", + "memberUpdateFailed": "ไม่สามารถอัปเดตข้อมูลสมาชิกกลุ่มยานพาหนะได้", + "tabRun": "เรียกใช้คำสั่ง", + "tabTransfer": "โอนไฟล์", + "tabInventory": "รายการสิ่งของ", + "openInventoryTab": "เปิดในแท็บเต็ม", + "tabPackages": "แพ็คเกจ", + "runOnFleet": "วิ่งบนกองเรือ", + "commandPlaceholder": "uptime && df -h", + "commandRequired": "จำเป็นต้องมีคำสั่ง", + "commandInputsLabel": "อินพุตคำสั่ง", + "commandSucceeded": "คำสั่งทำงานสำเร็จบนโฮสต์ทั้งหมด", + "commandPartialFailure": "โฮสต์ {{failed}} ล้มเหลว {{total}}", + "commandFailed": "ไม่สามารถเรียกใช้คำสั่งได้", + "resultSuccess": "ความสำเร็จ", + "resultFailed": "ล้มเหลว", + "push": "ดัน", + "pull": "ดึง", + "remotePathLabel": "เส้นทางระยะไกล", + "remotePathRequired": "จำเป็นต้องใช้เส้นทางระยะไกล", + "fileLabel": "ไฟล์", + "fileRequired": "จำเป็นต้องมีไฟล์", + "pushHint": "ไฟล์ที่เลือกจะถูกเขียนไปยังพาธที่ระบุไว้นี้บนทุกเครื่องในระบบเครือข่าย", + "pullHint": "ไฟล์ที่อยู่ในพาธนี้จะถูกอ่านจากทุกโฮสต์และดาวน์โหลดเป็นไฟล์ซิปเดียว โดยมีหนึ่งโฟลเดอร์ต่อหนึ่งโฮสต์", + "transferComplete": "การโอนเสร็จสมบูรณ์", + "transferFailed": "การโอนล้มเหลว", + "refreshInventory": "รีเฟรชสินค้าคงคลัง", + "inventoryLoadFailed": "ไม่สามารถโหลดสินค้าคงคลังได้", + "inventoryRefreshed": "อัปเดตสินค้าคงคลังแล้ว", + "inventoryRefreshFailed": "ไม่สามารถรีเฟรชสินค้าคงคลังได้", + "inventoryNoData": "ยังไม่มีข้อมูลสินค้าคงคลัง โปรดรีเฟรชหน้าเว็บเพื่อดูข้อมูล", + "inventoryHost": "เจ้าภาพ", + "inventoryCollectedCount": "{{count}}/{{total}} รวบรวมแล้ว", + "inventoryOs": "โอเอส", + "inventoryKernel": "เคอร์เนล", + "inventoryArch": "โค้ง", + "inventoryUptime": "เวลาใช้งาน", + "inventoryPackageManager": "ตัวจัดการแพ็กเกจ", + "inventoryCollectedAt": "รวบรวม", + "packageActionLabel": "การกระทำ", + "packageInstall": "ติดตั้ง", + "packageRemove": "ลบ", + "packageUpgradeAll": "อัปเกรดแพ็กเกจทั้งหมด", + "packageNameLabel": "ชื่อแพ็คเกจ", + "packageNameRequired": "จำเป็นต้องระบุชื่อแพ็กเกจ", + "packageHint": "ต้องมีสิทธิ์การเข้าถึงระดับจัดการต่อโฮสต์ และยกระดับสิทธิ์โดยใช้รหัสผ่าน sudo ที่บันทึกไว้ของโฮสต์" + } + } + }, + "nav": { + "fleets": "กองเรือ" + } +} diff --git a/plugins/fleets/locales/translated/tr_TR.json b/plugins/fleets/locales/translated/tr_TR.json new file mode 100644 index 000000000..c9be967cc --- /dev/null +++ b/plugins/fleets/locales/translated/tr_TR.json @@ -0,0 +1,89 @@ +{ + "newUi": { + "sidebar": { + "fleets": { + "title": "Filolar", + "createFleet": "Filo Oluştur", + "createFleetTitle": "Filo Oluştur", + "editFleetTitle": "Filoyu Düzenle", + "createFleetDescription": "Filo, birim olarak eylemler gerçekleştirebileceğiniz, adlandırılmış bir sunucu grubudur.", + "nameLabel": "İsim", + "namePlaceholder": "Örneğin, Web Sunucuları", + "nameRequired": "Filo adı zorunludur.", + "descriptionLabel": "Tanım", + "descriptionPlaceholder": "İsteğe bağlı açıklama", + "colorLabel": "Renk", + "tagRulesLabel": "Etiket kuralları", + "tagRulesPlaceholder": "prod-web, edge", + "tagRulesHint": "Bu etiketlerden herhangi birine sahip sunucular, manuel olarak eklenen sunuculara ek olarak otomatik olarak dahil edilir.", + "fleetCreated": "Filo oluşturuldu", + "fleetUpdated": "Filo güncellendi", + "fleetDeleted": "Filo silindi", + "saveFailed": "Filoyu kurtaramadık", + "deleteFailed": "Filoyu silme işlemi başarısız oldu.", + "loadFailed": "Filoların yüklenmesi başarısız oldu.", + "deleteFleetTitle": "Filoyu Sil", + "deleteFleetDescription": "\"{{name}}\" öğesini silmek istediğinizden emin misiniz? Bu işlem üye sunucuların kendilerini silmez.", + "searchFleets": "Filoları arayın...", + "noFleets": "Henüz filo yok. Başlamak için bir tane oluşturun.", + "memberCount": "{{count}} sunucu", + "memberCount_other": "{{count}} sunucular", + "manageMembers": "Üyeleri Yönet", + "manageMembersTitle": "Filo Üyelerini Yönetin", + "manageMembersDescription": "Sunucuları bu filonun statik üyeliğine dahil edin veya çıkarın. Etiket kurallarına göre eşleşen sunucular her zaman dahil edilir.", + "searchHosts": "Sunucu ara...", + "noHostsFound": "Hiçbir sunucu bulunamadı.", + "noMembers": "Bu filonun henüz üyesi yok. Sunucu ekleyin veya etiket kuralı belirleyin.", + "membersLoadFailed": "Filo üyeleri yüklenemedi.", + "memberUpdateFailed": "Filo üyeliği güncellenemedi.", + "tabRun": "Komutu Çalıştır", + "tabTransfer": "Dosya Aktarımı", + "tabInventory": "Envanter", + "openInventoryTab": "Tam sekmede aç", + "tabPackages": "Paketler", + "runOnFleet": "Filoda Çalıştır", + "commandPlaceholder": "çalışma süresi && df -h", + "commandRequired": "Bir komut gereklidir.", + "commandInputsLabel": "Komut girişleri", + "commandSucceeded": "Komut tüm sunucularda başarıyla tamamlandı.", + "commandPartialFailure": "{{failed}} / {{total}} sunucu başarısız oldu", + "commandFailed": "Komut çalıştırma başarısız oldu.", + "resultSuccess": "Başarı", + "resultFailed": "Arızalı", + "push": "İtmek", + "pull": "Çekmek", + "remotePathLabel": "Uzak yol", + "remotePathRequired": "Uzak bir yol gereklidir.", + "fileLabel": "Dosya", + "fileRequired": "Bir dosya gereklidir.", + "pushHint": "Seçilen dosya, filodaki her sunucuda tam olarak bu yola yazılır.", + "pullHint": "Bu yoldaki dosya her sunucudan okunur ve her sunucu için bir klasör olmak üzere tek bir zip dosyası olarak indirilir.", + "transferComplete": "Transfer tamamlandı", + "transferFailed": "Aktarım başarısız oldu", + "refreshInventory": "Envanteri Yenile", + "inventoryLoadFailed": "Envanter yüklenemedi.", + "inventoryRefreshed": "Stok güncellendi", + "inventoryRefreshFailed": "Envanter yenileme işlemi başarısız oldu.", + "inventoryNoData": "Henüz envanter verisi yok - verileri toplamak için sayfayı yenileyin.", + "inventoryHost": "Ev sahibi", + "inventoryCollectedCount": "{{count}}/{{total}} toplandı", + "inventoryOs": "İşletim sistemi", + "inventoryKernel": "Çekirdek", + "inventoryArch": "Kemer", + "inventoryUptime": "Çalışma süresi", + "inventoryPackageManager": "Paket yöneticisi", + "inventoryCollectedAt": "Toplandı", + "packageActionLabel": "Aksiyon", + "packageInstall": "Düzenlemek", + "packageRemove": "Kaldırmak", + "packageUpgradeAll": "Tüm paketleri yükseltin", + "packageNameLabel": "Paket adı", + "packageNameRequired": "Paket adı gereklidir.", + "packageHint": "Her sunucu için yönetim düzeyinde erişim gerektirir ve sunucunun kayıtlı sudo şifresi kullanılarak yetki yükseltilir." + } + } + }, + "nav": { + "fleets": "Filolar" + } +} diff --git a/plugins/fleets/locales/translated/uk_UA.json b/plugins/fleets/locales/translated/uk_UA.json new file mode 100644 index 000000000..8f49109bb --- /dev/null +++ b/plugins/fleets/locales/translated/uk_UA.json @@ -0,0 +1,89 @@ +{ + "newUi": { + "sidebar": { + "fleets": { + "title": "Флоти", + "createFleet": "Створити флот", + "createFleetTitle": "Створити флот", + "editFleetTitle": "Редагувати флот", + "createFleetDescription": "Флот — це іменована група хостів, проти яких можна виконувати дії як проти єдиного цілого.", + "nameLabel": "Ім'я", + "namePlaceholder": "наприклад, веб-сервери", + "nameRequired": "Потрібно вказати назву флоту", + "descriptionLabel": "Опис", + "descriptionPlaceholder": "Додатковий опис", + "colorLabel": "Колір", + "tagRulesLabel": "Правила тегів", + "tagRulesPlaceholder": "prod-web, край", + "tagRulesHint": "Хости з будь-яким із цих тегів додаються автоматично, окрім хостів, доданих вручну.", + "fleetCreated": "Створено флот", + "fleetUpdated": "Оновлено автопарк", + "fleetDeleted": "Флот видалено", + "saveFailed": "Не вдалося зберегти флот", + "deleteFailed": "Не вдалося видалити автопарк", + "loadFailed": "Не вдалося завантажити автопарки", + "deleteFleetTitle": "Видалити автопарк", + "deleteFleetDescription": "Ви впевнені, що хочете видалити \"{{name}}\"? Це не видаляє самі хости-учасники.", + "searchFleets": "Пошук автопарків...", + "noFleets": "Поки що немає автопарків. Створіть його, щоб розпочати.", + "memberCount": "{{count}} хост", + "memberCount_other": "{{count}} хости", + "manageMembers": "Керування учасниками", + "manageMembersTitle": "Керування членами автопарку", + "manageMembersDescription": "Вмикати або вимикати хости зі списку статичного членства цього флоту. Хости, що відповідають правилам тегів, завжди враховуються.", + "searchHosts": "Пошук хостів...", + "noHostsFound": "Хости не знайдено", + "noMembers": "Цей флот ще не має учасників. Додайте хостів або встановіть правило тегу.", + "membersLoadFailed": "Не вдалося завантажити учасників автопарку", + "memberUpdateFailed": "Не вдалося оновити членство в автопарку", + "tabRun": "Виконати команду", + "tabTransfer": "Передача файлів", + "tabInventory": "Інвентаризація", + "openInventoryTab": "Відкрити у повній вкладці", + "tabPackages": "Пакети", + "runOnFleet": "Запустити флот", + "commandPlaceholder": "час безперебійної роботи && df -h", + "commandRequired": "Потрібна команда", + "commandInputsLabel": "Вхідні команди", + "commandSucceeded": "Команда успішно виконана на всіх хостах", + "commandPartialFailure": "{{failed}} з {{total}} хостів не вдалося", + "commandFailed": "Не вдалося виконати команду", + "resultSuccess": "Успіх", + "resultFailed": "Не вдалося", + "push": "Натисніть", + "pull": "Тягнути", + "remotePathLabel": "Віддалений шлях", + "remotePathRequired": "Потрібен віддалений шлях", + "fileLabel": "Файл", + "fileRequired": "Потрібен файл", + "pushHint": "Вибраний файл записується саме за цим шляхом на кожному хості парку.", + "pullHint": "Файл за цим шляхом зчитується з кожного хоста та завантажується як один zip-архів, одна папка на хост.", + "transferComplete": "Перенесення завершено", + "transferFailed": "Передача не вдалася", + "refreshInventory": "Оновити інвентар", + "inventoryLoadFailed": "Не вдалося завантажити інвентар", + "inventoryRefreshed": "Інвентар оновлено", + "inventoryRefreshFailed": "Не вдалося оновити інвентар", + "inventoryNoData": "Даних про інвентаризацію ще немає – оновіть сторінку, щоб зібрати їх.", + "inventoryHost": "Хост", + "inventoryCollectedCount": "{{count}}/{{total}} зібрано", + "inventoryOs": "ОС", + "inventoryKernel": "Ядро", + "inventoryArch": "Арка", + "inventoryUptime": "Час безперебійної роботи", + "inventoryPackageManager": "Менеджер пакетів", + "inventoryCollectedAt": "Зібрано", + "packageActionLabel": "Дія", + "packageInstall": "Встановити", + "packageRemove": "Видалити", + "packageUpgradeAll": "Оновіть усі пакети", + "packageNameLabel": "Назва пакета", + "packageNameRequired": "Потрібна назва пакета", + "packageHint": "Потрібен доступ на рівні керування для кожного хоста та підвищення прав за допомогою збереженого пароля sudo хоста." + } + } + }, + "nav": { + "fleets": "Флоти" + } +} diff --git a/plugins/fleets/locales/translated/vi_VN.json b/plugins/fleets/locales/translated/vi_VN.json new file mode 100644 index 000000000..072a6eb42 --- /dev/null +++ b/plugins/fleets/locales/translated/vi_VN.json @@ -0,0 +1,89 @@ +{ + "newUi": { + "sidebar": { + "fleets": { + "title": "Hạm đội", + "createFleet": "Tạo đội tàu", + "createFleetTitle": "Tạo đội tàu", + "editFleetTitle": "Chỉnh sửa đội xe", + "createFleetDescription": "Hạm đội là một nhóm máy chủ được đặt tên mà bạn có thể thực hiện các hành động chống lại chúng như một đơn vị.", + "nameLabel": "Tên", + "namePlaceholder": "Ví dụ: Máy chủ web", + "nameRequired": "Tên đội xe là bắt buộc", + "descriptionLabel": "Sự miêu tả", + "descriptionPlaceholder": "Mô tả tùy chọn", + "colorLabel": "Màu sắc", + "tagRulesLabel": "Quy tắc gắn thẻ", + "tagRulesPlaceholder": "web sản xuất, cạnh", + "tagRulesHint": "Các máy chủ có bất kỳ thẻ nào trong số này sẽ tự động được thêm vào, bên cạnh các máy chủ được thêm thủ công.", + "fleetCreated": "Hạm đội đã tạo ra", + "fleetUpdated": "Đội tàu được cập nhật", + "fleetDeleted": "Hạm đội đã bị xóa", + "saveFailed": "Không thể cứu hạm đội.", + "deleteFailed": "Không thể xóa đội tàu", + "loadFailed": "Không thể tải đội xe", + "deleteFleetTitle": "Xóa hạm đội", + "deleteFleetDescription": "Bạn có chắc chắn muốn xóa \"{{name}}\" không? Thao tác này không xóa các máy chủ thành viên.", + "searchFleets": "Các hạm đội tìm kiếm...", + "noFleets": "Chưa có hạm đội nào. Hãy tạo một hạm đội để bắt đầu.", + "memberCount": "{{count}} máy chủ", + "memberCount_other": "{{count}} máy chủ", + "manageMembers": "Quản lý thành viên", + "manageMembersTitle": "Quản lý thành viên đội xe", + "manageMembersDescription": "Cho phép thêm hoặc xóa các máy chủ khỏi tư cách thành viên cố định của nhóm này. Các máy chủ phù hợp với quy tắc gắn thẻ luôn được bao gồm.", + "searchHosts": "Tìm kiếm máy chủ...", + "noHostsFound": "Không tìm thấy máy chủ nào", + "noMembers": "Hạm đội này chưa có thành viên nào. Thêm máy chủ hoặc thiết lập quy tắc gắn thẻ.", + "membersLoadFailed": "Không thể tải thông tin thành viên đội xe", + "memberUpdateFailed": "Không thể cập nhật thông tin thành viên đội tàu", + "tabRun": "Chạy lệnh", + "tabTransfer": "Chuyển tập tin", + "tabInventory": "Hàng tồn kho", + "openInventoryTab": "Mở ở chế độ toàn màn hình", + "tabPackages": "Gói hàng", + "runOnFleet": "Chạy trên Fleet", + "commandPlaceholder": "thời gian hoạt động && df -h", + "commandRequired": "Cần có lệnh", + "commandInputsLabel": "Đầu vào lệnh", + "commandSucceeded": "Lệnh đã được thực thi thành công trên tất cả các máy chủ.", + "commandPartialFailure": "{{failed}} trong số {{total}} máy chủ đã bị lỗi", + "commandFailed": "Không thể chạy lệnh.", + "resultSuccess": "Thành công", + "resultFailed": "Thất bại", + "push": "Xô", + "pull": "Sự lôi kéo", + "remotePathLabel": "Đường dẫn từ xa", + "remotePathRequired": "Cần có một đường dẫn từ xa.", + "fileLabel": "Tài liệu", + "fileRequired": "Cần có một tập tin.", + "pushHint": "Tệp đã chọn sẽ được ghi vào đúng đường dẫn này trên mọi máy chủ trong hệ thống.", + "pullHint": "Tệp tại đường dẫn này được đọc từ mọi máy chủ và tải xuống dưới dạng một tệp zip duy nhất, mỗi máy chủ một thư mục.", + "transferComplete": "Giao dịch hoàn tất", + "transferFailed": "Giao dịch chuyển khoản thất bại", + "refreshInventory": "Làm mới kho hàng", + "inventoryLoadFailed": "Không thể tải kho hàng", + "inventoryRefreshed": "Hàng tồn kho được cập nhật", + "inventoryRefreshFailed": "Không thể làm mới kho hàng", + "inventoryNoData": "Chưa có dữ liệu tồn kho - hãy làm mới trang để thu thập dữ liệu.", + "inventoryHost": "Chủ nhà", + "inventoryCollectedCount": "{{count}}/{{total}} đã thu thập", + "inventoryOs": "Hệ điều hành", + "inventoryKernel": "Hạt nhân", + "inventoryArch": "Vòm", + "inventoryUptime": "Thời gian hoạt động", + "inventoryPackageManager": "Trình quản lý gói", + "inventoryCollectedAt": "Đã thu thập", + "packageActionLabel": "Hoạt động", + "packageInstall": "Cài đặt", + "packageRemove": "Di dời", + "packageUpgradeAll": "Nâng cấp tất cả các gói", + "packageNameLabel": "Tên gói", + "packageNameRequired": "Cần phải có tên gói.", + "packageHint": "Yêu cầu quyền truy cập cấp quản trị cho mỗi máy chủ và nâng quyền bằng mật khẩu sudo được lưu trữ trên máy chủ đó." + } + } + }, + "nav": { + "fleets": "Hạm đội" + } +} diff --git a/plugins/fleets/locales/translated/zh_CN.json b/plugins/fleets/locales/translated/zh_CN.json new file mode 100644 index 000000000..c4968c954 --- /dev/null +++ b/plugins/fleets/locales/translated/zh_CN.json @@ -0,0 +1,89 @@ +{ + "newUi": { + "sidebar": { + "fleets": { + "title": "舰队", + "createFleet": "创建舰队", + "createFleetTitle": "创建舰队", + "editFleetTitle": "编辑舰队", + "createFleetDescription": "舰队是一个命名的主机组,你可以将其作为一个整体来执行操作。", + "nameLabel": "名称", + "namePlaceholder": "例如:Web 服务器", + "nameRequired": "需要填写舰队名称。", + "descriptionLabel": "描述", + "descriptionPlaceholder": "可选描述", + "colorLabel": "颜色", + "tagRulesLabel": "标签规则", + "tagRulesPlaceholder": "prod-web, edge", + "tagRulesHint": "带有这些标签的主机将自动包含在内,此外还可以手动添加主机。", + "fleetCreated": "舰队已创建", + "fleetUpdated": "舰队已更新", + "fleetDeleted": "舰队已删除", + "saveFailed": "保存舰队失败", + "deleteFailed": "删除舰队失败", + "loadFailed": "舰队加载失败", + "deleteFleetTitle": "删除舰队", + "deleteFleetDescription": "您确定要删除“{{name}}”吗?此操作不会删除成员主机本身。", + "searchFleets": "搜索舰队……", + "noFleets": "暂无舰队。创建舰队即可开始。", + "memberCount": "{{count}} 台主机", + "memberCount_other": "{{count}} 台主机", + "manageMembers": "管理成员", + "manageMembersTitle": "管理舰队成员", + "manageMembersDescription": "切换主机是否加入此舰队的静态成员列表。符合标签规则的主机始终包含在内。", + "searchHosts": "搜索主机...", + "noHostsFound": "未找到主机", + "noMembers": "此舰队目前尚无成员。请添加主机或设置标签规则。", + "membersLoadFailed": "加载舰队成员失败", + "memberUpdateFailed": "舰队成员信息更新失败", + "tabRun": "运行命令", + "tabTransfer": "传输文件", + "tabInventory": "清单", + "openInventoryTab": "在新标签页中打开", + "tabPackages": "软件包", + "runOnFleet": "在舰队上运行", + "commandPlaceholder": "uptime && df -h", + "commandRequired": "需要一条命令", + "commandInputsLabel": "命令输入", + "commandSucceeded": "命令在所有主机上均已成功执行。", + "commandPartialFailure": "{{total}} 台主机中有 {{failed}} 台失败", + "commandFailed": "命令运行失败", + "resultSuccess": "成功", + "resultFailed": "失败的", + "push": "推送", + "pull": "拉取", + "remotePathLabel": "远程路径", + "remotePathRequired": "需要远程路径", + "fileLabel": "文件", + "fileRequired": "需要选择文件", + "pushHint": "选定的文件将被写入舰队中每台主机上的指定路径。", + "pullHint": "从每个主机读取此路径下的文件,并将其下载为单个 zip 文件,每个主机一个文件夹。", + "transferComplete": "传输完成", + "transferFailed": "传输失败", + "refreshInventory": "刷新清单", + "inventoryLoadFailed": "加载清单失败", + "inventoryRefreshed": "清单已刷新", + "inventoryRefreshFailed": "刷新清单失败", + "inventoryNoData": "暂无清单数据 - 请刷新页面以获取数据。", + "inventoryHost": "主机", + "inventoryCollectedCount": "已收集 {{count}}/{{total}}", + "inventoryOs": "操作系统", + "inventoryKernel": "内核", + "inventoryArch": "架构", + "inventoryUptime": "运行时间", + "inventoryPackageManager": "软件包管理器", + "inventoryCollectedAt": "集", + "packageActionLabel": "行动", + "packageInstall": "安装", + "packageRemove": "移除", + "packageUpgradeAll": "升级所有软件包", + "packageNameLabel": "软件包名称", + "packageNameRequired": "必须提供软件包名称。", + "packageHint": "需要对每台主机具有管理级别的访问权限,并使用主机存储的 sudo 密码提升权限。" + } + } + }, + "nav": { + "fleets": "舰队" + } +} diff --git a/plugins/fleets/locales/translated/zh_TW.json b/plugins/fleets/locales/translated/zh_TW.json new file mode 100644 index 000000000..34e2bd7bc --- /dev/null +++ b/plugins/fleets/locales/translated/zh_TW.json @@ -0,0 +1,89 @@ +{ + "newUi": { + "sidebar": { + "fleets": { + "title": "艦隊", + "createFleet": "創建艦隊", + "createFleetTitle": "創建艦隊", + "editFleetTitle": "編輯艦隊", + "createFleetDescription": "艦隊是指你可以作為一個整體對一組主機執行操作的指定名稱的主機群組。", + "nameLabel": "姓名", + "namePlaceholder": "例如,Web伺服器", + "nameRequired": "必須填寫艦隊名稱。", + "descriptionLabel": "描述", + "descriptionPlaceholder": "選用描述", + "colorLabel": "顏色", + "tagRulesLabel": "標籤規則", + "tagRulesPlaceholder": "生產網絡,邊緣", + "tagRulesHint": "帶有這些標籤的主機將自動包含在內,此外還可以手動新增主機。", + "fleetCreated": "艦隊創建", + "fleetUpdated": "艦隊更新", + "fleetDeleted": "艦隊已刪除", + "saveFailed": "未能拯救艦隊", + "deleteFailed": "刪除艦隊失敗", + "loadFailed": "艦隊載入失敗", + "deleteFleetTitle": "刪除艦隊", + "deleteFleetDescription": "您確定要刪除“{{name}}”嗎?此操作不會刪除成員主機本身。", + "searchFleets": "搜索艦隊…", + "noFleets": "暫無艦隊。創建艦隊即可開始。", + "memberCount": "{{count}} 主機", + "memberCount_other": "{{count}} 主機", + "manageMembers": "管理成員", + "manageMembersTitle": "管理車隊成員", + "manageMembersDescription": "切換主機是否加入此艦隊的靜態成員清單。符合標籤規則的主機始終包含在內。", + "searchHosts": "搜尋主機...", + "noHostsFound": "未找到主機", + "noMembers": "此艦隊目前尚無成員。請新增主機或設定標籤規則。", + "membersLoadFailed": "載入艦隊成員失敗", + "memberUpdateFailed": "艦隊成員資訊更新失敗", + "tabRun": "運行命令", + "tabTransfer": "傳輸檔案", + "tabInventory": "存貨", + "openInventoryTab": "在新分頁中開啟", + "tabPackages": "包裹", + "runOnFleet": "艦隊運行", + "commandPlaceholder": "uptime && df -h", + "commandRequired": "需要一條命令", + "commandInputsLabel": "命令輸入", + "commandSucceeded": "指令在所有主機上均已成功執行。", + "commandPartialFailure": "{{failed}} 中的 {{total}} 台主機失敗", + "commandFailed": "命令運行失敗", + "resultSuccess": "成功", + "resultFailed": "失敗的", + "push": "推", + "pull": "拉", + "remotePathLabel": "遠端路徑", + "remotePathRequired": "需要遠端路徑", + "fileLabel": "文件", + "fileRequired": "需要提交文件", + "pushHint": "選定的檔案將被寫入叢集中每台主機上的指定路徑。", + "pullHint": "從每個主機讀取此路徑下的文件,並將其下載為單一 zip 文件,每個主機一個資料夾。", + "transferComplete": "轉帳完成", + "transferFailed": "轉帳失敗", + "refreshInventory": "刷新庫存", + "inventoryLoadFailed": "庫存載入失敗", + "inventoryRefreshed": "庫存已刷新", + "inventoryRefreshFailed": "刷新庫存失敗", + "inventoryNoData": "暫無庫存資料 - 請重新整理頁面以取得資料。", + "inventoryHost": "主持人", + "inventoryCollectedCount": "{{count}}/{{total}} 收集", + "inventoryOs": "作業系統", + "inventoryKernel": "核心", + "inventoryArch": "拱", + "inventoryUptime": "正常運作時間", + "inventoryPackageManager": "軟體套件管理器", + "inventoryCollectedAt": "集", + "packageActionLabel": "行動", + "packageInstall": "安裝", + "packageRemove": "消除", + "packageUpgradeAll": "升級所有套餐", + "packageNameLabel": "軟體包名稱", + "packageNameRequired": "必須提供軟體包名稱。", + "packageHint": "需要對每台主機具有管理層級的存取權限,並使用主機儲存的 sudo 密碼提升權限。" + } + } + }, + "nav": { + "fleets": "艦隊" + } +} diff --git a/plugins/fleets/manifest.json b/plugins/fleets/manifest.json index 55c4005f7..a4d831057 100644 --- a/plugins/fleets/manifest.json +++ b/plugins/fleets/manifest.json @@ -23,5 +23,22 @@ "ui:surface" ], "locales": "locales", - "platforms": ["linux", "win32", "darwin"] + "platforms": ["linux", "win32", "darwin"], + "contributes": { + "tabs": [ + { + "id": "fleet-inventory", + "titleKey": "nav.fleets", + "icon": "Boxes", + "openFrom": ["rail"] + } + ], + "panels": [ + { + "id": "fleets", + "titleKey": "nav.fleets", + "icon": "Boxes" + } + ] + } } diff --git a/plugins/fleets/src/frontend/FleetInventoryTab.tsx b/plugins/fleets/src/frontend/FleetInventoryTab.tsx index c16641447..b3009c72d 100644 --- a/plugins/fleets/src/frontend/FleetInventoryTab.tsx +++ b/plugins/fleets/src/frontend/FleetInventoryTab.tsx @@ -1,6 +1,6 @@ import { getErrorMessage } from "@/lib/error-message.js"; import { useEffect, useMemo, useState, useCallback } from "react"; -import { useTranslation } from "react-i18next"; +import { useTranslation } from "@termix/plugin-sdk/frontend"; import { toast } from "sonner"; import { ArrowDown, @@ -20,7 +20,7 @@ import { refreshFleetInventory, type FleetRow, type FleetInventoryEntry, -} from "@/api/fleets-api"; +} from "./fleets-api"; type SortKey = | "hostName" diff --git a/plugins/fleets/src/frontend/FleetsPanel.tsx b/plugins/fleets/src/frontend/FleetsPanel.tsx index 3aa07545b..af3ca0ee9 100644 --- a/plugins/fleets/src/frontend/FleetsPanel.tsx +++ b/plugins/fleets/src/frontend/FleetsPanel.tsx @@ -1,6 +1,6 @@ import { getErrorMessage } from "@/lib/error-message.js"; import { useState, useEffect, useCallback, useMemo, useRef } from "react"; -import { useTranslation } from "react-i18next"; +import { useTranslation } from "@termix/plugin-sdk/frontend"; import { toast } from "sonner"; import { Boxes, @@ -76,7 +76,7 @@ import { type FleetInventoryEntry, type FleetPackageAction, type FleetShareHostResult, -} from "@/api/fleets-api"; +} from "./fleets-api"; import type { SSHHost } from "@/types/index"; const SHARE_PERMISSION_LEVELS: SharePermissionLevel[] = [ diff --git a/src/ui/api/fleets-api.ts b/plugins/fleets/src/frontend/fleets-api.ts similarity index 100% rename from src/ui/api/fleets-api.ts rename to plugins/fleets/src/frontend/fleets-api.ts diff --git a/plugins/fleets/src/frontend/index.mjs b/plugins/fleets/src/frontend/index.mjs deleted file mode 100644 index 945fa4da1..000000000 --- a/plugins/fleets/src/frontend/index.mjs +++ /dev/null @@ -1,40 +0,0 @@ -/** - * Frontend half of the fleets plugin. - * - * FleetsPanel is a left-sidebar railView panel (opened from the rail, not a - * Tab), the same shape as HostsPanel/CredentialsPanel/AiPanel. None of those - * go through registerRailItem/registerTabComponent either -- per - * src/ui/shell/pluginLoader.ts's own comment, a rail-view panel like this is - * rendered directly by AppShell.tsx rather than registered at runtime, the - * same way ai's AiPanel is. FleetsPanel is reached today through a direct - * relative import in AppShell.tsx (../../plugins/fleets/frontend/FleetsPanel), - * not through register() below. - * - * register()/unregister() still follow the same shape every other plugin's - * frontend entry does, so this is ready the moment a real frontend plugin - * loader exists -- see plugins/ssh-terminal/frontend/index.mjs and - * src/ui/tests/sidebar/plugin-extension-seam.test.tsx, which says outright - * "there is no plugin loader yet". - * - * The fleet-inventory tab (opened from within FleetsPanel) is wired - * separately in src/ui/shell/tabUtils.tsx, the same way docker/host-metrics - * tabs are -- a plugin tab id that already exists in the built-in TabType - * union goes through the ordinary tabSurfaceLoaders/switch wiring there, not - * through registerTabComponent (which is for tab ids outside that union). - */ - -export const id = "fleets"; -export const railViewId = "fleets"; - -export async function register({ registerRailItem, icons }) { - registerRailItem?.({ - id: railViewId, - icon: icons.Boxes, - labelKey: "nav.fleets", - separatorAfter: true, - }); -} - -export async function unregister({ unregisterRailItem }) { - unregisterRailItem?.(railViewId); -} diff --git a/plugins/fleets/src/frontend/index.tsx b/plugins/fleets/src/frontend/index.tsx new file mode 100644 index 000000000..44314b249 --- /dev/null +++ b/plugins/fleets/src/frontend/index.tsx @@ -0,0 +1,55 @@ +import { Boxes } from "lucide-react"; +import type { + PanelProps, + TabProps, + TermixApp, +} from "@termix/plugin-sdk/frontend"; +import { FleetsPanel } from "./FleetsPanel"; +import { FleetInventoryTab } from "./FleetInventoryTab"; +import { listFleets } from "./fleets-api"; + +const INVENTORY_TAB = "fleet-inventory"; + +function Panel({ active, shell }: PanelProps) { + return ( + + shell.openSingletonTab(INVENTORY_TAB, { data: { fleetId } }) + } + /> + ); +} + +function InventoryTab({ tab, isVisible }: TabProps) { + const fleetId = tab.data?.fleetId; + return ( + + ); +} + +export function activate(app: TermixApp): void { + app.registerRailItem({ + id: "fleets", + icon: Boxes, + titleKey: "nav.fleets", + after: "macros", + order: 10, + }); + + // Kept mounted so a fleet being edited survives switching panels. + app.registerPanel("fleets", Panel, { keepMounted: true }); + + app.registerTab(INVENTORY_TAB, InventoryTab, { + icon: Boxes, + titleKey: "nav.fleets", + singleton: true, + hostless: true, + }); + + // Other plugins (automations' host picker) list fleets through this. + app.registerAction("fleets.list", () => listFleets()); +} diff --git a/plugins/fleets/tests/frontend/activate.test.tsx b/plugins/fleets/tests/frontend/activate.test.tsx new file mode 100644 index 000000000..814097280 --- /dev/null +++ b/plugins/fleets/tests/frontend/activate.test.tsx @@ -0,0 +1,53 @@ +import { afterEach, describe, expect, it } from "vitest"; +import { + renderWithApp, + type RenderedPluginApp, +} from "@termix/plugin-sdk/testing"; +import type { PluginManifest } from "@termix/plugin-sdk/manifest"; +import * as plugin from "../../src/frontend/index"; +import manifestJson from "../../manifest.json"; +import locales from "../../locales/en.json"; + +const manifest = manifestJson as unknown as PluginManifest; + +const declared = (views?: Array<{ id: string }>) => + (views ?? []).map((view) => view.id).sort(); + +let rendered: RenderedPluginApp | null = null; + +afterEach(async () => { + await rendered?.deactivate(); + rendered = null; +}); + +describe(`${manifest.id} activate`, () => { + it("activates and registers only views its manifest declares", async () => { + rendered = await renderWithApp(plugin, { manifest, locales }); + const contributes = manifest.contributes as unknown as Record< + string, + Array<{ id: string }> | undefined + >; + const tabs = declared(contributes.tabs); + // A rail panel may reuse one of the plugin's tab ids. + const panels = [...declared(contributes.panels), ...tabs]; + const cards = declared(contributes.dashboardCards); + for (const id of rendered.registered.tabs()) expect(tabs).toContain(id); + for (const id of rendered.registered.panels()) expect(panels).toContain(id); + for (const id of rendered.registered.dashboardCards()) { + expect(cards).toContain(id); + } + }); + + it("removes everything it registered on deactivate", async () => { + const app = await renderWithApp(plugin, { manifest, locales }); + await app.deactivate(); + expect(app.registered.tabs()).toEqual([]); + expect(app.registered.panels()).toEqual([]); + expect(app.registered.railItems()).toEqual([]); + expect(app.registered.hostActions()).toEqual([]); + expect(app.registered.hostEditorSections()).toEqual([]); + expect(app.registered.dashboardCards()).toEqual([]); + expect(app.registered.settingsComponents()).toEqual([]); + expect(app.registered.actions()).toEqual([]); + }); +}); diff --git a/plugins/host-metrics/locales/en.json b/plugins/host-metrics/locales/en.json index 0967ef424..df5cee0ff 100644 --- a/plugins/host-metrics/locales/en.json +++ b/plugins/host-metrics/locales/en.json @@ -1 +1,314 @@ -{} +{ + "nav": { + "proxmoxStats": "Proxmox Stats", + "hostMetrics": "Host Metrics" + }, + "hostMetrics": { + "cpu": "CPU", + "memory": "Memory", + "disk": "Disk", + "network": "Network", + "uptime": "Uptime", + "processes": "Processes", + "available": "Available", + "free": "Free", + "connecting": "Connecting...", + "connectionFailed": "Failed to connect to server", + "naCpus": "N/A CPU(s)", + "cpuCores_one": "{{count}} Core", + "cpuCores_other": "{{count}} Cores", + "cpuUsage": "CPU Usage", + "memoryUsage": "Memory Usage", + "diskUsage": "Disk Usage", + "selectFilesystem": "Select filesystem", + "temperature": "Temperature", + "highestTemperature": "Highest temperature", + "primaryTemperatureSensor": "Primary sensor", + "gpu": { + "title": "GPU", + "noDevice": "No NVIDIA GPU detected. Install the NVIDIA driver (it provides nvidia-smi) to see GPU metrics.", + "driver": "Driver {{version}}", + "utilization": "Utilization", + "memory": "VRAM", + "temperature": "Temp", + "power": "Power", + "fan": "Fan", + "processes": "GPU processes", + "noProcesses": "No processes are using the GPU" + }, + "failedToFetchHostConfig": "Failed to fetch host configuration", + "serverOffline": "Server Offline", + "cannotFetchMetrics": "Cannot fetch metrics from offline server", + "totpFailed": "TOTP verification failed", + "noneAuthNotSupported": "Host Metrics does not support 'none' authentication type.", + "noHostSelected": "No host selected", + "load": "Load", + "systemInfo": "System Information", + "hostname": "Hostname", + "operatingSystem": "Operating System", + "kernel": "Kernel", + "seconds": "seconds", + "networkInterfaces": "Network Interfaces", + "noInterfacesFound": "No network interfaces found", + "noProcessesFound": "No processes found", + "processesTotal": "total", + "processesRunning": "running", + "loginStats": "SSH Login Statistics", + "noRecentLoginData": "No recent login data", + "executingQuickAction": "Executing {{name}}...", + "quickActionSuccess": "{{name}} completed successfully", + "quickActionFailed": "{{name}} failed", + "quickActionError": "Failed to execute {{name}}", + "ports": { + "title": "Listening Ports", + "protocol": "Protocol", + "port": "Port", + "address": "Address", + "process": "Process", + "search": "Search ports...", + "allProtocols": "All", + "noData": "No listening ports data" + }, + "firewall": { + "title": "Firewall", + "inactive": "Inactive", + "policy": "Policy", + "rules": "rules", + "noRules": "No rules in this chain", + "noData": "No firewall data available", + "action": "Action", + "protocol": "Proto", + "port": "Port", + "source": "Source", + "anywhere": "Anywhere", + "chains": "chains" + }, + "loadAvg": "Load Avg", + "swap": "Swap", + "architecture": "Architecture", + "refresh": "Refresh", + "retry": "Retry", + "customize": "Customize layout", + "reset": "Reset", + "tabLive": "Live", + "editModeInstructions": "Drag cards to rearrange, drag the bottom edge to resize, and use the width button to change a card's span. Add or remove cards below.", + "managers": { + "services": "Services", + "processInspector": "Process Inspector", + "logViewer": "Log Viewer", + "cron": "Cron Jobs", + "packages": "Packages", + "ssl": "SSL Certificates", + "firewall": "Firewall", + "users": "Users & Permissions", + "healthCheck": "Health Checks", + "diskBreakdown": "Disk Breakdown", + "systemdTimers": "Timers", + "topMemory": "Top by Memory", + "noData": "No data", + "sudoHint": "Set a sudo password for this host in the host editor to enable privileged actions.", + "filter": "Filter...", + "start": "Start", + "stop": "Stop", + "restart": "Restart", + "actionDone": "{{name}} updated", + "actionFailed": "Action failed", + "signalSent": "Signal sent to PID {{pid}}", + "killHint": "Click: terminate (SIGTERM). Right-click: force kill (SIGKILL).", + "working": "Working...", + "update": "Update", + "upgradeAll": "Upgrade all", + "allUpToDate": "Everything is up to date", + "save": "Save", + "command": "Command", + "enabled": "Enabled", + "cronSaved": "Crontab updated", + "clients": "Clients", + "dryRun": "Dry run", + "renew": "Renew", + "noAcmeClient": "No ACME client (certbot or acme.sh) found on this host.", + "addInputRule": "Add INPUT rule", + "firewallWarning": "Changes are runtime-only until persisted. Be careful not to lock yourself out.", + "ruleApplied": "Rule applied", + "invalidPort": "Enter a valid port (1-65535)", + "newUsername": "New username", + "addUser": "Add", + "deleteUser": "Delete user", + "noHealthChecks": "No health checks configured yet.", + "follow": "Follow", + "noLogData": "No log output.", + "tree": "Tree", + "enableDisable": "Enable / disable at boot", + "grantSudo": "Grant sudo", + "revokeSudo": "Revoke sudo", + "sslIssueCert": "Issue certificate", + "sslExpired": "Expired", + "sslInDays": "in {{days}}d", + "sslNeedDomain": "Enter at least one domain", + "sslIssued": "Certificate issued", + "sslDomainsPlaceholder": "example.com, www.example.com", + "sslHttpStandalone": "HTTP (standalone)", + "sslHttpWebroot": "HTTP (webroot)", + "sslDns": "DNS", + "sslDnsProvider": "DNS provider (e.g. cloudflare)", + "sslIssueHint": "DNS provider credentials must already be configured on the host.", + "sslRevoke": "Revoke certificate", + "sslRevoked": "Certificate revoked", + "sslRevokeConfirm": "Revoke and remove the certificate \"{{name}}\"? This cannot be undone.", + "healthRun": "Run", + "healthName": "Name", + "healthTarget": "Host / address", + "healthAddCheck": "Add check", + "healthSaved": "Health checks saved", + "healthMissingFields": "Each check needs a name and target", + "logFile": "File", + "logUnit": "Unit", + "logCustomPath": "Custom path under /var/log (optional)", + "logGrep": "Filter lines...", + "firewallPersist": "Persist rules", + "firewallPersisted": "Firewall rules persisted", + "wireguard": "WireGuard", + "tailscale": "Tailscale", + "wgNotInstalled": "WireGuard is not installed on this host", + "wgNoInterfaces": "No WireGuard interfaces configured", + "wgInterfaceUp": "Bring up", + "wgInterfaceDown": "Bring down", + "wgBringingUp": "Bringing {{name}} up...", + "wgBringingDown": "Bringing {{name}} down...", + "wgInterfaceUpDone": "{{name}} is up", + "wgInterfaceDownDone": "{{name}} is down", + "wgListenPort": "Port", + "wgPublicKey": "Public key", + "wgEndpoint": "Endpoint", + "wgAllowedIPs": "Allowed IPs", + "wgLastHandshake": "Last handshake", + "wgHandshakeNever": "Never", + "wgTransfer": "Transfer", + "tsNotInstalled": "Tailscale is not installed on this host", + "tsRunning": "Running", + "tsStopped": "Stopped", + "tsEnable": "Connect", + "tsDisable": "Disconnect", + "tsEnabling": "Connecting to Tailscale...", + "tsDisabling": "Disconnecting from Tailscale...", + "tsEnabled": "Tailscale connected", + "tsDisabled": "Tailscale disconnected", + "tsIPs": "Tailscale IPs", + "tsPeers": "Peers", + "tsOnline": "Online", + "tsOffline": "Offline", + "tsExitNode": "Exit node", + "tsExitNodeActive": "Exit node active", + "tsHostname": "Hostname" + } + }, + "metricsHistory": { + "title": "Metrics History", + "historySuffix": "History", + "cpuMemoryDisk": "CPU / Memory / Disk", + "network": "Network", + "download": "RX", + "upload": "TX", + "noData": "No history data available for this time range.", + "custom": "Custom", + "to": "to", + "apply": "Apply", + "viewHistory": "View History" + }, + "proxmoxStats": { + "tabTitle": "Proxmox Stats", + "cpuUsage": "CPU Usage", + "memoryUsage": "Memory Usage", + "diskUsage": "Disk Usage", + "networkInterfaces": "Network Interfaces", + "uptime": "Uptime", + "systemInfo": "System Information", + "guestsSummary": "Guests", + "storagePools": "Storage Pools", + "clusterHealth": "Cluster Health", + "cpuCores_one": "{{count}} Core", + "cpuCores_other": "{{count}} Cores", + "used": "Used", + "total": "Total", + "hostname": "Hostname", + "kernel": "Kernel", + "pveVersion": "PVE Version", + "name": "Name", + "status": "Status", + "type": "Type", + "cpu": "CPU", + "mem": "Mem", + "disk": "Disk", + "running": "Running", + "stopped": "Stopped", + "guestCounts": "{{running}}/{{total}} running", + "inactive": "Inactive", + "notClustered": "Standalone node (not part of a cluster)", + "quorate": "Quorate", + "notQuorate": "Not quorate", + "nodeOnline": "Online", + "nodeOffline": "Offline", + "noHostSelected": "No host selected", + "pveshNotFound": "pvesh not found - is this a Proxmox node?", + "nodeDetectionFailed": "Unable to determine a valid Proxmox node name", + "connecting": "Connecting...", + "connectionFailed": "Failed to connect to Proxmox node", + "refresh": "Refresh", + "searchGuests": "Search guests...", + "filterAll": "All", + "filterVm": "VM", + "filterLxc": "LXC", + "noGuests": "No VMs or LXC containers found on this node.", + "noGuestsMatch": "No guests match the current filters." + }, + "hosts": { + "tabHostMetrics": "Host Metrics", + "enableProxmoxStats": "Enable Proxmox Stats", + "enableProxmoxStatsDesc": "Show a Proxmox Stats tab for this host with live node, guest, storage, and cluster stats collected over SSH.", + "proxmoxStatsPollInterval": "Poll interval (seconds)", + "proxmoxStatsPollIntervalDesc": "Minimum 15 seconds. How often to refresh Proxmox node stats.", + "proxmoxStatsNodeOverride": "Node name override", + "proxmoxStatsNodeOverrideDesc": "Override auto-detection of the Proxmox node name (detected via hostname by default).", + "proxmoxStatsNodeOverridePlaceholder": "Auto-detected from hostname", + "metricsCollectionLabel": "Metrics Collection", + "enableMetricsLabel": "Enable Metrics", + "enableMetricsDesc": "Collect CPU, RAM, disk, and other metrics from this host", + "useGlobalMetrics": "Use Global Interval", + "useGlobalMetricsDesc": "Override with the server-wide metrics interval", + "metricsIntervalS": "Metrics Interval (s)", + "metricsIntervalDesc2": "Seconds between metric snapshots", + "excludedMountsLabel": "Excluded Mounts", + "monitoredMountsLabel": "Custom monitored paths", + "monitoredMountsDesc": "Add paths that are not exposed as separate mounts, including bind-mounted Home Assistant paths such as /config.", + "monitoredMountPathPlaceholder": "Path (/config, /mnt/data)", + "monitoredMountLabelPlaceholder": "Label (optional)", + "addMonitoredMount": "Add path", + "excludedMountsDesc": "Hide specific mount points or filesystem types (e.g. nfs, cifs) from disk usage and alerts for this host.", + "excludedMountsPlaceholder": "Mount path (/mnt/nas) or filesystem type (nfs, cifs)", + "excludedMountsEmpty": "No mounts excluded. All detected filesystems are shown.", + "addExcludedMount": "Add", + "visibleWidgets": "Visible Widgets", + "widgetsMovedToHostMetrics": "Cards are now added, arranged, and resized directly in the Host Metrics tab. Open Host Metrics for this host and use Customize to choose which cards are shown.", + "quickActionsLabel": "Quick Actions", + "quickActionsToolbar": "Quick actions appear as buttons in the Host Metrics toolbar for one-click command execution.", + "noQuickActions": "No quick actions yet.", + "buttonLabel": "Button label", + "selectSnippetPlaceholder": "Select snippet...", + "addActionBtn": "Add Action" + }, + "onboarding": { + "feature_metrics": "Metrics and alerts", + "feature_metrics_desc": "Track CPU, memory and disk over time, and get alerted when they go bad." + }, + "admin": { + "metricsHistoryRetention": "Metrics History Retention", + "metricsHistoryRetentionRange": "1 to 90 days", + "days": "days" + }, + "homepage": { + "noData": "No data available", + "showCurrentValue": "Show Current Value", + "chartMetric": "Metric", + "metricRange": "Range" + } +} diff --git a/plugins/host-metrics/locales/translated/af_ZA.json b/plugins/host-metrics/locales/translated/af_ZA.json new file mode 100644 index 000000000..d9e93bb84 --- /dev/null +++ b/plugins/host-metrics/locales/translated/af_ZA.json @@ -0,0 +1,313 @@ +{ + "hostMetrics": { + "cpu": "SVE", + "memory": "Geheue", + "disk": "Skyf", + "network": "Netwerk", + "uptime": "Optyd", + "processes": "Prosesse", + "available": "Beskikbaar", + "free": "Gratis", + "connecting": "Verbind...", + "connectionFailed": "Kon nie aan bediener koppel nie", + "naCpus": "N/A SVE(s)", + "cpuCores_one": "{{count}} Kern", + "cpuCores_other": "{{count}} Kerne", + "cpuUsage": "SVE-gebruik", + "memoryUsage": "Geheuegebruik", + "diskUsage": "Skyfgebruik", + "selectFilesystem": "Kies lêerstelsel", + "temperature": "Temperatuur", + "highestTemperature": "Hoogste temperatuur", + "primaryTemperatureSensor": "Primêre sensor", + "gpu": { + "title": "GPU", + "noDevice": "Geen NVIDIA GPU bespeur nie. Installeer die NVIDIA-drywer (dit verskaf nvidia-smi) om GPU-metrieke te sien.", + "driver": "Bestuurder {{version}}", + "utilization": "Benutting", + "memory": "VRAM", + "temperature": "Temperatuur", + "power": "Krag", + "fan": "Waaier", + "processes": "GPU-prosesse", + "noProcesses": "Geen prosesse gebruik die GPU nie" + }, + "failedToFetchHostConfig": "Kon nie gasheerkonfigurasie haal nie", + "serverOffline": "Bediener vanlyn", + "cannotFetchMetrics": "Kan nie statistieke van vanlyn bediener haal nie", + "totpFailed": "TOTP-verifikasie het misluk", + "noneAuthNotSupported": "Host Metrics ondersteun nie die 'geen'-verifikasietipe nie.", + "noHostSelected": "Geen gasheer gekies nie", + "load": "Laai", + "systemInfo": "Stelselinligting", + "hostname": "Gasheernaam", + "operatingSystem": "Bedryfstelsel", + "kernel": "Kern", + "seconds": "sekondes", + "networkInterfaces": "Netwerkkoppelvlakke", + "noInterfacesFound": "Geen netwerkkoppelvlakke gevind nie", + "noProcessesFound": "Geen prosesse gevind nie", + "processesTotal": "totaal", + "processesRunning": "hardloop", + "loginStats": "SSH-aanmeldingstatistieke", + "noRecentLoginData": "Geen onlangse aanmelddata nie", + "executingQuickAction": "Voer tans {{name}} uit ...", + "quickActionSuccess": "{{name}} suksesvol voltooi", + "quickActionFailed": "{{name}} het misluk", + "quickActionError": "Kon nie {{name}} uitvoer nie", + "ports": { + "title": "Luisterpoorte", + "protocol": "Protokol", + "port": "Hawe", + "address": "Adres", + "process": "Proses", + "search": "Soek poorte...", + "allProtocols": "Alles", + "noData": "Geen luisterpoorte-data nie" + }, + "firewall": { + "title": "Firewall", + "inactive": "Onaktief", + "policy": "Beleid", + "rules": "reëls", + "noRules": "Geen reëls in hierdie ketting nie", + "noData": "Geen firewalldata beskikbaar nie", + "action": "Aksie", + "protocol": "Proto", + "port": "Hawe", + "source": "Bron", + "anywhere": "Enige plek", + "chains": "kettings" + }, + "loadAvg": "Laai Gem.", + "swap": "Ruil", + "architecture": "Argitektuur", + "refresh": "Verfris", + "retry": "Probeer weer", + "customize": "Pasmaak uitleg", + "reset": "Herstel", + "tabLive": "Lewendig", + "editModeInstructions": "Sleep kaarte om te herrangskik, sleep die onderste rand om die grootte te verander, en gebruik die breedteknoppie om 'n kaart se omvang te verander. Voeg kaarte hieronder by of verwyder hulle.", + "managers": { + "services": "Dienste", + "processInspector": "Prosesinspekteur", + "logViewer": "Logkyker", + "cron": "Cron-werk", + "packages": "Pakkette", + "ssl": "SSL-sertifikate", + "firewall": "Firewall", + "users": "Gebruikers en Toestemmings", + "healthCheck": "Gesondheidstoetse", + "diskBreakdown": "Skyfverdeling", + "systemdTimers": "Tydtellers", + "topMemory": "Top volgens geheue", + "noData": "Geen data nie", + "sudoHint": "Stel 'n sudo-wagwoord vir hierdie gasheer in die gasheerredigeerder om bevoorregte aksies moontlik te maak.", + "filter": "Filter...", + "start": "Begin", + "stop": "Stop", + "restart": "Herbegin", + "actionDone": "{{name}} opgedateer", + "actionFailed": "Aksie het misluk", + "signalSent": "Sein gestuur na PID {{pid}}", + "killHint": "Klik: beëindig (SIGTERM). Regskliek: forseer doodmaak (SIGKILL).", + "working": "Werk...", + "update": "Opdatering", + "upgradeAll": "Gradeer alles op", + "allUpToDate": "Alles is op datum", + "save": "Stoor", + "command": "Bevel", + "enabled": "Geaktiveer", + "cronSaved": "Crontab opgedateer", + "clients": "Kliënte", + "dryRun": "Droë lopie", + "renew": "Hernu", + "noAcmeClient": "Geen ACME-kliënt (certbot of acme.sh) op hierdie gasheer gevind nie.", + "addInputRule": "Voeg INPUT-reël by", + "firewallWarning": "Veranderinge is slegs looptyd totdat dit voortduur. Wees versigtig om jouself nie uit te sluit nie.", + "ruleApplied": "Reël toegepas", + "invalidPort": "Voer 'n geldige poort in (1-65535)", + "newUsername": "Nuwe gebruikersnaam", + "addUser": "Voeg by", + "deleteUser": "Vee gebruiker uit", + "noHealthChecks": "Geen gesondheidskontroles is nog opgestel nie.", + "follow": "Volg", + "noLogData": "Geen loguitvoer nie.", + "tree": "Boom", + "enableDisable": "Aktiveer/deaktiveer tydens opstart", + "grantSudo": "Gee sudo toe", + "revokeSudo": "Herroep sudo", + "sslIssueCert": "Uitgawesertifikaat", + "sslExpired": "Verstryk", + "sslInDays": "in {{days}}d", + "sslNeedDomain": "Voer ten minste een domein in", + "sslIssued": "Sertifikaat uitgereik", + "sslDomainsPlaceholder": "voorbeeld.com, www.voorbeeld.com", + "sslHttpStandalone": "HTTP (losstaande)", + "sslHttpWebroot": "HTTP (webwortel)", + "sslDns": "DNS", + "sslDnsProvider": "DNS-verskaffer (bv. cloudflare)", + "sslIssueHint": "DNS-verskaffer se geloofsbriewe moet reeds op die gasheer gekonfigureer wees.", + "sslRevoke": "Herroep sertifikaat", + "sslRevoked": "Sertifikaat herroep", + "sslRevokeConfirm": "Herroep en verwyder die sertifikaat \"{{name}}\"? Dit kan nie ongedaan gemaak word nie.", + "healthRun": "Hardloop", + "healthName": "Naam", + "healthTarget": "Gasheer / adres", + "healthAddCheck": "Voeg tjek by", + "healthSaved": "Gesondheidskontroles gestoor", + "healthMissingFields": "Elke tjek benodig 'n naam en teiken", + "logFile": "Lêer", + "logUnit": "Eenheid", + "logCustomPath": "Pasgemaakte pad onder /var/log (opsioneel)", + "logGrep": "Filterlyne...", + "firewallPersist": "Behou reëls", + "firewallPersisted": "Firewall-reëls het voortgeduur", + "wireguard": "Draadbeskerming", + "tailscale": "Stertskaal", + "wgNotInstalled": "WireGuard is nie op hierdie gasheer geïnstalleer nie", + "wgNoInterfaces": "Geen WireGuard-koppelvlakke gekonfigureer nie", + "wgInterfaceUp": "Bring op", + "wgInterfaceDown": "Bring af", + "wgBringingUp": "Bring {{name}} op...", + "wgBringingDown": "Bring {{name}} af...", + "wgInterfaceUpDone": "{{name}} is op", + "wgInterfaceDownDone": "{{name}} is af", + "wgListenPort": "Hawe", + "wgPublicKey": "Publieke sleutel", + "wgEndpoint": "Eindpunt", + "wgAllowedIPs": "Toegelate IP's", + "wgLastHandshake": "Laaste handdruk", + "wgHandshakeNever": "Nooit", + "wgTransfer": "Oordrag", + "tsNotInstalled": "Tailscale is nie op hierdie gasheer geïnstalleer nie", + "tsRunning": "Hardloop", + "tsStopped": "Gestop", + "tsEnable": "Verbind", + "tsDisable": "Ontkoppel", + "tsEnabling": "Verbind met Tailscale...", + "tsDisabling": "Ontkoppel tans van Tailscale...", + "tsEnabled": "Stertskaal gekoppel", + "tsDisabled": "Stertskaal ontkoppel", + "tsIPs": "Stertskaal-IP's", + "tsPeers": "Eweknieë", + "tsOnline": "Aanlyn", + "tsOffline": "Vanlyn", + "tsExitNode": "Uitgangsknoop", + "tsExitNodeActive": "Uitgangsknoop aktief", + "tsHostname": "Gasheernaam" + } + }, + "metricsHistory": { + "title": "Metrieke Geskiedenis", + "historySuffix": "Geskiedenis", + "cpuMemoryDisk": "SVE / Geheue / Skyf", + "network": "Netwerk", + "download": "RX", + "upload": "TX", + "noData": "Geen geskiedenisdata beskikbaar vir hierdie tydperk nie.", + "custom": "Pasgemaak", + "to": "om", + "apply": "Dien toe", + "viewHistory": "Bekyk Geskiedenis" + }, + "proxmoxStats": { + "tabTitle": "Proxmox-statistieke", + "cpuUsage": "SVE-gebruik", + "memoryUsage": "Geheuegebruik", + "diskUsage": "Skyfgebruik", + "networkInterfaces": "Netwerkkoppelvlakke", + "uptime": "Optyd", + "systemInfo": "Stelselinligting", + "guestsSummary": "Gaste", + "storagePools": "Bergingspoele", + "clusterHealth": "Klustergesondheid", + "cpuCores_one": "{{count}} Kern", + "cpuCores_other": "{{count}} Kerne", + "used": "Gebruik", + "total": "Totaal", + "hostname": "Gasheernaam", + "kernel": "Kern", + "pveVersion": "PVE-weergawe", + "name": "Naam", + "status": "Status", + "type": "Tipe", + "cpu": "SVE", + "mem": "Mem", + "disk": "Skyf", + "running": "Hardloop", + "stopped": "Gestop", + "guestCounts": "{{running}}/{{total}} hardloop", + "inactive": "Onaktief", + "notClustered": "Losstaande nodus (nie deel van 'n groep nie)", + "quorate": "Kworate", + "notQuorate": "Nie kworum nie", + "nodeOnline": "Aanlyn", + "nodeOffline": "Vanlyn", + "noHostSelected": "Geen gasheer gekies nie", + "pveshNotFound": "pvesh nie gevind nie - is dit 'n Proxmox-node?", + "nodeDetectionFailed": "Kan nie 'n geldige Proxmox-nodusnaam bepaal nie", + "connecting": "Verbind...", + "connectionFailed": "Kon nie aan die Proxmox-nodus koppel nie", + "refresh": "Verfris", + "searchGuests": "Soek gaste...", + "filterAll": "Alles", + "filterVm": "VM", + "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." + }, + "nav": { + "hostMetrics": "Gasheermetrieke" + }, + "hosts": { + "tabHostMetrics": "Gasheermetrieke", + "enableProxmoxStats": "Aktiveer Proxmox-statistieke", + "enableProxmoxStatsDesc": "Wys 'n Proxmox Statistiek-oortjie vir hierdie gasheer met lewendige nodus-, gas-, bergings- en groepstatistieke wat oor SSH versamel is.", + "proxmoxStatsPollInterval": "Stembusinterval (sekondes)", + "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", + "metricsCollectionLabel": "Metrieke-versameling", + "enableMetricsLabel": "Aktiveer Metrieke", + "enableMetricsDesc": "Versamel SVE-, RAM-, skyf- en ander statistieke van hierdie gasheer", + "useGlobalMetrics": "Gebruik globale interval", + "useGlobalMetricsDesc": "Oorskryf met die bedienerwye metrieke-interval", + "metricsIntervalS": "Metrieke Interval (s)", + "metricsIntervalDesc2": "Sekondes tussen metrieke momentopnames", + "excludedMountsLabel": "Uitgesluite Monterings", + "monitoredMountsLabel": "Pasgemaakte gemonitorde paaie", + "monitoredMountsDesc": "Voeg paaie by wat nie as aparte monterings blootgestel word nie, insluitend bind-gemonteerde Home Assistant-paaie soos /config.", + "monitoredMountPathPlaceholder": "Pad (/config, /mnt/data)", + "monitoredMountLabelPlaceholder": "Etiket (opsioneel)", + "addMonitoredMount": "Voeg pad by", + "excludedMountsDesc": "Versteek spesifieke koppelpunte of lêerstelseltipes (bv. nfs, cifs) van skyfgebruik en waarskuwings vir hierdie gasheer.", + "excludedMountsPlaceholder": "Monteerpad (/mnt/nas) of lêerstelseltipe (nfs, cifs)", + "excludedMountsEmpty": "Geen koppelstukke uitgesluit nie. Alle opgespoorde lêerstelsels word getoon.", + "addExcludedMount": "Voeg by", + "visibleWidgets": "Sigbare Widgets", + "widgetsMovedToHostMetrics": "Kaarte word nou direk in die Gasheermetrieke-oortjie bygevoeg, gerangskik en herskaal. Maak Gasheermetrieke vir hierdie gasheer oop en gebruik Pasmaak om te kies watter kaarte gewys word.", + "quickActionsLabel": "Vinnige Aksies", + "quickActionsToolbar": "Vinnige aksies verskyn as knoppies in die Host Metrics-nutsbalk vir die uitvoering van opdragte met een klik.", + "noQuickActions": "Geen vinnige aksies nog nie.", + "buttonLabel": "Knoppie-etiket", + "selectSnippetPlaceholder": "Kies uittreksel...", + "addActionBtn": "Voeg Aksie by" + }, + "onboarding": { + "feature_metrics": "Metrieke en waarskuwings", + "feature_metrics_desc": "Volg die SVE, geheue en skyf oor tyd en word gewaarsku wanneer hulle sleg word." + }, + "admin": { + "metricsHistoryRetention": "Metrieke Geskiedenis Behoud", + "metricsHistoryRetentionRange": "1 tot 90 dae", + "days": "dae" + }, + "homepage": { + "noData": "Geen data beskikbaar nie", + "showCurrentValue": "Wys huidige waarde", + "chartMetric": "Metrieke", + "metricRange": "Reikwydte" + } +} diff --git a/plugins/host-metrics/locales/translated/ar_SA.json b/plugins/host-metrics/locales/translated/ar_SA.json new file mode 100644 index 000000000..077964908 --- /dev/null +++ b/plugins/host-metrics/locales/translated/ar_SA.json @@ -0,0 +1,313 @@ +{ + "hostMetrics": { + "cpu": "المعالج", + "memory": "الذاكرة", + "disk": "القرص", + "network": "الشبكة", + "uptime": "مدة التشغيل", + "processes": "العمليات", + "available": "المتاح", + "free": "الخالي", + "connecting": "جارٍ الاتصال...", + "connectionFailed": "فشل الاتصال بالخادم", + "naCpus": "غير متوفر", + "cpuCores_one": "{{count}} نواة", + "cpuCores_other": "{{count}} نوى", + "cpuUsage": "استخدام المعالج", + "memoryUsage": "استخدام الذاكرة", + "diskUsage": "استخدام القرص", + "selectFilesystem": "حدد نظام الملفات", + "temperature": "درجة الحرارة", + "highestTemperature": "أعلى درجة حرارة", + "primaryTemperatureSensor": "المستشعر الأساسي", + "gpu": { + "title": "وحدة معالجة الرسومات", + "noDevice": "لم يتم الكشف عن وحدة معالجة رسومات NVIDIA. قم بتثبيت برنامج تشغيل NVIDIA (يوفر nvidia-smi) لعرض مقاييس وحدة معالجة الرسومات.", + "driver": "السائق {{version}}", + "utilization": "استخدام", + "memory": "ذاكرة الوصول العشوائي للفيديو", + "temperature": "درجة حرارة", + "power": "قوة", + "fan": "معجب", + "processes": "عمليات وحدة معالجة الرسومات", + "noProcesses": "لا توجد عمليات تستخدم وحدة معالجة الرسومات (GPU)." + }, + "failedToFetchHostConfig": "فشل جلب تكوين المضيف", + "serverOffline": "الخادم غير متصل", + "cannotFetchMetrics": "لا يمكن جلب المؤشرات من خادم غير متصل", + "totpFailed": "فشل التحقق من TOTP", + "noneAuthNotSupported": "مقاييس المضيف لا تدعم نوع المصادقة 'none'.", + "noHostSelected": "لم يتم تحديد مضيف", + "load": "الحمل", + "systemInfo": "معلومات النظام", + "hostname": "اسم المضيف", + "operatingSystem": "نظام التشغيل", + "kernel": "النواة", + "seconds": "ثوانٍ", + "networkInterfaces": "واجهات الشبكة", + "noInterfacesFound": "لم يتم العثور على واجهات شبكة", + "noProcessesFound": "لم يتم العثور على عمليات", + "processesTotal": "الإجمالي", + "processesRunning": "قيد التشغيل", + "loginStats": "إحصائيات تسجيل الدخول عبر SSH", + "noRecentLoginData": "لا توجد بيانات تسجيل دخول حديثة", + "executingQuickAction": "جارٍ تنفيذ {{name}}...", + "quickActionSuccess": "تم إكمال {{name}} بنجاح", + "quickActionFailed": "فشل {{name}}", + "quickActionError": "فشل تنفيذ {{name}}", + "ports": { + "title": "المنافذ المستمعة", + "protocol": "البروتوكول", + "port": "المنفذ", + "address": "العنوان", + "process": "العملية", + "search": "بحث في المنافذ...", + "allProtocols": "الكل", + "noData": "لا توجد بيانات للمنافذ المستمعة" + }, + "firewall": { + "title": "جدار الحماية", + "inactive": "غير نشط", + "policy": "السياسة", + "rules": "قواعد", + "noRules": "لا توجد قواعد في هذه السلسلة", + "noData": "لا توجد بيانات لجدار الحماية", + "action": "الإجراء", + "protocol": "البروتوكول", + "port": "المنفذ", + "source": "المصدر", + "anywhere": "أي مكان", + "chains": "السلاسل" + }, + "loadAvg": "متوسط التحميل", + "swap": "التبديل", + "architecture": "المعمارية", + "refresh": "تحديث", + "retry": "إعادة المحاولة", + "customize": "تخصيص التخطيط", + "reset": "إعادة تعيين", + "tabLive": "مباشر", + "editModeInstructions": "اسحب البطاقات لإعادة ترتيبها، واسحب الحافة السفلية لتغيير حجمها، واستخدم زر العرض لتغيير امتداد البطاقة. أضف البطاقات أو أزلها أدناه.", + "managers": { + "services": "الخدمات", + "processInspector": "مفتش العمليات", + "logViewer": "عارض السجلات", + "cron": "مهام كرون", + "packages": "الحزم", + "ssl": "شهادات SSL", + "firewall": "جدار الحماية", + "users": "المستخدمون والأذونات", + "healthCheck": "فحوصات الصحة", + "diskBreakdown": "تفصيل القرص", + "systemdTimers": "المؤقتات", + "topMemory": "الأعلى استهلاكًا للذاكرة", + "noData": "لا توجد بيانات", + "sudoHint": "قم بتعيين كلمة مرور sudo لهذا المضيف في محرر المضيف لتمكين الإجراءات المميزة.", + "filter": "تصفية...", + "start": "بدء", + "stop": "إيقاف", + "restart": "إعادة تشغيل", + "actionDone": "تم تحديث {{name}}", + "actionFailed": "فشل الإجراء", + "signalSent": "تم إرسال إشارة إلى PID {{pid}}", + "killHint": "نقرة: إنهاء (SIGTERM). نقرة بزر الماوس الأيمن: إنهاء إجباري (SIGKILL).", + "working": "جارٍ العمل...", + "update": "تحديث", + "upgradeAll": "ترقية الكل", + "allUpToDate": "كل شيء محدث", + "save": "حفظ", + "command": "أمر", + "enabled": "مفعل", + "cronSaved": "تم تحديث crontab", + "clients": "العملاء", + "dryRun": "تشغيل تجريبي", + "renew": "تجديد", + "noAcmeClient": "لم يتم العثور على عميل ACME (certbot أو acme.sh) على هذا المضيف.", + "addInputRule": "إضافة قاعدة INPUT", + "firewallWarning": "التغييرات مؤقتة حتى يتم حفظها. احذر من قفل وصولك.", + "ruleApplied": "تم تطبيق القاعدة", + "invalidPort": "أدخل منفذًا صالحًا (1-65535)", + "newUsername": "اسم مستخدم جديد", + "addUser": "إضافة", + "deleteUser": "حذف المستخدم", + "noHealthChecks": "لم يتم تكوين فحوصات الصحة بعد.", + "follow": "متابعة", + "noLogData": "لا توجد مخرجات سجل.", + "tree": "شجري", + "enableDisable": "تفعيل / تعطيل عند الإقلاع", + "grantSudo": "منح sudo", + "revokeSudo": "سحب sudo", + "sslIssueCert": "إصدار شهادة", + "sslExpired": "منتهية الصلاحية", + "sslInDays": "خلال {{days}} يومًا", + "sslNeedDomain": "أدخل نطاقًا واحدًا على الأقل", + "sslIssued": "تم إصدار الشهادة", + "sslDomainsPlaceholder": "example.com, www.example.com", + "sslHttpStandalone": "HTTP (مستقل)", + "sslHttpWebroot": "HTTP (webroot)", + "sslDns": "DNS", + "sslDnsProvider": "مزود DNS (مثل cloudflare)", + "sslIssueHint": "يجب أن تكون بيانات اعتماد مزود DNS قد تم تكوينها مسبقًا على المضيف.", + "sslRevoke": "إلغاء الشهادة", + "sslRevoked": "تم إلغاء الشهادة", + "sslRevokeConfirm": "هل تريد إلغاء الشهادة \"{{name}}\" وإزالتها؟ لا يمكن التراجع عن هذا الإجراء.", + "healthRun": "تشغيل", + "healthName": "الاسم", + "healthTarget": "المضيف / العنوان", + "healthAddCheck": "إضافة فحص", + "healthSaved": "تم حفظ فحوصات الصحة", + "healthMissingFields": "يتطلب كل فحص اسمًا وهدفًا", + "logFile": "ملف", + "logUnit": "وحدة", + "logCustomPath": "مسار مخصص تحت /var/log (اختياري)", + "logGrep": "تصفية السطور...", + "firewallPersist": "حفظ القواعد", + "firewallPersisted": "تم حفظ قواعد جدار الحماية", + "wireguard": "WireGuard", + "tailscale": "Tailscale", + "wgNotInstalled": "WireGuard غير مثبت على هذا المضيف", + "wgNoInterfaces": "لا توجد واجهات WireGuard مُعدّة", + "wgInterfaceUp": "رفع", + "wgInterfaceDown": "إنزال", + "wgBringingUp": "جارٍ رفع {{name}}...", + "wgBringingDown": "جارٍ إنزال {{name}}...", + "wgInterfaceUpDone": "{{name}} مرفوع", + "wgInterfaceDownDone": "{{name}} منزّل", + "wgListenPort": "المنفذ", + "wgPublicKey": "المفتاح العام", + "wgEndpoint": "نقطة النهاية", + "wgAllowedIPs": "عناوين IP المسموح بها", + "wgLastHandshake": "آخر مصافحة", + "wgHandshakeNever": "أبدًا", + "wgTransfer": "نقل", + "tsNotInstalled": "Tailscale غير مثبت على هذا المضيف", + "tsRunning": "يعمل", + "tsStopped": "متوقف", + "tsEnable": "اتصل", + "tsDisable": "افصل", + "tsEnabling": "جارٍ الاتصال بـ Tailscale...", + "tsDisabling": "جارٍ قطع الاتصال بـ Tailscale...", + "tsEnabled": "Tailscale متصل", + "tsDisabled": "Tailscale غير متصل", + "tsIPs": "عناوين IP لـ Tailscale", + "tsPeers": "الأقران", + "tsOnline": "متصل", + "tsOffline": "غير متصل", + "tsExitNode": "عقدة خروج", + "tsExitNodeActive": "عقدة خروج نشطة", + "tsHostname": "اسم المضيف" + } + }, + "metricsHistory": { + "title": "سجل المقاييس", + "historySuffix": "السجل", + "cpuMemoryDisk": "وحدة المعالجة المركزية / الذاكرة / القرص", + "network": "الشبكة", + "download": "استقبال", + "upload": "إرسال", + "noData": "لا توجد بيانات تاريخية متاحة لهذا النطاق الزمني.", + "custom": "مخصص", + "to": "إلى", + "apply": "تطبيق", + "viewHistory": "عرض السجل" + }, + "proxmoxStats": { + "tabTitle": "إحصائيات Proxmox", + "cpuUsage": "استخدام وحدة المعالجة المركزية", + "memoryUsage": "استخدام الذاكرة", + "diskUsage": "استخدام القرص", + "networkInterfaces": "واجهات الشبكة", + "uptime": "وقت التشغيل", + "systemInfo": "معلومات النظام", + "guestsSummary": "الضيوف", + "storagePools": "أحواض التخزين", + "clusterHealth": "الصحة العنقودية", + "cpuCores_one": "{{count}} النواة", + "cpuCores_other": "{{count}} النوى", + "used": "مستخدم", + "total": "المجموع", + "hostname": "اسم المضيف", + "kernel": "النواة", + "pveVersion": "إصدار لاعب ضد البيئة", + "name": "اسم", + "status": "حالة", + "type": "يكتب", + "cpu": "وحدة المعالجة المركزية", + "mem": "ميم", + "disk": "أدك", + "running": "جري", + "stopped": "توقف", + "guestCounts": "{{running}}/{{total}} قيد التشغيل", + "inactive": "غير نشط", + "notClustered": "عقدة مستقلة (ليست جزءًا من مجموعة)", + "quorate": "اقتبس", + "notQuorate": "غير مكتمل النصاب", + "nodeOnline": "متصل", + "nodeOffline": "غير متصل بالإنترنت", + "noHostSelected": "لم يتم تحديد أي مضيف", + "pveshNotFound": "لم يتم العثور على pvesh - هل هذه عقدة Proxmox؟", + "nodeDetectionFailed": "تعذر تحديد اسم عقدة Proxmox صالح", + "connecting": "جارٍ الاتصال...", + "connectionFailed": "فشل الاتصال بعقدة Proxmox", + "refresh": "ينعش", + "searchGuests": "ابحث عن الضيوف...", + "filterAll": "الجميع", + "filterVm": "آلة افتراضية", + "filterLxc": "LXC", + "noGuests": "لم يتم العثور على أي أجهزة افتراضية أو حاويات LXC على هذه العقدة.", + "noGuestsMatch": "لا يوجد ضيوف يطابقون المعايير الحالية." + }, + "nav": { + "hostMetrics": "مقاييس المضيف" + }, + "hosts": { + "tabHostMetrics": "مقاييس المضيف", + "enableProxmoxStats": "تفعيل إحصائيات Proxmox", + "enableProxmoxStatsDesc": "اعرض علامة تبويب إحصائيات Proxmox لهذا المضيف مع إحصائيات العقدة والضيف والتخزين والمجموعة التي تم جمعها عبر SSH.", + "proxmoxStatsPollInterval": "فاصل الاستطلاع (بالثواني)", + "proxmoxStatsPollIntervalDesc": "الحد الأدنى 15 ثانية. عدد مرات تحديث إحصائيات عقدة Proxmox.", + "proxmoxStatsNodeOverride": "تجاوز اسم العقدة", + "proxmoxStatsNodeOverrideDesc": "تجاوز الكشف التلقائي عن اسم عقدة Proxmox (يتم الكشف عنه عبر اسم المضيف افتراضيًا).", + "proxmoxStatsNodeOverridePlaceholder": "تم اكتشافه تلقائيًا من اسم المضيف", + "metricsCollectionLabel": "تجميع المقاييس", + "enableMetricsLabel": "تمكين المقاييس", + "enableMetricsDesc": "تجميع مقاييس وحدة المعالجة المركزية والذاكرة والقرص وغيرها من هذا المضيف", + "useGlobalMetrics": "استخدام الفاصل الزمني العام", + "useGlobalMetricsDesc": "تجاوز باستخدام فترة المقاييس على مستوى الخادم", + "metricsIntervalS": "فترة المقاييس (ثانية)", + "metricsIntervalDesc2": "الثواني بين لقطات المقاييس", + "excludedMountsLabel": "حوامل مستثناة", + "monitoredMountsLabel": "مسارات مراقبة مخصصة", + "monitoredMountsDesc": "أضف المسارات التي لا يتم عرضها كعمليات ربط منفصلة، بما في ذلك مسارات Home Assistant المرتبطة مثل /config.", + "monitoredMountPathPlaceholder": "المسار (/config، /mnt/data)", + "monitoredMountLabelPlaceholder": "ملصق (اختياري)", + "addMonitoredMount": "إضافة مسار", + "excludedMountsDesc": "إخفاء نقاط التحميل المحددة أو أنواع أنظمة الملفات (مثل nfs و cifs) من استخدام القرص والتنبيهات لهذا المضيف.", + "excludedMountsPlaceholder": "مسار التثبيت (/mnt/nas) أو نوع نظام الملفات (nfs، cifs)", + "excludedMountsEmpty": "لم يتم استبعاد أي وحدات تخزين. يتم عرض جميع أنظمة الملفات المكتشفة.", + "addExcludedMount": "يضيف", + "visibleWidgets": "الأدوات المرئية", + "widgetsMovedToHostMetrics": "تتم الآن إضافة البطاقات وترتيبها وتغيير حجمها مباشرةً في علامة تبويب مقاييس المضيف. افتح مقاييس المضيف لهذا المضيف واستخدم تخصيص لاختيار البطاقات التي ستظهر.", + "quickActionsLabel": "إجراءات سريعة", + "quickActionsToolbar": "تظهر الإجراءات السريعة كأزرار في شريط أدوات مقاييس المضيف لتنفيذ الأوامر بنقرة واحدة.", + "noQuickActions": "لا توجد إجراءات سريعة بعد.", + "buttonLabel": "تسمية الزر", + "selectSnippetPlaceholder": "اختر مقتطفًا...", + "addActionBtn": "إضافة إجراء" + }, + "onboarding": { + "feature_metrics": "المقاييس والتنبيهات", + "feature_metrics_desc": "تتبع أداء وحدة المعالجة المركزية والذاكرة والقرص بمرور الوقت، واحصل على تنبيهات عند حدوث مشاكل فيها." + }, + "admin": { + "metricsHistoryRetention": "الاحتفاظ بسجل المقاييس", + "metricsHistoryRetentionRange": "من 1 إلى 90 يومًا", + "days": "أيام" + }, + "homepage": { + "noData": "لا توجد بيانات", + "showCurrentValue": "إظهار القيمة الحالية", + "chartMetric": "المقياس", + "metricRange": "النطاق" + } +} diff --git a/plugins/host-metrics/locales/translated/bg_BG.json b/plugins/host-metrics/locales/translated/bg_BG.json new file mode 100644 index 000000000..b586eafc1 --- /dev/null +++ b/plugins/host-metrics/locales/translated/bg_BG.json @@ -0,0 +1,313 @@ +{ + "hostMetrics": { + "cpu": "Процесор", + "memory": "Памет", + "disk": "Диск", + "network": "Мрежа", + "uptime": "Време на работа", + "processes": "Процеси", + "available": "Налично", + "free": "Безплатно", + "connecting": "Свързване...", + "connectionFailed": "Неуспешно свързване със сървъра", + "naCpus": "Няма процесор(и)", + "cpuCores_one": "{{count}} Ядро", + "cpuCores_other": "{{count}} Ядра", + "cpuUsage": "Използване на процесора", + "memoryUsage": "Използване на паметта", + "diskUsage": "Използване на диска", + "selectFilesystem": "Изберете файлова система", + "temperature": "Температура", + "highestTemperature": "Най-висока температура", + "primaryTemperatureSensor": "Първичен сензор", + "gpu": { + "title": "Графичен процесор", + "noDevice": "Не е открит графичен процесор NVIDIA. Инсталирайте драйвера на NVIDIA (той предоставя nvidia-smi), за да видите показателите на графичния процесор.", + "driver": "Шофьор {{version}}", + "utilization": "Употреба", + "memory": "Видео памет (VRAM)", + "temperature": "Температура", + "power": "Мощност", + "fan": "Вентилатор", + "processes": "Процеси на графичния процесор", + "noProcesses": "Няма процеси, които да използват графичния процесор" + }, + "failedToFetchHostConfig": "Неуспешно извличане на конфигурацията на хоста", + "serverOffline": "Сървърът е офлайн", + "cannotFetchMetrics": "Не могат да се извлекат показатели от офлайн сървър", + "totpFailed": "Проверката на TOTP не бе успешна", + "noneAuthNotSupported": "Метриките на хоста не поддържат тип удостоверяване „няма“.", + "noHostSelected": "Няма избран хост", + "load": "Зареждане", + "systemInfo": "Системна информация", + "hostname": "Име на хост", + "operatingSystem": "Операционна система", + "kernel": "Ядро", + "seconds": "секунди", + "networkInterfaces": "Мрежови интерфейси", + "noInterfacesFound": "Не са намерени мрежови интерфейси", + "noProcessesFound": "Не са намерени процеси", + "processesTotal": "общо", + "processesRunning": "бягане", + "loginStats": "Статистика за SSH вход", + "noRecentLoginData": "Няма скорошни данни за вход", + "executingQuickAction": "Изпълнява се {{name}}...", + "quickActionSuccess": "{{name}} завършено успешно", + "quickActionFailed": "{{name}} неуспешно", + "quickActionError": "Неуспешно изпълнение на {{name}}", + "ports": { + "title": "Портове за слушане", + "protocol": "Протокол", + "port": "Порт", + "address": "Адрес", + "process": "Процес", + "search": "Търсене на портове...", + "allProtocols": "Всички", + "noData": "Няма данни за портове за слушане" + }, + "firewall": { + "title": "Защитна стена", + "inactive": "Неактивен", + "policy": "Политика", + "rules": "правила", + "noRules": "Няма правила в тази верига", + "noData": "Няма налични данни за защитната стена", + "action": "Действие", + "protocol": "Прото", + "port": "Порт", + "source": "Източник", + "anywhere": "Навсякъде", + "chains": "вериги" + }, + "loadAvg": "Зареждане на средно", + "swap": "Размяна", + "architecture": "Архитектура", + "refresh": "Обновяване", + "retry": "Опитай отново", + "customize": "Персонализиране на оформлението", + "reset": "Нулиране", + "tabLive": "На живо", + "editModeInstructions": "Плъзнете картите, за да ги пренаредите, плъзнете долния ръб, за да промените размера им, и използвайте бутона за ширина, за да промените обхвата на картата. Добавете или премахнете карти по-долу.", + "managers": { + "services": "Услуги", + "processInspector": "Инспектор на процеси", + "logViewer": "Преглед на лог файлове", + "cron": "Cron задачи", + "packages": "Пакети", + "ssl": "SSL сертификати", + "firewall": "Защитна стена", + "users": "Потребители и разрешения", + "healthCheck": "Проверки на състоянието", + "diskBreakdown": "Разбивка на диска", + "systemdTimers": "Таймери", + "topMemory": "Най-горе по памет", + "noData": "Няма данни", + "sudoHint": "Задайте парола за sudo за този хост в редактора на хостове, за да активирате привилегировани действия.", + "filter": "Филтър...", + "start": "Старт", + "stop": "Спри", + "restart": "Рестартиране", + "actionDone": "{{name}} актуализирано", + "actionFailed": "Действието е неуспешно", + "signalSent": "Сигнал, изпратен към PID {{pid}}", + "killHint": "Щракване: прекратяване (SIGTERM). Щракване с десен бутон: принудително прекъсване (SIGKILL).", + "working": "Работа...", + "update": "Актуализация", + "upgradeAll": "Надстройте всички", + "allUpToDate": "Всичко е актуално", + "save": "Запазване", + "command": "Команда", + "enabled": "Активирано", + "cronSaved": "Crontab е актуализиран", + "clients": "Клиенти", + "dryRun": "Сухо изпълнение", + "renew": "Подновяване", + "noAcmeClient": "Не е намерен ACME клиент (certbot или acme.sh) на този хост.", + "addInputRule": "Добавяне на правило INPUT", + "firewallWarning": "Промените са само по време на изпълнение, докато не бъдат запазени. Внимавайте да не се заключите.", + "ruleApplied": "Правилото е приложено", + "invalidPort": "Въведете валиден порт (1-65535)", + "newUsername": "Ново потребителско име", + "addUser": "Добавяне", + "deleteUser": "Изтриване на потребител", + "noHealthChecks": "Все още няма конфигурирани проверки за състоянието.", + "follow": "Следвай", + "noLogData": "Няма изходен лог.", + "tree": "Дърво", + "enableDisable": "Активиране/деактивиране при зареждане", + "grantSudo": "Грант sudo", + "revokeSudo": "Отмяна на sudo", + "sslIssueCert": "Издаване на сертификат", + "sslExpired": "Изтекъл", + "sslInDays": "в {{days}}дни", + "sslNeedDomain": "Въведете поне един домейн", + "sslIssued": "Издаден сертификат", + "sslDomainsPlaceholder": "пример.com, www.example.com", + "sslHttpStandalone": "HTTP (самостоятелен)", + "sslHttpWebroot": "HTTP (уебкорен)", + "sslDns": "ДНС", + "sslDnsProvider": "DNS доставчик (напр. cloudflare)", + "sslIssueHint": "Идентификационните данни на DNS доставчика трябва вече да са конфигурирани на хоста.", + "sslRevoke": "Анулиране на сертификат", + "sslRevoked": "Сертификатът е отменен", + "sslRevokeConfirm": "Да се отмени и премахне сертификатът „{{name}}“? Това не може да бъде отменено.", + "healthRun": "Бягане", + "healthName": "Име", + "healthTarget": "Хост / адрес", + "healthAddCheck": "Добавяне на чек", + "healthSaved": "Запазени са здравни проверки", + "healthMissingFields": "Всяка проверка се нуждае от име и цел", + "logFile": "Файл", + "logUnit": "Единица", + "logCustomPath": "Персонализиран път в /var/log (по избор)", + "logGrep": "Филтърни линии...", + "firewallPersist": "Запазване на правилата", + "firewallPersisted": "Правилата на защитната стена се запазиха", + "wireguard": "WireGuard", + "tailscale": "Задна скала", + "wgNotInstalled": "WireGuard не е инсталиран на този хост", + "wgNoInterfaces": "Няма конфигурирани WireGuard интерфейси", + "wgInterfaceUp": "Доведете", + "wgInterfaceDown": "Свалете", + "wgBringingUp": "Извеждане на {{name}} нагоре...", + "wgBringingDown": "Сваляне на {{name}}...", + "wgInterfaceUpDone": "{{name}} е нагоре", + "wgInterfaceDownDone": "{{name}} не работи", + "wgListenPort": "Порт", + "wgPublicKey": "Публичен ключ", + "wgEndpoint": "Крайна точка", + "wgAllowedIPs": "Разрешени IP адреси", + "wgLastHandshake": "Последно ръкостискане", + "wgHandshakeNever": "Никога", + "wgTransfer": "Трансфер", + "tsNotInstalled": "Tailscale не е инсталиран на този хост", + "tsRunning": "Бягане", + "tsStopped": "Спряно", + "tsEnable": "Свържете се", + "tsDisable": "Изключване", + "tsEnabling": "Свързване с Tailscale...", + "tsDisabling": "Изключване от Tailscale...", + "tsEnabled": "Свързана опашка", + "tsDisabled": "Задната скала е изключена", + "tsIPs": "IP адреси на Tailscale", + "tsPeers": "Връстници", + "tsOnline": "Онлайн", + "tsOffline": "Офлайн", + "tsExitNode": "Изходен възел", + "tsExitNodeActive": "Изходният възел е активен", + "tsHostname": "Име на хост" + } + }, + "metricsHistory": { + "title": "История на показателите", + "historySuffix": "История", + "cpuMemoryDisk": "Процесор / Памет / Диск", + "network": "Мрежа", + "download": "Рецепта", + "upload": "Тексас", + "noData": "Няма налични исторически данни за този период от време.", + "custom": "Персонализирано", + "to": "до", + "apply": "Приложи", + "viewHistory": "Преглед на историята" + }, + "proxmoxStats": { + "tabTitle": "Статистика на Proxmox", + "cpuUsage": "Използване на процесора", + "memoryUsage": "Използване на паметта", + "diskUsage": "Използване на диска", + "networkInterfaces": "Мрежови интерфейси", + "uptime": "Време на работа", + "systemInfo": "Системна информация", + "guestsSummary": "Гости", + "storagePools": "Пулове за съхранение", + "clusterHealth": "Здраве на клъстера", + "cpuCores_one": "{{count}} Ядро", + "cpuCores_other": "{{count}} Ядра", + "used": "Използван", + "total": "Общо", + "hostname": "Име на хост", + "kernel": "Ядро", + "pveVersion": "PVE версия", + "name": "Име", + "status": "Статус", + "type": "Тип", + "cpu": "Процесор", + "mem": "Мем", + "disk": "Диск", + "running": "Бягане", + "stopped": "Спряно", + "guestCounts": "{{running}}/{{total}} бягане", + "inactive": "Неактивен", + "notClustered": "Самостоятелен възел (не е част от клъстер)", + "quorate": "Кворат", + "notQuorate": "Няма кворум", + "nodeOnline": "Онлайн", + "nodeOffline": "Офлайн", + "noHostSelected": "Няма избран хост", + "pveshNotFound": "pvesh не е намерен - това Proxmox възел ли е?", + "nodeDetectionFailed": "Не може да се определи валидно име на възел Proxmox", + "connecting": "Свързване...", + "connectionFailed": "Неуспешно свързване с възел Proxmox", + "refresh": "Обновяване", + "searchGuests": "Търсене на гости...", + "filterAll": "Всички", + "filterVm": "ВМ", + "filterLxc": "LXC", + "noGuests": "На този възел не са намерени виртуални машини или LXC контейнери.", + "noGuestsMatch": "Няма гости, които да отговарят на текущите филтри." + }, + "nav": { + "hostMetrics": "Метрики на хоста" + }, + "hosts": { + "tabHostMetrics": "Метрики на хоста", + "enableProxmoxStats": "Активиране на Proxmox Stats", + "enableProxmoxStatsDesc": "Покажете раздела „Статистика на Proxmox“ за този хост с актуални статистически данни за възлите, госта, хранилището и клъстера, събрани през SSH.", + "proxmoxStatsPollInterval": "Интервал на анкетата (секунди)", + "proxmoxStatsPollIntervalDesc": "Минимум 15 секунди. Колко често да се обновяват статистическите данни за възлите на Proxmox.", + "proxmoxStatsNodeOverride": "Замяна на името на възела", + "proxmoxStatsNodeOverrideDesc": "Игнориране на автоматичното откриване на името на възела Proxmox (по подразбиране се открива чрез името на хоста).", + "proxmoxStatsNodeOverridePlaceholder": "Автоматично разпознато от името на хоста", + "metricsCollectionLabel": "Колекция от показатели", + "enableMetricsLabel": "Активиране на показатели", + "enableMetricsDesc": "Събиране на данни за процесора, RAM, диска и други показатели от този хост", + "useGlobalMetrics": "Използване на глобален интервал", + "useGlobalMetricsDesc": "Замяна с интервала на показателите за целия сървър", + "metricsIntervalS": "Интервал(и) на показателите", + "metricsIntervalDesc2": "Секунди между моментните снимки на показателите", + "excludedMountsLabel": "Изключени монтировки", + "monitoredMountsLabel": "Персонализирани наблюдавани пътища", + "monitoredMountsDesc": "Добавете пътища, които не са изложени като отделни монтирания, включително пътища за монтиран Home Assistant чрез свързване, като например /config.", + "monitoredMountPathPlaceholder": "Път (/config, /mnt/data)", + "monitoredMountLabelPlaceholder": "Етикет (по избор)", + "addMonitoredMount": "Добавяне на път", + "excludedMountsDesc": "Скриване на специфични точки на монтиране или типове файлови системи (напр. nfs, cifs) от използването на диска и предупрежденията за този хост.", + "excludedMountsPlaceholder": "Път за монтиране (/mnt/nas) или тип файлова система (nfs, cifs)", + "excludedMountsEmpty": "Няма изключени монтирания. Показват се всички открити файлови системи.", + "addExcludedMount": "Добавяне", + "visibleWidgets": "Видими джаджи", + "widgetsMovedToHostMetrics": "Картите вече се добавят, подреждат и преоразмеряват директно в раздела „Показатели за хоста“. Отворете „Показатели за хоста“ за този хост и използвайте „Персонализиране“, за да изберете кои карти да се показват.", + "quickActionsLabel": "Бързи действия", + "quickActionsToolbar": "Бързите действия се показват като бутони в лентата с инструменти Host Metrics за изпълнение на команди с едно щракване.", + "noQuickActions": "Все още няма бързи действия.", + "buttonLabel": "Етикет на бутона", + "selectSnippetPlaceholder": "Изберете фрагмент...", + "addActionBtn": "Добавяне на действие" + }, + "onboarding": { + "feature_metrics": "Показатели и сигнали", + "feature_metrics_desc": "Проследявайте процесора, паметта и диска с течение на времето и получавайте известия, когато се повредят." + }, + "admin": { + "metricsHistoryRetention": "Запазване на историята на показателите", + "metricsHistoryRetentionRange": "от 1 до 90 дни", + "days": "дни" + }, + "homepage": { + "noData": "Няма налични данни", + "showCurrentValue": "Показване на текущата стойност", + "chartMetric": "Метричен", + "metricRange": "Диапазон" + } +} diff --git a/plugins/host-metrics/locales/translated/bn_BD.json b/plugins/host-metrics/locales/translated/bn_BD.json new file mode 100644 index 000000000..c7ef381f2 --- /dev/null +++ b/plugins/host-metrics/locales/translated/bn_BD.json @@ -0,0 +1,313 @@ +{ + "hostMetrics": { + "cpu": "সিপিইউ", + "memory": "স্মৃতি", + "disk": "ডিস্ক", + "network": "নেটওয়ার্ক", + "uptime": "আপটাইম", + "processes": "প্রক্রিয়া", + "available": "উপলব্ধ", + "free": "বিনামূল্যে", + "connecting": "সংযোগ স্থাপন...", + "connectionFailed": "সার্ভারের সাথে সংযোগ করতে ব্যর্থ হয়েছে", + "naCpus": "প্রযোজ্য নয় সিপিইউ(গুলি)", + "cpuCores_one": "{{count}} কোর", + "cpuCores_other": "{{count}} কোর", + "cpuUsage": "সিপিইউ ব্যবহার", + "memoryUsage": "মেমরি ব্যবহার", + "diskUsage": "ডিস্ক ব্যবহার", + "selectFilesystem": "ফাইলসিস্টেম নির্বাচন করুন", + "temperature": "তাপমাত্রা", + "highestTemperature": "সর্বোচ্চ তাপমাত্রা", + "primaryTemperatureSensor": "প্রাথমিক সেন্সর", + "gpu": { + "title": "জিপিইউ", + "noDevice": "কোন NVIDIA GPU সনাক্ত করা যায়নি। GPU মেট্রিক্স দেখতে NVIDIA ড্রাইভারটি (যা nvidia-smi প্রদান করে) ইনস্টল করুন।", + "driver": "চালক {{version}}", + "utilization": "ব্যবহার", + "memory": "VRAM", + "temperature": "তাপমাত্রা", + "power": "শক্তি", + "fan": "ভক্ত", + "processes": "জিপিইউ প্রক্রিয়া", + "noProcesses": "কোনো প্রসেসই GPU ব্যবহার করছে না।" + }, + "failedToFetchHostConfig": "হোস্ট কনফিগারেশন আনতে ব্যর্থ হয়েছে", + "serverOffline": "সার্ভার অফলাইন", + "cannotFetchMetrics": "অফলাইন সার্ভার থেকে মেট্রিক্স সংগ্রহ করা যাচ্ছে না", + "totpFailed": "TOTP যাচাইকরণ ব্যর্থ হয়েছে", + "noneAuthNotSupported": "হোস্ট মেট্রিক্স 'none' অথেনটিকেশন টাইপ সমর্থন করে না।", + "noHostSelected": "কোন হোস্ট নির্বাচন করা হয়নি", + "load": "লোড", + "systemInfo": "সিস্টেমের তথ্য", + "hostname": "হোস্টনাম", + "operatingSystem": "অপারেটিং সিস্টেম", + "kernel": "কার্নেল", + "seconds": "সেকেন্ড", + "networkInterfaces": "নেটওয়ার্ক ইন্টারফেস", + "noInterfacesFound": "কোন নেটওয়ার্ক ইন্টারফেস খুঁজে পাওয়া যায়নি", + "noProcessesFound": "কোন প্রক্রিয়া খুঁজে পাওয়া যায়নি", + "processesTotal": "মোট", + "processesRunning": "দৌড়ানো", + "loginStats": "SSH লগইন পরিসংখ্যান", + "noRecentLoginData": "সাম্প্রতিক কোনো লগইন ডেটা নেই", + "executingQuickAction": "{{name}} কার্যকর করা হচ্ছে ...", + "quickActionSuccess": "{{name}} সফলভাবে সম্পন্ন হয়েছে", + "quickActionFailed": "{{name}} ব্যর্থ হয়েছে", + "quickActionError": "{{name}} কার্যকর করতে ব্যর্থ হয়েছে", + "ports": { + "title": "লিসেনিং পোর্ট", + "protocol": "প্রোটোকল", + "port": "বন্দর", + "address": "ঠিকানা", + "process": "প্রক্রিয়া", + "search": "পোর্ট অনুসন্ধান করুন...", + "allProtocols": "সব", + "noData": "কোন লিসেনিং পোর্ট ডেটা নেই" + }, + "firewall": { + "title": "ফায়ারওয়াল", + "inactive": "নিষ্ক্রিয়", + "policy": "নীতি", + "rules": "নিয়ম", + "noRules": "এই শৃঙ্খলে কোনো নিয়ম নেই", + "noData": "কোন ফায়ারওয়াল ডেটা উপলব্ধ নেই", + "action": "পদক্ষেপ", + "protocol": "প্রোটো", + "port": "বন্দর", + "source": "উৎস", + "anywhere": "যেকোনো জায়গায়", + "chains": "শৃঙ্খল" + }, + "loadAvg": "গড় লোড", + "swap": "অদলবদল", + "architecture": "স্থাপত্য", + "refresh": "রিফ্রেশ", + "retry": "পুনরায় চেষ্টা করুন", + "customize": "লেআউট কাস্টমাইজ করুন", + "reset": "রিসেট", + "tabLive": "সরাসরি", + "editModeInstructions": "কার্ডগুলো পুনর্বিন্যাস করতে টেনে আনুন, আকার পরিবর্তন করতে নিচের কিনারা টেনে আনুন এবং কার্ডের বিস্তার বদলাতে প্রস্থ বোতামটি ব্যবহার করুন। নিচে কার্ড যোগ বা অপসারণ করুন।", + "managers": { + "services": "পরিষেবা", + "processInspector": "প্রক্রিয়া পরিদর্শক", + "logViewer": "লগ ভিউয়ার", + "cron": "ক্রন জবস", + "packages": "প্যাকেজ", + "ssl": "SSL সার্টিফিকেট", + "firewall": "ফায়ারওয়াল", + "users": "ব্যবহারকারী ও অনুমতি", + "healthCheck": "স্বাস্থ্য পরীক্ষা", + "diskBreakdown": "ডিস্ক ব্রেকডাউন", + "systemdTimers": "টাইমার", + "topMemory": "স্মৃতি দ্বারা শীর্ষে", + "noData": "কোন ডেটা নেই", + "sudoHint": "বিশেষাধিকারপ্রাপ্ত কাজগুলো সক্ষম করতে হোস্ট এডিটরে এই হোস্টের জন্য একটি sudo পাসওয়ার্ড সেট করুন।", + "filter": "ফিল্টার...", + "start": "শুরু করুন", + "stop": "থামুন", + "restart": "পুনরায় চালু করুন", + "actionDone": "{{name}} আপডেট করা হয়েছে", + "actionFailed": "পদক্ষেপ ব্যর্থ হয়েছে", + "signalSent": "PID {{pid}}-তে সংকেত পাঠানো হয়েছে", + "killHint": "ক্লিক: বন্ধ করুন (SIGTERM)। ডান-ক্লিক: জোরপূর্বক বন্ধ করুন (SIGKILL)।", + "working": "কাজ চলছে...", + "update": "আপডেট", + "upgradeAll": "সব আপগ্রেড করুন", + "allUpToDate": "সবকিছু হালনাগাদ আছে", + "save": "সংরক্ষণ করুন", + "command": "আদেশ", + "enabled": "সক্ষম করা হয়েছে", + "cronSaved": "ক্রনট্যাব আপডেট করা হয়েছে", + "clients": "ক্লায়েন্টরা", + "dryRun": "ড্রাই রান", + "renew": "পুনর্নবীকরণ করুন", + "noAcmeClient": "এই হোস্টে কোনো ACME ক্লায়েন্ট (certbot বা acme.sh) খুঁজে পাওয়া যায়নি।", + "addInputRule": "ইনপুট নিয়ম যোগ করুন", + "firewallWarning": "স্থায়ী না হওয়া পর্যন্ত পরিবর্তনগুলো শুধুমাত্র রানটাইমে কার্যকর থাকে। খেয়াল রাখবেন যেন আপনি নিজে লক আউট না হয়ে যান।", + "ruleApplied": "নিয়ম প্রয়োগ করা হয়েছে", + "invalidPort": "একটি বৈধ পোর্ট প্রবেশ করান (1-65535)", + "newUsername": "নতুন ব্যবহারকারীর নাম", + "addUser": "যোগ করুন", + "deleteUser": "ব্যবহারকারীকে মুছে ফেলুন", + "noHealthChecks": "এখনো কোনো স্বাস্থ্য পরীক্ষা কনফিগার করা হয়নি।", + "follow": "অনুসরণ করুন", + "noLogData": "কোনো লগ আউটপুট নেই।", + "tree": "গাছ", + "enableDisable": "বুট করার সময় সক্ষম / অক্ষম করুন", + "grantSudo": "Grant sudo", + "revokeSudo": "sudo প্রত্যাহার করুন", + "sslIssueCert": "সার্টিফিকেট প্রদান করুন", + "sslExpired": "মেয়াদোত্তীর্ণ", + "sslInDays": "{{days}}d-তে", + "sslNeedDomain": "অন্তত একটি ডোমেইন প্রবেশ করান", + "sslIssued": "সার্টিফিকেট ইস্যু করা হয়েছে", + "sslDomainsPlaceholder": "example.com, www.example.com", + "sslHttpStandalone": "HTTP (স্বতন্ত্র)", + "sslHttpWebroot": "HTTP (ওয়েবরুট)", + "sslDns": "ডিএনএস", + "sslDnsProvider": "ডিএনএস প্রদানকারী (যেমন ক্লাউডফ্লেয়ার)", + "sslIssueHint": "হোস্টে ডিএনএস প্রদানকারীর ক্রেডেনশিয়াল অবশ্যই আগে থেকে কনফিগার করা থাকতে হবে।", + "sslRevoke": "সার্টিফিকেট বাতিল করুন", + "sslRevoked": "সার্টিফিকেট বাতিল করা হয়েছে", + "sslRevokeConfirm": "সার্টিফিকেট \"{{name}}\" বাতিল এবং অপসারণ করবেন? এটি পূর্বাবস্থায় ফেরানো যাবে না।", + "healthRun": "দৌড়", + "healthName": "নাম", + "healthTarget": "হোস্ট / ঠিকানা", + "healthAddCheck": "চেক যোগ করুন", + "healthSaved": "স্বাস্থ্য পরীক্ষা সংরক্ষিত", + "healthMissingFields": "প্রতিটি চেকের একটি নাম এবং লক্ষ্য থাকা প্রয়োজন।", + "logFile": "ফাইল", + "logUnit": "ইউনিট", + "logCustomPath": "/var/log-এর অধীনে নিজস্ব পথ (ঐচ্ছিক)", + "logGrep": "ফিল্টার লাইন...", + "firewallPersist": "অধ্যবসায় নিয়ম", + "firewallPersisted": "ফায়ারওয়াল নিয়মগুলি অব্যাহত ছিল", + "wireguard": "ওয়্যারগার্ড", + "tailscale": "লেজের স্কেল", + "wgNotInstalled": "এই হোস্টে WireGuard ইনস্টল করা নেই", + "wgNoInterfaces": "কোন WireGuard ইন্টারফেস কনফিগার করা নেই", + "wgInterfaceUp": "উত্থাপন করুন", + "wgInterfaceDown": "নামিয়ে আনুন", + "wgBringingUp": "{{name}} উপরে তুলে আনা...", + "wgBringingDown": "{{name}} কে নিচে নামিয়ে আনা হচ্ছে...", + "wgInterfaceUpDone": "{{name}} উপরে আছে", + "wgInterfaceDownDone": "{{name}} নিচে আছে", + "wgListenPort": "বন্দর", + "wgPublicKey": "পাবলিক কী", + "wgEndpoint": "এন্ডপয়েন্ট", + "wgAllowedIPs": "অনুমোদিত আইপি", + "wgLastHandshake": "শেষ করমর্দন", + "wgHandshakeNever": "কখনো না", + "wgTransfer": "স্থানান্তর", + "tsNotInstalled": "এই হোস্টে টেইলস্কেল ইনস্টল করা নেই।", + "tsRunning": "দৌড়ানো", + "tsStopped": "থামানো হয়েছে", + "tsEnable": "সংযোগ করুন", + "tsDisable": "সংযোগ বিচ্ছিন্ন করুন", + "tsEnabling": "টেইলস্কেলের সাথে সংযোগ স্থাপন করা হচ্ছে...", + "tsDisabling": "টেইলস্কেল থেকে সংযোগ বিচ্ছিন্ন হচ্ছে...", + "tsEnabled": "টেলস্কেল সংযুক্ত", + "tsDisabled": "টেলস্কেল সংযোগ বিচ্ছিন্ন", + "tsIPs": "টেইলস্কেল আইপি", + "tsPeers": "সমবয়সীরা", + "tsOnline": "অনলাইন", + "tsOffline": "অফলাইন", + "tsExitNode": "প্রস্থান নোড", + "tsExitNodeActive": "প্রস্থান নোড সক্রিয়", + "tsHostname": "হোস্টনাম" + } + }, + "metricsHistory": { + "title": "মেট্রিক্সের ইতিহাস", + "historySuffix": "ইতিহাস", + "cpuMemoryDisk": "সিপিইউ / মেমরি / ডিস্ক", + "network": "নেটওয়ার্ক", + "download": "আরএক্স", + "upload": "টেক্সাস", + "noData": "এই সময়সীমার জন্য কোনো ঐতিহাসিক তথ্য উপলব্ধ নেই।", + "custom": "কাস্টম", + "to": "থেকে", + "apply": "আবেদন করুন", + "viewHistory": "ইতিহাস দেখুন" + }, + "proxmoxStats": { + "tabTitle": "প্রক্সমক্স পরিসংখ্যান", + "cpuUsage": "সিপিইউ ব্যবহার", + "memoryUsage": "মেমরি ব্যবহার", + "diskUsage": "ডিস্ক ব্যবহার", + "networkInterfaces": "নেটওয়ার্ক ইন্টারফেস", + "uptime": "আপটাইম", + "systemInfo": "সিস্টেমের তথ্য", + "guestsSummary": "অতিথিরা", + "storagePools": "স্টোরেজ পুল", + "clusterHealth": "ক্লাস্টার স্বাস্থ্য", + "cpuCores_one": "{{count}} কোর", + "cpuCores_other": "{{count}} কোর", + "used": "ব্যবহৃত", + "total": "মোট", + "hostname": "হোস্টনাম", + "kernel": "কার্নেল", + "pveVersion": "PVE সংস্করণ", + "name": "নাম", + "status": "অবস্থা", + "type": "প্রকার", + "cpu": "সিপিইউ", + "mem": "মেম", + "disk": "ডিস্ক", + "running": "দৌড়ানো", + "stopped": "থামানো হয়েছে", + "guestCounts": "{{running}}/{{total}} চলমান", + "inactive": "নিষ্ক্রিয়", + "notClustered": "স্বতন্ত্র নোড (ক্লাস্টারের অংশ নয়)", + "quorate": "কোরাট", + "notQuorate": "কোরাম পূর্ণ নয়", + "nodeOnline": "অনলাইন", + "nodeOffline": "অফলাইন", + "noHostSelected": "কোন হোস্ট নির্বাচন করা হয়নি", + "pveshNotFound": "pvesh খুঁজে পাওয়া যায়নি - এটি কি একটি Proxmox নোড?", + "nodeDetectionFailed": "একটি বৈধ Proxmox নোডের নাম নির্ধারণ করা সম্ভব হয়নি।", + "connecting": "সংযোগ স্থাপন...", + "connectionFailed": "Proxmox নোডের সাথে সংযোগ করতে ব্যর্থ হয়েছে", + "refresh": "রিফ্রেশ", + "searchGuests": "অতিথিদের অনুসন্ধান করুন...", + "filterAll": "সব", + "filterVm": "ভিএম", + "filterLxc": "এলএক্সসি", + "noGuests": "এই নোডে কোনো ভিএম বা এলএক্সসি কন্টেইনার খুঁজে পাওয়া যায়নি।", + "noGuestsMatch": "বর্তমান ফিল্টারগুলোর সাথে কোনো অতিথি মেলে না।" + }, + "nav": { + "hostMetrics": "হোস্ট মেট্রিক্স" + }, + "hosts": { + "tabHostMetrics": "হোস্ট মেট্রিক্স", + "enableProxmoxStats": "Proxmox Stats সক্রিয় করুন", + "enableProxmoxStatsDesc": "এই হোস্টের জন্য একটি Proxmox Stats ট্যাব দেখান, যেখানে SSH-এর মাধ্যমে সংগৃহীত লাইভ নোড, গেস্ট, স্টোরেজ এবং ক্লাস্টার পরিসংখ্যান থাকবে।", + "proxmoxStatsPollInterval": "ভোটের ব্যবধান (সেকেন্ড)", + "proxmoxStatsPollIntervalDesc": "সর্বনিম্ন ১৫ সেকেন্ড। কত ঘন ঘন প্রক্সমক্স নোড স্ট্যাটস রিফ্রেশ করতে হবে।", + "proxmoxStatsNodeOverride": "নোডের নাম ওভাররাইড", + "proxmoxStatsNodeOverrideDesc": "প্রক্সমক্স নোডের নামের স্বয়ংক্রিয় সনাক্তকরণকে অগ্রাহ্য করুন (যা ডিফল্টরূপে হোস্টনেমের মাধ্যমে সনাক্ত করা হয়)।", + "proxmoxStatsNodeOverridePlaceholder": "হোস্টনেম থেকে স্বয়ংক্রিয়ভাবে শনাক্ত করা হয়েছে", + "metricsCollectionLabel": "মেট্রিক্স সংগ্রহ", + "enableMetricsLabel": "মেট্রিক্স সক্ষম করুন", + "enableMetricsDesc": "এই হোস্ট থেকে সিপিইউ, র‍্যাম, ডিস্ক এবং অন্যান্য মেট্রিক সংগ্রহ করুন।", + "useGlobalMetrics": "গ্লোবাল ইন্টারভাল ব্যবহার করুন", + "useGlobalMetricsDesc": "সার্ভার-ব্যাপী মেট্রিক্স ব্যবধান দিয়ে ওভাররাইড করুন", + "metricsIntervalS": "মেট্রিক্স ব্যবধান (সেকেন্ড)", + "metricsIntervalDesc2": "মেট্রিক স্ন্যাপশটগুলির মধ্যে সেকেন্ডের ব্যবধান", + "excludedMountsLabel": "বাদ দেওয়া মাউন্টগুলি", + "monitoredMountsLabel": "কাস্টম পর্যবেক্ষণ করা পথ", + "monitoredMountsDesc": "এমন পাথ যোগ করুন যা আলাদা মাউন্ট হিসাবে উন্মুক্ত নয়, যার মধ্যে /config-এর মতো বাইন্ড-মাউন্টেড Home Assistant পাথও অন্তর্ভুক্ত।", + "monitoredMountPathPlaceholder": "পাথ (/config, /mnt/data)", + "monitoredMountLabelPlaceholder": "লেবেল (ঐচ্ছিক)", + "addMonitoredMount": "পথ যোগ করুন", + "excludedMountsDesc": "এই হোস্টের জন্য ডিস্ক ব্যবহার এবং সতর্কতা থেকে নির্দিষ্ট মাউন্ট পয়েন্ট বা ফাইলসিস্টেমের ধরণ (যেমন nfs, cifs) লুকান।", + "excludedMountsPlaceholder": "মাউন্ট পাথ (/mnt/nas) অথবা ফাইলসিস্টেমের ধরণ (nfs, cifs)", + "excludedMountsEmpty": "কোনো মাউন্ট বাদ দেওয়া হয়নি। শনাক্তকৃত সকল ফাইলসিস্টেম দেখানো হয়েছে।", + "addExcludedMount": "যোগ করুন", + "visibleWidgets": "দৃশ্যমান উইজেট", + "widgetsMovedToHostMetrics": "এখন কার্ডগুলি সরাসরি হোস্ট মেট্রিক্স ট্যাবে যোগ, সাজানো এবং আকার পরিবর্তন করা যায়। এই হোস্টের জন্য হোস্ট মেট্রিক্স খুলুন এবং কোন কার্ডগুলি দেখানো হবে তা বেছে নিতে কাস্টমাইজ ব্যবহার করুন।", + "quickActionsLabel": "দ্রুত পদক্ষেপ", + "quickActionsToolbar": "এক ক্লিকে কমান্ড কার্যকর করার জন্য কুইক অ্যাকশনগুলো হোস্ট মেট্রিক্স টুলবারে বাটন হিসেবে প্রদর্শিত হয়।", + "noQuickActions": "এখনো কোনো দ্রুত পদক্ষেপ নেওয়া হয়নি।", + "buttonLabel": "বোতাম লেবেল", + "selectSnippetPlaceholder": "স্নিপেট নির্বাচন করুন...", + "addActionBtn": "অ্যাকশন যোগ করুন" + }, + "onboarding": { + "feature_metrics": "মেট্রিক্স এবং সতর্কতা", + "feature_metrics_desc": "সময়ের সাথে সাথে সিপিইউ, মেমরি এবং ডিস্কের অবস্থা পর্যবেক্ষণ করুন এবং সেগুলি বিকল হয়ে গেলে সতর্কবার্তা পান।" + }, + "admin": { + "metricsHistoryRetention": "মেট্রিক্সের ইতিহাস সংরক্ষণ", + "metricsHistoryRetentionRange": "১ থেকে ৯০ দিন", + "days": "দিন" + }, + "homepage": { + "noData": "কোন ডেটা উপলব্ধ নেই", + "showCurrentValue": "বর্তমান মান দেখান", + "chartMetric": "মেট্রিক", + "metricRange": "পরিসর" + } +} diff --git a/plugins/host-metrics/locales/translated/ca_ES.json b/plugins/host-metrics/locales/translated/ca_ES.json new file mode 100644 index 000000000..bcac1aae8 --- /dev/null +++ b/plugins/host-metrics/locales/translated/ca_ES.json @@ -0,0 +1,313 @@ +{ + "hostMetrics": { + "cpu": "CPU", + "memory": "Memòria", + "disk": "Disc", + "network": "Xarxa", + "uptime": "Temps de funcionament", + "processes": "Processos", + "available": "Disponible", + "free": "Gratuït", + "connecting": "Connectant...", + "connectionFailed": "No s'ha pogut connectar al servidor", + "naCpus": "CPU(s) N/A", + "cpuCores_one": "{{count}} Nucli", + "cpuCores_other": "{{count}} Nuclis", + "cpuUsage": "Ús de la CPU", + "memoryUsage": "Ús de memòria", + "diskUsage": "Ús del disc", + "selectFilesystem": "Selecciona el sistema de fitxers", + "temperature": "Temperatura", + "highestTemperature": "Temperatura més alta", + "primaryTemperatureSensor": "Sensor principal", + "gpu": { + "title": "GPU", + "noDevice": "No s'ha detectat cap GPU NVIDIA. Instal·leu el controlador NVIDIA (proporciona nvidia-smi) per veure les mètriques de la GPU.", + "driver": "Conductor {{version}}", + "utilization": "Utilització", + "memory": "VRAM", + "temperature": "Temperatura", + "power": "Poder", + "fan": "Ventilador", + "processes": "Processos de la GPU", + "noProcesses": "Cap procés utilitza la GPU" + }, + "failedToFetchHostConfig": "No s'ha pogut obtenir la configuració de l'amfitrió", + "serverOffline": "Servidor fora de línia", + "cannotFetchMetrics": "No es poden obtenir mètriques del servidor fora de línia", + "totpFailed": "La verificació TOTP ha fallat", + "noneAuthNotSupported": "Les mètriques de l'amfitrió no admeten el tipus d'autenticació \"cap\".", + "noHostSelected": "No s'ha seleccionat cap amfitrió", + "load": "Carrega", + "systemInfo": "Informació del sistema", + "hostname": "Nom d'amfitrió", + "operatingSystem": "Sistema operatiu", + "kernel": "Nucli", + "seconds": "segons", + "networkInterfaces": "Interfícies de xarxa", + "noInterfacesFound": "No s'han trobat interfícies de xarxa", + "noProcessesFound": "No s'han trobat processos", + "processesTotal": "total", + "processesRunning": "corrent", + "loginStats": "Estadístiques d'inici de sessió SSH", + "noRecentLoginData": "Sense dades d'inici de sessió recents", + "executingQuickAction": "Executant {{name}}...", + "quickActionSuccess": "{{name}} s'ha completat correctament", + "quickActionFailed": "{{name}} ha fallat", + "quickActionError": "No s'ha pogut executar {{name}}", + "ports": { + "title": "Ports d'escolta", + "protocol": "Protocol", + "port": "Port", + "address": "Adreça", + "process": "Procés", + "search": "Cerca ports...", + "allProtocols": "Tot", + "noData": "No hi ha dades de ports d'escolta" + }, + "firewall": { + "title": "Tallafocs", + "inactive": "Inactiu", + "policy": "Política", + "rules": "regles", + "noRules": "No hi ha regles en aquesta cadena", + "noData": "No hi ha dades de tallafocs disponibles", + "action": "Acció", + "protocol": "Proto", + "port": "Port", + "source": "Font", + "anywhere": "A qualsevol lloc", + "chains": "cadenes" + }, + "loadAvg": "Mitjana de càrrega", + "swap": "Intercanvi", + "architecture": "Arquitectura", + "refresh": "Actualitza", + "retry": "Torna-ho a intentar", + "customize": "Personalitza el disseny", + "reset": "Restablir", + "tabLive": "En directe", + "editModeInstructions": "Arrossega les cartes per reorganitzar-les, arrossega la vora inferior per canviar-ne la mida i utilitza el botó d'amplada per canviar l'extensió d'una carta. Afegeix o elimina cartes a continuació.", + "managers": { + "services": "Serveis", + "processInspector": "Inspector de processos", + "logViewer": "Visualitzador de registre", + "cron": "Treballs cron", + "packages": "Paquets", + "ssl": "Certificats SSL", + "firewall": "Tallafocs", + "users": "Usuaris i permisos", + "healthCheck": "Controls de salut", + "diskBreakdown": "Avaria del disc", + "systemdTimers": "Temporitzadors", + "topMemory": "Top per memòria", + "noData": "Sense dades", + "sudoHint": "Establiu una contrasenya sudo per a aquest host a l'editor d'hosts per habilitar accions privilegiades.", + "filter": "Filtra...", + "start": "Inici", + "stop": "Atura", + "restart": "Reinicia", + "actionDone": "{{name}} actualitzat", + "actionFailed": "L'acció ha fallat", + "signalSent": "Senyal enviat al PID {{pid}}", + "killHint": "Clic: finalitzar (SIGTERM). Clic amb el botó dret: forçar la mort (SIGKILL).", + "working": "Treballant...", + "update": "Actualització", + "upgradeAll": "Actualitza-ho tot", + "allUpToDate": "Tot està actualitzat", + "save": "Desa", + "command": "Comandament", + "enabled": "Activat", + "cronSaved": "Crontab actualitzat", + "clients": "Clients", + "dryRun": "Sessió en sec", + "renew": "Renovar", + "noAcmeClient": "No s'ha trobat cap client ACME (certbot o acme.sh) en aquest amfitrió.", + "addInputRule": "Afegeix una regla INPUT", + "firewallWarning": "Els canvis només són en temps d'execució fins que persisteixen. Aneu amb compte de no bloquejar-vos l'accés.", + "ruleApplied": "Regla aplicada", + "invalidPort": "Introduïu un port vàlid (1-65535)", + "newUsername": "Nou nom d'usuari", + "addUser": "Afegeix", + "deleteUser": "Suprimeix l'usuari", + "noHealthChecks": "Encara no s'ha configurat cap comprovació d'estat.", + "follow": "Segueix", + "noLogData": "No hi ha sortida de registre.", + "tree": "Arbre", + "enableDisable": "Activa / desactiva a l'arrencada", + "grantSudo": "Concedir sudo", + "revokeSudo": "Revoca sudo", + "sslIssueCert": "Emetre certificat", + "sslExpired": "Caducat", + "sslInDays": "en {{days}}d", + "sslNeedDomain": "Introduïu com a mínim un domini", + "sslIssued": "Certificat emès", + "sslDomainsPlaceholder": "exemple.com, www.exemple.com", + "sslHttpStandalone": "HTTP (autònom)", + "sslHttpWebroot": "HTTP (arrel web)", + "sslDns": "DNS", + "sslDnsProvider": "Proveïdor de DNS (per exemple, Cloudflare)", + "sslIssueHint": "Les credencials del proveïdor DNS ja han d'estar configurades a l'amfitrió.", + "sslRevoke": "Revoca el certificat", + "sslRevoked": "Certificat revocat", + "sslRevokeConfirm": "Voleu revocar i eliminar el certificat \"{{name}}\"? Això no es pot desfer.", + "healthRun": "Corre", + "healthName": "Nom", + "healthTarget": "Host / adreça", + "healthAddCheck": "Afegeix un xec", + "healthSaved": "S'han desat les comprovacions d'estat", + "healthMissingFields": "Cada comprovació necessita un nom i un objectiu", + "logFile": "Fitxer", + "logUnit": "Unitat", + "logCustomPath": "Ruta personalitzada a /var/log (opcional)", + "logGrep": "Línies de filtre...", + "firewallPersist": "Regles de persistència", + "firewallPersisted": "Les regles del tallafocs van persistir", + "wireguard": "WireGuard", + "tailscale": "Escala de cua", + "wgNotInstalled": "WireGuard no està instal·lat en aquest host.", + "wgNoInterfaces": "No hi ha cap interfície de WireGuard configurada", + "wgInterfaceUp": "Porta a col·lació", + "wgInterfaceDown": "Baixar", + "wgBringingUp": "S'està mostrant {{name}}...", + "wgBringingDown": "Baixant {{name}}...", + "wgInterfaceUpDone": "{{name}} està activat", + "wgInterfaceDownDone": "{{name}} està apagat", + "wgListenPort": "Port", + "wgPublicKey": "Clau pública", + "wgEndpoint": "Punt final", + "wgAllowedIPs": "IP permeses", + "wgLastHandshake": "Última encaixada de mans", + "wgHandshakeNever": "Mai", + "wgTransfer": "Transferència", + "tsNotInstalled": "Tailscale no està instal·lat en aquest amfitrió", + "tsRunning": "Córrer", + "tsStopped": "Aturat", + "tsEnable": "Connecta", + "tsDisable": "Desconnecta", + "tsEnabling": "Connectant a Tailscale...", + "tsDisabling": "Desconnectant de Tailscale...", + "tsEnabled": "Escala de cua connectada", + "tsDisabled": "Escala de cua desconnectada", + "tsIPs": "IP de cua escala", + "tsPeers": "Compañers", + "tsOnline": "En línia", + "tsOffline": "Fora de línia", + "tsExitNode": "Node de sortida", + "tsExitNodeActive": "Node de sortida actiu", + "tsHostname": "Nom d'amfitrió" + } + }, + "metricsHistory": { + "title": "Historial de mètriques", + "historySuffix": "Història", + "cpuMemoryDisk": "CPU / Memòria / Disc", + "network": "Xarxa", + "download": "RX", + "upload": "TX", + "noData": "No hi ha dades històriques disponibles per a aquest interval de temps.", + "custom": "Personalitzat", + "to": "a", + "apply": "Aplica", + "viewHistory": "Veure l'historial" + }, + "proxmoxStats": { + "tabTitle": "Estadístiques de Proxmox", + "cpuUsage": "Ús de la CPU", + "memoryUsage": "Ús de memòria", + "diskUsage": "Ús del disc", + "networkInterfaces": "Interfícies de xarxa", + "uptime": "Temps de funcionament", + "systemInfo": "Informació del sistema", + "guestsSummary": "Convidats", + "storagePools": "Piscines d'emmagatzematge", + "clusterHealth": "Salut del clúster", + "cpuCores_one": "{{count}} Nucli", + "cpuCores_other": "{{count}} Nuclis", + "used": "Usat", + "total": "Total", + "hostname": "Nom d'amfitrió", + "kernel": "Nucli", + "pveVersion": "Versió PVE", + "name": "Nom", + "status": "Estat", + "type": "Tipus", + "cpu": "CPU", + "mem": "Memòria", + "disk": "Disc", + "running": "Córrer", + "stopped": "Aturat", + "guestCounts": "{{running}}/{{total}} en execució", + "inactive": "Inactiu", + "notClustered": "Node autònom (no forma part d'un clúster)", + "quorate": "Quota", + "notQuorate": "Sense quòrum", + "nodeOnline": "En línia", + "nodeOffline": "Fora de línia", + "noHostSelected": "No s'ha seleccionat cap amfitrió", + "pveshNotFound": "No s'ha trobat pvesh: és un node de Proxmox?", + "nodeDetectionFailed": "No s'ha pogut determinar un nom de node Proxmox vàlid", + "connecting": "Connectant...", + "connectionFailed": "No s'ha pogut connectar al node de Proxmox.", + "refresh": "Actualitza", + "searchGuests": "Cerca convidats...", + "filterAll": "Tot", + "filterVm": "màquina virtual", + "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." + }, + "nav": { + "hostMetrics": "Mètriques de l'amfitrió" + }, + "hosts": { + "tabHostMetrics": "Mètriques de l'amfitrió", + "enableProxmoxStats": "Activa les estadístiques de Proxmox", + "enableProxmoxStatsDesc": "Mostra una pestanya Estadístiques de Proxmox per a aquest amfitrió amb estadístiques en directe de node, convidat, emmagatzematge i clúster recollides a través de SSH.", + "proxmoxStatsPollInterval": "Interval de sondeig (segons)", + "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ó", + "metricsCollectionLabel": "Col·lecció de mètriques", + "enableMetricsLabel": "Activa les mètriques", + "enableMetricsDesc": "Recopila mètriques de CPU, RAM, disc i altres d'aquest amfitrió", + "useGlobalMetrics": "Utilitza l'interval global", + "useGlobalMetricsDesc": "Substitueix amb l'interval de mètriques de tot el servidor", + "metricsIntervalS": "Interval de mètriques (s)", + "metricsIntervalDesc2": "Segons entre instantànies de mètriques", + "excludedMountsLabel": "Muntatges exclosos", + "monitoredMountsLabel": "Rutes monitoritzades personalitzades", + "monitoredMountsDesc": "Afegiu camins que no estiguin exposats com a muntatges separats, inclosos els camins de l'Assistent d'inici muntats per vinculació, com ara /config.", + "monitoredMountPathPlaceholder": "Camí (/config, /mnt/data)", + "monitoredMountLabelPlaceholder": "Etiqueta (opcional)", + "addMonitoredMount": "Afegeix un camí", + "excludedMountsDesc": "Amaga punts de muntatge o tipus de sistemes de fitxers específics (per exemple, nfs, cifs) de l'ús del disc i de les alertes per a aquest amfitrió.", + "excludedMountsPlaceholder": "Ruta de muntatge (/mnt/nas) o tipus de sistema de fitxers (nfs, cifs)", + "excludedMountsEmpty": "No s'han exclòs muntatges. Es mostren tots els sistemes de fitxers detectats.", + "addExcludedMount": "Afegeix", + "visibleWidgets": "Widgets visibles", + "widgetsMovedToHostMetrics": "Ara les targetes s'afegeixen, s'organitzen i es canvien de mida directament a la pestanya Mètriques de l'amfitrió. Obriu Mètriques de l'amfitrió per a aquest amfitrió i utilitzeu Personalitza per triar quines targetes es mostren.", + "quickActionsLabel": "Accions ràpides", + "quickActionsToolbar": "Les accions ràpides apareixen com a botons a la barra d'eines de mètriques de l'amfitrió per executar ordres amb un sol clic.", + "noQuickActions": "Encara no hi ha accions ràpides.", + "buttonLabel": "Etiqueta del botó", + "selectSnippetPlaceholder": "Selecciona un fragment...", + "addActionBtn": "Afegeix una acció" + }, + "onboarding": { + "feature_metrics": "Mètriques i alertes", + "feature_metrics_desc": "Fes un seguiment de la CPU, la memòria i el disc al llarg del temps i rep alertes quan es facin malbé." + }, + "admin": { + "metricsHistoryRetention": "Retenció de l'historial de mètriques", + "metricsHistoryRetentionRange": "D'1 a 90 dies", + "days": "dies" + }, + "homepage": { + "noData": "No hi ha dades disponibles", + "showCurrentValue": "Mostra el valor actual", + "chartMetric": "Mètrica", + "metricRange": "Rang" + } +} diff --git a/plugins/host-metrics/locales/translated/cs_CZ.json b/plugins/host-metrics/locales/translated/cs_CZ.json new file mode 100644 index 000000000..2686a4f80 --- /dev/null +++ b/plugins/host-metrics/locales/translated/cs_CZ.json @@ -0,0 +1,313 @@ +{ + "hostMetrics": { + "cpu": "Procesor", + "memory": "Paměť", + "disk": "Disk", + "network": "Síť", + "uptime": "Doba provozuschopnosti", + "processes": "Procesy", + "available": "K dispozici", + "free": "Uvolnit", + "connecting": "Spojovací...", + "connectionFailed": "Nepodařilo se připojit k serveru", + "naCpus": "CPU (procesory)", + "cpuCores_one": "{{count}} Jádro", + "cpuCores_other": "{{count}} Jádra", + "cpuUsage": "Využití CPU", + "memoryUsage": "Využití paměti", + "diskUsage": "Využití disku", + "selectFilesystem": "Vyberte souborový systém", + "temperature": "Teplota", + "highestTemperature": "Nejvyšší teplota", + "primaryTemperatureSensor": "Primární senzor", + "gpu": { + "title": "Grafický procesor", + "noDevice": "Nebyla detekována žádná grafická karta NVIDIA. Nainstalujte ovladač NVIDIA (obsahuje nvidia-smi) pro zobrazení metrik grafické karty.", + "driver": "Řidič {{version}}", + "utilization": "Využití", + "memory": "VRAM", + "temperature": "Dočasné", + "power": "Moc", + "fan": "Větrák", + "processes": "Procesy GPU", + "noProcesses": "Žádné procesy nepoužívají GPU" + }, + "failedToFetchHostConfig": "Nepodařilo se načíst konfiguraci hostitele", + "serverOffline": "Server offline", + "cannotFetchMetrics": "Nelze načíst metriky z offline serveru", + "totpFailed": "Ověření TOTP se nezdařilo", + "noneAuthNotSupported": "Metriky hostitele nepodporují typ ověřování „žádné“.", + "noHostSelected": "Nebyl vybrán žádný hostitel", + "load": "Zatížení", + "systemInfo": "Informace o systému", + "hostname": "Název hostitele", + "operatingSystem": "Operační systém", + "kernel": "Jádro", + "seconds": "sekundy", + "networkInterfaces": "Síťová rozhraní", + "noInterfacesFound": "Nenalezena žádná síťová rozhraní", + "noProcessesFound": "Nenalezeny žádné procesy", + "processesTotal": "celkový", + "processesRunning": "běh", + "loginStats": "Statistiky přihlášení SSH", + "noRecentLoginData": "Žádné nedávné přihlašovací údaje", + "executingQuickAction": "Spouštění {{name}}...", + "quickActionSuccess": "{{name}} úspěšně dokončeno", + "quickActionFailed": "{{name}} selhalo", + "quickActionError": "Nepodařilo se spustit {{name}}", + "ports": { + "title": "Poslouchající porty", + "protocol": "Protokol", + "port": "Přístav", + "address": "Adresa", + "process": "Proces", + "search": "Hledat porty...", + "allProtocols": "Vše", + "noData": "Žádná data naslouchajících portů" + }, + "firewall": { + "title": "Firewall", + "inactive": "Neaktivní", + "policy": "Politika", + "rules": "pravidla", + "noRules": "V tomto řetězci nejsou žádná pravidla", + "noData": "Nejsou k dispozici žádná data firewallu", + "action": "Akce", + "protocol": "Proto", + "port": "Přístav", + "source": "Zdroj", + "anywhere": "Kdekoli", + "chains": "řetězy" + }, + "loadAvg": "Průměrné zatížení", + "swap": "Výměna", + "architecture": "Architektura", + "refresh": "Obnovit", + "retry": "Zkusit znovu", + "customize": "Přizpůsobit rozvržení", + "reset": "Obnovit", + "tabLive": "Žít", + "editModeInstructions": "Přetažením karet změníte jejich uspořádání, přetažením spodního okraje změníte jejich velikost a pomocí tlačítka šířky změníte jejich rozpětí. Karty můžete přidávat nebo odebírat níže.", + "managers": { + "services": "Služby", + "processInspector": "Inspektor procesů", + "logViewer": "Prohlížeč protokolů", + "cron": "Cron úlohy", + "packages": "Balíčky", + "ssl": "SSL certifikáty", + "firewall": "Firewall", + "users": "Uživatelé a oprávnění", + "healthCheck": "Kontroly stavu", + "diskBreakdown": "Rozpad disku", + "systemdTimers": "Časovače", + "topMemory": "Nejlépe podle paměti", + "noData": "Žádná data", + "sudoHint": "V editoru hostitelů nastavte pro tento hostitel heslo sudo, abyste povolili privilegované akce.", + "filter": "Filtr...", + "start": "Start", + "stop": "Zastávka", + "restart": "Restartovat", + "actionDone": "{{name}} aktualizováno", + "actionFailed": "Akce se nezdařila", + "signalSent": "Signál odeslaný do PID {{pid}}", + "killHint": "Kliknutí: ukončení (SIGTERM). Kliknutí pravým tlačítkem: vynucené ukončení (SIGKILL).", + "working": "Pracovní...", + "update": "Aktualizovat", + "upgradeAll": "Upgradovat vše", + "allUpToDate": "Všechno je aktuální", + "save": "Uložit", + "command": "Příkaz", + "enabled": "Povoleno", + "cronSaved": "Crontab aktualizován", + "clients": "Klienti", + "dryRun": "Zkušební provoz", + "renew": "Obnovit", + "noAcmeClient": "Na tomto hostiteli nebyl nalezen žádný klient ACME (certbot ani acme.sh).", + "addInputRule": "Přidat pravidlo INPUT", + "firewallWarning": "Změny jsou platné pouze za běhu, dokud nejsou trvalé. Dávejte pozor, abyste se k nim nezablokovali.", + "ruleApplied": "Pravidlo bylo použito", + "invalidPort": "Zadejte platný port (1-65535)", + "newUsername": "Nové uživatelské jméno", + "addUser": "Přidat", + "deleteUser": "Smazat uživatele", + "noHealthChecks": "Zatím nejsou nakonfigurovány žádné kontroly stavu.", + "follow": "Následovat", + "noLogData": "Žádný výstup protokolu.", + "tree": "Strom", + "enableDisable": "Povolit/zakázat při spuštění", + "grantSudo": "Udělit sudo", + "revokeSudo": "Zrušit sudo", + "sslIssueCert": "Vydat certifikát", + "sslExpired": "Platnost vypršela", + "sslInDays": "v {{days}}d", + "sslNeedDomain": "Zadejte alespoň jednu doménu", + "sslIssued": "Vydaný certifikát", + "sslDomainsPlaceholder": "example.com, www.example.com", + "sslHttpStandalone": "HTTP (samostatný)", + "sslHttpWebroot": "HTTP (webroot)", + "sslDns": "DNS", + "sslDnsProvider": "Poskytovatel DNS (např. cloudflare)", + "sslIssueHint": "Přihlašovací údaje poskytovatele DNS musí být již na hostiteli nakonfigurovány.", + "sslRevoke": "Zrušit certifikát", + "sslRevoked": "Certifikát zrušen", + "sslRevokeConfirm": "Zrušit a odstranit certifikát „{{name}}“? Tuto akci nelze vrátit zpět.", + "healthRun": "Běh", + "healthName": "Jméno", + "healthTarget": "Hostitel / adresa", + "healthAddCheck": "Přidat šek", + "healthSaved": "Kontroly stavu uloženy", + "healthMissingFields": "Každá kontrola potřebuje název a cíl.", + "logFile": "Soubor", + "logUnit": "Jednotka", + "logCustomPath": "Vlastní cesta v /var/log (volitelné)", + "logGrep": "Filtrační potrubí...", + "firewallPersist": "Pravidla pro trvalé uložení", + "firewallPersisted": "Pravidla firewallu přetrvávala", + "wireguard": "WireGuard", + "tailscale": "Koncová stupnice", + "wgNotInstalled": "WireGuard není na tomto hostiteli nainstalován", + "wgNoInterfaces": "Žádná nakonfigurovaná rozhraní WireGuard", + "wgInterfaceUp": "Vychovat", + "wgInterfaceDown": "Snížit", + "wgBringingUp": "Vyvolávám {{name}}...", + "wgBringingDown": "Snižování {{name}}...", + "wgInterfaceUpDone": "{{name}} je aktivní", + "wgInterfaceDownDone": "{{name}} je nefunkční", + "wgListenPort": "Přístav", + "wgPublicKey": "Veřejný klíč", + "wgEndpoint": "Koncový bod", + "wgAllowedIPs": "Povolené IP adresy", + "wgLastHandshake": "Poslední podání ruky", + "wgHandshakeNever": "Nikdy", + "wgTransfer": "Převod", + "tsNotInstalled": "Tailscale není na tomto hostiteli nainstalován", + "tsRunning": "Běh", + "tsStopped": "Zastaveno", + "tsEnable": "Připojit", + "tsDisable": "Odpojit", + "tsEnabling": "Připojování k Tailscale...", + "tsDisabling": "Odpojování od Tailscale...", + "tsEnabled": "Koncová váha připojena", + "tsDisabled": "Tailscale odpojeno", + "tsIPs": "IP adresy Tailscale", + "tsPeers": "Vrstevníci", + "tsOnline": "Online", + "tsOffline": "Offline", + "tsExitNode": "Východový uzel", + "tsExitNodeActive": "Výstupní uzel je aktivní", + "tsHostname": "Název hostitele" + } + }, + "metricsHistory": { + "title": "Historie metrik", + "historySuffix": "Dějiny", + "cpuMemoryDisk": "CPU / Paměť / Disk", + "network": "Síť", + "download": "RX", + "upload": "Texas", + "noData": "Pro toto časové období nejsou k dispozici žádná historická data.", + "custom": "Zvyk", + "to": "na", + "apply": "Použít", + "viewHistory": "Zobrazit historii" + }, + "proxmoxStats": { + "tabTitle": "Statistiky Proxmoxu", + "cpuUsage": "Využití CPU", + "memoryUsage": "Využití paměti", + "diskUsage": "Využití disku", + "networkInterfaces": "Síťová rozhraní", + "uptime": "Doba provozuschopnosti", + "systemInfo": "Informace o systému", + "guestsSummary": "Hosté", + "storagePools": "Úložné fondy", + "clusterHealth": "Zdraví klastru", + "cpuCores_one": "{{count}} Jádro", + "cpuCores_other": "{{count}} Jádra", + "used": "Použitý", + "total": "Celkový", + "hostname": "Název hostitele", + "kernel": "Jádro", + "pveVersion": "PVE verze", + "name": "Jméno", + "status": "Postavení", + "type": "Typ", + "cpu": "Procesor", + "mem": "Paměť", + "disk": "Disk", + "running": "Běh", + "stopped": "Zastaveno", + "guestCounts": "{{running}}/{{total}} běží", + "inactive": "Neaktivní", + "notClustered": "Samostatný uzel (není součástí clusteru)", + "quorate": "Kvorát", + "notQuorate": "Není usnášeníschopný", + "nodeOnline": "Online", + "nodeOffline": "Offline", + "noHostSelected": "Nebyl vybrán žádný hostitel", + "pveshNotFound": "pvesh nenalezen - je to uzel Proxmox?", + "nodeDetectionFailed": "Nelze určit platný název uzlu Proxmox.", + "connecting": "Spojovací...", + "connectionFailed": "Nepodařilo se připojit k uzlu Proxmox", + "refresh": "Obnovit", + "searchGuests": "Hledat hosty...", + "filterAll": "Vše", + "filterVm": "virtuální počítač", + "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é." + }, + "nav": { + "hostMetrics": "Metriky hostitele" + }, + "hosts": { + "tabHostMetrics": "Metriky hostitele", + "enableProxmoxStats": "Povolit statistiky Proxmoxu", + "enableProxmoxStatsDesc": "Zobrazit kartu Statistiky Proxmoxu pro tohoto hostitele s aktivními statistikami uzlů, hostů, úložišť a clusterů shromážděnými přes SSH.", + "proxmoxStatsPollInterval": "Interval dotazování (sekundy)", + "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", + "metricsCollectionLabel": "Sbírka metrik", + "enableMetricsLabel": "Povolit metriky", + "enableMetricsDesc": "Shromažďujte metriky CPU, RAM, disku a další z tohoto hostitele", + "useGlobalMetrics": "Použít globální interval", + "useGlobalMetricsDesc": "Přepsat intervalem metrik na úrovni celého serveru", + "metricsIntervalS": "Interval metrik (y)", + "metricsIntervalDesc2": "Sekundy mezi snímky metrik", + "excludedMountsLabel": "Vyloučené držáky", + "monitoredMountsLabel": "Vlastní monitorované cesty", + "monitoredMountsDesc": "Přidejte cesty, které nejsou zobrazeny jako samostatné připojení, včetně cest připojených k Home Assistant, jako je /config.", + "monitoredMountPathPlaceholder": "Cesta (/config, /mnt/data)", + "monitoredMountLabelPlaceholder": "Štítek (volitelné)", + "addMonitoredMount": "Přidat cestu", + "excludedMountsDesc": "Skrýt konkrétní body připojení nebo typy souborových systémů (např. nfs, cifs) před využitím disku a upozorněními pro tento hostitel.", + "excludedMountsPlaceholder": "Cesta připojení (/mnt/nas) nebo typ souborového systému (nfs, cifs)", + "excludedMountsEmpty": "Žádné připojení nejsou vyloučena. Zobrazí se všechny detekované souborové systémy.", + "addExcludedMount": "Přidat", + "visibleWidgets": "Viditelné widgety", + "widgetsMovedToHostMetrics": "Karty se nyní přidávají, uspořádávají a mění jejich velikost přímo na kartě Metriky hostitele. Otevřete Metriky hostitele pro tohoto hostitele a pomocí možnosti Přizpůsobit vyberte, které karty se zobrazí.", + "quickActionsLabel": "Rychlé akce", + "quickActionsToolbar": "Rychlé akce se zobrazují jako tlačítka v panelu nástrojů Metriky hostitele pro spuštění příkazů jedním kliknutím.", + "noQuickActions": "Zatím žádné rychlé akce.", + "buttonLabel": "Štítek tlačítka", + "selectSnippetPlaceholder": "Vybrat úryvek...", + "addActionBtn": "Přidat akci" + }, + "onboarding": { + "feature_metrics": "Metriky a upozornění", + "feature_metrics_desc": "Sledujte CPU, paměť a disk v průběhu času a nechte se upozornit, když se pokazí." + }, + "admin": { + "metricsHistoryRetention": "Uchovávání historie metrik", + "metricsHistoryRetentionRange": "1 až 90 dní", + "days": "dny" + }, + "homepage": { + "noData": "Nejsou k dispozici žádná data", + "showCurrentValue": "Zobrazit aktuální hodnotu", + "chartMetric": "Metrický", + "metricRange": "Rozsah" + } +} diff --git a/plugins/host-metrics/locales/translated/da_DK.json b/plugins/host-metrics/locales/translated/da_DK.json new file mode 100644 index 000000000..787792ab3 --- /dev/null +++ b/plugins/host-metrics/locales/translated/da_DK.json @@ -0,0 +1,313 @@ +{ + "hostMetrics": { + "cpu": "CPU", + "memory": "Hukommelse", + "disk": "Disk", + "network": "Netværk", + "uptime": "Oppetid", + "processes": "Processer", + "available": "Tilgængelig", + "free": "Gratis", + "connecting": "Forbinder...", + "connectionFailed": "Kunne ikke oprette forbindelse til serveren", + "naCpus": "Ikke tilgængelig CPU(er)", + "cpuCores_one": "{{count}} Kerne", + "cpuCores_other": "{{count}} Kerner", + "cpuUsage": "CPU-forbrug", + "memoryUsage": "Hukommelsesforbrug", + "diskUsage": "Diskforbrug", + "selectFilesystem": "Vælg filsystem", + "temperature": "Temperatur", + "highestTemperature": "Højeste temperatur", + "primaryTemperatureSensor": "Primær sensor", + "gpu": { + "title": "GPU", + "noDevice": "Ingen NVIDIA GPU fundet. Installer NVIDIA-driveren (den leverer nvidia-smi) for at se GPU-målinger.", + "driver": "Chauffør {{version}}", + "utilization": "Udnyttelse", + "memory": "VRAM", + "temperature": "Temp.", + "power": "Magt", + "fan": "Ventilator", + "processes": "GPU-processer", + "noProcesses": "Ingen processer bruger GPU'en" + }, + "failedToFetchHostConfig": "Kunne ikke hente værtkonfigurationen", + "serverOffline": "Server offline", + "cannotFetchMetrics": "Kan ikke hente målinger fra offlineserveren", + "totpFailed": "TOTP-bekræftelse mislykkedes", + "noneAuthNotSupported": "Host Metrics understøtter ikke godkendelsestypen 'ingen'.", + "noHostSelected": "Ingen vært valgt", + "load": "Indlæs", + "systemInfo": "Systemoplysninger", + "hostname": "Værtsnavn", + "operatingSystem": "Operativsystem", + "kernel": "Kernen", + "seconds": "sekunder", + "networkInterfaces": "Netværksgrænseflader", + "noInterfacesFound": "Ingen netværksgrænseflader fundet", + "noProcessesFound": "Ingen processer fundet", + "processesTotal": "total", + "processesRunning": "løb", + "loginStats": "SSH-loginstatistik", + "noRecentLoginData": "Ingen nylige logindata", + "executingQuickAction": "Udfører {{name}}...", + "quickActionSuccess": "{{name}} gennemført", + "quickActionFailed": "{{name}} mislykkedes", + "quickActionError": "Kunne ikke udføre {{name}}", + "ports": { + "title": "Lytteporte", + "protocol": "Protokol", + "port": "Havn", + "address": "Adresse", + "process": "Behandle", + "search": "Søg efter porte...", + "allProtocols": "Alle", + "noData": "Ingen data om lytteporte" + }, + "firewall": { + "title": "Firewall", + "inactive": "Inaktiv", + "policy": "Politik", + "rules": "regler", + "noRules": "Ingen regler i denne kæde", + "noData": "Ingen firewalldata tilgængelige", + "action": "Handling", + "protocol": "Proto", + "port": "Havn", + "source": "Kilde", + "anywhere": "Hvor som helst", + "chains": "kæder" + }, + "loadAvg": "Indlæs gennemsnit", + "swap": "Byt", + "architecture": "Arkitektur", + "refresh": "Opfriske", + "retry": "Prøv igen", + "customize": "Tilpas layout", + "reset": "Nulstil", + "tabLive": "Levende", + "editModeInstructions": "Træk kort for at omarrangere, træk i den nederste kant for at ændre størrelsen, og brug breddeknappen til at ændre et korts spændvidde. Tilføj eller fjern kort nedenfor.", + "managers": { + "services": "Tjenester", + "processInspector": "Procesinspektør", + "logViewer": "Logfremviser", + "cron": "Cron-job", + "packages": "Pakker", + "ssl": "SSL-certifikater", + "firewall": "Firewall", + "users": "Brugere og tilladelser", + "healthCheck": "Sundhedstjek", + "diskBreakdown": "Disknedbrydning", + "systemdTimers": "Timere", + "topMemory": "Top efter hukommelse", + "noData": "Ingen data", + "sudoHint": "Angiv en sudo-adgangskode til denne vært i værtseditoren for at aktivere privilegerede handlinger.", + "filter": "Filter...", + "start": "Starte", + "stop": "Stop", + "restart": "Genstart", + "actionDone": "{{name}} opdateret", + "actionFailed": "Handlingen mislykkedes", + "signalSent": "Signal sendt til PID {{pid}}", + "killHint": "Klik: afslut (SIGTERM). Højreklik: tvungen afbrydelse (SIGKILL).", + "working": "Arbejder...", + "update": "Opdatering", + "upgradeAll": "Opgrader alle", + "allUpToDate": "Alt er opdateret", + "save": "Spare", + "command": "Kommando", + "enabled": "Aktiveret", + "cronSaved": "Crontab opdateret", + "clients": "Klienter", + "dryRun": "Tørløb", + "renew": "Forny", + "noAcmeClient": "Ingen ACME-klient (certbot eller acme.sh) fundet på denne vært.", + "addInputRule": "Tilføj INPUT-regel", + "firewallWarning": "Ændringer gælder kun for kørsel, indtil de bevares. Pas på ikke at låse dig selv ude.", + "ruleApplied": "Regel anvendt", + "invalidPort": "Indtast en gyldig port (1-65535)", + "newUsername": "Nyt brugernavn", + "addUser": "Tilføje", + "deleteUser": "Slet bruger", + "noHealthChecks": "Ingen sundhedstjek konfigureret endnu.", + "follow": "Følge", + "noLogData": "Ingen log-output.", + "tree": "Træ", + "enableDisable": "Aktivér/deaktiver ved opstart", + "grantSudo": "Giv sudo", + "revokeSudo": "Tilbagekald sudo", + "sslIssueCert": "Udstedelsescertifikat", + "sslExpired": "Udløbet", + "sslInDays": "i {{days}}d", + "sslNeedDomain": "Angiv mindst ét domæne", + "sslIssued": "Certifikat udstedt", + "sslDomainsPlaceholder": "eksempel.com, www.eksempel.com", + "sslHttpStandalone": "HTTP (selvstændig)", + "sslHttpWebroot": "HTTP (webroot)", + "sslDns": "DNS", + "sslDnsProvider": "DNS-udbyder (f.eks. Cloudflare)", + "sslIssueHint": "DNS-udbyderens legitimationsoplysninger skal allerede være konfigureret på værten.", + "sslRevoke": "Tilbagekald certifikat", + "sslRevoked": "Certifikat tilbagekaldt", + "sslRevokeConfirm": "Tilbagekald og fjern certifikatet \"{{name}}\"? Dette kan ikke fortrydes.", + "healthRun": "Løbe", + "healthName": "Navn", + "healthTarget": "Vært / adresse", + "healthAddCheck": "Tilføj check", + "healthSaved": "Sundhedstjek gemt", + "healthMissingFields": "Hver check skal have et navn og et mål", + "logFile": "Fil", + "logUnit": "Enhed", + "logCustomPath": "Brugerdefineret sti under /var/log (valgfrit)", + "logGrep": "Filtrer linjer...", + "firewallPersist": "Vedvarende regler", + "firewallPersisted": "Firewallregler bevares", + "wireguard": "WireGuard", + "tailscale": "Haleskala", + "wgNotInstalled": "WireGuard er ikke installeret på denne vært", + "wgNoInterfaces": "Ingen WireGuard-grænseflader konfigureret", + "wgInterfaceUp": "Bring op", + "wgInterfaceDown": "Bring ned", + "wgBringingUp": "Bringer {{name}} op...", + "wgBringingDown": "Bringer {{name}} ned...", + "wgInterfaceUpDone": "{{name}} er oppe", + "wgInterfaceDownDone": "{{name}} er nede", + "wgListenPort": "Havn", + "wgPublicKey": "Offentlig nøgle", + "wgEndpoint": "Endepunkt", + "wgAllowedIPs": "Tilladte IP-adresser", + "wgLastHandshake": "Sidste håndtryk", + "wgHandshakeNever": "Aldrig", + "wgTransfer": "Overførsel", + "tsNotInstalled": "Tailscale er ikke installeret på denne vært", + "tsRunning": "Løb", + "tsStopped": "Stoppet", + "tsEnable": "Forbinde", + "tsDisable": "Afbryde", + "tsEnabling": "Forbinder til Tailscale...", + "tsDisabling": "Afbryder forbindelsen til Tailscale...", + "tsEnabled": "Haleskala forbundet", + "tsDisabled": "Haleskalaen er afbrudt", + "tsIPs": "Haleskalerings-IP'er", + "tsPeers": "Peers", + "tsOnline": "Online", + "tsOffline": "Offline", + "tsExitNode": "Udgangsnode", + "tsExitNodeActive": "Afslut node aktiv", + "tsHostname": "Værtsnavn" + } + }, + "metricsHistory": { + "title": "Metrikhistorik", + "historySuffix": "Historie", + "cpuMemoryDisk": "CPU / Hukommelse / Disk", + "network": "Netværk", + "download": "RX", + "upload": "TX", + "noData": "Der er ingen historiske data tilgængelige for dette tidsinterval.", + "custom": "Skik", + "to": "til", + "apply": "Anvende", + "viewHistory": "Vis historik" + }, + "proxmoxStats": { + "tabTitle": "Proxmox-statistik", + "cpuUsage": "CPU-forbrug", + "memoryUsage": "Hukommelsesforbrug", + "diskUsage": "Diskforbrug", + "networkInterfaces": "Netværksgrænseflader", + "uptime": "Oppetid", + "systemInfo": "Systemoplysninger", + "guestsSummary": "Gæster", + "storagePools": "Opbevaringsbassiner", + "clusterHealth": "Klyngesundhed", + "cpuCores_one": "{{count}} Kerne", + "cpuCores_other": "{{count}} Kerner", + "used": "Brugt", + "total": "Total", + "hostname": "Værtsnavn", + "kernel": "Kernen", + "pveVersion": "PVE-version", + "name": "Navn", + "status": "Status", + "type": "Type", + "cpu": "CPU", + "mem": "Mem", + "disk": "Disk", + "running": "Løb", + "stopped": "Stoppet", + "guestCounts": "{{running}}/{{total}} løber", + "inactive": "Inaktiv", + "notClustered": "Selvstændig node (ikke en del af en klynge)", + "quorate": "Kvorat", + "notQuorate": "Ikke quorable", + "nodeOnline": "Online", + "nodeOffline": "Offline", + "noHostSelected": "Ingen vært valgt", + "pveshNotFound": "pvesh ikke fundet - er dette en Proxmox-node?", + "nodeDetectionFailed": "Kan ikke bestemme et gyldigt Proxmox-nodenavn", + "connecting": "Forbinder...", + "connectionFailed": "Kunne ikke oprette forbindelse til Proxmox-noden", + "refresh": "Opfriske", + "searchGuests": "Søg gæster...", + "filterAll": "Alle", + "filterVm": "VM", + "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." + }, + "nav": { + "hostMetrics": "Værtsmålinger" + }, + "hosts": { + "tabHostMetrics": "Værtsmålinger", + "enableProxmoxStats": "Aktivér Proxmox-statistik", + "enableProxmoxStatsDesc": "Vis en Proxmox Stats-faneblad for denne vært med live node-, gæst-, lager- og klyngestatistikker indsamlet via SSH.", + "proxmoxStatsPollInterval": "Afstemningsinterval (sekunder)", + "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", + "metricsCollectionLabel": "Metriksamling", + "enableMetricsLabel": "Aktivér metrikker", + "enableMetricsDesc": "Indsaml CPU-, RAM-, disk- og andre målinger fra denne vært", + "useGlobalMetrics": "Brug globalt interval", + "useGlobalMetricsDesc": "Tilsidesæt med det serveromfattende metrikinterval", + "metricsIntervalS": "Målinger Interval (s)", + "metricsIntervalDesc2": "Sekunder mellem metriske snapshots", + "excludedMountsLabel": "Ekskluderede monteringer", + "monitoredMountsLabel": "Brugerdefinerede overvågede stier", + "monitoredMountsDesc": "Tilføj stier, der ikke er eksponeret som separate monteringer, herunder bind-monterede Home Assistant-stier såsom /config.", + "monitoredMountPathPlaceholder": "Sti (/config, /mnt/data)", + "monitoredMountLabelPlaceholder": "Etiket (valgfrit)", + "addMonitoredMount": "Tilføj sti", + "excludedMountsDesc": "Skjul specifikke monteringspunkter eller filsystemtyper (f.eks. nfs, cifs) fra diskbrug og advarsler for denne vært.", + "excludedMountsPlaceholder": "Monteringssti (/mnt/nas) eller filsystemtype (nfs, cifs)", + "excludedMountsEmpty": "Ingen monteringer er udelukket. Alle detekterede filsystemer vises.", + "addExcludedMount": "Tilføje", + "visibleWidgets": "Synlige widgets", + "widgetsMovedToHostMetrics": "Kort tilføjes, arrangeres og skaleres nu direkte i fanen Værtsmål. Åbn Værtsmål for denne vært, og brug Tilpas til at vælge, hvilke kort der vises.", + "quickActionsLabel": "Hurtige handlinger", + "quickActionsToolbar": "Hurtige handlinger vises som knapper i værktøjslinjen Host Metrics til udførelse af kommandoer med et enkelt klik.", + "noQuickActions": "Ingen hurtige handlinger endnu.", + "buttonLabel": "Knapmærke", + "selectSnippetPlaceholder": "Vælg uddrag...", + "addActionBtn": "Tilføj handling" + }, + "onboarding": { + "feature_metrics": "Målinger og advarsler", + "feature_metrics_desc": "Spor CPU, hukommelse og disk over tid, og få en advarsel, når de bliver dårlige." + }, + "admin": { + "metricsHistoryRetention": "Opbevaring af metrikhistorik", + "metricsHistoryRetentionRange": "1 til 90 dage", + "days": "dage" + }, + "homepage": { + "noData": "Ingen data tilgængelige", + "showCurrentValue": "Vis aktuel værdi", + "chartMetric": "Metrisk", + "metricRange": "Rækkevidde" + } +} diff --git a/plugins/host-metrics/locales/translated/de_DE.json b/plugins/host-metrics/locales/translated/de_DE.json new file mode 100644 index 000000000..c77ae891f --- /dev/null +++ b/plugins/host-metrics/locales/translated/de_DE.json @@ -0,0 +1,313 @@ +{ + "hostMetrics": { + "cpu": "CPU", + "memory": "Arbeitsspeicher", + "disk": "Festplatte", + "network": "Netzwerk", + "uptime": "Betriebszeit", + "processes": "Prozesse", + "available": "Verfügbar", + "free": "Frei", + "connecting": "Verbinden...", + "connectionFailed": "Verbindung zum Server fehlgeschlagen", + "naCpus": "N/A CPU(s)", + "cpuCores_one": "{{count}} Kern", + "cpuCores_other": "{{count}} Kerne", + "cpuUsage": "CPU-Auslastung", + "memoryUsage": "Arbeitsspeicherauslastung", + "diskUsage": "Festplattenauslastung", + "selectFilesystem": "Dateisystem auswählen", + "temperature": "Temperatur", + "highestTemperature": "Höchste Temperatur", + "primaryTemperatureSensor": "Primärsensor", + "gpu": { + "title": "GPU", + "noDevice": "Es wurde keine NVIDIA-GPU erkannt. Installieren Sie den NVIDIA-Treiber (dieser stellt nvidia-smi bereit), um die GPU-Metriken anzuzeigen.", + "driver": "Fahrer {{version}}", + "utilization": "Verwendung", + "memory": "VRAM", + "temperature": "Temp", + "power": "Leistung", + "fan": "Lüfter", + "processes": "GPU-Prozesse", + "noProcesses": "Es werden keine Prozesse die GPU nutzen." + }, + "failedToFetchHostConfig": "Fehler beim Abrufen der Host-Konfiguration", + "serverOffline": "Server offline", + "cannotFetchMetrics": "Metriken können nicht vom Offline-Server abgerufen werden", + "totpFailed": "TOTP-Überprüfung fehlgeschlagen", + "noneAuthNotSupported": "Host Metrics unterstützt den Authentifizierungstyp 'none' nicht.", + "noHostSelected": "Kein Host ausgewählt", + "load": "Auslastung", + "systemInfo": "Systeminformationen", + "hostname": "Hostname", + "operatingSystem": "Betriebssystem", + "kernel": "Kernel", + "seconds": "Sekunden", + "networkInterfaces": "Netzwerkschnittstellen", + "noInterfacesFound": "Keine Netzwerkschnittstellen gefunden", + "noProcessesFound": "Keine Prozesse gefunden", + "processesTotal": "gesamt", + "processesRunning": "laufend", + "loginStats": "SSH-Anmeldestatistiken", + "noRecentLoginData": "Keine aktuellen Anmeldedaten", + "executingQuickAction": "{{name}} wird ausgeführt...", + "quickActionSuccess": "{{name}} erfolgreich abgeschlossen", + "quickActionFailed": "{{name}} fehlgeschlagen", + "quickActionError": "Fehler beim Ausführen von {{name}}", + "ports": { + "title": "Lauschende Ports", + "protocol": "Protokoll", + "port": "Port", + "address": "Adresse", + "process": "Prozess", + "search": "Ports durchsuchen...", + "allProtocols": "Alle", + "noData": "Keine Daten zu lauschenden Ports" + }, + "firewall": { + "title": "Firewall", + "inactive": "Inaktiv", + "policy": "Richtlinie", + "rules": "Regeln", + "noRules": "Keine Regeln in dieser Kette", + "noData": "Keine Firewall-Daten verfügbar", + "action": "Aktion", + "protocol": "Proto", + "port": "Port", + "source": "Quelle", + "anywhere": "Überall", + "chains": "Ketten" + }, + "loadAvg": "Lastdurchschnitt", + "swap": "Swap", + "architecture": "Architektur", + "refresh": "Aktualisieren", + "retry": "Wiederholen", + "customize": "Layout anpassen", + "reset": "Zurücksetzen", + "tabLive": "Live", + "editModeInstructions": "Ziehen Sie Karten, um sie neu anzuordnen, ziehen Sie die untere Kante, um die Größe zu ändern, und verwenden Sie die Breitenschaltfläche, um die Breite einer Karte anzupassen. Fügen Sie Karten unten hinzu oder entfernen Sie sie.", + "managers": { + "services": "Dienste", + "processInspector": "Prozessinspektor", + "logViewer": "Protokollbetrachter", + "cron": "Cron-Jobs", + "packages": "Pakete", + "ssl": "SSL-Zertifikate", + "firewall": "Firewall", + "users": "Benutzer & Berechtigungen", + "healthCheck": "Gesundheitsprüfungen", + "diskBreakdown": "Datenträgeraufschlüsselung", + "systemdTimers": "Timer", + "topMemory": "Top nach Speicher", + "noData": "Keine Daten", + "sudoHint": "Legen Sie im Host-Editor ein sudo-Passwort für diesen Host fest, um privilegierte Aktionen zu ermöglichen.", + "filter": "Filtern...", + "start": "Starten", + "stop": "Stoppen", + "restart": "Neustarten", + "actionDone": "{{name}} aktualisiert", + "actionFailed": "Aktion fehlgeschlagen", + "signalSent": "Signal an PID {{pid}} gesendet", + "killHint": "Klicken: Beenden (SIGTERM). Rechtsklick: Erzwungenes Beenden (SIGKILL).", + "working": "In Bearbeitung...", + "update": "Aktualisieren", + "upgradeAll": "Alle upgraden", + "allUpToDate": "Alles ist auf dem neuesten Stand", + "save": "Speichern", + "command": "Befehl", + "enabled": "Aktiviert", + "cronSaved": "Crontab aktualisiert", + "clients": "Clients", + "dryRun": "Trockenlauf", + "renew": "Erneuern", + "noAcmeClient": "Kein ACME-Client (certbot oder acme.sh) auf diesem Host gefunden.", + "addInputRule": "INPUT-Regel hinzufügen", + "firewallWarning": "Änderungen sind nur zur Laufzeit wirksam, bis sie gespeichert werden. Achten Sie darauf, sich nicht auszusperren.", + "ruleApplied": "Regel angewendet", + "invalidPort": "Gültigen Port eingeben (1–65535)", + "newUsername": "Neuer Benutzername", + "addUser": "Hinzufügen", + "deleteUser": "Benutzer löschen", + "noHealthChecks": "Noch keine Zustandsprüfungen konfiguriert.", + "follow": "Folgen", + "noLogData": "Keine Protokollausgabe.", + "tree": "Baum", + "enableDisable": "Beim Start aktivieren / deaktivieren", + "grantSudo": "sudo gewähren", + "revokeSudo": "sudo entziehen", + "sslIssueCert": "Zertifikat ausstellen", + "sslExpired": "Abgelaufen", + "sslInDays": "in {{days}} T", + "sslNeedDomain": "Geben Sie mindestens eine Domain ein", + "sslIssued": "Zertifikat ausgestellt", + "sslDomainsPlaceholder": "example.com, www.example.com", + "sslHttpStandalone": "HTTP (Standalone)", + "sslHttpWebroot": "HTTP (Webroot)", + "sslDns": "DNS", + "sslDnsProvider": "DNS-Anbieter (z. B. cloudflare)", + "sslIssueHint": "Anmeldedaten des DNS-Anbieters müssen bereits auf dem Host konfiguriert sein.", + "sslRevoke": "Zertifikat widerrufen", + "sslRevoked": "Zertifikat wurde widerrufen", + "sslRevokeConfirm": "Zertifikat \"{{name}}\" widerrufen und entfernen? Dies kann nicht rückgängig gemacht werden.", + "healthRun": "Ausführen", + "healthName": "Name", + "healthTarget": "Host / Adresse", + "healthAddCheck": "Prüfung hinzufügen", + "healthSaved": "Statusprüfungen gespeichert", + "healthMissingFields": "Jede Prüfung benötigt einen Namen und ein Ziel", + "logFile": "Datei", + "logUnit": "Unit", + "logCustomPath": "Benutzerdefinierter Pfad unter /var/log (optional)", + "logGrep": "Zeilen filtern...", + "firewallPersist": "Regeln dauerhaft speichern", + "firewallPersisted": "Firewall-Regeln dauerhaft gespeichert", + "wireguard": "WireGuard", + "tailscale": "Tailscale", + "wgNotInstalled": "WireGuard ist auf diesem Host nicht installiert", + "wgNoInterfaces": "Keine WireGuard-Schnittstellen konfiguriert", + "wgInterfaceUp": "Aktivieren", + "wgInterfaceDown": "Deaktivieren", + "wgBringingUp": "{{name}} wird aktiviert...", + "wgBringingDown": "{{name}} wird deaktiviert...", + "wgInterfaceUpDone": "{{name}} ist aktiv", + "wgInterfaceDownDone": "{{name}} ist deaktiviert", + "wgListenPort": "Port", + "wgPublicKey": "Öffentlicher Schlüssel", + "wgEndpoint": "Endpunkt", + "wgAllowedIPs": "Erlaubte IPs", + "wgLastHandshake": "Letzter Handshake", + "wgHandshakeNever": "Nie", + "wgTransfer": "Übertragung", + "tsNotInstalled": "Tailscale ist auf diesem Host nicht installiert", + "tsRunning": "Aktiv", + "tsStopped": "Gestoppt", + "tsEnable": "Verbinden", + "tsDisable": "Trennen", + "tsEnabling": "Verbinde mit Tailscale...", + "tsDisabling": "Trenne von Tailscale...", + "tsEnabled": "Tailscale verbunden", + "tsDisabled": "Tailscale getrennt", + "tsIPs": "Tailscale-IPs", + "tsPeers": "Peers", + "tsOnline": "Online", + "tsOffline": "Offline", + "tsExitNode": "Exit-Knoten", + "tsExitNodeActive": "Exit-Knoten aktiv", + "tsHostname": "Hostname" + } + }, + "metricsHistory": { + "title": "Metrikenverlauf", + "historySuffix": "Verlauf", + "cpuMemoryDisk": "CPU / RAM / Festplatte", + "network": "Netzwerk", + "download": "RX", + "upload": "TX", + "noData": "Keine Verlaufsdaten für diesen Zeitraum verfügbar.", + "custom": "Benutzerdefiniert", + "to": "bis", + "apply": "Anwenden", + "viewHistory": "Verlauf anzeigen" + }, + "proxmoxStats": { + "tabTitle": "Proxmox-Statistiken", + "cpuUsage": "CPU-Auslastung", + "memoryUsage": "Speichernutzung", + "diskUsage": "Festplattennutzung", + "networkInterfaces": "Netzwerkschnittstellen", + "uptime": "Betriebszeit", + "systemInfo": "Systeminformationen", + "guestsSummary": "Gäste", + "storagePools": "Speicherbecken", + "clusterHealth": "Cluster Health", + "cpuCores_one": "{{count}} Kern", + "cpuCores_other": "{{count}} Kerne", + "used": "Gebraucht", + "total": "Gesamt", + "hostname": "Hostname", + "kernel": "Kernel", + "pveVersion": "PVE-Version", + "name": "Name", + "status": "Status", + "type": "Typ", + "cpu": "CPU", + "mem": "Mitglied", + "disk": "Scheibe", + "running": "Läuft", + "stopped": "Angehalten", + "guestCounts": "{{running}}/{{total}} läuft", + "inactive": "Inaktiv", + "notClustered": "Eigenständiger Knoten (nicht Teil eines Clusters)", + "quorate": "Quorum", + "notQuorate": "Nicht beschlussfähig", + "nodeOnline": "Online", + "nodeOffline": "Offline", + "noHostSelected": "Kein Host ausgewählt", + "pveshNotFound": "pvesh nicht gefunden - handelt es sich um einen Proxmox-Knoten?", + "nodeDetectionFailed": "Es konnte kein gültiger Proxmox-Knotenname ermittelt werden.", + "connecting": "Verbindung wird hergestellt...", + "connectionFailed": "Verbindung zum Proxmox-Knoten fehlgeschlagen.", + "refresh": "Aktualisieren", + "searchGuests": "Gäste suchen...", + "filterAll": "Alle", + "filterVm": "VM", + "filterLxc": "LXC", + "noGuests": "Auf diesem Knoten wurden keine VMs oder LXC-Container gefunden.", + "noGuestsMatch": "Es gibt keine Gäste, die den aktuellen Filtern entsprechen." + }, + "nav": { + "hostMetrics": "Host-Metriken" + }, + "hosts": { + "tabHostMetrics": "Host-Metriken", + "enableProxmoxStats": "Proxmox-Statistiken aktivieren", + "enableProxmoxStatsDesc": "Zeigen Sie für diesen Host eine Registerkarte „Proxmox Stats“ mit Live-Statistiken zu Knoten, Gastsystemen, Speicher und Cluster an, die über SSH erfasst werden.", + "proxmoxStatsPollInterval": "Abfrageintervall (Sekunden)", + "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", + "metricsCollectionLabel": "Metrikerfassung", + "enableMetricsLabel": "Metriken aktivieren", + "enableMetricsDesc": "CPU, RAM, Festplatten und andere Metriken von diesem Host erfassen", + "useGlobalMetrics": "Globales Intervall verwenden", + "useGlobalMetricsDesc": "Mit dem serverweiten Metrikintervall überschreiben", + "metricsIntervalS": "Metrikintervall (s)", + "metricsIntervalDesc2": "Sekunden zwischen Metrik-Momentaufnahmen", + "excludedMountsLabel": "Ausgeschlossene Halterungen", + "monitoredMountsLabel": "Benutzerdefinierte überwachte Pfade", + "monitoredMountsDesc": "Fügen Sie Pfade hinzu, die nicht als separate Mounts verfügbar sind, einschließlich bind-gebundener Home Assistant-Pfade wie /config.", + "monitoredMountPathPlaceholder": "Pfad (/config, /mnt/data)", + "monitoredMountLabelPlaceholder": "Etikett (optional)", + "addMonitoredMount": "Pfad hinzufügen", + "excludedMountsDesc": "Bestimmte Mountpunkte oder Dateisystemtypen (z. B. nfs, cifs) können von der Festplattennutzung und Warnmeldungen für diesen Host ausgeblendet werden.", + "excludedMountsPlaceholder": "Mount-Pfad (/mnt/nas) oder Dateisystemtyp (nfs, cifs)", + "excludedMountsEmpty": "Keine Mounts ausgeschlossen. Alle erkannten Dateisysteme werden angezeigt.", + "addExcludedMount": "Hinzufügen", + "visibleWidgets": "Sichtbare Widgets", + "widgetsMovedToHostMetrics": "Karten werden jetzt direkt im Tab „Host-Metriken“ hinzugefügt, angeordnet und in der Größe verändert. Öffnen Sie die Host-Metriken für diesen Host und verwenden Sie „Anpassen“, um auszuwählen, welche Karten angezeigt werden.", + "quickActionsLabel": "Schnellaktionen", + "quickActionsToolbar": "Schnellaktionen erscheinen als Schaltflächen in der Host-Metriken-Symbolleiste zur Ausführung von Befehlen mit einem Klick.", + "noQuickActions": "Noch keine Schnellaktionen.", + "buttonLabel": "Schaltflächenbeschriftung", + "selectSnippetPlaceholder": "Snippet auswählen...", + "addActionBtn": "Aktion hinzufügen" + }, + "onboarding": { + "feature_metrics": "Kennzahlen und Warnmeldungen", + "feature_metrics_desc": "Verfolgen Sie CPU, Arbeitsspeicher und Festplatte im Zeitverlauf und lassen Sie sich benachrichtigen, wenn diese Werte sinken." + }, + "admin": { + "metricsHistoryRetention": "Aufbewahrungsdauer der Metriken", + "metricsHistoryRetentionRange": "1 bis 90 Tage", + "days": "Tage" + }, + "homepage": { + "noData": "Keine Daten verfügbar", + "showCurrentValue": "Aktuellen Wert anzeigen", + "chartMetric": "Metrik", + "metricRange": "Bereich" + } +} diff --git a/plugins/host-metrics/locales/translated/el_GR.json b/plugins/host-metrics/locales/translated/el_GR.json new file mode 100644 index 000000000..1c903f935 --- /dev/null +++ b/plugins/host-metrics/locales/translated/el_GR.json @@ -0,0 +1,313 @@ +{ + "hostMetrics": { + "cpu": "ΚΜΕ", + "memory": "Μνήμη", + "disk": "Δίσκος", + "network": "Δίκτυο", + "uptime": "Χρόνος λειτουργίας", + "processes": "Διαδικασίες", + "available": "Διαθέσιμος", + "free": "Δωρεάν", + "connecting": "Συνδετικός...", + "connectionFailed": "Αποτυχία σύνδεσης με τον διακομιστή", + "naCpus": "Δ/Υ CPU(s)", + "cpuCores_one": "{{count}} Πυρήνας", + "cpuCores_other": "{{count}} Πυρήνες", + "cpuUsage": "Χρήση CPU", + "memoryUsage": "Χρήση μνήμης", + "diskUsage": "Χρήση δίσκου", + "selectFilesystem": "Επιλογή συστήματος αρχείων", + "temperature": "Θερμοκρασία", + "highestTemperature": "Υψηλότερη θερμοκρασία", + "primaryTemperatureSensor": "Κύριος αισθητήρας", + "gpu": { + "title": "GPU", + "noDevice": "Δεν εντοπίστηκε GPU NVIDIA. Εγκαταστήστε το πρόγραμμα οδήγησης NVIDIA (παρέχει nvidia-smi) για να δείτε τις μετρήσεις GPU.", + "driver": "Οδηγός {{version}}", + "utilization": "Χρησιμοποίηση", + "memory": "VRAM", + "temperature": "Θερμοκρασία", + "power": "Εξουσία", + "fan": "Ανεμιστήρας", + "processes": "Διαδικασίες GPU", + "noProcesses": "Δεν υπάρχουν διεργασίες που να χρησιμοποιούν την GPU" + }, + "failedToFetchHostConfig": "Αποτυχία ανάκτησης διαμόρφωσης κεντρικού υπολογιστή", + "serverOffline": "Διακομιστής εκτός σύνδεσης", + "cannotFetchMetrics": "Δεν είναι δυνατή η ανάκτηση μετρήσεων από διακομιστή εκτός σύνδεσης", + "totpFailed": "Η επαλήθευση TOTP απέτυχε.", + "noneAuthNotSupported": "Το Host Metrics δεν υποστηρίζει τον τύπο ελέγχου ταυτότητας 'κανένας'.", + "noHostSelected": "Δεν έχει επιλεγεί κεντρικός υπολογιστής", + "load": "Φορτίο", + "systemInfo": "Πληροφορίες συστήματος", + "hostname": "Όνομα κεντρικού υπολογιστή", + "operatingSystem": "Λειτουργικό σύστημα", + "kernel": "Πυρήνας", + "seconds": "δευτερόλεπτα", + "networkInterfaces": "Διεπαφές δικτύου", + "noInterfacesFound": "Δεν βρέθηκαν διεπαφές δικτύου", + "noProcessesFound": "Δεν βρέθηκαν διεργασίες", + "processesTotal": "σύνολο", + "processesRunning": "τρέξιμο", + "loginStats": "Στατιστικά στοιχεία σύνδεσης SSH", + "noRecentLoginData": "Δεν υπάρχουν πρόσφατα δεδομένα σύνδεσης", + "executingQuickAction": "Εκτέλεση {{name}}...", + "quickActionSuccess": "{{name}} ολοκληρώθηκε με επιτυχία", + "quickActionFailed": "{{name}} απέτυχε", + "quickActionError": "Αποτυχία εκτέλεσης {{name}}", + "ports": { + "title": "Θύρες ακρόασης", + "protocol": "Πρωτόκολλο", + "port": "Λιμάνι", + "address": "Διεύθυνση", + "process": "Διαδικασία", + "search": "Αναζήτηση θυρών...", + "allProtocols": "Ολοι", + "noData": "Δεν υπάρχουν δεδομένα θυρών ακρόασης" + }, + "firewall": { + "title": "Τείχος προστασίας", + "inactive": "Αδρανής", + "policy": "Πολιτική", + "rules": "κανόνες", + "noRules": "Δεν υπάρχουν κανόνες σε αυτήν την αλυσίδα", + "noData": "Δεν υπάρχουν διαθέσιμα δεδομένα τείχους προστασίας", + "action": "Δράση", + "protocol": "Πρωτό", + "port": "Λιμάνι", + "source": "Πηγή", + "anywhere": "Οπουδήποτε", + "chains": "αλυσίδες" + }, + "loadAvg": "Μέσος όρος φορτίου", + "swap": "Ανταλαγή", + "architecture": "Αρχιτεκτονική", + "refresh": "Φρεσκάρω", + "retry": "Δοκιμάζω πάλι", + "customize": "Προσαρμογή διάταξης", + "reset": "Επαναφορά", + "tabLive": "Ζω", + "editModeInstructions": "Σύρετε τις κάρτες για αναδιάταξη, σύρετε την κάτω άκρη για αλλαγή μεγέθους και χρησιμοποιήστε το κουμπί πλάτους για να αλλάξετε το εύρος μιας κάρτας. Προσθέστε ή αφαιρέστε κάρτες παρακάτω.", + "managers": { + "services": "Υπηρεσίες", + "processInspector": "Επιθεωρητής Διαδικασίας", + "logViewer": "Πρόγραμμα προβολής αρχείων καταγραφής", + "cron": "Cron Jobs", + "packages": "Πακέτα", + "ssl": "Πιστοποιητικά SSL", + "firewall": "Τείχος προστασίας", + "users": "Χρήστες και Δικαιώματα", + "healthCheck": "Έλεγχοι υγείας", + "diskBreakdown": "Ανάλυση δίσκου", + "systemdTimers": "Χρονόμετρα", + "topMemory": "Κορυφαία κατά Μνήμη", + "noData": "Δεν υπάρχουν δεδομένα", + "sudoHint": "Ορίστε έναν κωδικό πρόσβασης sudo για αυτόν τον κεντρικό υπολογιστή στον επεξεργαστή κεντρικού υπολογιστή για να ενεργοποιήσετε τις προνομιακές ενέργειες.", + "filter": "Φίλτρο...", + "start": "Αρχή", + "stop": "Στάση", + "restart": "Επανεκκίνηση", + "actionDone": "{{name}} ενημερώθηκε", + "actionFailed": "Η ενέργεια απέτυχε", + "signalSent": "Σήμα που στάλθηκε στο PID {{pid}}", + "killHint": "Κάντε κλικ: τερματισμός (SIGTERM). Δεξί κλικ: αναγκαστική τερματισμός (SIGKILL).", + "working": "Εργαζόμενος...", + "update": "Εκσυγχρονίζω", + "upgradeAll": "Αναβάθμιση όλων", + "allUpToDate": "Όλα είναι ενημερωμένα", + "save": "Εκτός", + "command": "Εντολή", + "enabled": "Ενεργοποιημένο", + "cronSaved": "Το Crontab ενημερώθηκε", + "clients": "Πελάτες", + "dryRun": "Ξηρή λειτουργία", + "renew": "Ανανεώνω", + "noAcmeClient": "Δεν βρέθηκε πρόγραμμα-πελάτης ACME (certbot ή acme.sh) σε αυτόν τον κεντρικό υπολογιστή.", + "addInputRule": "Προσθήκη κανόνα INPUT", + "firewallWarning": "Οι αλλαγές ισχύουν μόνο κατά τον χρόνο εκτέλεσης μέχρι να διατηρηθούν. Προσέξτε να μην κλειδωθείτε έξω.", + "ruleApplied": "Εφαρμόστηκε κανόνας", + "invalidPort": "Εισαγάγετε μια έγκυρη θύρα (1-65535)", + "newUsername": "Νέο όνομα χρήστη", + "addUser": "Προσθέτω", + "deleteUser": "Διαγραφή χρήστη", + "noHealthChecks": "Δεν έχουν ρυθμιστεί ακόμη έλεγχοι εύρυθμης λειτουργίας.", + "follow": "Ακολουθώ", + "noLogData": "Δεν υπάρχει έξοδος αρχείου καταγραφής.", + "tree": "Δέντρο", + "enableDisable": "Ενεργοποίηση/απενεργοποίηση κατά την εκκίνηση", + "grantSudo": "Grant sudo", + "revokeSudo": "Ανάκληση sudo", + "sslIssueCert": "Έκδοση πιστοποιητικού", + "sslExpired": "Λήξη", + "sslInDays": "σε {{days}}δ", + "sslNeedDomain": "Εισαγάγετε τουλάχιστον έναν τομέα", + "sslIssued": "Πιστοποιητικό που εκδόθηκε", + "sslDomainsPlaceholder": "example.com, www.example.com", + "sslHttpStandalone": "HTTP (αυτόνομο)", + "sslHttpWebroot": "HTTP (weberroot)", + "sslDns": "DNS", + "sslDnsProvider": "Πάροχος DNS (π.χ. cloudflare)", + "sslIssueHint": "Τα διαπιστευτήρια του παρόχου DNS πρέπει να έχουν ήδη διαμορφωθεί στον κεντρικό υπολογιστή.", + "sslRevoke": "Ανάκληση πιστοποιητικού", + "sslRevoked": "Το πιστοποιητικό ανακλήθηκε", + "sslRevokeConfirm": "Ανάκληση και κατάργηση του πιστοποιητικού \"{{name}}\"; Αυτή η ενέργεια δεν μπορεί να αναιρεθεί.", + "healthRun": "Τρέξιμο", + "healthName": "Ονομα", + "healthTarget": "Υποδοχή / διεύθυνση", + "healthAddCheck": "Προσθήκη επιταγής", + "healthSaved": "Οι έλεγχοι υγείας αποθηκεύτηκαν", + "healthMissingFields": "Κάθε έλεγχος χρειάζεται ένα όνομα και έναν στόχο", + "logFile": "Αρχείο", + "logUnit": "Μονάδα", + "logCustomPath": "Προσαρμοσμένη διαδρομή στο /var/log (προαιρετικό)", + "logGrep": "Γραμμές φιλτραρίσματος...", + "firewallPersist": "Επιμονή στους κανόνες", + "firewallPersisted": "Οι κανόνες του τείχους προστασίας παρέμειναν", + "wireguard": "WireGuard", + "tailscale": "Κλίμακα ουράς", + "wgNotInstalled": "Το WireGuard δεν είναι εγκατεστημένο σε αυτόν τον κεντρικό υπολογιστή", + "wgNoInterfaces": "Δεν έχουν ρυθμιστεί διεπαφές WireGuard", + "wgInterfaceUp": "Ανατρέφω", + "wgInterfaceDown": "Ρίχνω", + "wgBringingUp": "Εμφάνιση του {{name}}...", + "wgBringingDown": "Κατεβάζοντας το {{name}}...", + "wgInterfaceUpDone": "Το {{name}} είναι ενεργό", + "wgInterfaceDownDone": "Το {{name}} δεν λειτουργεί", + "wgListenPort": "Λιμάνι", + "wgPublicKey": "Δημόσιο κλειδί", + "wgEndpoint": "Τελικό σημείο", + "wgAllowedIPs": "Επιτρεπόμενες IP", + "wgLastHandshake": "Τελευταία χειραψία", + "wgHandshakeNever": "Ποτέ", + "wgTransfer": "Μεταφορά", + "tsNotInstalled": "Το Tailscale δεν είναι εγκατεστημένο σε αυτόν τον κεντρικό υπολογιστή", + "tsRunning": "Τρέξιμο", + "tsStopped": "Σταμάτησε", + "tsEnable": "Συνδέω", + "tsDisable": "Αποσυνδέω", + "tsEnabling": "Σύνδεση με το Tailscale...", + "tsDisabling": "Αποσύνδεση από το Tailscale...", + "tsEnabled": "Συνδεδεμένο με κλίμακα ουράς", + "tsDisabled": "Η κλίμακα ουράς αποσυνδέθηκε", + "tsIPs": "IP κλίμακας ουράς", + "tsPeers": "Ομότιμοι", + "tsOnline": "Διαδικτυακά", + "tsOffline": "Εκτός σύνδεσης", + "tsExitNode": "Κόμβος εξόδου", + "tsExitNodeActive": "Κόμβος εξόδου ενεργός", + "tsHostname": "Όνομα κεντρικού υπολογιστή" + } + }, + "metricsHistory": { + "title": "Ιστορικό μετρήσεων", + "historySuffix": "Ιστορία", + "cpuMemoryDisk": "CPU / Μνήμη / Δίσκος", + "network": "Δίκτυο", + "download": "Συνάντηση", + "upload": "Τέξας", + "noData": "Δεν υπάρχουν διαθέσιμα δεδομένα ιστορικού για αυτό το χρονικό εύρος.", + "custom": "Εθιμο", + "to": "να", + "apply": "Εφαρμόζω", + "viewHistory": "Προβολή ιστορικού" + }, + "proxmoxStats": { + "tabTitle": "Στατιστικά Proxmox", + "cpuUsage": "Χρήση CPU", + "memoryUsage": "Χρήση μνήμης", + "diskUsage": "Χρήση δίσκου", + "networkInterfaces": "Διεπαφές δικτύου", + "uptime": "Χρόνος λειτουργίας", + "systemInfo": "Πληροφορίες συστήματος", + "guestsSummary": "Επισκέπτες", + "storagePools": "Πισίνες αποθήκευσης", + "clusterHealth": "Υγεία συμπλέγματος", + "cpuCores_one": "{{count}} Πυρήνας", + "cpuCores_other": "{{count}} Πυρήνες", + "used": "Μεταχειρισμένος", + "total": "Σύνολο", + "hostname": "Όνομα κεντρικού υπολογιστή", + "kernel": "Πυρήνας", + "pveVersion": "Έκδοση PVE", + "name": "Ονομα", + "status": "Κατάσταση", + "type": "Τύπος", + "cpu": "ΚΜΕ", + "mem": "Μνήμη", + "disk": "Δίσκος", + "running": "Τρέξιμο", + "stopped": "Σταμάτησε", + "guestCounts": "{{running}}/{{total}} σε λειτουργία", + "inactive": "Αδρανής", + "notClustered": "Αυτόνομος κόμβος (δεν αποτελεί μέρος συμπλέγματος)", + "quorate": "Απαρτίζω", + "notQuorate": "Δεν υπάρχει απαρτία", + "nodeOnline": "Διαδικτυακά", + "nodeOffline": "Εκτός σύνδεσης", + "noHostSelected": "Δεν έχει επιλεγεί κεντρικός υπολογιστής", + "pveshNotFound": "Το pvesh δεν βρέθηκε - είναι αυτός κόμβος Proxmox;", + "nodeDetectionFailed": "Δεν είναι δυνατός ο προσδιορισμός ενός έγκυρου ονόματος κόμβου Proxmox", + "connecting": "Συνδετικός...", + "connectionFailed": "Αποτυχία σύνδεσης με τον κόμβο Proxmox", + "refresh": "Φρεσκάρω", + "searchGuests": "Αναζήτηση επισκεπτών...", + "filterAll": "Ολοι", + "filterVm": "Εικονική Μηχανή", + "filterLxc": "LXC", + "noGuests": "Δεν βρέθηκαν εικονικές μηχανές ή κοντέινερ LXC σε αυτόν τον κόμβο.", + "noGuestsMatch": "Δεν υπάρχουν επισκέπτες που να αντιστοιχούν στα τρέχοντα φίλτρα." + }, + "nav": { + "hostMetrics": "Μετρήσεις κεντρικού υπολογιστή" + }, + "hosts": { + "tabHostMetrics": "Μετρήσεις κεντρικού υπολογιστή", + "enableProxmoxStats": "Ενεργοποίηση στατιστικών Proxmox", + "enableProxmoxStatsDesc": "Εμφάνιση μιας καρτέλας Proxmox Stats για αυτόν τον κεντρικό υπολογιστή με στατιστικά στοιχεία ζωντανού κόμβου, επισκέπτη, χώρου αποθήκευσης και συμπλέγματος που συλλέγονται μέσω SSH.", + "proxmoxStatsPollInterval": "Διάστημα δημοσκόπησης (δευτερόλεπτα)", + "proxmoxStatsPollIntervalDesc": "Ελάχιστο 15 δευτερόλεπτα. Πόσο συχνά θα ανανεώνονται τα στατιστικά στοιχεία του κόμβου Proxmox.", + "proxmoxStatsNodeOverride": "Παράκαμψη ονόματος κόμβου", + "proxmoxStatsNodeOverrideDesc": "Παράκαμψη αυτόματης ανίχνευσης του ονόματος κόμβου Proxmox (εντοπίζεται μέσω του ονόματος κεντρικού υπολογιστή από προεπιλογή).", + "proxmoxStatsNodeOverridePlaceholder": "Αυτόματη ανίχνευση από το όνομα κεντρικού υπολογιστή", + "metricsCollectionLabel": "Συλλογή μετρήσεων", + "enableMetricsLabel": "Ενεργοποίηση μετρήσεων", + "enableMetricsDesc": "Συλλογή μετρήσεων CPU, RAM, δίσκου και άλλων από αυτόν τον κεντρικό υπολογιστή", + "useGlobalMetrics": "Χρήση καθολικού διαστήματος", + "useGlobalMetricsDesc": "Παράκαμψη με το διάστημα μετρήσεων σε ολόκληρο τον διακομιστή", + "metricsIntervalS": "Διάστημα μετρήσεων (s)", + "metricsIntervalDesc2": "Δευτερόλεπτα μεταξύ στιγμιότυπων μετρήσεων", + "excludedMountsLabel": "Εξαιρούμενες βάσεις", + "monitoredMountsLabel": "Προσαρμοσμένες παρακολουθούμενες διαδρομές", + "monitoredMountsDesc": "Προσθέστε διαδρομές που δεν εκτίθενται ως ξεχωριστές προσαρτήσεις, συμπεριλαμβανομένων των διαδρομών του Home Assistant που είναι προσαρτημένες στο bind, όπως το /config.", + "monitoredMountPathPlaceholder": "Διαδρομή (/config, /mnt/data)", + "monitoredMountLabelPlaceholder": "Ετικέτα (προαιρετικά)", + "addMonitoredMount": "Προσθήκη διαδρομής", + "excludedMountsDesc": "Απόκρυψη συγκεκριμένων σημείων προσάρτησης ή τύπων συστημάτων αρχείων (π.χ. nfs, cifs) από τη χρήση δίσκου και τις ειδοποιήσεις για αυτόν τον κεντρικό υπολογιστή.", + "excludedMountsPlaceholder": "Διαδρομή προσάρτησης (/mnt/nas) ή τύπος συστήματος αρχείων (nfs, cifs)", + "excludedMountsEmpty": "Δεν εξαιρούνται προσαρτήσεις. Εμφανίζονται όλα τα εντοπισμένα συστήματα αρχείων.", + "addExcludedMount": "Προσθέτω", + "visibleWidgets": "Ορατά γραφικά στοιχεία", + "widgetsMovedToHostMetrics": "Οι κάρτες προστίθενται, ταξινομούνται και αλλάζουν μέγεθος απευθείας στην καρτέλα Μετρήσεις κεντρικού υπολογιστή. Ανοίξτε τις Μετρήσεις κεντρικού υπολογιστή για αυτόν τον κεντρικό υπολογιστή και χρησιμοποιήστε την Προσαρμογή για να επιλέξετε ποιες κάρτες θα εμφανίζονται.", + "quickActionsLabel": "Γρήγορες ενέργειες", + "quickActionsToolbar": "Οι γρήγορες ενέργειες εμφανίζονται ως κουμπιά στη γραμμή εργαλείων Μετρήσεων κεντρικού υπολογιστή για εκτέλεση εντολών με ένα κλικ.", + "noQuickActions": "Δεν υπάρχουν ακόμη γρήγορες ενέργειες.", + "buttonLabel": "Ετικέτα κουμπιού", + "selectSnippetPlaceholder": "Επιλογή αποσπάσματος...", + "addActionBtn": "Προσθήκη ενέργειας" + }, + "onboarding": { + "feature_metrics": "Μετρήσεις και ειδοποιήσεις", + "feature_metrics_desc": "Παρακολουθήστε την CPU, τη μνήμη και τον δίσκο με την πάροδο του χρόνου και λάβετε ειδοποίηση όταν παρουσιάσουν προβλήματα." + }, + "admin": { + "metricsHistoryRetention": "Διατήρηση ιστορικού μετρήσεων", + "metricsHistoryRetentionRange": "1 έως 90 ημέρες", + "days": "ημέρες" + }, + "homepage": { + "noData": "Δεν υπάρχουν διαθέσιμα δεδομένα", + "showCurrentValue": "Εμφάνιση τρέχουσας τιμής", + "chartMetric": "Μετρικός", + "metricRange": "Σειρά" + } +} diff --git a/plugins/host-metrics/locales/translated/es_ES.json b/plugins/host-metrics/locales/translated/es_ES.json new file mode 100644 index 000000000..90c37b70a --- /dev/null +++ b/plugins/host-metrics/locales/translated/es_ES.json @@ -0,0 +1,313 @@ +{ + "hostMetrics": { + "cpu": "CPU", + "memory": "Memoria", + "disk": "Disco", + "network": "Red", + "uptime": "Tiempo de actividad", + "processes": "Procesos", + "available": "Disponible", + "free": "Libre", + "connecting": "Conectando...", + "connectionFailed": "Error al conectar con el servidor", + "naCpus": "CPU(s) N/D", + "cpuCores_one": "{{count}} núcleo", + "cpuCores_other": "{{count}} núcleos", + "cpuUsage": "Uso de CPU", + "memoryUsage": "Uso de memoria", + "diskUsage": "Uso del disco", + "selectFilesystem": "Seleccionar sistema de archivos", + "temperature": "Temperatura", + "highestTemperature": "Temperatura más alta", + "primaryTemperatureSensor": "Sensor primario", + "gpu": { + "title": "GPU", + "noDevice": "No se ha detectado ninguna GPU NVIDIA. Instale el controlador NVIDIA (que incluye nvidia-smi) para ver las métricas de la GPU.", + "driver": "Conductor {{version}}", + "utilization": "Utilización", + "memory": "VRAM", + "temperature": "Temperatura", + "power": "Fuerza", + "fan": "Admirador", + "processes": "procesos de GPU", + "noProcesses": "Ningún proceso está utilizando la GPU." + }, + "failedToFetchHostConfig": "Error al obtener la configuración del host", + "serverOffline": "Servidor fuera de línea", + "cannotFetchMetrics": "No se pueden obtener métricas de un servidor fuera de línea", + "totpFailed": "Error en la verificación TOTP", + "noneAuthNotSupported": "Host Metrics no admite el tipo de autenticación 'none'.", + "noHostSelected": "Ningún host seleccionado", + "load": "Carga", + "systemInfo": "Información del sistema", + "hostname": "Nombre de host", + "operatingSystem": "Sistema operativo", + "kernel": "Kernel", + "seconds": "segundos", + "networkInterfaces": "Interfaces de red", + "noInterfacesFound": "No se encontraron interfaces de red", + "noProcessesFound": "No se encontraron procesos", + "processesTotal": "total", + "processesRunning": "en ejecución", + "loginStats": "Estadísticas de inicio de sesión SSH", + "noRecentLoginData": "No hay datos de inicio de sesión recientes", + "executingQuickAction": "Ejecutando {{name}}...", + "quickActionSuccess": "{{name}} completado correctamente", + "quickActionFailed": "{{name}} falló", + "quickActionError": "Error al ejecutar {{name}}", + "ports": { + "title": "Puertos en escucha", + "protocol": "Protocolo", + "port": "Puerto", + "address": "Dirección", + "process": "Proceso", + "search": "Buscar puertos...", + "allProtocols": "Todos", + "noData": "No hay datos de puertos en escucha" + }, + "firewall": { + "title": "Cortafuegos", + "inactive": "Inactivo", + "policy": "Política", + "rules": "reglas", + "noRules": "No hay reglas en esta cadena", + "noData": "No hay datos del cortafuegos disponibles", + "action": "Acción", + "protocol": "Proto", + "port": "Puerto", + "source": "Origen", + "anywhere": "Cualquier origen", + "chains": "cadenas" + }, + "loadAvg": "Carga Promedio", + "swap": "Swap", + "architecture": "Arquitectura", + "refresh": "Refrescar", + "retry": "Reintentar", + "customize": "Personalizar diseño", + "reset": "Restablecer", + "tabLive": "En vivo", + "editModeInstructions": "Arrastre las tarjetas para reorganizarlas, arrastre el borde inferior para redimensionarlas, y use el botón de ancho para cambiar el ancho de una tarjeta. Añada o elimine tarjetas a continuación.", + "managers": { + "services": "Servicios", + "processInspector": "Inspector de procesos", + "logViewer": "Visor de registros", + "cron": "Tareas Cron", + "packages": "Paquetes", + "ssl": "Certificados SSL", + "firewall": "Firewall", + "users": "Usuarios y permisos", + "healthCheck": "Comprobaciones de estado", + "diskBreakdown": "Desglose de disco", + "systemdTimers": "Temporizadores", + "topMemory": "Top por memoria", + "noData": "Sin datos", + "sudoHint": "Establezca una contraseña de sudo para este host en el editor del host para habilitar acciones privilegiadas.", + "filter": "Filtrar...", + "start": "Iniciar", + "stop": "Detener", + "restart": "Reiniciar", + "actionDone": "{{name}} actualizado", + "actionFailed": "Acción fallida", + "signalSent": "Señal enviada a PID {{pid}}", + "killHint": "Clic: terminar (SIGTERM). Clic derecho: forzar cierre (SIGKILL).", + "working": "Trabajando...", + "update": "Actualizar", + "upgradeAll": "Actualizar todo", + "allUpToDate": "Todo está actualizado", + "save": "Guardar", + "command": "Comando", + "enabled": "Activado", + "cronSaved": "Crontab actualizado", + "clients": "Clientes", + "dryRun": "Simulación", + "renew": "Renovar", + "noAcmeClient": "No se encontró ningún cliente ACME (certbot o acme.sh) en este host.", + "addInputRule": "Añadir regla INPUT", + "firewallWarning": "Los cambios son solo en tiempo de ejecución hasta que se persisten. Tenga cuidado de no quedarse bloqueado fuera.", + "ruleApplied": "Regla aplicada", + "invalidPort": "Introduzca un puerto válido (1-65535)", + "newUsername": "Nuevo nombre de usuario", + "addUser": "Añadir", + "deleteUser": "Eliminar usuario", + "noHealthChecks": "Aún no se han configurado comprobaciones de estado.", + "follow": "Seguir", + "noLogData": "Sin salida de registro.", + "tree": "Árbol", + "enableDisable": "Activar / desactivar al arrancar", + "grantSudo": "Conceder sudo", + "revokeSudo": "Revocar sudo", + "sslIssueCert": "Emitir certificado", + "sslExpired": "Caducado", + "sslInDays": "en {{days}}d", + "sslNeedDomain": "Introduzca al menos un dominio", + "sslIssued": "Certificado emitido", + "sslDomainsPlaceholder": "example.com, www.example.com", + "sslHttpStandalone": "HTTP (standalone)", + "sslHttpWebroot": "HTTP (webroot)", + "sslDns": "DNS", + "sslDnsProvider": "Proveedor DNS (p. ej. cloudflare)", + "sslIssueHint": "Las credenciales del proveedor DNS ya deben estar configuradas en el host.", + "sslRevoke": "Revocar certificado", + "sslRevoked": "Certificado revocado", + "sslRevokeConfirm": "¿Revocar y eliminar el certificado \"{{name}}\"? Esta acción no se puede deshacer.", + "healthRun": "Ejecutar", + "healthName": "Nombre", + "healthTarget": "Host / dirección", + "healthAddCheck": "Añadir verificación", + "healthSaved": "Verificaciones de estado guardadas", + "healthMissingFields": "Cada verificación necesita un nombre y un destino", + "logFile": "Archivo", + "logUnit": "Unidad", + "logCustomPath": "Ruta personalizada bajo /var/log (opcional)", + "logGrep": "Filtrar líneas...", + "firewallPersist": "Persistir reglas", + "firewallPersisted": "Reglas del firewall persistidas", + "wireguard": "WireGuard", + "tailscale": "Tailscale", + "wgNotInstalled": "WireGuard no está instalado en este host", + "wgNoInterfaces": "No hay interfaces WireGuard configuradas", + "wgInterfaceUp": "Activar", + "wgInterfaceDown": "Desactivar", + "wgBringingUp": "Activando {{name}}...", + "wgBringingDown": "Desactivando {{name}}...", + "wgInterfaceUpDone": "{{name}} está activado", + "wgInterfaceDownDone": "{{name}} está desactivado", + "wgListenPort": "Puerto", + "wgPublicKey": "Clave pública", + "wgEndpoint": "Endpoint", + "wgAllowedIPs": "IPs permitidas", + "wgLastHandshake": "Último handshake", + "wgHandshakeNever": "Nunca", + "wgTransfer": "Transferencia", + "tsNotInstalled": "Tailscale no está instalado en este host", + "tsRunning": "Ejecutándose", + "tsStopped": "Detenido", + "tsEnable": "Conectar", + "tsDisable": "Desconectar", + "tsEnabling": "Conectando a Tailscale...", + "tsDisabling": "Desconectando de Tailscale...", + "tsEnabled": "Tailscale conectado", + "tsDisabled": "Tailscale desconectado", + "tsIPs": "IPs de Tailscale", + "tsPeers": "Pares", + "tsOnline": "En línea", + "tsOffline": "Desconectado", + "tsExitNode": "Nodo de salida", + "tsExitNodeActive": "Nodo de salida activo", + "tsHostname": "Nombre de host" + } + }, + "metricsHistory": { + "title": "Historial de Métricas", + "historySuffix": "Historial", + "cpuMemoryDisk": "CPU / Memoria / Disco", + "network": "Red", + "download": "RX", + "upload": "TX", + "noData": "No hay datos de historial disponibles para este rango de tiempo.", + "custom": "Personalizado", + "to": "a", + "apply": "Aplicar", + "viewHistory": "Ver Historial" + }, + "proxmoxStats": { + "tabTitle": "Estadísticas de Proxmox", + "cpuUsage": "Uso de la CPU", + "memoryUsage": "Uso de memoria", + "diskUsage": "Uso del disco", + "networkInterfaces": "Interfaces de red", + "uptime": "Tiempo de actividad", + "systemInfo": "Información del sistema", + "guestsSummary": "Huéspedes", + "storagePools": "Piscinas de almacenamiento", + "clusterHealth": "Salud en grupo", + "cpuCores_one": "{{count}} Núcleo", + "cpuCores_other": "{{count}} Núcleos", + "used": "Usado", + "total": "Total", + "hostname": "nombre de host", + "kernel": "Núcleo", + "pveVersion": "Versión PVE", + "name": "Nombre", + "status": "Estado", + "type": "Tipo", + "cpu": "UPC", + "mem": "Memoria", + "disk": "Disco", + "running": "Correr", + "stopped": "Interrumpido", + "guestCounts": "{{running}}/{{total}} corriendo", + "inactive": "Inactivo", + "notClustered": "Nodo independiente (no forma parte de un clúster)", + "quorate": "Con quórum", + "notQuorate": "No hay quórum", + "nodeOnline": "En línea", + "nodeOffline": "Desconectado", + "noHostSelected": "No se ha seleccionado ningún host.", + "pveshNotFound": "pvesh no encontrado - ¿es este un nodo Proxmox?", + "nodeDetectionFailed": "No se pudo determinar un nombre de nodo Proxmox válido.", + "connecting": "Conectando...", + "connectionFailed": "No se pudo conectar con el nodo Proxmox.", + "refresh": "Refrescar", + "searchGuests": "Buscar huéspedes...", + "filterAll": "Todo", + "filterVm": "VM", + "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." + }, + "nav": { + "hostMetrics": "Métricas del host" + }, + "hosts": { + "tabHostMetrics": "Métricas del host", + "enableProxmoxStats": "Habilitar estadísticas de Proxmox", + "enableProxmoxStatsDesc": "Muestra una pestaña de estadísticas de Proxmox para este host con estadísticas en tiempo real del nodo, invitado, almacenamiento y clúster recopiladas a través de SSH.", + "proxmoxStatsPollInterval": "Intervalo de sondeo (segundos)", + "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.", + "metricsCollectionLabel": "Recopilación de métricas", + "enableMetricsLabel": "Habilitar métricas", + "enableMetricsDesc": "Recopilar CPU, RAM, disco y otras métricas de este host.", + "useGlobalMetrics": "Usar intervalo global", + "useGlobalMetricsDesc": "Sobrescribir con el intervalo de métricas global del servidor.", + "metricsIntervalS": "Intervalo de métricas (s)", + "metricsIntervalDesc2": "Segundos entre instantáneas de métricas.", + "excludedMountsLabel": "Monturas excluidas", + "monitoredMountsLabel": "Rutas personalizadas monitorizadas", + "monitoredMountsDesc": "Agregue rutas que no estén expuestas como montajes separados, incluidas las rutas de Home Assistant montadas mediante enlace, como /config.", + "monitoredMountPathPlaceholder": "Ruta (/config, /mnt/data)", + "monitoredMountLabelPlaceholder": "Etiqueta (opcional)", + "addMonitoredMount": "Agregar ruta", + "excludedMountsDesc": "Oculta puntos de montaje o tipos de sistema de archivos específicos (por ejemplo, nfs, cifs) del uso del disco y las alertas para este host.", + "excludedMountsPlaceholder": "Ruta de montaje (/mnt/nas) o tipo de sistema de archivos (nfs, cifs)", + "excludedMountsEmpty": "No se excluye ningún punto de montaje. Se muestran todos los sistemas de archivos detectados.", + "addExcludedMount": "Agregar", + "visibleWidgets": "Widgets visibles", + "widgetsMovedToHostMetrics": "Ahora las tarjetas se añaden, organizan y redimensionan directamente en la pestaña Métricas del host. Abre Métricas del host para este host y usa Personalizar para elegir qué tarjetas se muestran.", + "quickActionsLabel": "Acciones rápidas", + "quickActionsToolbar": "Las acciones rápidas aparecen como botones en la barra de herramientas de Métricas del host para la ejecución de comandos con un solo clic.", + "noQuickActions": "Aún no hay acciones rápidas.", + "buttonLabel": "Etiqueta del botón", + "selectSnippetPlaceholder": "Seleccionar fragmento...", + "addActionBtn": "Añadir acción" + }, + "onboarding": { + "feature_metrics": "Métricas y alertas", + "feature_metrics_desc": "Realiza un seguimiento del rendimiento de la CPU, la memoria y el disco duro a lo largo del tiempo, y recibe alertas cuando alguno falle." + }, + "admin": { + "metricsHistoryRetention": "Retención del historial de métricas", + "metricsHistoryRetentionRange": "De 1 a 90 días", + "days": "días" + }, + "homepage": { + "noData": "Sin datos disponibles", + "showCurrentValue": "Mostrar valor actual", + "chartMetric": "Métrica", + "metricRange": "Rango" + } +} diff --git a/plugins/host-metrics/locales/translated/fi_FI.json b/plugins/host-metrics/locales/translated/fi_FI.json new file mode 100644 index 000000000..4fe271fa5 --- /dev/null +++ b/plugins/host-metrics/locales/translated/fi_FI.json @@ -0,0 +1,313 @@ +{ + "hostMetrics": { + "cpu": "Suoritin", + "memory": "Muisti", + "disk": "Levy", + "network": "Verkko", + "uptime": "Käyttöaika", + "processes": "Prosessit", + "available": "Saatavilla", + "free": "Ilmainen", + "connecting": "Yhdistetään...", + "connectionFailed": "Palvelimeen ei saatu yhteyttä", + "naCpus": "Ei saatavilla olevaa suoritinta", + "cpuCores_one": "{{count}} Ydin", + "cpuCores_other": "{{count}} Ytimet", + "cpuUsage": "Suorittimen käyttö", + "memoryUsage": "Muistin käyttö", + "diskUsage": "Levyn käyttö", + "selectFilesystem": "Valitse tiedostojärjestelmä", + "temperature": "Lämpötila", + "highestTemperature": "Korkein lämpötila", + "primaryTemperatureSensor": "Ensisijainen anturi", + "gpu": { + "title": "Näytönohjain", + "noDevice": "NVIDIA-näytönohjainta ei havaittu. Asenna NVIDIA-ajuri (se tarjoaa nvidia-smi-ajurin) nähdäksesi näytönohjaimen tiedot.", + "driver": "Kuljettaja {{version}}", + "utilization": "Käyttö", + "memory": "VRAM-muisti", + "temperature": "Lämpötila", + "power": "Voima", + "fan": "Tuuletin", + "processes": "GPU-prosessit", + "noProcesses": "Mikään prosessi ei käytä grafiikkasuoritinta" + }, + "failedToFetchHostConfig": "Isännän määritysten nouto epäonnistui", + "serverOffline": "Palvelin offline-tilassa", + "cannotFetchMetrics": "Mittarien nouto offline-palvelimelta ei onnistu", + "totpFailed": "TOTP-vahvistus epäonnistui", + "noneAuthNotSupported": "Isäntämittarit eivät tue 'none'-todennustyyppiä.", + "noHostSelected": "Ei valittua isäntää", + "load": "Ladata", + "systemInfo": "Järjestelmätiedot", + "hostname": "Isäntänimi", + "operatingSystem": "Käyttöjärjestelmä", + "kernel": "Ydin", + "seconds": "sekuntia", + "networkInterfaces": "Verkkoliitännät", + "noInterfacesFound": "Verkkoliitäntöjä ei löytynyt", + "noProcessesFound": "Ei prosesseja", + "processesTotal": "kokonais-", + "processesRunning": "juokseminen", + "loginStats": "SSH-kirjautumistilastot", + "noRecentLoginData": "Ei viimeaikaisia kirjautumistietoja", + "executingQuickAction": "Suoritetaan {{name}}...", + "quickActionSuccess": "{{name}} suoritettu onnistuneesti", + "quickActionFailed": "{{name}} epäonnistui", + "quickActionError": "Suoritus epäonnistui {{name}}", + "ports": { + "title": "Kuunteluportit", + "protocol": "Protokolla", + "port": "Portti", + "address": "Osoite", + "process": "Käsitellä", + "search": "Hakusatamat...", + "allProtocols": "Kaikki", + "noData": "Ei kuunteluporttien tietoja" + }, + "firewall": { + "title": "Palomuuri", + "inactive": "Passiivinen", + "policy": "Käytäntö", + "rules": "säännöt", + "noRules": "Ei sääntöjä tässä ketjussa", + "noData": "Palomuuritietoja ei ole saatavilla", + "action": "Toiminta", + "protocol": "Proto", + "port": "Portti", + "source": "Lähde", + "anywhere": "Missä tahansa", + "chains": "ketjut" + }, + "loadAvg": "Keskimääräinen lataus", + "swap": "Vaihtaa", + "architecture": "Arkkitehtuuri", + "refresh": "Päivitä", + "retry": "Yritä uudelleen", + "customize": "Mukauta asettelua", + "reset": "Nollaa", + "tabLive": "Elää", + "editModeInstructions": "Vedä kortteja järjestelläksesi niitä uudelleen, vedä alareunaa muuttaaksesi kokoa ja käytä leveyspainiketta muuttaaksesi kortin väliä. Lisää tai poista kortteja alla.", + "managers": { + "services": "Palvelut", + "processInspector": "Prosessitarkastaja", + "logViewer": "Lokikatseluohjelma", + "cron": "Cron-työt", + "packages": "Paketit", + "ssl": "SSL-sertifikaatit", + "firewall": "Palomuuri", + "users": "Käyttäjät ja käyttöoikeudet", + "healthCheck": "Terveystarkastukset", + "diskBreakdown": "Levyn erittely", + "systemdTimers": "Ajastimet", + "topMemory": "Muistin mukaan huippu", + "noData": "Ei tietoja", + "sudoHint": "Aseta tälle isännälle sudo-salasana isäntäeditorissa ottaaksesi käyttöön etuoikeutetut toiminnot.", + "filter": "Suodattaa...", + "start": "Aloita", + "stop": "Stop", + "restart": "Käynnistä uudelleen", + "actionDone": "{{name}} päivitetty", + "actionFailed": "Toiminto epäonnistui", + "signalSent": "Signaali lähetetään PID:lle {{pid}}", + "killHint": "Napsauta: lopeta (SIGTERM). Napsauta hiiren kakkospainikkeella: pakota lopettaminen (SIGKILL).", + "working": "Työskentely...", + "update": "Päivittää", + "upgradeAll": "Päivitä kaikki", + "allUpToDate": "Kaikki on ajan tasalla", + "save": "Tallentaa", + "command": "Komento", + "enabled": "Käytössä", + "cronSaved": "Crontab päivitetty", + "clients": "Asiakkaat", + "dryRun": "Kuiva ajo", + "renew": "Uudista", + "noAcmeClient": "Tältä isännältä ei löytynyt ACME-asiakasohjelmaa (certbot tai acme.sh).", + "addInputRule": "Lisää SYÖTTÖSääntö", + "firewallWarning": "Muutokset ovat vain ajonaikaisia, kunnes ne pysyvät voimassa. Varo lukitsemasta itseäsi ulos.", + "ruleApplied": "Sääntö sovellettu", + "invalidPort": "Anna kelvollinen portti (1-65535)", + "newUsername": "Uusi käyttäjätunnus", + "addUser": "Lisätä", + "deleteUser": "Poista käyttäjä", + "noHealthChecks": "Ei vielä määritettyjä kuntotarkastuksia.", + "follow": "Seuraa", + "noLogData": "Ei lokitulostetta.", + "tree": "Puu", + "enableDisable": "Ota käyttöön / poista käytöstä käynnistyksen yhteydessä", + "grantSudo": "Myönnä sudo", + "revokeSudo": "Peruuta sudo", + "sslIssueCert": "Myöntötodistus", + "sslExpired": "Vanhentunut", + "sslInDays": "{{days}}d:ssä", + "sslNeedDomain": "Anna vähintään yksi verkkotunnus", + "sslIssued": "Todistus myönnetty", + "sslDomainsPlaceholder": "esimerkki.com, www.esimerkki.com", + "sslHttpStandalone": "HTTP (erillinen)", + "sslHttpWebroot": "HTTP (verkkojuuri)", + "sslDns": "DNS", + "sslDnsProvider": "DNS-palveluntarjoaja (esim. cloudflare)", + "sslIssueHint": "DNS-palveluntarjoajan tunnistetietojen on oltava jo määritettyinä isännälle.", + "sslRevoke": "Peruuta varmenne", + "sslRevoked": "Varmenne peruutettu", + "sslRevokeConfirm": "Peruuttaa ja poistaa varmenne \"{{name}}\"? Tätä ei voi perua.", + "healthRun": "Juokse", + "healthName": "Nimi", + "healthTarget": "Isäntä / osoite", + "healthAddCheck": "Lisää shekki", + "healthSaved": "Terveystarkastukset tallennettu", + "healthMissingFields": "Jokaisella tarkistuksella on oltava nimi ja kohde", + "logFile": "Tiedosto", + "logUnit": "Yksikkö", + "logCustomPath": "Mukautettu polku /var/log-hakemistossa (valinnainen)", + "logGrep": "Suodata viivat...", + "firewallPersist": "Säilytä säännöt", + "firewallPersisted": "Palomuurisäännöt säilyivät", + "wireguard": "WireGuard", + "tailscale": "Tailscale", + "wgNotInstalled": "WireGuardia ei ole asennettu tälle koneelle", + "wgNoInterfaces": "Ei WireGuard-liitäntöjä määritettynä", + "wgInterfaceUp": "Tuo esiin", + "wgInterfaceDown": "Alentaa", + "wgBringingUp": "Tuodaan {{name}} esiin...", + "wgBringingDown": "Lasketaan {{name}} alas...", + "wgInterfaceUpDone": "{{name}} on ylhäällä", + "wgInterfaceDownDone": "{{name}} on alhaalla", + "wgListenPort": "Portti", + "wgPublicKey": "Julkinen avain", + "wgEndpoint": "Päätepiste", + "wgAllowedIPs": "Sallitut IP-osoitteet", + "wgLastHandshake": "Viimeinen kädenpuristus", + "wgHandshakeNever": "Ei koskaan", + "wgTransfer": "Siirtää", + "tsNotInstalled": "Tailscalea ei ole asennettu tälle isännälle", + "tsRunning": "Juoksu", + "tsStopped": "Pysähtynyt", + "tsEnable": "Yhdistä", + "tsDisable": "Katkaise yhteys", + "tsEnabling": "Yhdistetään Tailscaleen...", + "tsDisabling": "Yhteyden katkaiseminen Tailscaleen...", + "tsEnabled": "Tailscale yhdistetty", + "tsDisabled": "Tailscale irrotettu", + "tsIPs": "Tailscale IP-osoitteet", + "tsPeers": "Vertaiset", + "tsOnline": "Verkossa", + "tsOffline": "Offline-tilassa", + "tsExitNode": "Poistumissolmu", + "tsExitNodeActive": "Poistumissolmu aktiivinen", + "tsHostname": "Isäntänimi" + } + }, + "metricsHistory": { + "title": "Mittarihistoria", + "historySuffix": "Historia", + "cpuMemoryDisk": "CPU / Muisti / Levy", + "network": "Verkko", + "download": "Vastaanotto", + "upload": "Teksas", + "noData": "Tältä aikaväliltä ei ole saatavilla historiatietoja.", + "custom": "Mukautettu", + "to": "että", + "apply": "Käytä", + "viewHistory": "Näytä historia" + }, + "proxmoxStats": { + "tabTitle": "Proxmox-tilastot", + "cpuUsage": "Suorittimen käyttö", + "memoryUsage": "Muistin käyttö", + "diskUsage": "Levyn käyttö", + "networkInterfaces": "Verkkoliitännät", + "uptime": "Käyttöaika", + "systemInfo": "Järjestelmätiedot", + "guestsSummary": "Vieraat", + "storagePools": "Varastoaltaat", + "clusterHealth": "Klusterin terveys", + "cpuCores_one": "{{count}} Ydin", + "cpuCores_other": "{{count}} Ytimet", + "used": "Käytetty", + "total": "Kokonais", + "hostname": "Isäntänimi", + "kernel": "Ydin", + "pveVersion": "PVE-versio", + "name": "Nimi", + "status": "Status", + "type": "Tyyppi", + "cpu": "Suoritin", + "mem": "Mem", + "disk": "Levy", + "running": "Juoksu", + "stopped": "Pysähtynyt", + "guestCounts": "{{running}}/{{total}} käynnissä", + "inactive": "Passiivinen", + "notClustered": "Itsenäinen solmu (ei osa klusteria)", + "quorate": "Päätösvaltainen", + "notQuorate": "Ei päätöslauselma", + "nodeOnline": "Verkossa", + "nodeOffline": "Offline-tilassa", + "noHostSelected": "Ei valittua isäntää", + "pveshNotFound": "pvesh-solmua ei löytynyt - onko tämä Proxmox-solmu?", + "nodeDetectionFailed": "Kelvollista Proxmox-solmun nimeä ei voitu määrittää.", + "connecting": "Yhdistetään...", + "connectionFailed": "Yhteyden muodostaminen Proxmox-solmuun epäonnistui", + "refresh": "Päivitä", + "searchGuests": "Hae vieraita...", + "filterAll": "Kaikki", + "filterVm": "Virtuaalikone", + "filterLxc": "LXC", + "noGuests": "Tältä solmulta ei löytynyt virtuaalikoneita tai LXC-säilöjä.", + "noGuestsMatch": "Yksikään vieras ei vastaa nykyisiä suodattimia." + }, + "nav": { + "hostMetrics": "Isännän mittarit" + }, + "hosts": { + "tabHostMetrics": "Isännän mittarit", + "enableProxmoxStats": "Ota Proxmox-tilastot käyttöön", + "enableProxmoxStatsDesc": "Näytä tämän isännän Proxmox-tilastot -välilehti, jossa on SSH:n kautta kerätyt reaaliaikaiset solmu-, vieras-, tallennus- ja klusteritilastot.", + "proxmoxStatsPollInterval": "Kyselyväli (sekuntia)", + "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ä", + "metricsCollectionLabel": "Mittarikokoelma", + "enableMetricsLabel": "Ota mittarit käyttöön", + "enableMetricsDesc": "Kerää prosessorin, RAMin, levyn ja muita mittareita tältä isännältä", + "useGlobalMetrics": "Käytä globaalia intervallia", + "useGlobalMetricsDesc": "Ohita palvelimen laajuisella mittarivälillä", + "metricsIntervalS": "Mittariväli (s)", + "metricsIntervalDesc2": "Sekunteja mittareiden tilannevedosten välillä", + "excludedMountsLabel": "Poissuljetut kiinnikkeet", + "monitoredMountsLabel": "Mukautetut valvotut polut", + "monitoredMountsDesc": "Lisää polut, joita ei näytetä erillisinä liitoskohtina, mukaan lukien sidotut Home Assistant -polut, kuten /config.", + "monitoredMountPathPlaceholder": "Polku (/config, /mnt/data)", + "monitoredMountLabelPlaceholder": "Tarra (valinnainen)", + "addMonitoredMount": "Lisää polku", + "excludedMountsDesc": "Piilota tietyt liitoskohdat tai tiedostojärjestelmätyypit (esim. nfs, cifs) levyn käytöstä ja hälytyksistä tälle isännälle.", + "excludedMountsPlaceholder": "Liitospolku (/mnt/nas) tai tiedostojärjestelmän tyyppi (nfs, cifs)", + "excludedMountsEmpty": "Ei poissuljettuja liitäntöjä. Kaikki havaitut tiedostojärjestelmät näytetään.", + "addExcludedMount": "Lisätä", + "visibleWidgets": "Näkyvät widgetit", + "widgetsMovedToHostMetrics": "Kortteja lisätään, järjestetään ja niiden kokoa muutetaan nyt suoraan Isännän mittarit -välilehdellä. Avaa tämän isännän Isännän mittarit ja valitse näytettävät kortit Mukauta-toiminnolla.", + "quickActionsLabel": "Pikatoiminnot", + "quickActionsToolbar": "Pikatoiminnot näkyvät painikkeina isäntämetriikkatyökalurivillä komentojen suorittamista varten yhdellä napsautuksella.", + "noQuickActions": "Ei vielä nopeita toimia.", + "buttonLabel": "Painikkeen nimi", + "selectSnippetPlaceholder": "Valitse katkelma...", + "addActionBtn": "Lisää toiminto" + }, + "onboarding": { + "feature_metrics": "Mittarit ja hälytykset", + "feature_metrics_desc": "Seuraa suorittimen, muistin ja levyn toimintaa ajan kuluessa ja saat ilmoituksen, kun ne vikaantuvat." + }, + "admin": { + "metricsHistoryRetention": "Mittarihistorian säilytys", + "metricsHistoryRetentionRange": "1–90 päivää", + "days": "päivää" + }, + "homepage": { + "noData": "Ei tietoja saatavilla", + "showCurrentValue": "Näytä nykyinen arvo", + "chartMetric": "Metrinen", + "metricRange": "Alue" + } +} diff --git a/plugins/host-metrics/locales/translated/fr_FR.json b/plugins/host-metrics/locales/translated/fr_FR.json new file mode 100644 index 000000000..22079d218 --- /dev/null +++ b/plugins/host-metrics/locales/translated/fr_FR.json @@ -0,0 +1,313 @@ +{ + "hostMetrics": { + "cpu": "CPU", + "memory": "Mémoire", + "disk": "Disque", + "network": "Réseau", + "uptime": "Uptime", + "processes": "Processus", + "available": "Disponible", + "free": "Libre", + "connecting": "Connexion en cours…", + "connectionFailed": "Échec de la connexion au serveur", + "naCpus": "CPU(s) N/A", + "cpuCores_one": "{{count}} cœur", + "cpuCores_other": "{{count}} cœurs", + "cpuUsage": "Utilisation CPU", + "memoryUsage": "Utilisation mémoire", + "diskUsage": "Utilisation disque", + "selectFilesystem": "Sélectionner le système de fichiers", + "temperature": "Température", + "highestTemperature": "Température maximale", + "primaryTemperatureSensor": "Capteur principal", + "gpu": { + "title": "GPU", + "noDevice": "Aucune carte graphique NVIDIA n'a été détectée. Installez le pilote NVIDIA (qui fournit nvidia-smi) pour consulter les métriques du GPU.", + "driver": "Conducteur {{version}}", + "utilization": "Utilisation", + "memory": "VRAM", + "temperature": "Temp", + "power": "Pouvoir", + "fan": "Ventilateur", + "processes": "Processus GPU", + "noProcesses": "Aucun processus n'utilise le GPU." + }, + "failedToFetchHostConfig": "Échec de la récupération de la configuration de l'hôte", + "serverOffline": "Serveur hors ligne", + "cannotFetchMetrics": "Impossible de récupérer les métriques du serveur hors ligne", + "totpFailed": "Échec de la vérification TOTP", + "noneAuthNotSupported": "Les métriques de l'hôte ne prennent pas en charge le type d'authentification 'none'.", + "noHostSelected": "Aucun hôte sélectionné", + "load": "Charge", + "systemInfo": "Informations système", + "hostname": "Nom d'hôte", + "operatingSystem": "Système d'exploitation", + "kernel": "Noyau", + "seconds": "secondes", + "networkInterfaces": "Interfaces réseau", + "noInterfacesFound": "Aucune interface réseau trouvée", + "noProcessesFound": "Aucun processus trouvé", + "processesTotal": "total", + "processesRunning": "en cours", + "loginStats": "Statistiques de connexion SSH", + "noRecentLoginData": "Aucune donnée de connexion récente", + "executingQuickAction": "Exécution de {{name}}...", + "quickActionSuccess": "{{name}} terminé avec succès", + "quickActionFailed": "Échec de {{name}}", + "quickActionError": "Échec de l'exécution de {{name}}", + "ports": { + "title": "Ports en écoute", + "protocol": "Protocole", + "port": "Port", + "address": "Adresse", + "process": "Processus", + "search": "Rechercher des ports...", + "allProtocols": "Tous", + "noData": "Aucune donnée de ports en écoute" + }, + "firewall": { + "title": "Pare-feu", + "inactive": "Inactif", + "policy": "Politique", + "rules": "règles", + "noRules": "Aucune règle dans cette chaîne", + "noData": "Aucune donnée de pare-feu disponible", + "action": "Action", + "protocol": "Proto", + "port": "Port", + "source": "Source", + "anywhere": "Partout", + "chains": "chaînes" + }, + "loadAvg": "Charge moyenne", + "swap": "Swap", + "architecture": "Architecture", + "refresh": "Actualiser", + "retry": "Réessayer", + "customize": "Personnaliser la disposition", + "reset": "Réinitialiser", + "tabLive": "En direct", + "editModeInstructions": "Faites glisser les cartes pour les réorganiser, faites glisser le bord inférieur pour les redimensionner, et utilisez le bouton de largeur pour modifier l'étendue d'une carte. Ajoutez ou retirez des cartes ci-dessous.", + "managers": { + "services": "Services", + "processInspector": "Inspecteur de processus", + "logViewer": "Visualiseur de logs", + "cron": "Tâches Cron", + "packages": "Paquets", + "ssl": "Certificats SSL", + "firewall": "Pare-feu", + "users": "Utilisateurs et permissions", + "healthCheck": "Contrôles de santé", + "diskBreakdown": "Ventilation du disque", + "systemdTimers": "Timers", + "topMemory": "Top mémoire", + "noData": "Aucune donnée", + "sudoHint": "Définissez un mot de passe sudo pour cet hôte dans l'éditeur d'hôte pour activer les actions privilégiées.", + "filter": "Filtrer...", + "start": "Démarrer", + "stop": "Arrêter", + "restart": "Redémarrer", + "actionDone": "{{name}} mis à jour", + "actionFailed": "Action échouée", + "signalSent": "Signal envoyé au PID {{pid}}", + "killHint": "Clic : terminer (SIGTERM). Clic droit : forcer l'arrêt (SIGKILL).", + "working": "En cours...", + "update": "Mettre à jour", + "upgradeAll": "Tout mettre à niveau", + "allUpToDate": "Tout est à jour", + "save": "Enregistrer", + "command": "Commande", + "enabled": "Activé", + "cronSaved": "Crontab mis à jour", + "clients": "Clients", + "dryRun": "Simulation", + "renew": "Renouveler", + "noAcmeClient": "Aucun client ACME (certbot ou acme.sh) trouvé sur cet hôte.", + "addInputRule": "Ajouter une règle INPUT", + "firewallWarning": "Les modifications sont appliquées uniquement en mémoire jusqu'à leur persistance. Veillez à ne pas vous bloquer l'accès.", + "ruleApplied": "Règle appliquée", + "invalidPort": "Saisissez un port valide (1-65535)", + "newUsername": "Nouveau nom d'utilisateur", + "addUser": "Ajouter", + "deleteUser": "Supprimer l'utilisateur", + "noHealthChecks": "Aucune vérification d'état configurée pour le moment.", + "follow": "Suivre", + "noLogData": "Aucun journal disponible.", + "tree": "Arborescence", + "enableDisable": "Activer / désactiver au démarrage", + "grantSudo": "Accorder sudo", + "revokeSudo": "Révoquer sudo", + "sslIssueCert": "Émettre le certificat", + "sslExpired": "Expiré", + "sslInDays": "dans {{days}} j", + "sslNeedDomain": "Saisissez au moins un domaine", + "sslIssued": "Certificat émis", + "sslDomainsPlaceholder": "example.com, www.example.com", + "sslHttpStandalone": "HTTP (autonome)", + "sslHttpWebroot": "HTTP (webroot)", + "sslDns": "DNS", + "sslDnsProvider": "Fournisseur DNS (ex. cloudflare)", + "sslIssueHint": "Les identifiants du fournisseur DNS doivent déjà être configurés sur l’hôte.", + "sslRevoke": "Révoquer le certificat", + "sslRevoked": "Certificat révoqué", + "sslRevokeConfirm": "Révoquer et supprimer le certificat « {{name}} » ? Cette action est irréversible.", + "healthRun": "Exécuter", + "healthName": "Nom", + "healthTarget": "Hôte / adresse", + "healthAddCheck": "Ajouter une vérification", + "healthSaved": "Vérifications de santé enregistrées", + "healthMissingFields": "Chaque vérification nécessite un nom et une cible", + "logFile": "Fichier", + "logUnit": "Unité", + "logCustomPath": "Chemin personnalisé sous /var/log (optionnel)", + "logGrep": "Filtrer les lignes...", + "firewallPersist": "Persister les règles", + "firewallPersisted": "Règles du pare-feu rendues persistantes", + "wireguard": "WireGuard", + "tailscale": "Tailscale", + "wgNotInstalled": "WireGuard n’est pas installé sur cet hôte", + "wgNoInterfaces": "Aucune interface WireGuard configurée", + "wgInterfaceUp": "Activer", + "wgInterfaceDown": "Désactiver", + "wgBringingUp": "Activation de {{name}}...", + "wgBringingDown": "Désactivation de {{name}}...", + "wgInterfaceUpDone": "{{name}} est activé", + "wgInterfaceDownDone": "{{name}} est désactivé", + "wgListenPort": "Port", + "wgPublicKey": "Clé publique", + "wgEndpoint": "Point de terminaison", + "wgAllowedIPs": "IP autorisées", + "wgLastHandshake": "Dernière poignée de main", + "wgHandshakeNever": "Jamais", + "wgTransfer": "Transfert", + "tsNotInstalled": "Tailscale n’est pas installé sur cet hôte", + "tsRunning": "Actif", + "tsStopped": "Arrêté", + "tsEnable": "Connecter", + "tsDisable": "Déconnecter", + "tsEnabling": "Connexion à Tailscale...", + "tsDisabling": "Déconnexion de Tailscale...", + "tsEnabled": "Tailscale connecté", + "tsDisabled": "Tailscale déconnecté", + "tsIPs": "IPs Tailscale", + "tsPeers": "Pairs", + "tsOnline": "En ligne", + "tsOffline": "Hors ligne", + "tsExitNode": "Nœud de sortie", + "tsExitNodeActive": "Nœud de sortie actif", + "tsHostname": "Nom d'hôte" + } + }, + "metricsHistory": { + "title": "Historique des métriques", + "historySuffix": "Historique", + "cpuMemoryDisk": "CPU / Mémoire / Disque", + "network": "Réseau", + "download": "RX", + "upload": "TX", + "noData": "Aucune donnée d'historique disponible pour cette plage de temps.", + "custom": "Personnalisé", + "to": "à", + "apply": "Appliquer", + "viewHistory": "Voir l'historique" + }, + "proxmoxStats": { + "tabTitle": "Statistiques Proxmox", + "cpuUsage": "Utilisation du processeur", + "memoryUsage": "Utilisation de la mémoire", + "diskUsage": "Utilisation du disque", + "networkInterfaces": "Interfaces réseau", + "uptime": "Disponibilité", + "systemInfo": "Informations système", + "guestsSummary": "Les invités", + "storagePools": "Piscines de stockage", + "clusterHealth": "Cluster Health", + "cpuCores_one": "{{count}} Noyau", + "cpuCores_other": "{{count}} Noyaux", + "used": "Utilisé", + "total": "Total", + "hostname": "Nom d'hôte", + "kernel": "Noyau", + "pveVersion": "Version JcE", + "name": "Nom", + "status": "Statut", + "type": "Taper", + "cpu": "processeur", + "mem": "Mem", + "disk": "Disque", + "running": "En cours d'exécution", + "stopped": "Arrêté", + "guestCounts": "{{running}}/{{total}} en cours", + "inactive": "Inactif", + "notClustered": "Nœud autonome (ne faisant pas partie d'un cluster)", + "quorate": "Quaire", + "notQuorate": "Pas de quorum", + "nodeOnline": "En ligne", + "nodeOffline": "Hors ligne", + "noHostSelected": "Aucun hôte sélectionné", + "pveshNotFound": "pvesh introuvable - s'agit-il d'un nœud Proxmox ?", + "nodeDetectionFailed": "Impossible de déterminer un nom de nœud Proxmox valide", + "connecting": "De liaison...", + "connectionFailed": "Échec de la connexion au nœud Proxmox", + "refresh": "Rafraîchir", + "searchGuests": "Rechercher des invités...", + "filterAll": "Tous", + "filterVm": "VM", + "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." + }, + "nav": { + "hostMetrics": "Métriques de l'hôte" + }, + "hosts": { + "tabHostMetrics": "Métriques de l'hôte", + "enableProxmoxStats": "Activer les statistiques Proxmox", + "enableProxmoxStatsDesc": "Afficher un onglet Statistiques Proxmox pour cet hôte avec des statistiques en direct sur les nœuds, les invités, le stockage et le cluster collectées via SSH.", + "proxmoxStatsPollInterval": "Intervalle d'interrogation (secondes)", + "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", + "metricsCollectionLabel": "Collecte de métriques", + "enableMetricsLabel": "Activer les métriques", + "enableMetricsDesc": "Collecter les métriques CPU, RAM, disque et autres de cet hôte", + "useGlobalMetrics": "Utiliser l'intervalle global", + "useGlobalMetricsDesc": "Remplacer par l'intervalle de métriques défini à l'échelle du serveur", + "metricsIntervalS": "Intervalle de métriques (s)", + "metricsIntervalDesc2": "Secondes entre les instantanés de métriques", + "excludedMountsLabel": "Supports exclus", + "monitoredMountsLabel": "Chemins surveillés personnalisés", + "monitoredMountsDesc": "Ajoutez les chemins qui ne sont pas exposés en tant que points de montage séparés, y compris les chemins Home Assistant montés par liaison tels que /config.", + "monitoredMountPathPlaceholder": "Chemin (/config, /mnt/data)", + "monitoredMountLabelPlaceholder": "Étiquette (facultatif)", + "addMonitoredMount": "Ajouter un chemin", + "excludedMountsDesc": "Masquer certains points de montage ou types de systèmes de fichiers (par exemple nfs, cifs) des données d'utilisation du disque et des alertes pour cet hôte.", + "excludedMountsPlaceholder": "Chemin de montage (/mnt/nas) ou type de système de fichiers (nfs, cifs)", + "excludedMountsEmpty": "Aucun point de montage n'est exclu. Tous les systèmes de fichiers détectés sont affichés.", + "addExcludedMount": "Ajouter", + "visibleWidgets": "Widgets visibles", + "widgetsMovedToHostMetrics": "Les cartes sont désormais ajoutées, organisées et redimensionnées directement dans l'onglet Métriques de l'hôte. Ouvrez les métriques de cet hôte et utilisez Personnaliser pour choisir les cartes à afficher.", + "quickActionsLabel": "Actions rapides", + "quickActionsToolbar": "Les actions rapides apparaissent sous forme de boutons dans la barre d'outils Métriques de l'hôte pour une exécution en un clic.", + "noQuickActions": "Aucune action rapide pour le moment.", + "buttonLabel": "Étiquette du bouton", + "selectSnippetPlaceholder": "Sélectionner un snippet...", + "addActionBtn": "Ajouter une action" + }, + "onboarding": { + "feature_metrics": "Métriques et alertes", + "feature_metrics_desc": "Surveillez l'évolution du processeur, de la mémoire et du disque au fil du temps et recevez une alerte en cas de défaillance." + }, + "admin": { + "metricsHistoryRetention": "Rétention de l'historique des métriques", + "metricsHistoryRetentionRange": "1 à 90 jours", + "days": "jours" + }, + "homepage": { + "noData": "Aucune donnée disponible", + "showCurrentValue": "Afficher la valeur actuelle", + "chartMetric": "Métrique", + "metricRange": "Plage" + } +} diff --git a/plugins/host-metrics/locales/translated/he_IL.json b/plugins/host-metrics/locales/translated/he_IL.json new file mode 100644 index 000000000..d5c7b3bdc --- /dev/null +++ b/plugins/host-metrics/locales/translated/he_IL.json @@ -0,0 +1,313 @@ +{ + "hostMetrics": { + "cpu": "מעבד", + "memory": "זֵכֶר", + "disk": "דִיסק", + "network": "רֶשֶׁת", + "uptime": "זמן פעולה", + "processes": "תהליכים", + "available": "זָמִין", + "free": "לְשַׁחְרֵר", + "connecting": "מְקַשֵׁר...", + "connectionFailed": "נכשלה ההתחברות לשרת", + "naCpus": "מעבדים לא רלוונטיים", + "cpuCores_one": "{{count}} ליבה", + "cpuCores_other": "{{count}} ליבות", + "cpuUsage": "שימוש במעבד", + "memoryUsage": "שימוש בזיכרון", + "diskUsage": "שימוש בדיסק", + "selectFilesystem": "בחירת מערכת קבצים", + "temperature": "טֶמפֶּרָטוּרָה", + "highestTemperature": "הטמפרטורה הגבוהה ביותר", + "primaryTemperatureSensor": "חיישן ראשי", + "gpu": { + "title": "כרטיס מסך", + "noDevice": "לא זוהה כרטיס מסך של NVIDIA. התקן את מנהל ההתקן של NVIDIA (הוא מספק nvidia-smi) כדי לראות את מדדי הכרטיס המסך.", + "driver": "נהג {{version}}", + "utilization": "ניצול", + "memory": "זיכרון RAM", + "temperature": "טמפ'", + "power": "כּוֹחַ", + "fan": "מְנִיפָה", + "processes": "תהליכי GPU", + "noProcesses": "אף תהליכים לא משתמשים ב-GPU" + }, + "failedToFetchHostConfig": "נכשל באחזור תצורת המארח", + "serverOffline": "שרת לא מקוון", + "cannotFetchMetrics": "לא ניתן לאחזר מדדים משרת לא מקוון", + "totpFailed": "אימות TOTP נכשל", + "noneAuthNotSupported": "Host Metrics אינו תומך בסוג אימות 'ללא'.", + "noHostSelected": "לא נבחר מארח", + "load": "לִטעוֹן", + "systemInfo": "מידע מערכת", + "hostname": "שם מארח", + "operatingSystem": "מַעֲרֶכֶת הַפעָלָה", + "kernel": "גַרעִין", + "seconds": "שניות", + "networkInterfaces": "ממשקי רשת", + "noInterfacesFound": "לא נמצאו ממשקי רשת", + "noProcessesFound": "לא נמצאו תהליכים", + "processesTotal": "סַך הַכֹּל", + "processesRunning": "רִיצָה", + "loginStats": "סטטיסטיקות כניסה ל-SSH", + "noRecentLoginData": "אין נתוני התחברות אחרונים", + "executingQuickAction": "מבצע {{name}}...", + "quickActionSuccess": "{{name}} הושלם בהצלחה", + "quickActionFailed": "{{name}} נכשל", + "quickActionError": "נכשל בביצוע {{name}}", + "ports": { + "title": "יציאות האזנה", + "protocol": "פּרוֹטוֹקוֹל", + "port": "נָמָל", + "address": "כְּתוֹבֶת", + "process": "תַהֲלִיך", + "search": "חיפוש פורטים...", + "allProtocols": "כֹּל", + "noData": "אין נתוני יציאות האזנה" + }, + "firewall": { + "title": "חומת אש", + "inactive": "לֹא פָּעִיל", + "policy": "מְדִינִיוּת", + "rules": "כללים", + "noRules": "אין חוקים בשרשרת הזו", + "noData": "אין נתוני חומת אש זמינים", + "action": "פְּעוּלָה", + "protocol": "פרוטו", + "port": "נָמָל", + "source": "מָקוֹר", + "anywhere": "בְּכָל מָקוֹם", + "chains": "שרשראות" + }, + "loadAvg": "טען ממוצע", + "swap": "לְהַחלִיף", + "architecture": "אַדְרִיכָלוּת", + "refresh": "לְרַעֲנֵן", + "retry": "נסה שוב", + "customize": "התאמה אישית של הפריסה", + "reset": "אִתחוּל", + "tabLive": "לִחיוֹת", + "editModeInstructions": "גרור כרטיסים כדי לסדר מחדש, גרור את הקצה התחתון כדי לשנות את הגודל, והשתמש בלחצן הרוחב כדי לשנות את טווח הכרטיס. הוסף או הסר כרטיסים למטה.", + "managers": { + "services": "שירותים", + "processInspector": "מפקח תהליכים", + "logViewer": "מציג יומנים", + "cron": "עבודות קרון", + "packages": "חבילות", + "ssl": "תעודות SSL", + "firewall": "חומת אש", + "users": "משתמשים והרשאות", + "healthCheck": "בדיקות בריאות", + "diskBreakdown": "פירוט דיסק", + "systemdTimers": "טיימרים", + "topMemory": "מובילים לפי זיכרון", + "noData": "אין נתונים", + "sudoHint": "הגדר סיסמת sudo עבור מארח זה בעורך המארחים כדי לאפשר פעולות הרשאות.", + "filter": "לְסַנֵן...", + "start": "הַתחָלָה", + "stop": "לְהַפְסִיק", + "restart": "הפעלה מחדש", + "actionDone": "{{name}} updated", + "actionFailed": "הפעולה נכשלה", + "signalSent": "אות שנשלח ל-PID {{pid}}", + "killHint": "לחיצה: סיום (SIGTERM). לחיצה ימנית: כיבוי בכוח (SIGKILL).", + "working": "עובד...", + "update": "לְעַדְכֵּן", + "upgradeAll": "שדרגו הכל", + "allUpToDate": "הכל מעודכן", + "save": "לְהַצִיל", + "command": "פְּקוּדָה", + "enabled": "מופעל", + "cronSaved": "קרונטאב עודכן", + "clients": "לקוחות", + "dryRun": "ריצה יבשה", + "renew": "לְחַדֵשׁ", + "noAcmeClient": "לא נמצא לקוח ACME ‏(certbot או acme.sh) בשרת זה.", + "addInputRule": "הוסף כלל INPUT", + "firewallWarning": "שינויים הם בזמן ריצה בלבד עד שהם מתמשכים. היזהרו לא לנעול את עצמכם מחוץ למערכת.", + "ruleApplied": "כלל שהוחל", + "invalidPort": "הזן פורט תקין (1-65535)", + "newUsername": "שם משתמש חדש", + "addUser": "לְהוֹסִיף", + "deleteUser": "מחיקת משתמש", + "noHealthChecks": "עדיין לא הוגדרו בדיקות תקינות.", + "follow": "לַעֲקוֹב", + "noLogData": "אין פלט יומן.", + "tree": "עֵץ", + "enableDisable": "הפעלה/השבתה בעת האתחול", + "grantSudo": "גרנט סודו", + "revokeSudo": "בטל את הסודו", + "sslIssueCert": "הנפקת תעודה", + "sslExpired": "פג תוקף", + "sslInDays": "ב- {{days}}ד'", + "sslNeedDomain": "הזן לפחות דומיין אחד", + "sslIssued": "תעודה שהונפקה", + "sslDomainsPlaceholder": "example.com, www.example.com", + "sslHttpStandalone": "HTTP (עצמאי)", + "sslHttpWebroot": "HTTP (שורש רשת)", + "sslDns": "DNS", + "sslDnsProvider": "ספק DNS (למשל cloudflare)", + "sslIssueHint": "יש להגדיר את פרטי הגישה של ספק ה-DNS כבר במארח.", + "sslRevoke": "בטל את האישור", + "sslRevoked": "התעודה בוטלה", + "sslRevokeConfirm": "לבטל ולהסיר את האישור \"{{name}}\"? לא ניתן לבטל פעולה זו.", + "healthRun": "לָרוּץ", + "healthName": "שֵׁם", + "healthTarget": "מארח / כתובת", + "healthAddCheck": "הוסף צ'ק", + "healthSaved": "בדיקות הבריאות נשמרו", + "healthMissingFields": "כל צ'ק צריך שם ומטרה", + "logFile": "קוֹבֶץ", + "logUnit": "יְחִידָה", + "logCustomPath": "נתיב מותאם אישית תחת /var/log (אופציונלי)", + "logGrep": "קווי סינון...", + "firewallPersist": "כללים קבועים", + "firewallPersisted": "כללי חומת האש נשמרו", + "wireguard": "WireGuard", + "tailscale": "קנה מידה זנב", + "wgNotInstalled": "WireGuard אינו מותקן על מחשב זה", + "wgNoInterfaces": "לא הוגדרו ממשקי WireGuard", + "wgInterfaceUp": "לְהַעֲלוֹת", + "wgInterfaceDown": "לְהַפִּיל", + "wgBringingUp": "מעלה {{name}}...", + "wgBringingDown": "מוריד את {{name}}...", + "wgInterfaceUpDone": "{{name}} פעיל", + "wgInterfaceDownDone": "{{name}} מושבת", + "wgListenPort": "נָמָל", + "wgPublicKey": "מפתח ציבורי", + "wgEndpoint": "נקודת קצה", + "wgAllowedIPs": "כתובות IP מותרות", + "wgLastHandshake": "לחיצת יד אחרונה", + "wgHandshakeNever": "לְעוֹלָם לֹא", + "wgTransfer": "לְהַעֲבִיר", + "tsNotInstalled": "Tailscale אינו מותקן על מחשב אחסון זה", + "tsRunning": "רִיצָה", + "tsStopped": "נֶעצָר", + "tsEnable": "לְחַבֵּר", + "tsDisable": "לְנַתֵק", + "tsEnabling": "מתחבר ל-Tailscale...", + "tsDisabling": "מתנתק מ-Tailscale...", + "tsEnabled": "זנבסקאלה מחוברת", + "tsDisabled": "ניתוק של קנה המידה של הזנב", + "tsIPs": "כתובות IP של זנבות", + "tsPeers": "עמיתים", + "tsOnline": "באינטרנט", + "tsOffline": "לא מקוון", + "tsExitNode": "צומת יציאה", + "tsExitNodeActive": "צומת יציאה פעיל", + "tsHostname": "שם מארח" + } + }, + "metricsHistory": { + "title": "היסטוריית מדדים", + "historySuffix": "הִיסטוֹרִיָה", + "cpuMemoryDisk": "מעבד / זיכרון / דיסק", + "network": "רֶשֶׁת", + "download": "מרשם", + "upload": "טקסס", + "noData": "אין נתוני היסטוריה זמינים עבור טווח זמן זה.", + "custom": "מִנְהָג", + "to": "אֶל", + "apply": "לִפְנוֹת", + "viewHistory": "הצג היסטוריה" + }, + "proxmoxStats": { + "tabTitle": "סטטיסטיקות פרוקסמוקס", + "cpuUsage": "שימוש במעבד", + "memoryUsage": "שימוש בזיכרון", + "diskUsage": "שימוש בדיסק", + "networkInterfaces": "ממשקי רשת", + "uptime": "זמן פעולה", + "systemInfo": "מידע מערכת", + "guestsSummary": "אורחים", + "storagePools": "בריכות אחסון", + "clusterHealth": "בריאות אשכול", + "cpuCores_one": "{{count}} ליבה", + "cpuCores_other": "{{count}} ליבות", + "used": "מְשׁוּמָשׁ", + "total": "סַך הַכֹּל", + "hostname": "שם מארח", + "kernel": "גַרעִין", + "pveVersion": "גרסת PVE", + "name": "שֵׁם", + "status": "סטָטוּס", + "type": "סוּג", + "cpu": "מעבד", + "mem": "מ", + "disk": "דִיסק", + "running": "רִיצָה", + "stopped": "נֶעצָר", + "guestCounts": "ריצה {{running}}/ ריצה{{total}}", + "inactive": "לֹא פָּעִיל", + "notClustered": "צומת עצמאי (לא חלק מאשכול)", + "quorate": "קוורט", + "notQuorate": "לא נמצא מניין חוקי", + "nodeOnline": "באינטרנט", + "nodeOffline": "לא מקוון", + "noHostSelected": "לא נבחר מארח", + "pveshNotFound": "pvesh לא נמצא - האם זהו צומת Proxmox?", + "nodeDetectionFailed": "לא ניתן לקבוע שם צומת Proxmox תקין", + "connecting": "מְקַשֵׁר...", + "connectionFailed": "נכשלה ההתחברות לצומת Proxmox", + "refresh": "לְרַעֲנֵן", + "searchGuests": "חיפוש אורחים...", + "filterAll": "כֹּל", + "filterVm": "מכונה וירטואלית", + "filterLxc": "LXC", + "noGuests": "לא נמצאו מכונות וירטואליות או מכולות LXC בצומת זה.", + "noGuestsMatch": "אין אורחים התואמים את המסננים הנוכחיים." + }, + "nav": { + "hostMetrics": "מדדי מארח" + }, + "hosts": { + "tabHostMetrics": "מדדי מארח", + "enableProxmoxStats": "הפעל סטטיסטיקות Proxmox", + "enableProxmoxStatsDesc": "הצג כרטיסיית סטטיסטיקות Proxmox עבור מארח זה עם סטטיסטיקות של צומת, אורח, אחסון ואשכול שנאספו דרך SSH.", + "proxmoxStatsPollInterval": "מרווח זמן בין סקר (שניות)", + "proxmoxStatsPollIntervalDesc": "מינימום 15 שניות. באיזו תדירות לרענן את סטטיסטיקות הצומת של Proxmox.", + "proxmoxStatsNodeOverride": "עקיפת שם הצומת", + "proxmoxStatsNodeOverrideDesc": "עקיפת זיהוי אוטומטי של שם הצומת Proxmox (מזוהה דרך שם המארח כברירת מחדל).", + "proxmoxStatsNodeOverridePlaceholder": "זוהה אוטומטית משם המארח", + "metricsCollectionLabel": "אוסף מדדים", + "enableMetricsLabel": "הפעל מדדים", + "enableMetricsDesc": "איסוף מדדים של מעבד, זיכרון RAM, דיסק ומדדים אחרים ממארח זה", + "useGlobalMetrics": "השתמש במרווח גלובלי", + "useGlobalMetricsDesc": "עקיפה עם מרווח המדדים הכולל של השרת", + "metricsIntervalS": "מרווח מדדים (ים)", + "metricsIntervalDesc2": "שניות בין תמונות מצב של מדדים", + "excludedMountsLabel": "תושבות לא כלולות", + "monitoredMountsLabel": "נתיבים מנוטרים בהתאמה אישית", + "monitoredMountsDesc": "הוסף נתיבים שאינם חשופים כחיבורים נפרדים, כולל נתיבי Home Assistant המותקנים באמצעות binding כגון /config.", + "monitoredMountPathPlaceholder": "נתיב (/config, /mnt/data)", + "monitoredMountLabelPlaceholder": "תווית (אופציונלי)", + "addMonitoredMount": "הוסף נתיב", + "excludedMountsDesc": "הסתר נקודות הרכבה או סוגי מערכת קבצים ספציפיים (למשל nfs, cifs) משימוש בדיסק והתראות עבור מארח זה.", + "excludedMountsPlaceholder": "נתיב הרכבה (/mnt/nas) או סוג מערכת קבצים (nfs, cifs)", + "excludedMountsEmpty": "לא נכללו רכיבי טעינה. כל מערכות הקבצים שזוהו מוצגות.", + "addExcludedMount": "לְהוֹסִיף", + "visibleWidgets": "ווידג'טים גלויים", + "widgetsMovedToHostMetrics": "כעת ניתן להוסיף, לסידור ולשנות את גודל הכרטיסים ישירות בכרטיסייה 'מדדי מארח'. פתחו את 'מדדי מארח' עבור מארח זה והשתמשו באפשרות 'התאמה אישית' כדי לבחור אילו כרטיסים יוצגו.", + "quickActionsLabel": "פעולות מהירות", + "quickActionsToolbar": "פעולות מהירות מופיעות ככפתורים בסרגל הכלים של Host Metrics לביצוע פקודה בלחיצה אחת.", + "noQuickActions": "אין עדיין פעולות מהירות.", + "buttonLabel": "תווית כפתור", + "selectSnippetPlaceholder": "בחר קטע...", + "addActionBtn": "הוסף פעולה" + }, + "onboarding": { + "feature_metrics": "מדדים והתראות", + "feature_metrics_desc": "עקוב אחר המעבד, הזיכרון והדיסק לאורך זמן, וקבל התראות כאשר הם מתקלקלים." + }, + "admin": { + "metricsHistoryRetention": "שמירת היסטוריית מדדים", + "metricsHistoryRetentionRange": "יום אחד עד 90 ימים", + "days": "ימים" + }, + "homepage": { + "noData": "אין נתונים זמינים", + "showCurrentValue": "הצג ערך נוכחי", + "chartMetric": "מֶטרִי", + "metricRange": "לָנוּעַ" + } +} diff --git a/plugins/host-metrics/locales/translated/hi_IN.json b/plugins/host-metrics/locales/translated/hi_IN.json new file mode 100644 index 000000000..99811cfa1 --- /dev/null +++ b/plugins/host-metrics/locales/translated/hi_IN.json @@ -0,0 +1,313 @@ +{ + "hostMetrics": { + "cpu": "CPU", + "memory": "मेमोरी", + "disk": "डिस्क", + "network": "नेटवर्क", + "uptime": "अपटाइम", + "processes": "प्रोसेसेस", + "available": "उपलब्ध", + "free": "फ्री", + "connecting": "कनेक्ट हो रहा है...", + "connectionFailed": "सर्वर से कनेक्ट करने में विफल", + "naCpus": "N/A CPU(s)", + "cpuCores_one": "{{count}} कोर", + "cpuCores_other": "{{count}} कोर", + "cpuUsage": "CPU उपयोग", + "memoryUsage": "मेमोरी उपयोग", + "diskUsage": "डिस्क उपयोग", + "selectFilesystem": "फ़ाइल सिस्टम का चयन करें", + "temperature": "तापमान", + "highestTemperature": "उच्चतम तापमान", + "primaryTemperatureSensor": "प्राथमिक सेंसर", + "gpu": { + "title": "जीपीयू", + "noDevice": "कोई NVIDIA GPU नहीं मिला। GPU मेट्रिक्स देखने के लिए NVIDIA ड्राइवर (जो nvidia-smi प्रदान करता है) इंस्टॉल करें।", + "driver": "ड्राइवर {{version}}", + "utilization": "उपयोग", + "memory": "वीआरएएम", + "temperature": "अस्थायी", + "power": "शक्ति", + "fan": "पंखा", + "processes": "जीपीयू प्रक्रियाएँ", + "noProcesses": "कोई भी प्रक्रिया जीपीयू का उपयोग नहीं कर रही है।" + }, + "failedToFetchHostConfig": "होस्ट कॉन्फ़िगरेशन प्राप्त करने में विफल", + "serverOffline": "सर्वर ऑफ़लाइन", + "cannotFetchMetrics": "ऑफ़लाइन सर्वर से मीट्रिक्स प्राप्त नहीं कर सकते", + "totpFailed": "TOTP सत्यापन विफल", + "noneAuthNotSupported": "होस्ट मेट्रिक्स 'none' प्रमाणीकरण प्रकार का समर्थन नहीं करता।", + "noHostSelected": "कोई होस्ट चयनित नहीं", + "load": "लोड", + "systemInfo": "सिस्टम जानकारी", + "hostname": "होस्टनाम", + "operatingSystem": "ऑपरेटिंग सिस्टम", + "kernel": "कर्नेल", + "seconds": "सेकंड", + "networkInterfaces": "नेटवर्क इंटरफ़ेस", + "noInterfacesFound": "कोई नेटवर्क इंटरफ़ेस नहीं मिला", + "noProcessesFound": "कोई प्रोसेस नहीं मिला", + "processesTotal": "कुल", + "processesRunning": "चल रहे", + "loginStats": "SSH लॉगिन आँकड़े", + "noRecentLoginData": "कोई हालिया लॉगिन डेटा नहीं", + "executingQuickAction": "{{name}} निष्पादित हो रहा है...", + "quickActionSuccess": "{{name}} सफलतापूर्वक पूर्ण हुआ", + "quickActionFailed": "{{name}} विफल रहा", + "quickActionError": "{{name}} निष्पादित करने में विफल", + "ports": { + "title": "लिसनिंग पोर्ट", + "protocol": "प्रोटोकॉल", + "port": "पोर्ट", + "address": "पता", + "process": "प्रोसेस", + "search": "पोर्ट खोजें...", + "allProtocols": "सभी", + "noData": "कोई लिसनिंग पोर्ट डेटा नहीं" + }, + "firewall": { + "title": "फ़ायरवॉल", + "inactive": "निष्क्रिय", + "policy": "नीति", + "rules": "नियम", + "noRules": "इस चेन में कोई नियम नहीं", + "noData": "कोई फ़ायरवॉल डेटा उपलब्ध नहीं", + "action": "कार्रवाई", + "protocol": "प्रोटो", + "port": "पोर्ट", + "source": "स्रोत", + "anywhere": "कहीं भी", + "chains": "चेन्स" + }, + "loadAvg": "लोड औसत", + "swap": "स्वैप", + "architecture": "आर्किटेक्चर", + "refresh": "रीफ़्रेश", + "retry": "पुनः प्रयास करें", + "customize": "लेआउट अनुकूलित करें", + "reset": "रीसेट", + "tabLive": "लाइव", + "editModeInstructions": "कार्ड को पुनर्व्यवस्थित करने के लिए खींचें, आकार बदलने के लिए निचले किनारे को खींचें, और कार्ड की चौड़ाई बदलने के लिए चौड़ाई बटन का उपयोग करें। नीचे कार्ड जोड़ें या हटाएं।", + "managers": { + "services": "सेवाएँ", + "processInspector": "प्रोसेस इंस्पेक्टर", + "logViewer": "लॉग व्यूअर", + "cron": "क्रॉन जॉब्स", + "packages": "पैकेजेस", + "ssl": "SSL प्रमाणपत्र", + "firewall": "फ़ायरवॉल", + "users": "उपयोगकर्ता और अनुमतियाँ", + "healthCheck": "स्वास्थ्य जांच", + "diskBreakdown": "डिस्क ब्रेकडाउन", + "systemdTimers": "टाइमर", + "topMemory": "मेमोरी के अनुसार शीर्ष", + "noData": "कोई डेटा नहीं", + "sudoHint": "विशेषाधिकार क्रियाओं को सक्षम करने के लिए होस्ट संपादक में इस होस्ट के लिए एक sudo पासवर्ड सेट करें।", + "filter": "फ़िल्टर...", + "start": "प्रारंभ", + "stop": "रोकें", + "restart": "पुनरारंभ", + "actionDone": "{{name}} अद्यतित", + "actionFailed": "कार्रवाई विफल", + "signalSent": "PID {{pid}} को सिग्नल भेजा गया", + "killHint": "क्लिक: समाप्त करें (SIGTERM)। राइट-क्लिक: बलपूर्वक समाप्त करें (SIGKILL)।", + "working": "काम कर रहा है...", + "update": "अपडेट करें", + "upgradeAll": "सभी अपग्रेड करें", + "allUpToDate": "सब कुछ अप टू डेट है", + "save": "सहेजें", + "command": "कमांड", + "enabled": "सक्षम", + "cronSaved": "क्रॉनटैब अपडेट किया गया", + "clients": "क्लाइंट", + "dryRun": "ड्राई रन", + "renew": "रीन्यू करें", + "noAcmeClient": "इस होस्ट पर कोई ACME क्लाइंट (certbot या acme.sh) नहीं मिला।", + "addInputRule": "INPUT नियम जोड़ें", + "firewallWarning": "परिवर्तन केवल रनटाइम के लिए हैं जब तक स्थायी न हों। स्वयं को लॉक आउट करने से सावधान रहें।", + "ruleApplied": "नियम लागू किया गया", + "invalidPort": "एक वैध पोर्ट दर्ज करें (1-65535)", + "newUsername": "नया उपयोगकर्ता नाम", + "addUser": "जोड़ें", + "deleteUser": "उपयोगकर्ता हटाएं", + "noHealthChecks": "अभी तक कोई हेल्थ चेक कॉन्फ़िगर नहीं किया गया है।", + "follow": "अनुसरण करें", + "noLogData": "कोई लॉग आउटपुट नहीं।", + "tree": "ट्री", + "enableDisable": "बूट पर सक्षम / अक्षम करें", + "grantSudo": "sudo दें", + "revokeSudo": "sudo वापस लें", + "sslIssueCert": "प्रमाणपत्र जारी करें", + "sslExpired": "समाप्त", + "sslInDays": "{{days}} दिनों में", + "sslNeedDomain": "कम से कम एक डोमेन दर्ज करें", + "sslIssued": "प्रमाणपत्र जारी किया गया", + "sslDomainsPlaceholder": "example.com, www.example.com", + "sslHttpStandalone": "HTTP (स्टैंडअलोन)", + "sslHttpWebroot": "HTTP (वेबरूट)", + "sslDns": "DNS", + "sslDnsProvider": "DNS प्रदाता (उदा. cloudflare)", + "sslIssueHint": "DNS प्रदाता क्रेडेंशियल पहले से होस्ट पर कॉन्फ़िगर किए गए होने चाहिए।", + "sslRevoke": "प्रमाणपत्र निरस्त करें", + "sslRevoked": "प्रमाणपत्र निरस्त किया गया", + "sslRevokeConfirm": "प्रमाणपत्र \"{{name}}\" निरस्त करें और हटाएं? यह पूर्ववत नहीं किया जा सकता।", + "healthRun": "चलाएं", + "healthName": "नाम", + "healthTarget": "होस्ट / पता", + "healthAddCheck": "जांच जोड़ें", + "healthSaved": "स्वास्थ्य जांच सहेजी गईं", + "healthMissingFields": "प्रत्येक जांच के लिए एक नाम और लक्ष्य आवश्यक है", + "logFile": "फ़ाइल", + "logUnit": "यूनिट", + "logCustomPath": "/var/log के अंतर्गत कस्टम पथ (वैकल्पिक)", + "logGrep": "लाइनें फ़िल्टर करें...", + "firewallPersist": "नियम स्थायी करें", + "firewallPersisted": "फ़ायरवॉल नियम स्थायी किए गए", + "wireguard": "WireGuard", + "tailscale": "Tailscale", + "wgNotInstalled": "WireGuard इस होस्ट पर स्थापित नहीं है", + "wgNoInterfaces": "कोई WireGuard इंटरफ़ेस कॉन्फ़िगर्ड नहीं हैं", + "wgInterfaceUp": "चालू करें", + "wgInterfaceDown": "बंद करें", + "wgBringingUp": "{{name}} चालू किया जा रहा है...", + "wgBringingDown": "{{name}} बंद किया जा रहा है...", + "wgInterfaceUpDone": "{{name}} चालू है", + "wgInterfaceDownDone": "{{name}} बंद है", + "wgListenPort": "पोर्ट", + "wgPublicKey": "सार्वजनिक कुंजी", + "wgEndpoint": "एंडपॉइंट", + "wgAllowedIPs": "अनुमत IPs", + "wgLastHandshake": "अंतिम हैंडशेक", + "wgHandshakeNever": "कभी नहीं", + "wgTransfer": "ट्रांसफर", + "tsNotInstalled": "Tailscale इस होस्ट पर स्थापित नहीं है", + "tsRunning": "चालू", + "tsStopped": "बंद", + "tsEnable": "कनेक्ट करें", + "tsDisable": "डिस्कनेक्ट करें", + "tsEnabling": "Tailscale से कनेक्ट हो रहा है...", + "tsDisabling": "Tailscale से डिस्कनेक्ट हो रहा है...", + "tsEnabled": "Tailscale कनेक्टेड", + "tsDisabled": "Tailscale डिस्कनेक्टेड", + "tsIPs": "Tailscale IPs", + "tsPeers": "पीयर्स", + "tsOnline": "ऑनलाइन", + "tsOffline": "ऑफलाइन", + "tsExitNode": "एक्जिट नोड", + "tsExitNodeActive": "एक्जिट नोड सक्रिय", + "tsHostname": "होस्टनाम" + } + }, + "metricsHistory": { + "title": "मेट्रिक्स इतिहास", + "historySuffix": "इतिहास", + "cpuMemoryDisk": "CPU / मेमोरी / डिस्क", + "network": "नेटवर्क", + "download": "RX", + "upload": "TX", + "noData": "इस समय सीमा के लिए कोई इतिहास डेटा उपलब्ध नहीं है।", + "custom": "कस्टम", + "to": "तक", + "apply": "लागू करें", + "viewHistory": "इतिहास देखें" + }, + "proxmoxStats": { + "tabTitle": "प्रॉक्समॉक्स आँकड़े", + "cpuUsage": "सीपीयू उपयोग", + "memoryUsage": "स्मृति प्रयोग", + "diskUsage": "डिस्क उपयोग", + "networkInterfaces": "नेटवर्क इंटरफेस", + "uptime": "अपटाइम", + "systemInfo": "व्यवस्था जानकारी", + "guestsSummary": "अतिथियों", + "storagePools": "भंडारण पूल", + "clusterHealth": "क्लस्टर स्वास्थ्य", + "cpuCores_one": "{{count}} कोर", + "cpuCores_other": "{{count}} कोर", + "used": "इस्तेमाल किया गया", + "total": "कुल", + "hostname": "होस्ट का नाम", + "kernel": "गुठली", + "pveVersion": "PVE संस्करण", + "name": "नाम", + "status": "स्थिति", + "type": "प्रकार", + "cpu": "CPU", + "mem": "मेम", + "disk": "डिस्क", + "running": "दौड़ना", + "stopped": "रुका हुआ", + "guestCounts": "{{running}}/{{total}} चल रहा है", + "inactive": "निष्क्रिय", + "notClustered": "स्टैंडअलोन नोड (क्लस्टर का हिस्सा नहीं)", + "quorate": "कोरेट", + "notQuorate": "निर्धारित संख्या पूरी नहीं है", + "nodeOnline": "ऑनलाइन", + "nodeOffline": "ऑफलाइन", + "noHostSelected": "कोई होस्ट चयनित नहीं है", + "pveshNotFound": "pvesh नहीं मिला - क्या यह Proxmox नोड है?", + "nodeDetectionFailed": "वैध प्रोक्समॉक्स नोड नाम निर्धारित करने में असमर्थ", + "connecting": "कनेक्ट हो रहा है...", + "connectionFailed": "Proxmox नोड से कनेक्ट करने में विफल", + "refresh": "ताज़ा करना", + "searchGuests": "अतिथियों को खोजें...", + "filterAll": "सभी", + "filterVm": "वीएम", + "filterLxc": "एलएक्ससी", + "noGuests": "इस नोड पर कोई वीएम या एलएक्ससी कंटेनर नहीं मिला।", + "noGuestsMatch": "वर्तमान फ़िल्टरों से कोई अतिथि मेल नहीं खाता।" + }, + "nav": { + "hostMetrics": "होस्ट मेट्रिक्स" + }, + "hosts": { + "tabHostMetrics": "होस्ट मेट्रिक्स", + "enableProxmoxStats": "Proxmox सांख्यिकी सक्षम करें", + "enableProxmoxStatsDesc": "इस होस्ट के लिए एक प्रोक्समॉक्स स्टैट्स टैब दिखाएं जिसमें एसएसएच के माध्यम से एकत्रित किए गए लाइव नोड, गेस्ट, स्टोरेज और क्लस्टर स्टैट्स शामिल हों।", + "proxmoxStatsPollInterval": "मतदान अंतराल (सेकंड)", + "proxmoxStatsPollIntervalDesc": "कम से कम 15 सेकंड। प्रोक्समॉक्स नोड के आंकड़ों को कितनी बार रीफ्रेश करना है?", + "proxmoxStatsNodeOverride": "नोड नाम ओवरराइड", + "proxmoxStatsNodeOverrideDesc": "Proxmox नोड नाम की स्वतः पहचान को ओवरराइड करें (जो डिफ़ॉल्ट रूप से होस्टनाम के माध्यम से पता लगाया जाता है)।", + "proxmoxStatsNodeOverridePlaceholder": "होस्टनाम से स्वतः पता लगाया गया", + "metricsCollectionLabel": "मेट्रिक्स संग्रह", + "enableMetricsLabel": "मेट्रिक्स सक्षम करें", + "enableMetricsDesc": "इस होस्ट से CPU, RAM, डिस्क और अन्य मेट्रिक्स एकत्र करें", + "useGlobalMetrics": "वैश्विक अंतराल का उपयोग करें", + "useGlobalMetricsDesc": "सर्वर-व्यापी मेट्रिक्स अंतराल से ओवरराइड करें", + "metricsIntervalS": "मेट्रिक्स अंतराल (सेकंड)", + "metricsIntervalDesc2": "मेट्रिक स्नैपशॉट के बीच सेकंड", + "excludedMountsLabel": "बहिष्कृत पर्वत", + "monitoredMountsLabel": "कस्टम मॉनिटर किए गए पथ", + "monitoredMountsDesc": "उन पथों को जोड़ें जो अलग-अलग माउंट के रूप में उजागर नहीं होते हैं, जिनमें बाइंड-माउंटेड होम असिस्टेंट पथ जैसे कि /config शामिल हैं।", + "monitoredMountPathPlaceholder": "पथ (/config, /mnt/data)", + "monitoredMountLabelPlaceholder": "लेबल (वैकल्पिक)", + "addMonitoredMount": "पथ जोड़ें", + "excludedMountsDesc": "इस होस्ट के लिए डिस्क उपयोग और अलर्ट से विशिष्ट माउंट पॉइंट या फ़ाइल सिस्टम प्रकार (जैसे nfs, cifs) को छिपाएँ।", + "excludedMountsPlaceholder": "माउंट पथ (/mnt/nas) या फ़ाइल सिस्टम प्रकार (nfs, cifs)", + "excludedMountsEmpty": "कोई भी माउंट बाहर नहीं रखा गया है। सभी पहचाने गए फ़ाइल सिस्टम दिखाए गए हैं।", + "addExcludedMount": "जोड़ना", + "visibleWidgets": "दृश्यमान विजेट्स", + "widgetsMovedToHostMetrics": "कार्ड अब सीधे होस्ट मेट्रिक्स टैब में जोड़े, व्यवस्थित और आकार बदले जा सकते हैं। इस होस्ट के लिए होस्ट मेट्रिक्स खोलें और यह चुनने के लिए कस्टमाइज़ का उपयोग करें कि कौन से कार्ड दिखाए जाएँ।", + "quickActionsLabel": "त्वरित कार्रवाइयाँ", + "quickActionsToolbar": "त्वरित कार्रवाइयाँ एक-क्लिक कमांड निष्पादन के लिए होस्ट मेट्रिक्स टूलबार में बटन के रूप में दिखाई देती हैं।", + "noQuickActions": "अभी तक कोई त्वरित कार्रवाई नहीं।", + "buttonLabel": "बटन लेबल", + "selectSnippetPlaceholder": "स्निपेट चुनें...", + "addActionBtn": "कार्रवाई जोड़ें" + }, + "onboarding": { + "feature_metrics": "मैट्रिक्स और अलर्ट", + "feature_metrics_desc": "समय के साथ सीपीयू, मेमोरी और डिस्क की स्थिति पर नज़र रखें और उनके खराब होने पर अलर्ट प्राप्त करें।" + }, + "admin": { + "metricsHistoryRetention": "मेट्रिक्स इतिहास प्रतिधारण", + "metricsHistoryRetentionRange": "1 से 90 दिन", + "days": "दिन" + }, + "homepage": { + "noData": "कोई डेटा उपलब्ध नहीं", + "showCurrentValue": "वर्तमान मान दिखाएं", + "chartMetric": "मीट्रिक", + "metricRange": "सीमा" + } +} diff --git a/plugins/host-metrics/locales/translated/hu_HU.json b/plugins/host-metrics/locales/translated/hu_HU.json new file mode 100644 index 000000000..7c3280dc4 --- /dev/null +++ b/plugins/host-metrics/locales/translated/hu_HU.json @@ -0,0 +1,313 @@ +{ + "hostMetrics": { + "cpu": "CPU", + "memory": "Memória", + "disk": "Korong", + "network": "Hálózat", + "uptime": "Üzemidő", + "processes": "Folyamatok", + "available": "Elérhető", + "free": "Ingyenes", + "connecting": "Kapcsolódás...", + "connectionFailed": "Nem sikerült csatlakozni a szerverhez", + "naCpus": "Nincs CPU", + "cpuCores_one": "{{count}} Mag", + "cpuCores_other": "{{count}} Magok", + "cpuUsage": "CPU-használat", + "memoryUsage": "Memóriahasználat", + "diskUsage": "Lemezhasználat", + "selectFilesystem": "Fájlrendszer kiválasztása", + "temperature": "Hőmérséklet", + "highestTemperature": "Legmagasabb hőmérséklet", + "primaryTemperatureSensor": "Elsődleges érzékelő", + "gpu": { + "title": "GPU", + "noDevice": "Nem észlelhető NVIDIA GPU. Telepítse az NVIDIA illesztőprogramot (ez biztosítja az nvidia-smi-t) a GPU-metrikák megtekintéséhez.", + "driver": "Sofőr {{version}}", + "utilization": "Hasznosítás", + "memory": "VRAM", + "temperature": "Hőmérséklet", + "power": "Hatalom", + "fan": "Ventilátor", + "processes": "GPU-folyamatok", + "noProcesses": "Egyik folyamat sem használja a GPU-t" + }, + "failedToFetchHostConfig": "Nem sikerült lekérni a gazdagép konfigurációját", + "serverOffline": "Szerver offline állapotban", + "cannotFetchMetrics": "Nem lehet metrikákat lekérni az offline szerverről", + "totpFailed": "TOTP-ellenőrzés sikertelen", + "noneAuthNotSupported": "A Host Metrics nem támogatja a „nincs” hitelesítési típust.", + "noHostSelected": "Nincs kiválasztva gazdagép", + "load": "Terhelés", + "systemInfo": "Rendszerinformációk", + "hostname": "Gazdagépnév", + "operatingSystem": "Operációs rendszer", + "kernel": "Kernel", + "seconds": "másodperc", + "networkInterfaces": "Hálózati interfészek", + "noInterfacesFound": "Nem találhatók hálózati interfészek", + "noProcessesFound": "Nem találhatók folyamatok", + "processesTotal": "teljes", + "processesRunning": "futás", + "loginStats": "SSH bejelentkezési statisztikák", + "noRecentLoginData": "Nincsenek friss bejelentkezési adatok", + "executingQuickAction": "{{name}} végrehajtása ...", + "quickActionSuccess": "{{name}} sikeresen befejeződött", + "quickActionFailed": "{{name}} sikertelen", + "quickActionError": "Nem sikerült végrehajtani a {{name}} parancsot.", + "ports": { + "title": "Figyelő portok", + "protocol": "Jegyzőkönyv", + "port": "Kikötő", + "address": "Cím", + "process": "Folyamat", + "search": "Keresési portok...", + "allProtocols": "Minden", + "noData": "Nincsenek figyelőport-adatok" + }, + "firewall": { + "title": "Tűzfal", + "inactive": "Inaktív", + "policy": "Politika", + "rules": "szabályok", + "noRules": "Nincsenek szabályok ebben a láncban", + "noData": "Nincsenek elérhető tűzfaladatok", + "action": "Akció", + "protocol": "Proto", + "port": "Kikötő", + "source": "Forrás", + "anywhere": "Bárhol", + "chains": "láncok" + }, + "loadAvg": "Átlagos betöltés", + "swap": "Csere", + "architecture": "Építészet", + "refresh": "Frissítés", + "retry": "Újrapróbálkozás", + "customize": "Elrendezés testreszabása", + "reset": "Visszaállítás", + "tabLive": "Élő", + "editModeInstructions": "Húzd a kártyákat az átrendezéshez, húzd az alsó szélüket az átméretezéshez, és használd a szélesség gombot a kártya szélességének módosításához. Alább adj hozzá vagy távolíts el kártyákat.", + "managers": { + "services": "Szolgáltatások", + "processInspector": "Folyamatfelügyelő", + "logViewer": "Naplómegjelenítő", + "cron": "Cron-feladatok", + "packages": "Csomagok", + "ssl": "SSL tanúsítványok", + "firewall": "Tűzfal", + "users": "Felhasználók és engedélyek", + "healthCheck": "Egészségügyi ellenőrzések", + "diskBreakdown": "Lemezbontás", + "systemdTimers": "Időzítők", + "topMemory": "Top by Memory", + "noData": "Nincsenek adatok", + "sudoHint": "Állítson be egy sudo jelszót ehhez a gazdagéphez a gazdagép-szerkesztőben a privilegizált műveletek engedélyezéséhez.", + "filter": "Szűrő...", + "start": "Indul", + "stop": "Stop", + "restart": "Újraindítás", + "actionDone": "{{name}} frissítve", + "actionFailed": "Sikertelen művelet", + "signalSent": "PID {{pid}}-ra küldött jel", + "killHint": "Kattintás: leállítás (SIGTERM). Jobb klikk: kényszerített leállítás (SIGKILL).", + "working": "Dolgozó...", + "update": "Frissítés", + "upgradeAll": "Összes frissítése", + "allUpToDate": "Minden naprakész", + "save": "Megtakarítás", + "command": "Parancs", + "enabled": "Engedélyezve", + "cronSaved": "Crontab frissítve", + "clients": "Ügyfelek", + "dryRun": "Száraz futás", + "renew": "Megújítás", + "noAcmeClient": "Nem található ACME kliens (certbot vagy acme.sh) ezen a gazdagépen.", + "addInputRule": "INPUT szabály hozzáadása", + "firewallWarning": "A változtatások csak futásidejűek, amíg meg nem őrizve nem lesznek. Ügyeljen arra, hogy ne zárja ki magát.", + "ruleApplied": "Szabály alkalmazva", + "invalidPort": "Adjon meg egy érvényes portszámot (1-65535)", + "newUsername": "Új felhasználónév", + "addUser": "Hozzáadás", + "deleteUser": "Felhasználó törlése", + "noHealthChecks": "Még nincsenek konfigurálva állapotfelmérések.", + "follow": "Követés", + "noLogData": "Nincs naplókimenet.", + "tree": "Fa", + "enableDisable": "Engedélyezés / letiltás rendszerindításkor", + "grantSudo": "Sudo engedélyezése", + "revokeSudo": "Sudo visszavonása", + "sslIssueCert": "Kibocsátási tanúsítvány", + "sslExpired": "Lejárt", + "sslInDays": "{{days}}d-ben", + "sslNeedDomain": "Adjon meg legalább egy domaint", + "sslIssued": "Kiállított tanúsítvány", + "sslDomainsPlaceholder": "példa.com, www.példa.com", + "sslHttpStandalone": "HTTP (önálló)", + "sslHttpWebroot": "HTTP (webroot)", + "sslDns": "DNS", + "sslDnsProvider": "DNS-szolgáltató (pl. cloudflare)", + "sslIssueHint": "A DNS-szolgáltató hitelesítő adatait már konfigurálni kell a gazdagépen.", + "sslRevoke": "Tanúsítvány visszavonása", + "sslRevoked": "Tanúsítvány visszavonva", + "sslRevokeConfirm": "Visszavonja és eltávolítja a(z) \"{{name}}\" tanúsítványt? Ez nem vonható vissza.", + "healthRun": "Fut", + "healthName": "Név", + "healthTarget": "Gazdagép / cím", + "healthAddCheck": "Csekk hozzáadása", + "healthSaved": "Egészségügyi ellenőrzések mentve", + "healthMissingFields": "Minden ellenőrzéshez kell egy név és egy cél.", + "logFile": "Fájl", + "logUnit": "Egység", + "logCustomPath": "Egyéni elérési út a /var/log könyvtárban (opcionális)", + "logGrep": "Szűrővonalak...", + "firewallPersist": "Szabályok megőrzése", + "firewallPersisted": "A tűzfalszabályok megmaradtak", + "wireguard": "Drótvédő", + "tailscale": "Farokskála", + "wgNotInstalled": "A WireGuard nincs telepítve erre a gépre", + "wgNoInterfaces": "Nincsenek konfigurált WireGuard interfészek", + "wgInterfaceUp": "Felnevel", + "wgInterfaceDown": "Lehoz", + "wgBringingUp": "{{name}} felhozása...", + "wgBringingDown": "{{name}} lehozása...", + "wgInterfaceUpDone": "{{name}} fent van", + "wgInterfaceDownDone": "{{name}} nem működik", + "wgListenPort": "Kikötő", + "wgPublicKey": "Nyilvános kulcs", + "wgEndpoint": "Végpont", + "wgAllowedIPs": "Engedélyezett IP-címek", + "wgLastHandshake": "Utolsó kézfogás", + "wgHandshakeNever": "Soha", + "wgTransfer": "Átruházás", + "tsNotInstalled": "A Tailscale nincs telepítve erre a gazdagépre", + "tsRunning": "Futás", + "tsStopped": "Leállítva", + "tsEnable": "Csatlakozás", + "tsDisable": "Leválasztás", + "tsEnabling": "Kapcsolódás a Tailscale-hez...", + "tsDisabling": "Lecsatlakozás a Tailscale-ről...", + "tsEnabled": "Farokméret csatlakoztatva", + "tsDisabled": "Farokváz leválasztva", + "tsIPs": "Tailscale IP-címek", + "tsPeers": "Társak", + "tsOnline": "Online", + "tsOffline": "Offline", + "tsExitNode": "Kilépési csomópont", + "tsExitNodeActive": "Kilépési csomópont aktív", + "tsHostname": "Gazdagépnév" + } + }, + "metricsHistory": { + "title": "Metrikák előzményei", + "historySuffix": "Történelem", + "cpuMemoryDisk": "CPU / Memória / Lemez", + "network": "Hálózat", + "download": "Vétel", + "upload": "Texas", + "noData": "Ehhez az időtartományhoz nem állnak rendelkezésre előzményadatok.", + "custom": "Szokás", + "to": "hogy", + "apply": "Jelentkezés", + "viewHistory": "Előzmények megtekintése" + }, + "proxmoxStats": { + "tabTitle": "Proxmox statisztikák", + "cpuUsage": "CPU-használat", + "memoryUsage": "Memóriahasználat", + "diskUsage": "Lemezhasználat", + "networkInterfaces": "Hálózati interfészek", + "uptime": "Üzemidő", + "systemInfo": "Rendszerinformációk", + "guestsSummary": "Vendégek", + "storagePools": "Tárolómedencék", + "clusterHealth": "Klaszter Egészségügy", + "cpuCores_one": "{{count}} Mag", + "cpuCores_other": "{{count}} Magok", + "used": "Használt", + "total": "Teljes", + "hostname": "Gazdagépnév", + "kernel": "Kernel", + "pveVersion": "PVE verzió", + "name": "Név", + "status": "Állapot", + "type": "Típus", + "cpu": "CPU", + "mem": "Mem", + "disk": "Korong", + "running": "Futás", + "stopped": "Leállítva", + "guestCounts": "{{running}}/{{total}} fut", + "inactive": "Inaktív", + "notClustered": "Önálló csomópont (nem része fürtnek)", + "quorate": "Kvórat", + "notQuorate": "Nem határozatképes", + "nodeOnline": "Online", + "nodeOffline": "Offline", + "noHostSelected": "Nincs kiválasztva gazdagép", + "pveshNotFound": "pvesh nem található - ez egy Proxmox csomópont?", + "nodeDetectionFailed": "Nem sikerült érvényes Proxmox csomópontnevet meghatározni.", + "connecting": "Kapcsolódás...", + "connectionFailed": "Nem sikerült csatlakozni a Proxmox csomóponthoz", + "refresh": "Frissítés", + "searchGuests": "Vendégek keresése...", + "filterAll": "Minden", + "filterVm": "Virtuális gép", + "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." + }, + "nav": { + "hostMetrics": "Gazdagép-metrikák" + }, + "hosts": { + "tabHostMetrics": "Gazdagép-metrikák", + "enableProxmoxStats": "Proxmox statisztikák engedélyezése", + "enableProxmoxStatsDesc": "Proxmox Statisztika fül megjelenítése ehhez a gazdagéphez, élő csomópont-, vendég-, tároló- és fürtstatisztikákkal, SSH-n keresztül gyűjtött adatokkal.", + "proxmoxStatsPollInterval": "Lekérdezési intervallum (másodperc)", + "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", + "metricsCollectionLabel": "Metrikagyűjtemény", + "enableMetricsLabel": "Metrikák engedélyezése", + "enableMetricsDesc": "CPU, RAM, lemez és egyéb mérőszámok gyűjtése erről a gazdagépről", + "useGlobalMetrics": "Globális intervallum használata", + "useGlobalMetricsDesc": "Felülbírálás a szerverszintű metrika intervallummal", + "metricsIntervalS": "Mérési intervallum (s)", + "metricsIntervalDesc2": "Metrika pillanatképek között eltelt másodpercek", + "excludedMountsLabel": "Kizárt tartók", + "monitoredMountsLabel": "Egyéni figyelt útvonalak", + "monitoredMountsDesc": "Adjon hozzá olyan elérési utakat, amelyek nincsenek különálló csatolásként közzétéve, beleértve a kötésként csatolt Home Assistant elérési utakat, például a /config-ot.", + "monitoredMountPathPlaceholder": "Útvonal (/config, /mnt/data)", + "monitoredMountLabelPlaceholder": "Címke (opcionális)", + "addMonitoredMount": "Útvonal hozzáadása", + "excludedMountsDesc": "Rejtsd el az adott csatolási pontokat vagy fájlrendszertípusokat (pl. nfs, cifs) a lemezhasználat és a riasztások elől ennél a gazdagépnél.", + "excludedMountsPlaceholder": "Csatlakoztatási útvonal (/mnt/nas) vagy fájlrendszer típusa (nfs, cifs)", + "excludedMountsEmpty": "Nincsenek kizárva csatolások. Minden észlelt fájlrendszer látható.", + "addExcludedMount": "Hozzáadás", + "visibleWidgets": "Látható widgetek", + "widgetsMovedToHostMetrics": "A kártyák mostantól közvetlenül a Gazdagép metrikái lapon adhatók hozzá, rendezhetők el és méretezhetők át. Nyissa meg a Gazdagép metrikái oldalt ehhez a gazdagéphez, és a Testreszabás gombbal válassza ki, hogy mely kártyák jelenjenek meg.", + "quickActionsLabel": "Gyors műveletek", + "quickActionsToolbar": "A gyors műveletek gombokként jelennek meg a Host Metrics eszköztáron, így egyetlen kattintással végrehajthatók a parancsok.", + "noQuickActions": "Még nincsenek gyors intézkedések.", + "buttonLabel": "Gomb felirata", + "selectSnippetPlaceholder": "Válasszon részletet...", + "addActionBtn": "Művelet hozzáadása" + }, + "onboarding": { + "feature_metrics": "Metrikák és riasztások", + "feature_metrics_desc": "Kövesse nyomon a CPU, a memória és a lemez teljesítményét az idő múlásával, és kapjon értesítést, ha meghibásodnak." + }, + "admin": { + "metricsHistoryRetention": "Metrikák előzményeinek megőrzése", + "metricsHistoryRetentionRange": "1-90 nap", + "days": "napok" + }, + "homepage": { + "noData": "Nincsenek elérhető adatok", + "showCurrentValue": "Aktuális érték megjelenítése", + "chartMetric": "Metrika", + "metricRange": "Hatótávolság" + } +} diff --git a/plugins/host-metrics/locales/translated/id_ID.json b/plugins/host-metrics/locales/translated/id_ID.json new file mode 100644 index 000000000..3dee0cf93 --- /dev/null +++ b/plugins/host-metrics/locales/translated/id_ID.json @@ -0,0 +1,313 @@ +{ + "hostMetrics": { + "cpu": "CPU", + "memory": "Ingatan", + "disk": "Disk", + "network": "Jaringan", + "uptime": "Waktu aktif", + "processes": "Proses", + "available": "Tersedia", + "free": "Bebas", + "connecting": "Menghubungkan...", + "connectionFailed": "Gagal terhubung ke server", + "naCpus": "CPU tidak tersedia", + "cpuCores_one": "{{count}} Inti", + "cpuCores_other": "{{count}} Inti", + "cpuUsage": "Penggunaan CPU", + "memoryUsage": "Penggunaan Memori", + "diskUsage": "Penggunaan Disk", + "selectFilesystem": "Pilih sistem file", + "temperature": "Suhu", + "highestTemperature": "Suhu tertinggi", + "primaryTemperatureSensor": "Sensor utama", + "gpu": { + "title": "GPU", + "noDevice": "GPU NVIDIA tidak terdeteksi. Instal driver NVIDIA (yang menyediakan nvidia-smi) untuk melihat metrik GPU.", + "driver": "Pengemudi {{version}}", + "utilization": "Pemanfaatan", + "memory": "VRAM", + "temperature": "Suhu", + "power": "Kekuatan", + "fan": "Penggemar", + "processes": "Proses GPU", + "noProcesses": "Tidak ada proses yang menggunakan GPU." + }, + "failedToFetchHostConfig": "Gagal mengambil konfigurasi host", + "serverOffline": "Server Offline", + "cannotFetchMetrics": "Tidak dapat mengambil metrik dari server offline.", + "totpFailed": "Verifikasi TOTP gagal", + "noneAuthNotSupported": "Host Metrics tidak mendukung tipe otentikasi 'none'.", + "noHostSelected": "Tidak ada pembawa acara yang dipilih.", + "load": "Memuat", + "systemInfo": "Informasi Sistem", + "hostname": "Nama host", + "operatingSystem": "Sistem Operasi", + "kernel": "Inti", + "seconds": "detik", + "networkInterfaces": "Antarmuka Jaringan", + "noInterfacesFound": "Tidak ditemukan antarmuka jaringan.", + "noProcessesFound": "Tidak ada proses yang ditemukan.", + "processesTotal": "total", + "processesRunning": "berlari", + "loginStats": "Statistik Login SSH", + "noRecentLoginData": "Tidak ada data login terbaru.", + "executingQuickAction": "Menjalankan {{name}}...", + "quickActionSuccess": "{{name}} berhasil diselesaikan", + "quickActionFailed": "{{name}} gagal", + "quickActionError": "Gagal mengeksekusi {{name}}", + "ports": { + "title": "Port Pendengaran", + "protocol": "Protokol", + "port": "Pelabuhan", + "address": "Alamat", + "process": "Proses", + "search": "Cari pelabuhan...", + "allProtocols": "Semua", + "noData": "Tidak ada data port yang mendengarkan." + }, + "firewall": { + "title": "Firewall", + "inactive": "Tidak aktif", + "policy": "Kebijakan", + "rules": "aturan", + "noRules": "Tidak ada aturan dalam rantai ini", + "noData": "Tidak ada data firewall yang tersedia.", + "action": "Tindakan", + "protocol": "Proto", + "port": "Pelabuhan", + "source": "Sumber", + "anywhere": "Di mana saja", + "chains": "rantai" + }, + "loadAvg": "Beban Rata-rata", + "swap": "Menukar", + "architecture": "Arsitektur", + "refresh": "Menyegarkan", + "retry": "Mencoba kembali", + "customize": "Sesuaikan tata letak", + "reset": "Mengatur ulang", + "tabLive": "Hidup", + "editModeInstructions": "Seret kartu untuk mengatur ulang, seret tepi bawah untuk mengubah ukurannya, dan gunakan tombol lebar untuk mengubah rentang kartu. Tambahkan atau hapus kartu di bawah ini.", + "managers": { + "services": "Layanan", + "processInspector": "Inspektur Proses", + "logViewer": "Penampil Log", + "cron": "Tugas Cron", + "packages": "Paket", + "ssl": "Sertifikat SSL", + "firewall": "Firewall", + "users": "Pengguna & Izin", + "healthCheck": "Pemeriksaan Kesehatan", + "diskBreakdown": "Kerusakan Disk", + "systemdTimers": "Pengatur waktu", + "topMemory": "Atas oleh Memory", + "noData": "Tidak ada data", + "sudoHint": "Tetapkan kata sandi sudo untuk host ini di editor host untuk mengaktifkan tindakan istimewa.", + "filter": "Menyaring...", + "start": "Awal", + "stop": "Berhenti", + "restart": "Mulai ulang", + "actionDone": "{{name}} diperbarui", + "actionFailed": "Tindakan gagal", + "signalSent": "Sinyal dikirim ke PID {{pid}}", + "killHint": "Klik: akhiri (SIGTERM). Klik kanan: paksa matikan (SIGKILL).", + "working": "Bekerja...", + "update": "Memperbarui", + "upgradeAll": "Tingkatkan semuanya", + "allUpToDate": "Semuanya sudah diperbarui", + "save": "Menyimpan", + "command": "Memerintah", + "enabled": "Diaktifkan", + "cronSaved": "Crontab diperbarui", + "clients": "Klien", + "dryRun": "Simulasi", + "renew": "Memperbarui", + "noAcmeClient": "Tidak ditemukan klien ACME (certbot atau acme.sh) pada host ini.", + "addInputRule": "Tambahkan aturan INPUT", + "firewallWarning": "Perubahan hanya berlaku saat runtime hingga disimpan. Berhati-hatilah agar tidak mengunci akses Anda sendiri.", + "ruleApplied": "Aturan diterapkan", + "invalidPort": "Masukkan port yang valid (1-65535)", + "newUsername": "Nama pengguna baru", + "addUser": "Menambahkan", + "deleteUser": "Hapus pengguna", + "noHealthChecks": "Belum ada pemeriksaan kesehatan yang dikonfigurasi.", + "follow": "Mengikuti", + "noLogData": "Tidak ada output log.", + "tree": "Pohon", + "enableDisable": "Aktifkan/nonaktifkan saat booting", + "grantSudo": "Berikan sudo", + "revokeSudo": "Cabut sudo", + "sslIssueCert": "Menerbitkan sertifikat", + "sslExpired": "Kedaluwarsa", + "sslInDays": "di {{days}}d", + "sslNeedDomain": "Masukkan setidaknya satu domain", + "sslIssued": "Sertifikat diterbitkan", + "sslDomainsPlaceholder": "example.com, www.example.com", + "sslHttpStandalone": "HTTP (mandiri)", + "sslHttpWebroot": "HTTP (webroot)", + "sslDns": "DNS", + "sslDnsProvider": "Penyedia DNS (misalnya Cloudflare)", + "sslIssueHint": "Kredensial penyedia DNS harus sudah dikonfigurasi pada host.", + "sslRevoke": "Cabut sertifikat", + "sslRevoked": "Sertifikat dicabut", + "sslRevokeConfirm": "Cabut dan hapus sertifikat \"{{name}}\"? Ini tidak dapat dibatalkan.", + "healthRun": "Berlari", + "healthName": "Nama", + "healthTarget": "Host / alamat", + "healthAddCheck": "Tambahkan pemeriksaan", + "healthSaved": "Pemeriksaan kesehatan tersimpan", + "healthMissingFields": "Setiap cek memerlukan nama dan target.", + "logFile": "Mengajukan", + "logUnit": "Satuan", + "logCustomPath": "Jalur khusus di bawah /var/log (opsional)", + "logGrep": "Garis filter...", + "firewallPersist": "Pertahankan aturan", + "firewallPersisted": "Aturan firewall tetap berlaku.", + "wireguard": "Pelindung Kawat", + "tailscale": "Skala ekor", + "wgNotInstalled": "WireGuard tidak terpasang pada host ini.", + "wgNoInterfaces": "Tidak ada antarmuka WireGuard yang dikonfigurasi.", + "wgInterfaceUp": "Membesarkan", + "wgInterfaceDown": "Menurunkan", + "wgBringingUp": "Membawa {{name}} ke atas...", + "wgBringingDown": "Menurunkan {{name}}...", + "wgInterfaceUpDone": "{{name}} sudah aktif", + "wgInterfaceDownDone": "{{name}} sedang down", + "wgListenPort": "Pelabuhan", + "wgPublicKey": "Kunci publik", + "wgEndpoint": "Titik akhir", + "wgAllowedIPs": "IP yang Diizinkan", + "wgLastHandshake": "Jabat tangan terakhir", + "wgHandshakeNever": "Tidak pernah", + "wgTransfer": "Transfer", + "tsNotInstalled": "Tailscale tidak terpasang pada host ini.", + "tsRunning": "Berlari", + "tsStopped": "Berhenti", + "tsEnable": "Menghubungkan", + "tsDisable": "Memutuskan", + "tsEnabling": "Menghubungkan ke Tailscale...", + "tsDisabling": "Memutus koneksi dari Tailscale...", + "tsEnabled": "Sisik ekor terhubung", + "tsDisabled": "Sisik ekor terputus", + "tsIPs": "IP Tailscale", + "tsPeers": "Rekan sejawat", + "tsOnline": "On line", + "tsOffline": "Offline", + "tsExitNode": "Node keluar", + "tsExitNodeActive": "Node keluar aktif", + "tsHostname": "Nama host" + } + }, + "metricsHistory": { + "title": "Riwayat Metrik", + "historySuffix": "Sejarah", + "cpuMemoryDisk": "CPU / Memori / Disk", + "network": "Jaringan", + "download": "RX", + "upload": "TX", + "noData": "Tidak ada data riwayat yang tersedia untuk rentang waktu ini.", + "custom": "Kebiasaan", + "to": "ke", + "apply": "Menerapkan", + "viewHistory": "Lihat Riwayat" + }, + "proxmoxStats": { + "tabTitle": "Statistik Proxmox", + "cpuUsage": "Penggunaan CPU", + "memoryUsage": "Penggunaan Memori", + "diskUsage": "Penggunaan Disk", + "networkInterfaces": "Antarmuka Jaringan", + "uptime": "Waktu aktif", + "systemInfo": "Informasi Sistem", + "guestsSummary": "Tamu", + "storagePools": "Kolam Penyimpanan", + "clusterHealth": "Kesehatan Klaster", + "cpuCores_one": "{{count}} Inti", + "cpuCores_other": "{{count}} Inti", + "used": "Digunakan", + "total": "Total", + "hostname": "Nama host", + "kernel": "Inti", + "pveVersion": "Versi PVE", + "name": "Nama", + "status": "Status", + "type": "Jenis", + "cpu": "CPU", + "mem": "Mem", + "disk": "Disk", + "running": "Berlari", + "stopped": "Berhenti", + "guestCounts": "{{running}}/{{total}} berjalan", + "inactive": "Tidak aktif", + "notClustered": "Node mandiri (bukan bagian dari klaster)", + "quorate": "Kutipan", + "notQuorate": "Tidak memenuhi kuorum", + "nodeOnline": "On line", + "nodeOffline": "Offline", + "noHostSelected": "Tidak ada pembawa acara yang dipilih.", + "pveshNotFound": "pvesh tidak ditemukan - apakah ini node Proxmox?", + "nodeDetectionFailed": "Tidak dapat menentukan nama node Proxmox yang valid.", + "connecting": "Menghubungkan...", + "connectionFailed": "Gagal terhubung ke node Proxmox", + "refresh": "Menyegarkan", + "searchGuests": "Mencari tamu...", + "filterAll": "Semua", + "filterVm": "Mesin virtual", + "filterLxc": "LXC", + "noGuests": "Tidak ditemukan VM atau kontainer LXC pada node ini.", + "noGuestsMatch": "Tidak ada tamu yang sesuai dengan filter saat ini." + }, + "nav": { + "hostMetrics": "Metrik Host" + }, + "hosts": { + "tabHostMetrics": "Metrik Host", + "enableProxmoxStats": "Aktifkan Statistik Proxmox", + "enableProxmoxStatsDesc": "Tampilkan tab Statistik Proxmox untuk host ini dengan statistik node, guest, penyimpanan, dan cluster secara langsung yang dikumpulkan melalui SSH.", + "proxmoxStatsPollInterval": "Interval polling (detik)", + "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", + "metricsCollectionLabel": "Pengumpulan Metrik", + "enableMetricsLabel": "Aktifkan Metrik", + "enableMetricsDesc": "Kumpulkan data CPU, RAM, disk, dan metrik lainnya dari host ini.", + "useGlobalMetrics": "Gunakan Interval Global", + "useGlobalMetricsDesc": "Ganti dengan interval metrik di seluruh server.", + "metricsIntervalS": "Interval Metrik (detik)", + "metricsIntervalDesc2": "Detik antara pengambilan snapshot metrik", + "excludedMountsLabel": "Dudukan yang Dikecualikan", + "monitoredMountsLabel": "Jalur pemantauan khusus", + "monitoredMountsDesc": "Tambahkan jalur yang tidak terekspos sebagai mount terpisah, termasuk jalur Home Assistant yang dipasang secara bind-mount seperti /config.", + "monitoredMountPathPlaceholder": "Jalur (/config, /mnt/data)", + "monitoredMountLabelPlaceholder": "Label (opsional)", + "addMonitoredMount": "Tambahkan jalur", + "excludedMountsDesc": "Sembunyikan titik pemasangan atau jenis sistem file tertentu (misalnya nfs, cifs) dari penggunaan disk dan peringatan untuk host ini.", + "excludedMountsPlaceholder": "Jalur pemasangan (/mnt/nas) atau tipe sistem file (nfs, cifs)", + "excludedMountsEmpty": "Tidak ada mount yang dikecualikan. Semua sistem file yang terdeteksi ditampilkan.", + "addExcludedMount": "Menambahkan", + "visibleWidgets": "Widget yang Terlihat", + "widgetsMovedToHostMetrics": "Kartu sekarang ditambahkan, diatur, dan diubah ukurannya langsung di tab Metrik Host. Buka Metrik Host untuk host ini dan gunakan Sesuaikan untuk memilih kartu mana yang akan ditampilkan.", + "quickActionsLabel": "Tindakan Cepat", + "quickActionsToolbar": "Tindakan cepat muncul sebagai tombol di bilah alat Metrik Host untuk eksekusi perintah sekali klik.", + "noQuickActions": "Belum ada tindakan cepat.", + "buttonLabel": "Label tombol", + "selectSnippetPlaceholder": "Pilih cuplikan...", + "addActionBtn": "Tambahkan Tindakan" + }, + "onboarding": { + "feature_metrics": "Metrik dan peringatan", + "feature_metrics_desc": "Pantau CPU, memori, dan disk dari waktu ke waktu, dan dapatkan peringatan saat terjadi kerusakan." + }, + "admin": { + "metricsHistoryRetention": "Retensi Riwayat Metrik", + "metricsHistoryRetentionRange": "1 hingga 90 hari", + "days": "hari" + }, + "homepage": { + "noData": "Tidak ada data yang tersedia", + "showCurrentValue": "Tampilkan Nilai Saat Ini", + "chartMetric": "Metrik", + "metricRange": "Jangkauan" + } +} diff --git a/plugins/host-metrics/locales/translated/it_IT.json b/plugins/host-metrics/locales/translated/it_IT.json new file mode 100644 index 000000000..76bed8ab2 --- /dev/null +++ b/plugins/host-metrics/locales/translated/it_IT.json @@ -0,0 +1,313 @@ +{ + "hostMetrics": { + "cpu": "CPU", + "memory": "Memoria", + "disk": "Disco", + "network": "Rete", + "uptime": "Tempo di attività", + "processes": "Processi", + "available": "Disponibile", + "free": "Libero", + "connecting": "Connessione in corso...", + "connectionFailed": "Connessione al server non riuscita", + "naCpus": "CPU N/D", + "cpuCores_one": "{{count}} Core", + "cpuCores_other": "{{count}} Core", + "cpuUsage": "Utilizzo CPU", + "memoryUsage": "Utilizzo memoria", + "diskUsage": "Utilizzo disco", + "selectFilesystem": "Seleziona il filesystem", + "temperature": "Temperatura", + "highestTemperature": "Temperatura massima", + "primaryTemperatureSensor": "Sensore primario", + "gpu": { + "title": "GPU", + "noDevice": "Nessuna GPU NVIDIA rilevata. Installa il driver NVIDIA (che fornisce nvidia-smi) per visualizzare le metriche della GPU.", + "driver": "Autista {{version}}", + "utilization": "Utilizzo", + "memory": "VRAM", + "temperature": "Temp", + "power": "Energia", + "fan": "Fan", + "processes": "Elaborazione GPU", + "noProcesses": "Nessun processo sta utilizzando la GPU" + }, + "failedToFetchHostConfig": "Recupero configurazione host non riuscito", + "serverOffline": "Server offline", + "cannotFetchMetrics": "Impossibile recuperare le metriche dal server offline", + "totpFailed": "Verifica TOTP non riuscita", + "noneAuthNotSupported": "Host Metrics non supporta il tipo di autenticazione 'none'.", + "noHostSelected": "Nessun host selezionato", + "load": "Carico", + "systemInfo": "Informazioni di sistema", + "hostname": "Nome host", + "operatingSystem": "Sistema operativo", + "kernel": "Kernel", + "seconds": "secondi", + "networkInterfaces": "Interfacce di rete", + "noInterfacesFound": "Nessuna interfaccia di rete trovata", + "noProcessesFound": "Nessun processo trovato", + "processesTotal": "totale", + "processesRunning": "in esecuzione", + "loginStats": "Statistiche di accesso SSH", + "noRecentLoginData": "Nessun dato di accesso recente", + "executingQuickAction": "Esecuzione di {{name}}...", + "quickActionSuccess": "{{name}} completato con successo", + "quickActionFailed": "{{name}} non riuscito", + "quickActionError": "Impossibile eseguire {{name}}", + "ports": { + "title": "Porte in ascolto", + "protocol": "Protocollo", + "port": "Porta", + "address": "Indirizzo", + "process": "Processo", + "search": "Cerca porte...", + "allProtocols": "Tutti", + "noData": "Nessun dato sulle porte in ascolto" + }, + "firewall": { + "title": "Firewall", + "inactive": "Inattivo", + "policy": "Politica", + "rules": "regole", + "noRules": "Nessuna regola in questa catena", + "noData": "Nessun dato sul firewall disponibile", + "action": "Azione", + "protocol": "Proto", + "port": "Porta", + "source": "Sorgente", + "anywhere": "Ovunque", + "chains": "Catene" + }, + "loadAvg": "Carico medio", + "swap": "Swap", + "architecture": "Architettura", + "refresh": "Aggiorna", + "retry": "Riprova", + "customize": "Personalizza layout", + "reset": "Reimposta", + "tabLive": "Live", + "editModeInstructions": "Trascina le schede per riordinarle, trascina il bordo inferiore per ridimensionarle e usa il pulsante della larghezza per modificare l'estensione della scheda. Aggiungi o rimuovi schede qui sotto.", + "managers": { + "services": "Servizi", + "processInspector": "Ispettore dei processi", + "logViewer": "Visualizzatore di log", + "cron": "Cron", + "packages": "Pacchetti", + "ssl": "Certificati SSL", + "firewall": "Firewall", + "users": "Utenti e permessi", + "healthCheck": "Controlli di integrità", + "diskBreakdown": "Analisi del disco", + "systemdTimers": "Timer", + "topMemory": "Principali per memoria", + "noData": "Nessun dato", + "sudoHint": "Imposta una password sudo per questo host nell'editor host per abilitare azioni privilegiate.", + "filter": "Filtra...", + "start": "Avvia", + "stop": "Ferma", + "restart": "Riavvia", + "actionDone": "{{name}} aggiornato", + "actionFailed": "Azione non riuscita", + "signalSent": "Segnale inviato al PID {{pid}}", + "killHint": "Clic: termina (SIGTERM). Clic destro: terminazione forzata (SIGKILL).", + "working": "In corso...", + "update": "Aggiorna", + "upgradeAll": "Aggiorna tutto", + "allUpToDate": "Tutto aggiornato", + "save": "Salva", + "command": "Comando", + "enabled": "Abilitato", + "cronSaved": "Crontab aggiornato", + "clients": "Client", + "dryRun": "Prova", + "renew": "Rinnova", + "noAcmeClient": "Nessun client ACME (certbot o acme.sh) trovato su questo host.", + "addInputRule": "Aggiungi regola INPUT", + "firewallWarning": "Le modifiche sono solo runtime finché non vengono rese permanenti. Fai attenzione a non rimanere bloccato fuori.", + "ruleApplied": "Regola applicata", + "invalidPort": "Inserisci una porta valida (1-65535)", + "newUsername": "Nuovo nome utente", + "addUser": "Aggiungi", + "deleteUser": "Elimina utente", + "noHealthChecks": "Nessun health check configurato al momento.", + "follow": "Segui", + "noLogData": "Nessun output di log.", + "tree": "Albero", + "enableDisable": "Abilita / disabilita all'avvio", + "grantSudo": "Concedi sudo", + "revokeSudo": "Revoca sudo", + "sslIssueCert": "Emetti certificato", + "sslExpired": "Scaduto", + "sslInDays": "in {{days}}d", + "sslNeedDomain": "Inserisci almeno un dominio", + "sslIssued": "Certificato emesso", + "sslDomainsPlaceholder": "example.com, www.example.com", + "sslHttpStandalone": "HTTP (standalone)", + "sslHttpWebroot": "HTTP (webroot)", + "sslDns": "DNS", + "sslDnsProvider": "Provider DNS (es. cloudflare)", + "sslIssueHint": "Le credenziali del provider DNS devono essere già configurate sull'host.", + "sslRevoke": "Revoca certificato", + "sslRevoked": "Certificato revocato", + "sslRevokeConfirm": "Revocare e rimuovere il certificato \"{{name}}\"? Questa azione non può essere annullata.", + "healthRun": "Esegui", + "healthName": "Nome", + "healthTarget": "Host / indirizzo", + "healthAddCheck": "Aggiungi controllo", + "healthSaved": "Controlli di integrità salvati", + "healthMissingFields": "Ogni controllo richiede un nome e un obiettivo", + "logFile": "File", + "logUnit": "Unità", + "logCustomPath": "Percorso personalizzato in /var/log (opzionale)", + "logGrep": "Filtra righe...", + "firewallPersist": "Rendi permanenti le regole", + "firewallPersisted": "Regole del firewall rese permanenti", + "wireguard": "WireGuard", + "tailscale": "Tailscale", + "wgNotInstalled": "WireGuard non è installato su questo host", + "wgNoInterfaces": "Nessuna interfaccia WireGuard configurata", + "wgInterfaceUp": "Attiva", + "wgInterfaceDown": "Disattiva", + "wgBringingUp": "Attivazione di {{name}} in corso...", + "wgBringingDown": "Disattivazione di {{name}} in corso...", + "wgInterfaceUpDone": "{{name}} è attivo", + "wgInterfaceDownDone": "{{name}} è disattivo", + "wgListenPort": "Porta", + "wgPublicKey": "Chiave pubblica", + "wgEndpoint": "Endpoint", + "wgAllowedIPs": "IP consentiti", + "wgLastHandshake": "Ultimo handshake", + "wgHandshakeNever": "Mai", + "wgTransfer": "Trasferimento", + "tsNotInstalled": "Tailscale non è installato su questo host", + "tsRunning": "In esecuzione", + "tsStopped": "Arrestato", + "tsEnable": "Connetti", + "tsDisable": "Disconnetti", + "tsEnabling": "Connessione a Tailscale in corso...", + "tsDisabling": "Disconnessione da Tailscale in corso...", + "tsEnabled": "Tailscale connesso", + "tsDisabled": "Tailscale disconnesso", + "tsIPs": "IP Tailscale", + "tsPeers": "Peer", + "tsOnline": "Online", + "tsOffline": "Offline", + "tsExitNode": "Nodo di uscita", + "tsExitNodeActive": "Nodo di uscita attivo", + "tsHostname": "Nome host" + } + }, + "metricsHistory": { + "title": "Cronologia metriche", + "historySuffix": "Cronologia", + "cpuMemoryDisk": "CPU / Memoria / Disco", + "network": "Rete", + "download": "RX", + "upload": "TX", + "noData": "Nessun dato storico disponibile per questo intervallo di tempo.", + "custom": "Personalizzato", + "to": "a", + "apply": "Applica", + "viewHistory": "Visualizza cronologia" + }, + "proxmoxStats": { + "tabTitle": "Statistiche di Proxmox", + "cpuUsage": "Utilizzo della CPU", + "memoryUsage": "Utilizzo della memoria", + "diskUsage": "Utilizzo del disco", + "networkInterfaces": "Interfacce di rete", + "uptime": "Tempo di attività", + "systemInfo": "Informazioni di sistema", + "guestsSummary": "Ospiti", + "storagePools": "Piscine di stoccaggio", + "clusterHealth": "Cluster Health", + "cpuCores_one": "{{count}} Nucleo", + "cpuCores_other": "{{count}} Nuclei", + "used": "Usato", + "total": "Totale", + "hostname": "Nome host", + "kernel": "Kernel", + "pveVersion": "Versione PVE", + "name": "Nome", + "status": "Stato", + "type": "Tipo", + "cpu": "processore", + "mem": "Mem", + "disk": "Disco", + "running": "Corsa", + "stopped": "Si è fermato", + "guestCounts": "{{running}}/{{total}} in esecuzione", + "inactive": "Inattivo", + "notClustered": "Nodo autonomo (non facente parte di un cluster)", + "quorate": "Citazione", + "notQuorate": "Non è stato raggiunto il quorum", + "nodeOnline": "Online", + "nodeOffline": "Offline", + "noHostSelected": "Nessun host selezionato", + "pveshNotFound": "pvesh non trovato: si tratta di un nodo Proxmox?", + "nodeDetectionFailed": "Impossibile determinare un nome nodo Proxmox valido", + "connecting": "Connessione in corso...", + "connectionFailed": "Impossibile connettersi al nodo Proxmox", + "refresh": "Rinfrescato", + "searchGuests": "Cerca ospiti...", + "filterAll": "Tutto", + "filterVm": "VM", + "filterLxc": "LXC", + "noGuests": "Nessuna macchina virtuale o container LXC trovato su questo nodo.", + "noGuestsMatch": "Nessun ospite corrisponde ai filtri attualmente attivi." + }, + "nav": { + "hostMetrics": "Metriche host" + }, + "hosts": { + "tabHostMetrics": "Metriche host", + "enableProxmoxStats": "Abilita le statistiche di Proxmox", + "enableProxmoxStatsDesc": "Mostra la scheda Statistiche di Proxmox per questo host con statistiche in tempo reale su nodi, guest, storage e cluster, raccolte tramite SSH.", + "proxmoxStatsPollInterval": "Intervallo di polling (secondi)", + "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", + "metricsCollectionLabel": "Raccolta metriche", + "enableMetricsLabel": "Abilita metriche", + "enableMetricsDesc": "Raccogli CPU, RAM, disco e altre metriche da questo host", + "useGlobalMetrics": "Usa intervallo globale", + "useGlobalMetricsDesc": "Sovrascrivi con l'intervallo delle metriche del server", + "metricsIntervalS": "Intervallo metriche (s)", + "metricsIntervalDesc2": "Secondi tra uno snapshot delle metriche e l'altro", + "excludedMountsLabel": "Montature escluse", + "monitoredMountsLabel": "Percorsi monitorati personalizzati", + "monitoredMountsDesc": "Aggiungi i percorsi che non sono esposti come mount separati, inclusi i percorsi di Home Assistant montati tramite bind, come /config.", + "monitoredMountPathPlaceholder": "Percorso (/config, /mnt/data)", + "monitoredMountLabelPlaceholder": "Etichetta (facoltativa)", + "addMonitoredMount": "Aggiungi percorso", + "excludedMountsDesc": "Nascondi specifici punti di montaggio o tipi di filesystem (ad esempio nfs, cifs) dall'utilizzo del disco e dagli avvisi per questo host.", + "excludedMountsPlaceholder": "Percorso di montaggio (/mnt/nas) o tipo di filesystem (nfs, cifs)", + "excludedMountsEmpty": "Nessun mount escluso. Vengono mostrati tutti i filesystem rilevati.", + "addExcludedMount": "Aggiungere", + "visibleWidgets": "Widget visibili", + "widgetsMovedToHostMetrics": "Le schede ora vengono aggiunte, disposte e ridimensionate direttamente nella scheda Metriche host. Apri Metriche host per questo host e usa Personalizza per scegliere quali schede mostrare.", + "quickActionsLabel": "Azioni Rapide", + "quickActionsToolbar": "Le azioni rapide appaiono come pulsanti nella barra delle metriche host per l'esecuzione di comandi con un clic.", + "noQuickActions": "Nessuna azione rapida ancora.", + "buttonLabel": "Etichetta pulsante", + "selectSnippetPlaceholder": "Seleziona snippet...", + "addActionBtn": "Aggiungi Azione" + }, + "onboarding": { + "feature_metrics": "Metriche e avvisi", + "feature_metrics_desc": "Monitora l'utilizzo di CPU, memoria e disco nel tempo e ricevi avvisi in caso di malfunzionamenti." + }, + "admin": { + "metricsHistoryRetention": "Conservazione cronologia metriche", + "metricsHistoryRetentionRange": "Da 1 a 90 giorni", + "days": "giorni" + }, + "homepage": { + "noData": "Nessun dato disponibile", + "showCurrentValue": "Mostra valore corrente", + "chartMetric": "Metrica", + "metricRange": "Intervallo" + } +} diff --git a/plugins/host-metrics/locales/translated/ja_JP.json b/plugins/host-metrics/locales/translated/ja_JP.json new file mode 100644 index 000000000..d5071d549 --- /dev/null +++ b/plugins/host-metrics/locales/translated/ja_JP.json @@ -0,0 +1,313 @@ +{ + "hostMetrics": { + "cpu": "CPU", + "memory": "メモリ", + "disk": "ディスク", + "network": "ネットワーク", + "uptime": "稼働時間", + "processes": "プロセス", + "available": "利用可能", + "free": "空き", + "connecting": "接続中...", + "connectionFailed": "サーバーへの接続に失敗しました", + "naCpus": "N/A CPU", + "cpuCores_one": "{{count}} コア", + "cpuCores_other": "{{count}} コア", + "cpuUsage": "CPU使用率", + "memoryUsage": "メモリ使用率", + "diskUsage": "ディスク使用率", + "selectFilesystem": "ファイルシステムを選択", + "temperature": "温度", + "highestTemperature": "最高温度", + "primaryTemperatureSensor": "プライマリーセンサー", + "gpu": { + "title": "GPU", + "noDevice": "NVIDIA GPUが検出されませんでした。GPUのメトリックを表示するには、NVIDIAドライバーをインストールしてください(ドライバーにはnvidia-smiが含まれています)。", + "driver": "ドライバー {{version}}", + "utilization": "利用", + "memory": "VRAM", + "temperature": "温度", + "power": "力", + "fan": "ファン", + "processes": "GPUプロセス", + "noProcesses": "GPUを使用しているプロセスはありません" + }, + "failedToFetchHostConfig": "ホスト設定の取得に失敗しました", + "serverOffline": "サーバーオフライン", + "cannotFetchMetrics": "オフラインのサーバーからメトリクスを取得できません。", + "totpFailed": "TOTP検証に失敗しました", + "noneAuthNotSupported": "ホストメトリクスは「none」認証タイプをサポートしていません。", + "noHostSelected": "ホストが選択されていません", + "load": "負荷", + "systemInfo": "システム情報", + "hostname": "ホスト名", + "operatingSystem": "オペレーティングシステム", + "kernel": "カーネル", + "seconds": "秒", + "networkInterfaces": "ネットワークインターフェース", + "noInterfacesFound": "ネットワークインターフェースが見つかりません", + "noProcessesFound": "プロセスが見つかりません", + "processesTotal": "合計", + "processesRunning": "実行中", + "loginStats": "SSHログイン統計", + "noRecentLoginData": "最近のログインデータがありません", + "executingQuickAction": "{{name}} を実行中...", + "quickActionSuccess": "{{name}} が正常に完了しました", + "quickActionFailed": "{{name}} が失敗しました", + "quickActionError": "{{name}} の実行に失敗しました", + "ports": { + "title": "リスニングポート", + "protocol": "プロトコル", + "port": "ポート", + "address": "アドレス", + "process": "プロセス", + "search": "ポートを検索...", + "allProtocols": "すべて", + "noData": "リスニングポートのデータがありません" + }, + "firewall": { + "title": "ファイアウォール", + "inactive": "非アクティブ", + "policy": "ポリシー", + "rules": "ルール", + "noRules": "このチェーンにルールはありません", + "noData": "利用可能なファイアウォールデータがありません", + "action": "アクション", + "protocol": "プロトコル", + "port": "ポート", + "source": "ソース", + "anywhere": "任意", + "chains": "チェーン" + }, + "loadAvg": "ロードアベレージ", + "swap": "スワップ", + "architecture": "アーキテクチャ", + "refresh": "更新", + "retry": "再試行", + "customize": "レイアウトをカスタマイズ", + "reset": "リセット", + "tabLive": "ライブ", + "editModeInstructions": "カードをドラッグして並べ替え、下辺をドラッグしてサイズを変更し、幅ボタンでカードのスパンを変更します。下のボタンでカードを追加または削除してください。", + "managers": { + "services": "サービス", + "processInspector": "プロセスインスペクタ", + "logViewer": "ログビューア", + "cron": "Cronジョブ", + "packages": "パッケージ", + "ssl": "SSL証明書", + "firewall": "ファイアウォール", + "users": "ユーザーと権限", + "healthCheck": "ヘルスチェック", + "diskBreakdown": "ディスク内訳", + "systemdTimers": "タイマー", + "topMemory": "メモリ使用量トップ", + "noData": "データなし", + "sudoHint": "特権アクションを有効にするには、ホストエディタでこのホストのsudoパスワードを設定してください。", + "filter": "フィルター...", + "start": "起動", + "stop": "停止", + "restart": "再起動", + "actionDone": "{{name}} が更新されました", + "actionFailed": "アクションに失敗しました", + "signalSent": "PID {{pid}} にシグナルが送信されました", + "killHint": "クリック: 終了 (SIGTERM)。右クリック: 強制終了 (SIGKILL)。", + "working": "処理中...", + "update": "更新", + "upgradeAll": "すべてアップグレード", + "allUpToDate": "すべて最新です", + "save": "保存", + "command": "コマンド", + "enabled": "有効", + "cronSaved": "crontab を更新しました", + "clients": "クライアント", + "dryRun": "ドライラン", + "renew": "更新", + "noAcmeClient": "このホストに ACME クライアント (certbot または acme.sh) が見つかりません。", + "addInputRule": "INPUT ルールを追加", + "firewallWarning": "変更は永続化されるまで実行中のみ有効です。自分をロックアウトしないよう注意してください。", + "ruleApplied": "ルールを適用しました", + "invalidPort": "有効なポート番号 (1-65535) を入力してください", + "newUsername": "新しいユーザー名", + "addUser": "追加", + "deleteUser": "ユーザーを削除", + "noHealthChecks": "ヘルスチェックはまだ設定されていません。", + "follow": "フォロー", + "noLogData": "ログ出力がありません。", + "tree": "ツリー", + "enableDisable": "起動時に有効/無効", + "grantSudo": "sudo 権限を付与", + "revokeSudo": "sudo 権限を剥奪", + "sslIssueCert": "証明書を発行", + "sslExpired": "期限切れ", + "sslInDays": "あと {{days}} 日", + "sslNeedDomain": "少なくとも1つのドメインを入力してください", + "sslIssued": "証明書が発行されました", + "sslDomainsPlaceholder": "example.com, www.example.com", + "sslHttpStandalone": "HTTP (スタンドアロン)", + "sslHttpWebroot": "HTTP (webroot)", + "sslDns": "DNS", + "sslDnsProvider": "DNSプロバイダ(例: cloudflare)", + "sslIssueHint": "DNSプロバイダの認証情報はホストに設定済みである必要があります。", + "sslRevoke": "証明書を失効", + "sslRevoked": "証明書が失効しました", + "sslRevokeConfirm": "証明書 \"{{name}}\"を失効して削除しますか?この操作は取り消せません。", + "healthRun": "実行", + "healthName": "名前", + "healthTarget": "ホスト / アドレス", + "healthAddCheck": "チェックを追加", + "healthSaved": "ヘルスチェックが保存されました", + "healthMissingFields": "各チェックには名前とターゲットが必要です", + "logFile": "ファイル", + "logUnit": "ユニット", + "logCustomPath": "/var/log 以下のカスタムパス (任意)", + "logGrep": "行をフィルタ...", + "firewallPersist": "ルールを永続化", + "firewallPersisted": "ファイアウォールルールが永続化されました", + "wireguard": "WireGuard", + "tailscale": "Tailscale", + "wgNotInstalled": "このホストにWireGuardがインストールされていません", + "wgNoInterfaces": "WireGuardインターフェースが設定されていません", + "wgInterfaceUp": "起動", + "wgInterfaceDown": "停止", + "wgBringingUp": "{{name}}を起動中...", + "wgBringingDown": "{{name}}を停止中...", + "wgInterfaceUpDone": "{{name}}が起動しました", + "wgInterfaceDownDone": "{{name}}が停止しました", + "wgListenPort": "ポート", + "wgPublicKey": "公開鍵", + "wgEndpoint": "エンドポイント", + "wgAllowedIPs": "許可されたIP", + "wgLastHandshake": "最終ハンドシェイク", + "wgHandshakeNever": "なし", + "wgTransfer": "転送量", + "tsNotInstalled": "このホストにTailscaleがインストールされていません", + "tsRunning": "実行中", + "tsStopped": "停止中", + "tsEnable": "接続", + "tsDisable": "切断", + "tsEnabling": "Tailscaleに接続中...", + "tsDisabling": "Tailscaleから切断中...", + "tsEnabled": "Tailscale接続済み", + "tsDisabled": "Tailscale切断済み", + "tsIPs": "Tailscale IP", + "tsPeers": "ピア", + "tsOnline": "オンライン", + "tsOffline": "オフライン", + "tsExitNode": "Exitノード", + "tsExitNodeActive": "Exitノード有効", + "tsHostname": "ホスト名" + } + }, + "metricsHistory": { + "title": "メトリクス履歴", + "historySuffix": "履歴", + "cpuMemoryDisk": "CPU / メモリ / ディスク", + "network": "ネットワーク", + "download": "受信", + "upload": "送信", + "noData": "この期間の履歴データはありません。", + "custom": "カスタム", + "to": "~", + "apply": "適用", + "viewHistory": "履歴を表示" + }, + "proxmoxStats": { + "tabTitle": "Proxmox統計情報", + "cpuUsage": "CPU使用率", + "memoryUsage": "メモリ使用量", + "diskUsage": "ディスク使用量", + "networkInterfaces": "ネットワークインターフェース", + "uptime": "稼働時間", + "systemInfo": "システム情報", + "guestsSummary": "ゲスト", + "storagePools": "ストレージプール", + "clusterHealth": "クラスターヘルス", + "cpuCores_one": "{{count}} コア", + "cpuCores_other": "{{count}} コア", + "used": "使用済み", + "total": "合計", + "hostname": "ホスト名", + "kernel": "カーネル", + "pveVersion": "PVEバージョン", + "name": "名前", + "status": "状態", + "type": "タイプ", + "cpu": "CPU", + "mem": "メモリ", + "disk": "ディスク", + "running": "ランニング", + "stopped": "停止しました", + "guestCounts": "{{running}}/{{total}} 実行中", + "inactive": "非アクティブ", + "notClustered": "スタンドアロンノード(クラスタの一部ではない)", + "quorate": "引用", + "notQuorate": "定足数に満たない", + "nodeOnline": "オンライン", + "nodeOffline": "オフライン", + "noHostSelected": "ホストが選択されていません", + "pveshNotFound": "pveshが見つかりません - これはProxmoxノードですか?", + "nodeDetectionFailed": "有効な Proxmox ノード名を特定できません", + "connecting": "接続中...", + "connectionFailed": "Proxmoxノードへの接続に失敗しました", + "refresh": "更新", + "searchGuests": "ゲストを検索...", + "filterAll": "全て", + "filterVm": "VM", + "filterLxc": "LXC", + "noGuests": "このノード上にはVMまたはLXCコンテナは見つかりませんでした。", + "noGuestsMatch": "現在の検索条件に一致するゲストはいません。" + }, + "nav": { + "hostMetrics": "ホストメトリクス" + }, + "hosts": { + "tabHostMetrics": "ホストメトリクス", + "enableProxmoxStats": "Proxmox Statsを有効にする", + "enableProxmoxStatsDesc": "SSH経由で収集された、このホストのリアルタイムのノード、ゲスト、ストレージ、およびクラスタの統計情報を表示するProxmox統計タブを表示します。", + "proxmoxStatsPollInterval": "ポーリング間隔(秒)", + "proxmoxStatsPollIntervalDesc": "最低15秒。Proxmoxノードの統計情報を更新する頻度。", + "proxmoxStatsNodeOverride": "ノード名の上書き", + "proxmoxStatsNodeOverrideDesc": "Proxmoxノード名の自動検出(デフォルトではホスト名で検出)を上書きします。", + "proxmoxStatsNodeOverridePlaceholder": "ホスト名から自動検出", + "metricsCollectionLabel": "メトリクス収集", + "enableMetricsLabel": "メトリクスを有効にする", + "enableMetricsDesc": "このホストから CPU、RAM、ディスクなどのメトリクスを収集します", + "useGlobalMetrics": "グローバル間隔を使用する", + "useGlobalMetricsDesc": "サーバー全体のメトリクス収集間隔で上書きします", + "metricsIntervalS": "メトリクス間隔 (秒)", + "metricsIntervalDesc2": "メトリクススナップショットの間隔 (秒)", + "excludedMountsLabel": "除外されるマウント", + "monitoredMountsLabel": "カスタム監視パス", + "monitoredMountsDesc": "/config などのバインドマウントされた Home Assistant パスを含め、個別のマウントとして公開されていないパスを追加します。", + "monitoredMountPathPlaceholder": "パス(/config、/mnt/data)", + "monitoredMountLabelPlaceholder": "ラベル(任意)", + "addMonitoredMount": "パスを追加", + "excludedMountsDesc": "このホストのディスク使用量とアラートから、特定のマウントポイントまたはファイルシステムの種類(例:NFS、CIFS)を非表示にします。", + "excludedMountsPlaceholder": "マウントパス(/mnt/nas)またはファイルシステムの種類(nfs、cifs)", + "excludedMountsEmpty": "マウントポイントは除外されません。検出されたすべてのファイルシステムが表示されます。", + "addExcludedMount": "追加", + "visibleWidgets": "表示するウィジェット", + "widgetsMovedToHostMetrics": "カードは、ホストメトリクスタブで直接追加、配置、サイズ変更できるようになりました。このホストのホストメトリクスを開き、カスタマイズを使用して表示するカードを選択してください。", + "quickActionsLabel": "クイックアクション", + "quickActionsToolbar": "クイックアクションはホストメトリクスツールバーにボタンとして表示され、ワンクリックでコマンドを実行できます。", + "noQuickActions": "クイックアクションはまだありません", + "buttonLabel": "ボタンラベル", + "selectSnippetPlaceholder": "スニペットを選択...", + "addActionBtn": "アクションを追加" + }, + "onboarding": { + "feature_metrics": "指標とアラート", + "feature_metrics_desc": "CPU、メモリ、ディスクの使用状況を長期的に監視し、異常が発生した際にアラートを受け取ることができます。" + }, + "admin": { + "metricsHistoryRetention": "メトリクス履歴保持期間", + "metricsHistoryRetentionRange": "1〜90日", + "days": "日" + }, + "homepage": { + "noData": "利用可能なデータはありません", + "showCurrentValue": "現在の値を表示", + "chartMetric": "メトリック", + "metricRange": "範囲" + } +} diff --git a/plugins/host-metrics/locales/translated/ko_KR.json b/plugins/host-metrics/locales/translated/ko_KR.json new file mode 100644 index 000000000..95fc5e82b --- /dev/null +++ b/plugins/host-metrics/locales/translated/ko_KR.json @@ -0,0 +1,313 @@ +{ + "hostMetrics": { + "cpu": "CPU", + "memory": "메모리", + "disk": "디스크", + "network": "네트워크", + "uptime": "업타임", + "processes": "프로세스", + "available": "사용 가능", + "free": "여유", + "connecting": "연결 중...", + "connectionFailed": "서버 연결 실패", + "naCpus": "N/A CPU", + "cpuCores_one": "{{count}} 코어", + "cpuCores_other": "{{count}} 코어", + "cpuUsage": "CPU 사용률", + "memoryUsage": "메모리 사용률", + "diskUsage": "디스크 사용률", + "selectFilesystem": "파일 시스템을 선택하세요", + "temperature": "온도", + "highestTemperature": "최고 온도", + "primaryTemperatureSensor": "1차 센서", + "gpu": { + "title": "GPU", + "noDevice": "NVIDIA GPU가 감지되지 않았습니다. NVIDIA 드라이버를 설치하세요(드라이버에는 nvidia-smi가 포함되어 있습니다). 그러면 GPU 메트릭을 확인할 수 있습니다.", + "driver": "드라이버 {{version}}", + "utilization": "이용", + "memory": "VRAM", + "temperature": "임시", + "power": "힘", + "fan": "팬", + "processes": "GPU 프로세스", + "noProcesses": "GPU를 사용하는 프로세스가 없습니다." + }, + "failedToFetchHostConfig": "호스트 구성 가져오기 실패", + "serverOffline": "서버 오프라인", + "cannotFetchMetrics": "오프라인 서버에서 메트릭 가져오기 불가", + "totpFailed": "TOTP 인증 실패", + "noneAuthNotSupported": "호스트 메트릭에서 'none' 인증 유형을 지원하지 않습니다.", + "noHostSelected": "호스트가 선택되지 않았습니다.", + "load": "부하", + "systemInfo": "시스템 정보", + "hostname": "호스트 이름", + "operatingSystem": "운영 체제", + "kernel": "커널", + "seconds": "초", + "networkInterfaces": "네트워크 인터페이스", + "noInterfacesFound": "네트워크 인터페이스를 찾을 수 없습니다.", + "noProcessesFound": "프로세스를 찾을 수 없습니다.", + "processesTotal": "전체", + "processesRunning": "실행 중", + "loginStats": "SSH 로그인 통계", + "noRecentLoginData": "최근 로그인 데이터가 없습니다.", + "executingQuickAction": "{{name}} 실행 중...", + "quickActionSuccess": "{{name}}이(가) 성공적으로 완료되었습니다.", + "quickActionFailed": "{{name}} 실패", + "quickActionError": "{{name}} 실행에 실패했습니다.", + "ports": { + "title": "수신 대기 포트", + "protocol": "프로토콜", + "port": "포트", + "address": "주소", + "process": "프로세스", + "search": "포트 검색...", + "allProtocols": "전체", + "noData": "수신 대기 포트 데이터가 없습니다." + }, + "firewall": { + "title": "방화벽", + "inactive": "비활성", + "policy": "정책", + "rules": "규칙", + "noRules": "이 체인에 규칙이 없습니다.", + "noData": "방화벽 데이터를 사용할 수 없습니다.", + "action": "동작", + "protocol": "프로토콜", + "port": "포트", + "source": "소스", + "anywhere": "모든 곳", + "chains": "체인" + }, + "loadAvg": "로드 평균", + "swap": "스왑", + "architecture": "아키텍처", + "refresh": "새로 고침", + "retry": "재시도", + "customize": "레이아웃 사용자 정의", + "reset": "초기화", + "tabLive": "실시간", + "editModeInstructions": "카드를 드래그하여 재배열하고, 아래쪽 가장자리를 드래그하여 크기를 조정하며, 너비 버튼을 사용해 카드의 가로 폭을 변경하세요. 아래에서 카드를 추가하거나 제거할 수 있습니다.", + "managers": { + "services": "서비스", + "processInspector": "프로세스 검사기", + "logViewer": "로그 뷰어", + "cron": "크론 작업", + "packages": "패키지", + "ssl": "SSL 인증서", + "firewall": "방화벽", + "users": "사용자 및 권한", + "healthCheck": "상태 검사", + "diskBreakdown": "디스크 분석", + "systemdTimers": "타이머", + "topMemory": "메모리 사용량 상위", + "noData": "데이터 없음", + "sudoHint": "호스트 편집기에서 이 호스트의 sudo 암호를 설정하여 권한이 필요한 작업을 활성화하세요.", + "filter": "필터...", + "start": "시작", + "stop": "중지", + "restart": "재시작", + "actionDone": "{{name}} 업데이트됨", + "actionFailed": "작업 실패", + "signalSent": "PID {{pid}}에 시그널 전송됨", + "killHint": "클릭: 종료 (SIGTERM). 마우스 오른쪽 클릭: 강제 종료 (SIGKILL).", + "working": "작업 중...", + "update": "업데이트", + "upgradeAll": "모두 업그레이드", + "allUpToDate": "모든 항목이 최신 상태입니다", + "save": "저장", + "command": "명령", + "enabled": "활성화됨", + "cronSaved": "Crontab이 업데이트되었습니다", + "clients": "클라이언트", + "dryRun": "테스트 실행", + "renew": "갱신", + "noAcmeClient": "이 호스트에 ACME 클라이언트(certbot 또는 acme.sh)가 없습니다.", + "addInputRule": "INPUT 규칙 추가", + "firewallWarning": "변경 사항은 저장하기 전까지 런타임에만 적용됩니다. 접근이 차단되지 않도록 주의하세요.", + "ruleApplied": "규칙이 적용되었습니다", + "invalidPort": "유효한 포트(1-65535)를 입력하세요", + "newUsername": "새 사용자 이름", + "addUser": "추가", + "deleteUser": "사용자 삭제", + "noHealthChecks": "아직 상태 점검이 구성되지 않았습니다.", + "follow": "따라가기", + "noLogData": "로그 출력이 없습니다.", + "tree": "트리", + "enableDisable": "부팅 시 활성화/비활성화", + "grantSudo": "sudo 권한 부여", + "revokeSudo": "sudo 권한 회수", + "sslIssueCert": "인증서 발급", + "sslExpired": "만료됨", + "sslInDays": "{{days}}일 후", + "sslNeedDomain": "최소 하나의 도메인을 입력하세요", + "sslIssued": "인증서가 발급되었습니다", + "sslDomainsPlaceholder": "example.com, www.example.com", + "sslHttpStandalone": "HTTP (독립형)", + "sslHttpWebroot": "HTTP (웹루트)", + "sslDns": "DNS", + "sslDnsProvider": "DNS 공급자 (예: cloudflare)", + "sslIssueHint": "DNS 공급자 자격 증명이 호스트에 이미 구성되어 있어야 합니다.", + "sslRevoke": "인증서 폐기", + "sslRevoked": "인증서가 폐기되었습니다", + "sslRevokeConfirm": "인증서 \"{{name}}\"을(를) 폐기하고 제거하시겠습니까? 이 작업은 취소할 수 없습니다.", + "healthRun": "실행", + "healthName": "이름", + "healthTarget": "호스트 / 주소", + "healthAddCheck": "검사 추가", + "healthSaved": "상태 검사가 저장되었습니다", + "healthMissingFields": "각 검사에는 이름과 대상이 필요합니다", + "logFile": "파일", + "logUnit": "유닛", + "logCustomPath": "/var/log 아래의 사용자 지정 경로 (선택 사항)", + "logGrep": "줄 필터...", + "firewallPersist": "규칙 영구 저장", + "firewallPersisted": "방화벽 규칙이 영구 저장되었습니다", + "wireguard": "WireGuard", + "tailscale": "Tailscale", + "wgNotInstalled": "이 호스트에 WireGuard가 설치되어 있지 않습니다", + "wgNoInterfaces": "구성된 WireGuard 인터페이스가 없습니다", + "wgInterfaceUp": "올리기", + "wgInterfaceDown": "내리기", + "wgBringingUp": "{{name}} 올리는 중...", + "wgBringingDown": "{{name}} 내리는 중...", + "wgInterfaceUpDone": "{{name}}이(가) 올라왔습니다", + "wgInterfaceDownDone": "{{name}}이(가) 내려갔습니다", + "wgListenPort": "포트", + "wgPublicKey": "공개 키", + "wgEndpoint": "엔드포인트", + "wgAllowedIPs": "허용된 IP", + "wgLastHandshake": "마지막 핸드셰이크", + "wgHandshakeNever": "없음", + "wgTransfer": "전송", + "tsNotInstalled": "이 호스트에 Tailscale이 설치되어 있지 않습니다", + "tsRunning": "실행 중", + "tsStopped": "중지됨", + "tsEnable": "연결", + "tsDisable": "연결 해제", + "tsEnabling": "Tailscale에 연결 중...", + "tsDisabling": "Tailscale 연결 해제 중...", + "tsEnabled": "Tailscale 연결됨", + "tsDisabled": "Tailscale 연결 해제됨", + "tsIPs": "Tailscale IP", + "tsPeers": "피어", + "tsOnline": "온라인", + "tsOffline": "오프라인", + "tsExitNode": "출구 노드", + "tsExitNodeActive": "출구 노드 활성", + "tsHostname": "호스트명" + } + }, + "metricsHistory": { + "title": "메트릭 기록", + "historySuffix": "기록", + "cpuMemoryDisk": "CPU / 메모리 / 디스크", + "network": "네트워크", + "download": "RX", + "upload": "TX", + "noData": "이 시간 범위에 대한 기록 데이터가 없습니다.", + "custom": "사용자 지정", + "to": "~", + "apply": "적용", + "viewHistory": "기록 보기" + }, + "proxmoxStats": { + "tabTitle": "프록스목스 통계", + "cpuUsage": "CPU 사용량", + "memoryUsage": "메모리 사용량", + "diskUsage": "디스크 사용량", + "networkInterfaces": "네트워크 인터페이스", + "uptime": "가동 시간", + "systemInfo": "시스템 정보", + "guestsSummary": "손님", + "storagePools": "저장 풀", + "clusterHealth": "클러스터 헬스", + "cpuCores_one": "{{count}} 코어", + "cpuCores_other": "{{count}} 코어", + "used": "사용된", + "total": "총", + "hostname": "호스트 이름", + "kernel": "핵심", + "pveVersion": "PVE 버전", + "name": "이름", + "status": "상태", + "type": "유형", + "cpu": "CPU", + "mem": "메모리", + "disk": "디스크", + "running": "달리기", + "stopped": "멈췄습니다", + "guestCounts": "{{running}}/{{total}} 실행 중", + "inactive": "비활성화됨", + "notClustered": "독립형 노드(클러스터의 일부가 아님)", + "quorate": "할당량", + "notQuorate": "정족수 미달", + "nodeOnline": "온라인", + "nodeOffline": "오프라인", + "noHostSelected": "호스트가 선택되지 않았습니다.", + "pveshNotFound": "pvesh를 찾을 수 없습니다. Proxmox 노드입니까?", + "nodeDetectionFailed": "유효한 Proxmox 노드 이름을 확인할 수 없습니다.", + "connecting": "연결 중...", + "connectionFailed": "Proxmox 노드에 연결하지 못했습니다.", + "refresh": "새로 고치다", + "searchGuests": "투숙객 검색...", + "filterAll": "모두", + "filterVm": "VM", + "filterLxc": "LXC", + "noGuests": "이 노드에서 VM 또는 LXC 컨테이너를 찾을 수 없습니다.", + "noGuestsMatch": "현재 필터 조건에 맞는 투숙객이 없습니다." + }, + "nav": { + "hostMetrics": "호스트 메트릭" + }, + "hosts": { + "tabHostMetrics": "호스트 메트릭", + "enableProxmoxStats": "Proxmox 통계 활성화", + "enableProxmoxStatsDesc": "SSH를 통해 수집된 실시간 노드, 게스트, 스토리지 및 클러스터 통계를 포함하는 이 호스트의 Proxmox 통계 탭을 표시합니다.", + "proxmoxStatsPollInterval": "폴링 간격(초)", + "proxmoxStatsPollIntervalDesc": "최소 15초. Proxmox 노드 통계를 새로 고치는 빈도.", + "proxmoxStatsNodeOverride": "노드 이름 재정의", + "proxmoxStatsNodeOverrideDesc": "Proxmox 노드 이름 자동 감지 기능을 재정의합니다(기본적으로 호스트 이름을 통해 감지됨).", + "proxmoxStatsNodeOverridePlaceholder": "호스트 이름에서 자동 감지됨", + "metricsCollectionLabel": "메트릭 수집", + "enableMetricsLabel": "메트릭 활성화", + "enableMetricsDesc": "이 호스트에서 CPU, RAM, 디스크 및 기타 메트릭을 수집합니다.", + "useGlobalMetrics": "전역 간격 사용", + "useGlobalMetricsDesc": "서버 전체 메트릭 간격으로 재정의합니다.", + "metricsIntervalS": "메트릭 간격(초)", + "metricsIntervalDesc2": "메트릭 스냅샷 간격(초)", + "excludedMountsLabel": "제외된 마운트", + "monitoredMountsLabel": "사용자 지정 모니터링 경로", + "monitoredMountsDesc": "/config와 같이 바인드 마운트된 Home Assistant 경로를 포함하여 별도의 마운트로 노출되지 않는 경로를 추가합니다.", + "monitoredMountPathPlaceholder": "경로(/config, /mnt/data)", + "monitoredMountLabelPlaceholder": "라벨 (선택 사항)", + "addMonitoredMount": "경로를 추가합니다", + "excludedMountsDesc": "이 호스트의 디스크 사용량 및 알림에서 특정 마운트 지점 또는 파일 시스템 유형(예: NFS, CIFS)을 숨깁니다.", + "excludedMountsPlaceholder": "마운트 경로(/mnt/nas) 또는 파일 시스템 유형(nfs, cifs)", + "excludedMountsEmpty": "마운트된 항목을 제외하지 않습니다. 감지된 모든 파일 시스템이 표시됩니다.", + "addExcludedMount": "추가하다", + "visibleWidgets": "표시 위젯", + "widgetsMovedToHostMetrics": "카드는 이제 호스트 메트릭 탭에서 직접 추가, 정렬 및 크기 조정됩니다. 이 호스트의 호스트 메트릭을 열고 사용자 정의를 사용하여 표시할 카드를 선택하세요.", + "quickActionsLabel": "빠른 작업", + "quickActionsToolbar": "빠른 작업은 한 번의 클릭으로 명령을 실행할 수 있도록 호스트 메트릭 도구 모음에 버튼으로 표시됩니다.", + "noQuickActions": "아직 빠른 작업이 없습니다.", + "buttonLabel": "버튼 레이블", + "selectSnippetPlaceholder": "스니펫 선택...", + "addActionBtn": "작업 추가" + }, + "onboarding": { + "feature_metrics": "지표 및 알림", + "feature_metrics_desc": "CPU, 메모리 및 디스크 사용량을 시간 경과에 따라 추적하고, 문제가 발생하면 알림을 받으세요." + }, + "admin": { + "metricsHistoryRetention": "메트릭 이력 보존 기간", + "metricsHistoryRetentionRange": "1~90일", + "days": "일" + }, + "homepage": { + "noData": "데이터 없음", + "showCurrentValue": "현재 값 표시", + "chartMetric": "메트릭", + "metricRange": "범위" + } +} diff --git a/plugins/host-metrics/locales/translated/nl_NL.json b/plugins/host-metrics/locales/translated/nl_NL.json new file mode 100644 index 000000000..b670796de --- /dev/null +++ b/plugins/host-metrics/locales/translated/nl_NL.json @@ -0,0 +1,313 @@ +{ + "hostMetrics": { + "cpu": "CPU", + "memory": "Geheugen", + "disk": "Schijf", + "network": "Netwerk", + "uptime": "Beschikbaarheid", + "processes": "Processen", + "available": "Beschikbaar", + "free": "Vrij", + "connecting": "Verbinden...", + "connectionFailed": "Verbinding met de server mislukt.", + "naCpus": "Niet van toepassing CPU('s)", + "cpuCores_one": "{{count}} Kern", + "cpuCores_other": "{{count}} Kernen", + "cpuUsage": "CPU-gebruik", + "memoryUsage": "Geheugengebruik", + "diskUsage": "Schijfgebruik", + "selectFilesystem": "Selecteer bestandssysteem", + "temperature": "Temperatuur", + "highestTemperature": "Hoogste temperatuur", + "primaryTemperatureSensor": "Primaire sensor", + "gpu": { + "title": "GPU", + "noDevice": "Geen NVIDIA GPU gedetecteerd. Installeer het NVIDIA-stuurprogramma (dit levert nvidia-smi) om GPU-statistieken te bekijken.", + "driver": "Bestuurder {{version}}", + "utilization": "Gebruik", + "memory": "VRAM", + "temperature": "Temp", + "power": "Stroom", + "fan": "Fan", + "processes": "GPU-processen", + "noProcesses": "Er zijn geen processen die de GPU gebruiken." + }, + "failedToFetchHostConfig": "Het ophalen van de hostconfiguratie is mislukt.", + "serverOffline": "Server offline", + "cannotFetchMetrics": "Het is niet mogelijk om meetgegevens op te halen van een offline server.", + "totpFailed": "TOTP-verificatie mislukt", + "noneAuthNotSupported": "Host Metrics ondersteunt geen authenticatietype 'none'.", + "noHostSelected": "Geen host geselecteerd", + "load": "Laden", + "systemInfo": "Systeeminformatie", + "hostname": "Hostnaam", + "operatingSystem": "Besturingssysteem", + "kernel": "Kernel", + "seconds": "seconden", + "networkInterfaces": "Netwerkinterfaces", + "noInterfacesFound": "Geen netwerkinterfaces gevonden", + "noProcessesFound": "Geen processen gevonden", + "processesTotal": "totaal", + "processesRunning": "rennen", + "loginStats": "SSH-aanmeldingsstatistieken", + "noRecentLoginData": "Geen recente inloggegevens", + "executingQuickAction": "Het uitvoeren van {{name}}...", + "quickActionSuccess": "{{name}} succesvol voltooid", + "quickActionFailed": "{{name}} mislukt", + "quickActionError": "Het uitvoeren van {{name}} is mislukt.", + "ports": { + "title": "Luisterpoorten", + "protocol": "Protocol", + "port": "Haven", + "address": "Adres", + "process": "Proces", + "search": "Poorten doorzoeken...", + "allProtocols": "Alle", + "noData": "Geen gegevens over luisterpoorten" + }, + "firewall": { + "title": "Firewall", + "inactive": "Inactief", + "policy": "Beleid", + "rules": "regels", + "noRules": "Er zijn geen regels in deze keten.", + "noData": "Geen firewallgegevens beschikbaar", + "action": "Actie", + "protocol": "Proto", + "port": "Haven", + "source": "Bron", + "anywhere": "Overal", + "chains": "kettingen" + }, + "loadAvg": "Gemiddelde belasting", + "swap": "Ruil", + "architecture": "Architectuur", + "refresh": "Vernieuwen", + "retry": "Opnieuw proberen", + "customize": "Lay-out aanpassen", + "reset": "Reset", + "tabLive": "Live", + "editModeInstructions": "Sleep kaarten om ze te herschikken, sleep de onderrand om het formaat aan te passen en gebruik de breedteknop om de afmetingen van een kaart te wijzigen. Voeg hieronder kaarten toe of verwijder ze.", + "managers": { + "services": "Diensten", + "processInspector": "Procesinspecteur", + "logViewer": "Logboekviewer", + "cron": "Cron Jobs", + "packages": "Pakketten", + "ssl": "SSL-certificaten", + "firewall": "Firewall", + "users": "Gebruikers en machtigingen", + "healthCheck": "Gezondheidscontroles", + "diskBreakdown": "Schijfdefect", + "systemdTimers": "Timers", + "topMemory": "Top op geheugen", + "noData": "Geen gegevens", + "sudoHint": "Stel een sudo-wachtwoord in voor deze host in de hosteditor om acties met verhoogde bevoegdheden mogelijk te maken.", + "filter": "Filter...", + "start": "Begin", + "stop": "Stop", + "restart": "Opnieuw opstarten", + "actionDone": "{{name}} bijgewerkt", + "actionFailed": "Actie mislukt", + "signalSent": "Signaal verzonden naar PID {{pid}}", + "killHint": "Klikken: beëindigen (SIGTERM). Rechtsklikken: geforceerd afsluiten (SIGKILL).", + "working": "Bezig met verwerken...", + "update": "Update", + "upgradeAll": "Upgrade alles", + "allUpToDate": "Alles is actueel.", + "save": "Redden", + "command": "Commando", + "enabled": "Ingeschakeld", + "cronSaved": "Crontab bijgewerkt", + "clients": "Klanten", + "dryRun": "Proefloop", + "renew": "Vernieuwen", + "noAcmeClient": "Er is geen ACME-client (certbot of acme.sh) gevonden op deze host.", + "addInputRule": "Voeg een INPUT-regel toe", + "firewallWarning": "Wijzigingen zijn alleen tijdens de uitvoering van het programma geldig totdat ze zijn opgeslagen. Pas op dat u uzelf niet buitensluit.", + "ruleApplied": "Toegepaste regel", + "invalidPort": "Voer een geldig poortnummer in (1-65535)", + "newUsername": "Nieuwe gebruikersnaam", + "addUser": "Toevoegen", + "deleteUser": "Gebruiker verwijderen", + "noHealthChecks": "Er zijn nog geen gezondheidscontroles geconfigureerd.", + "follow": "Volgen", + "noLogData": "Geen loguitvoer.", + "tree": "Boom", + "enableDisable": "In-/uitschakelen bij het opstarten", + "grantSudo": "Verleen sudo", + "revokeSudo": "Sudo intrekken", + "sslIssueCert": "Certificaat uitreiken", + "sslExpired": "Verlopen", + "sslInDays": "in {{days}}d", + "sslNeedDomain": "Voer ten minste één domein in", + "sslIssued": "Certificaat afgegeven", + "sslDomainsPlaceholder": "example.com, www.example.com", + "sslHttpStandalone": "HTTP (zelfstandig)", + "sslHttpWebroot": "HTTP (webroot)", + "sslDns": "DNS", + "sslDnsProvider": "DNS-provider (bijv. Cloudflare)", + "sslIssueHint": "De inloggegevens van de DNS-provider moeten al op de host geconfigureerd zijn.", + "sslRevoke": "Certificaat intrekken", + "sslRevoked": "Certificaat ingetrokken", + "sslRevokeConfirm": "Het certificaat \"{{name}}\" intrekken en verwijderen? Dit kan niet ongedaan gemaakt worden.", + "healthRun": "Loop", + "healthName": "Naam", + "healthTarget": "Host / adres", + "healthAddCheck": "Voeg een controle toe", + "healthSaved": "Gezondheidscontroles opgeslagen", + "healthMissingFields": "Elke controle heeft een naam en een doel nodig.", + "logFile": "Bestand", + "logUnit": "Eenheid", + "logCustomPath": "Aangepast pad onder /var/log (optioneel)", + "logGrep": "Filterlijnen...", + "firewallPersist": "Persist-regels", + "firewallPersisted": "De firewallregels bleven van kracht.", + "wireguard": "WireGuard", + "tailscale": "Staartschaal", + "wgNotInstalled": "WireGuard is niet geïnstalleerd op deze host.", + "wgNoInterfaces": "Er zijn geen WireGuard-interfaces geconfigureerd.", + "wgInterfaceUp": "Breng ter sprake", + "wgInterfaceDown": "Neerhalen", + "wgBringingUp": "{{name}} wordt geladen...", + "wgBringingDown": "{{name}} naar beneden halen...", + "wgInterfaceUpDone": "{{name}} is up", + "wgInterfaceDownDone": "{{name}} is omlaag", + "wgListenPort": "Haven", + "wgPublicKey": "Openbare sleutel", + "wgEndpoint": "Eindpunt", + "wgAllowedIPs": "Toegestane IP-adressen", + "wgLastHandshake": "Laatste handdruk", + "wgHandshakeNever": "Nooit", + "wgTransfer": "Overdracht", + "tsNotInstalled": "Tailscale is niet geïnstalleerd op deze host.", + "tsRunning": "Rennen", + "tsStopped": "Gestopt", + "tsEnable": "Verbinden", + "tsDisable": "Verbinding verbreken", + "tsEnabling": "Verbinding maken met Tailscale...", + "tsDisabling": "Verbinding met Tailscale verbreken...", + "tsEnabled": "Aangesloten staartschaal", + "tsDisabled": "Staartschaal losgekoppeld", + "tsIPs": "Tailscale IP-adressen", + "tsPeers": "Leeftijdsgenoten", + "tsOnline": "Online", + "tsOffline": "Offline", + "tsExitNode": "Uitgangsknooppunt", + "tsExitNodeActive": "Uitgangsknooppunt actief", + "tsHostname": "Hostnaam" + } + }, + "metricsHistory": { + "title": "Statistiekengeschiedenis", + "historySuffix": "Geschiedenis", + "cpuMemoryDisk": "CPU / Geheugen / Schijf", + "network": "Netwerk", + "download": "RX", + "upload": "TX", + "noData": "Er zijn geen historische gegevens beschikbaar voor deze periode.", + "custom": "Aangepast", + "to": "naar", + "apply": "Toepassen", + "viewHistory": "Geschiedenis bekijken" + }, + "proxmoxStats": { + "tabTitle": "Proxmox-statistieken", + "cpuUsage": "CPU-gebruik", + "memoryUsage": "Geheugengebruik", + "diskUsage": "Schijfgebruik", + "networkInterfaces": "Netwerkinterfaces", + "uptime": "Beschikbaarheid", + "systemInfo": "Systeeminformatie", + "guestsSummary": "Gasten", + "storagePools": "Opslagbassins", + "clusterHealth": "Clustergezondheid", + "cpuCores_one": "{{count}} Kern", + "cpuCores_other": "{{count}} Kernen", + "used": "Gebruikt", + "total": "Totaal", + "hostname": "Hostnaam", + "kernel": "Kernel", + "pveVersion": "PVE-versie", + "name": "Naam", + "status": "Status", + "type": "Type", + "cpu": "CPU", + "mem": "Mem", + "disk": "Schijf", + "running": "Rennen", + "stopped": "Gestopt", + "guestCounts": "{{running}}/{{total}} rennend", + "inactive": "Inactief", + "notClustered": "Zelfstandig knooppunt (geen onderdeel van een cluster)", + "quorate": "Quoraat", + "notQuorate": "Niet quorum", + "nodeOnline": "Online", + "nodeOffline": "Offline", + "noHostSelected": "Geen host geselecteerd", + "pveshNotFound": "pvesh niet gevonden - is dit een Proxmox-node?", + "nodeDetectionFailed": "Kan geen geldige Proxmox-knooppuntnaam bepalen", + "connecting": "Verbinden...", + "connectionFailed": "Verbinding met Proxmox-node mislukt.", + "refresh": "Vernieuwen", + "searchGuests": "Gasten zoeken...", + "filterAll": "Alle", + "filterVm": "VM", + "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." + }, + "nav": { + "hostMetrics": "Hoststatistieken" + }, + "hosts": { + "tabHostMetrics": "Hoststatistieken", + "enableProxmoxStats": "Proxmox-statistieken inschakelen", + "enableProxmoxStatsDesc": "Toon een tabblad Proxmox-statistieken voor deze host met live statistieken van knooppunten, gastsystemen, opslag en het cluster, verzameld via SSH.", + "proxmoxStatsPollInterval": "Pollinterval (seconden)", + "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", + "metricsCollectionLabel": "Gegevensverzameling", + "enableMetricsLabel": "Statistieken inschakelen", + "enableMetricsDesc": "Verzamel gegevens over CPU, RAM, schijfgebruik en andere parameters van deze host.", + "useGlobalMetrics": "Gebruik globaal interval", + "useGlobalMetricsDesc": "Overschrijf dit met het serverbrede metrische interval.", + "metricsIntervalS": "Metriekinterval (s)", + "metricsIntervalDesc2": "Seconden tussen momentopnamen van de meetwaarden", + "excludedMountsLabel": "Uitgesloten montagesystemen", + "monitoredMountsLabel": "Aangepaste bewaakte paden", + "monitoredMountsDesc": "Voeg paden toe die niet als aparte mounts worden weergegeven, inclusief bind-mounted Home Assistant-paden zoals /config.", + "monitoredMountPathPlaceholder": "Pad (/config, /mnt/data)", + "monitoredMountLabelPlaceholder": "Label (optioneel)", + "addMonitoredMount": "Pad toevoegen", + "excludedMountsDesc": "Verberg specifieke koppelpunten of bestandssysteemtypen (bijv. nfs, cifs) voor schijfgebruik en waarschuwingen voor deze host.", + "excludedMountsPlaceholder": "Mountpad (/mnt/nas) of bestandssysteemtype (nfs, cifs)", + "excludedMountsEmpty": "Geen mounts uitgesloten. Alle gedetecteerde bestandssystemen worden weergegeven.", + "addExcludedMount": "Toevoegen", + "visibleWidgets": "Zichtbare widgets", + "widgetsMovedToHostMetrics": "Kaarten kunnen nu rechtstreeks in het tabblad Hoststatistieken worden toegevoegd, gerangschikt en van formaat worden veranderd. Open Hoststatistieken voor deze host en gebruik Aanpassen om te kiezen welke kaarten worden weergegeven.", + "quickActionsLabel": "Snelle acties", + "quickActionsToolbar": "Snelle acties verschijnen als knoppen in de Host Metrics-werkbalk, zodat u opdrachten met één klik kunt uitvoeren.", + "noQuickActions": "Nog geen snelle acties ondernomen.", + "buttonLabel": "Knoplabel", + "selectSnippetPlaceholder": "Selecteer fragment...", + "addActionBtn": "Actie toevoegen" + }, + "onboarding": { + "feature_metrics": "Statistieken en waarschuwingen", + "feature_metrics_desc": "Volg de CPU, het geheugen en de schijf gedurende een bepaalde tijd en ontvang een melding wanneer ze defect raken." + }, + "admin": { + "metricsHistoryRetention": "Historische statistieken bewaren", + "metricsHistoryRetentionRange": "1 tot 90 dagen", + "days": "dagen" + }, + "homepage": { + "noData": "Geen gegevens beschikbaar", + "showCurrentValue": "Toon huidige waarde", + "chartMetric": "Metrisch", + "metricRange": "Bereik" + } +} diff --git a/plugins/host-metrics/locales/translated/no_NO.json b/plugins/host-metrics/locales/translated/no_NO.json new file mode 100644 index 000000000..2f864ae82 --- /dev/null +++ b/plugins/host-metrics/locales/translated/no_NO.json @@ -0,0 +1,313 @@ +{ + "hostMetrics": { + "cpu": "CPU", + "memory": "Hukommelse", + "disk": "Disk", + "network": "Nettverk", + "uptime": "Oppetid", + "processes": "Prosesser", + "available": "Tilgjengelig", + "free": "Gratis", + "connecting": "Kobler til...", + "connectionFailed": "Kunne ikke koble til serveren", + "naCpus": "Ikke tilgjengelig CPU(er)", + "cpuCores_one": "{{count}} Kjerne", + "cpuCores_other": "{{count}} Kjerner", + "cpuUsage": "CPU-bruk", + "memoryUsage": "Minnebruk", + "diskUsage": "Diskbruk", + "selectFilesystem": "Velg filsystem", + "temperature": "Temperatur", + "highestTemperature": "Høyeste temperatur", + "primaryTemperatureSensor": "Primærsensor", + "gpu": { + "title": "GPU", + "noDevice": "Ingen NVIDIA GPU funnet. Installer NVIDIA-driveren (den inneholder nvidia-smi) for å se GPU-målinger.", + "driver": "Sjåfør {{version}}", + "utilization": "Utnyttelse", + "memory": "VRAM", + "temperature": "Temp.", + "power": "Makt", + "fan": "Fan", + "processes": "GPU-prosesser", + "noProcesses": "Ingen prosesser bruker GPU-en" + }, + "failedToFetchHostConfig": "Kunne ikke hente vertskonfigurasjonen", + "serverOffline": "Server frakoblet", + "cannotFetchMetrics": "Kan ikke hente målinger fra frakoblet server", + "totpFailed": "TOTP-verifisering mislyktes", + "noneAuthNotSupported": "Host Metrics støtter ikke autentiseringstypen «ingen».", + "noHostSelected": "Ingen vert valgt", + "load": "Laste", + "systemInfo": "Systeminformasjon", + "hostname": "Vertsnavn", + "operatingSystem": "Operativsystem", + "kernel": "Kjerne", + "seconds": "sekunder", + "networkInterfaces": "Nettverksgrensesnitt", + "noInterfacesFound": "Ingen nettverksgrensesnitt funnet", + "noProcessesFound": "Ingen prosesser funnet", + "processesTotal": "total", + "processesRunning": "løping", + "loginStats": "SSH-påloggingsstatistikk", + "noRecentLoginData": "Ingen nylige påloggingsdata", + "executingQuickAction": "Utfører {{name}}...", + "quickActionSuccess": "{{name}} fullført", + "quickActionFailed": "{{name}} mislyktes", + "quickActionError": "Kunne ikke utføre {{name}}", + "ports": { + "title": "Lytteporter", + "protocol": "Protokoll", + "port": "Havn", + "address": "Adresse", + "process": "Behandle", + "search": "Søk etter porter...", + "allProtocols": "Alle", + "noData": "Ingen data om lytteporter" + }, + "firewall": { + "title": "Brannmur", + "inactive": "Inaktiv", + "policy": "Politikk", + "rules": "regler", + "noRules": "Ingen regler i denne kjeden", + "noData": "Ingen brannmurdata tilgjengelig", + "action": "Handling", + "protocol": "Proto", + "port": "Havn", + "source": "Kilde", + "anywhere": "Hvor som helst", + "chains": "kjeder" + }, + "loadAvg": "Last inn gjennomsnitt", + "swap": "Bytte", + "architecture": "Arkitektur", + "refresh": "Forfriske", + "retry": "Prøv på nytt", + "customize": "Tilpass oppsettet", + "reset": "Tilbakestill", + "tabLive": "Bo", + "editModeInstructions": "Dra kort for å omorganisere, dra i den nederste kanten for å endre størrelsen, og bruk breddeknappen for å endre kortets rekkevidde. Legg til eller fjern kort nedenfor.", + "managers": { + "services": "Tjenester", + "processInspector": "Prosessinspektør", + "logViewer": "Loggviser", + "cron": "Cron-jobber", + "packages": "Pakker", + "ssl": "SSL-sertifikater", + "firewall": "Brannmur", + "users": "Brukere og tillatelser", + "healthCheck": "Helsesjekker", + "diskBreakdown": "Disknedbrytning", + "systemdTimers": "Tidtakere", + "topMemory": "Topp etter minne", + "noData": "Ingen data", + "sudoHint": "Angi et sudo-passord for denne verten i vertredigeringsprogrammet for å aktivere privilegerte handlinger.", + "filter": "Filter...", + "start": "Start", + "stop": "Stoppe", + "restart": "Start på nytt", + "actionDone": "{{name}} oppdatert", + "actionFailed": "Handlingen mislyktes", + "signalSent": "Signal sendt til PID {{pid}}", + "killHint": "Klikk: avslutt (SIGTERM). Høyreklikk: tvungen avslutning (SIGKILL).", + "working": "Arbeider...", + "update": "Oppdatering", + "upgradeAll": "Oppgrader alle", + "allUpToDate": "Alt er oppdatert", + "save": "Spare", + "command": "Kommando", + "enabled": "Aktivert", + "cronSaved": "Crontab oppdatert", + "clients": "Klienter", + "dryRun": "Tørrløp", + "renew": "Fornye", + "noAcmeClient": "Ingen ACME-klient (certbot eller acme.sh) funnet på denne verten.", + "addInputRule": "Legg til INPUT-regel", + "firewallWarning": "Endringene gjelder kun for kjøring inntil de lagres. Vær forsiktig så du ikke låser deg ute.", + "ruleApplied": "Regel brukt", + "invalidPort": "Skriv inn en gyldig port (1-65535)", + "newUsername": "Nytt brukernavn", + "addUser": "Legge til", + "deleteUser": "Slett bruker", + "noHealthChecks": "Ingen helsesjekker er konfigurert ennå.", + "follow": "Følge", + "noLogData": "Ingen loggutgang.", + "tree": "Tre", + "enableDisable": "Aktiver/deaktiver ved oppstart", + "grantSudo": "Gi sudo", + "revokeSudo": "Tilbakekalle sudo", + "sslIssueCert": "Utsted sertifikat", + "sslExpired": "Utløpt", + "sslInDays": "i {{days}}d", + "sslNeedDomain": "Angi minst ett domene", + "sslIssued": "Sertifikat utstedt", + "sslDomainsPlaceholder": "eksempel.com, www.eksempel.com", + "sslHttpStandalone": "HTTP (frittstående)", + "sslHttpWebroot": "HTTP (nettrot)", + "sslDns": "DNS", + "sslDnsProvider": "DNS-leverandør (f.eks. Cloudflare)", + "sslIssueHint": "DNS-leverandørens påloggingsinformasjon må allerede være konfigurert på verten.", + "sslRevoke": "Tilbakekalle sertifikat", + "sslRevoked": "Sertifikatet er tilbakekalt", + "sslRevokeConfirm": "Tilbakekalle og fjerne sertifikatet «{{name}}»? Dette kan ikke angres.", + "healthRun": "Løp", + "healthName": "Navn", + "healthTarget": "Vert / adresse", + "healthAddCheck": "Legg til sjekk", + "healthSaved": "Helsesjekker lagret", + "healthMissingFields": "Hver sjekk trenger et navn og et mål", + "logFile": "Fil", + "logUnit": "Enhet", + "logCustomPath": "Tilpasset sti under /var/log (valgfritt)", + "logGrep": "Filtrer linjer...", + "firewallPersist": "Vedvarende regler", + "firewallPersisted": "Brannmurregler beholdt", + "wireguard": "WireGuard", + "tailscale": "Haleskala", + "wgNotInstalled": "WireGuard er ikke installert på denne verten", + "wgNoInterfaces": "Ingen WireGuard-grensesnitt konfigurert", + "wgInterfaceUp": "Ta opp", + "wgInterfaceDown": "Ta ned", + "wgBringingUp": "Tar opp {{name}}...", + "wgBringingDown": "Å bringe {{name}} ned...", + "wgInterfaceUpDone": "{{name}} er oppe", + "wgInterfaceDownDone": "{{name}} er nede", + "wgListenPort": "Havn", + "wgPublicKey": "Offentlig nøkkel", + "wgEndpoint": "Endepunkt", + "wgAllowedIPs": "Tillatte IP-adresser", + "wgLastHandshake": "Siste håndtrykk", + "wgHandshakeNever": "Aldri", + "wgTransfer": "Overføre", + "tsNotInstalled": "Tailscale er ikke installert på denne verten", + "tsRunning": "Løping", + "tsStopped": "Stoppet", + "tsEnable": "Koble til", + "tsDisable": "Frakople", + "tsEnabling": "Kobler til Tailscale...", + "tsDisabling": "Kobler fra Tailscale...", + "tsEnabled": "Haleskala tilkoblet", + "tsDisabled": "Haleskala frakoblet", + "tsIPs": "Haleskalerings-IP-er", + "tsPeers": "jevnaldrende", + "tsOnline": "På nett", + "tsOffline": "Frakoblet", + "tsExitNode": "Utgangsnode", + "tsExitNodeActive": "Avslutt node aktiv", + "tsHostname": "Vertsnavn" + } + }, + "metricsHistory": { + "title": "Metrikkhistorikk", + "historySuffix": "Historie", + "cpuMemoryDisk": "CPU / Minne / Disk", + "network": "Nettverk", + "download": "RX", + "upload": "TX", + "noData": "Ingen historikkdata tilgjengelig for denne tidsperioden.", + "custom": "Skikk", + "to": "til", + "apply": "Søke", + "viewHistory": "Vis historikk" + }, + "proxmoxStats": { + "tabTitle": "Proxmox-statistikk", + "cpuUsage": "CPU-bruk", + "memoryUsage": "Minnebruk", + "diskUsage": "Diskbruk", + "networkInterfaces": "Nettverksgrensesnitt", + "uptime": "Oppetid", + "systemInfo": "Systeminformasjon", + "guestsSummary": "Gjester", + "storagePools": "Lagringsbassenger", + "clusterHealth": "Klyngehelse", + "cpuCores_one": "{{count}} Kjerne", + "cpuCores_other": "{{count}} Kjerner", + "used": "Brukt", + "total": "Total", + "hostname": "Vertsnavn", + "kernel": "Kjerne", + "pveVersion": "PVE-versjon", + "name": "Navn", + "status": "Status", + "type": "Type", + "cpu": "CPU", + "mem": "Minne", + "disk": "Disk", + "running": "Løping", + "stopped": "Stoppet", + "guestCounts": "{{running}}/{{total}} løping", + "inactive": "Inaktiv", + "notClustered": "Frittstående node (ikke en del av en klynge)", + "quorate": "Kvorat", + "notQuorate": "Ikke beslutningsdyktig", + "nodeOnline": "På nett", + "nodeOffline": "Frakoblet", + "noHostSelected": "Ingen vert valgt", + "pveshNotFound": "pvesh ikke funnet – er dette en Proxmox-node?", + "nodeDetectionFailed": "Kan ikke bestemme et gyldig Proxmox-nodenavn", + "connecting": "Kobler til...", + "connectionFailed": "Kunne ikke koble til Proxmox-noden", + "refresh": "Forfriske", + "searchGuests": "Søk etter gjester...", + "filterAll": "Alle", + "filterVm": "VM", + "filterLxc": "LXC", + "noGuests": "Ingen virtuelle maskiner eller LXC-containere funnet på denne noden.", + "noGuestsMatch": "Ingen gjester samsvarer med de gjeldende filtrene." + }, + "nav": { + "hostMetrics": "Vertsmålinger" + }, + "hosts": { + "tabHostMetrics": "Vertsmålinger", + "enableProxmoxStats": "Aktiver Proxmox-statistikk", + "enableProxmoxStatsDesc": "Vis en Proxmox-statistikkfane for denne verten med live node-, gjeste-, lagrings- og klyngestatistikk samlet inn via SSH.", + "proxmoxStatsPollInterval": "Avstemningsintervall (sekunder)", + "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", + "metricsCollectionLabel": "Metriksamling", + "enableMetricsLabel": "Aktiver målinger", + "enableMetricsDesc": "Samle inn CPU-, RAM-, disk- og andre målinger fra denne verten", + "useGlobalMetrics": "Bruk globalt intervall", + "useGlobalMetricsDesc": "Overstyr med det serveromfattende måleintervallet", + "metricsIntervalS": "Måleintervall (s)", + "metricsIntervalDesc2": "Sekunder mellom målebilder", + "excludedMountsLabel": "Ekskluderte fester", + "monitoredMountsLabel": "Tilpassede overvåkede stier", + "monitoredMountsDesc": "Legg til stier som ikke er eksponert som separate monteringer, inkludert bindingsmonterte Home Assistant-stier som /config.", + "monitoredMountPathPlaceholder": "Sti (/config, /mnt/data)", + "monitoredMountLabelPlaceholder": "Etikett (valgfritt)", + "addMonitoredMount": "Legg til sti", + "excludedMountsDesc": "Skjul spesifikke monteringspunkter eller filsystemtyper (f.eks. nfs, cifs) fra diskbruk og varsler for denne verten.", + "excludedMountsPlaceholder": "Monteringssti (/mnt/nas) eller filsystemtype (nfs, cifs)", + "excludedMountsEmpty": "Ingen monteringer er utelukket. Alle oppdagede filsystemer vises.", + "addExcludedMount": "Legge til", + "visibleWidgets": "Synlige widgeter", + "widgetsMovedToHostMetrics": "Kort legges nå til, arrangeres og endres i størrelse direkte i fanen Vertsmålinger. Åpne Vertsmålinger for denne verten og bruk Tilpass for å velge hvilke kort som vises.", + "quickActionsLabel": "Hurtighandlinger", + "quickActionsToolbar": "Hurtighandlinger vises som knapper i verktøylinjen for vertsmålinger for utførelse av kommandoer med ett klikk.", + "noQuickActions": "Ingen hurtighandlinger ennå.", + "buttonLabel": "Knappetikett", + "selectSnippetPlaceholder": "Velg utdrag...", + "addActionBtn": "Legg til handling" + }, + "onboarding": { + "feature_metrics": "Målinger og varsler", + "feature_metrics_desc": "Spor CPU, minne og disk over tid, og bli varslet når de blir dårlige." + }, + "admin": { + "metricsHistoryRetention": "Oppbevaring av metrikkhistorikk", + "metricsHistoryRetentionRange": "1 til 90 dager", + "days": "dager" + }, + "homepage": { + "noData": "Ingen data tilgjengelig", + "showCurrentValue": "Vis gjeldende verdi", + "chartMetric": "Metrisk", + "metricRange": "Spekter" + } +} diff --git a/plugins/host-metrics/locales/translated/pl_PL.json b/plugins/host-metrics/locales/translated/pl_PL.json new file mode 100644 index 000000000..90eaa7630 --- /dev/null +++ b/plugins/host-metrics/locales/translated/pl_PL.json @@ -0,0 +1,313 @@ +{ + "hostMetrics": { + "cpu": "Procesor", + "memory": "Pamięć", + "disk": "Dysk", + "network": "Sieć", + "uptime": "Czas działania", + "processes": "Procesy", + "available": "Dostępne", + "free": "Wolne", + "connecting": "Łączenie...", + "connectionFailed": "Nie udało się połączyć z serwerem", + "naCpus": "Brak danych o CPU", + "cpuCores_one": "{{count}} rdzeń", + "cpuCores_other": "{{count}} rdzeni", + "cpuUsage": "Wykorzystanie procesora", + "memoryUsage": "Wykorzystanie pamięci", + "diskUsage": "Wykorzystanie dysku", + "selectFilesystem": "Wybierz system plików", + "temperature": "Temperatura", + "highestTemperature": "Najwyższa temperatura", + "primaryTemperatureSensor": "Główny czujnik", + "gpu": { + "title": "Procesor graficzny", + "noDevice": "Nie wykryto procesora graficznego NVIDIA. Zainstaluj sterownik NVIDIA (zawiera on nvidia-smi), aby wyświetlić dane dotyczące procesora graficznego.", + "driver": "Kierowca {{version}}", + "utilization": "Wykorzystanie", + "memory": "Pamięć VRAM", + "temperature": "Temp", + "power": "Moc", + "fan": "Wentylator", + "processes": "Procesy GPU", + "noProcesses": "Żaden proces nie wykorzystuje procesora GPU" + }, + "failedToFetchHostConfig": "Nie udało się pobrać konfiguracji hosta", + "serverOffline": "Serwer offline", + "cannotFetchMetrics": "Nie można pobrać metryk z serwera offline", + "totpFailed": "Weryfikacja TOTP nie powiodła się", + "noneAuthNotSupported": "Metryki hosta nie obsługują typu uwierzytelniania „none”.", + "noHostSelected": "Nie wybrano hosta", + "load": "Obciążenie", + "systemInfo": "Informacje o systemie", + "hostname": "Nazwa hosta", + "operatingSystem": "System operacyjny", + "kernel": "Jądro", + "seconds": "sekundy", + "networkInterfaces": "Interfejsy sieciowe", + "noInterfacesFound": "Nie znaleziono interfejsów sieciowych", + "noProcessesFound": "Nie znaleziono procesów", + "processesTotal": "łącznie", + "processesRunning": "działa", + "loginStats": "Statystyki logowania SSH", + "noRecentLoginData": "Brak ostatnich danych logowania", + "executingQuickAction": "Wykonywanie {{name}}...", + "quickActionSuccess": "{{name}} ukończono pomyślnie", + "quickActionFailed": "{{name}} nie powiodło się", + "quickActionError": "Nie udało się wykonać {{name}}", + "ports": { + "title": "Porty nasłuchujące", + "protocol": "Protokół", + "port": "Port", + "address": "Adres", + "process": "Proces", + "search": "Przeszukaj porty...", + "allProtocols": "Wszystkie", + "noData": "Brak danych portów nasłuchujących" + }, + "firewall": { + "title": "Zapora sieciowa", + "inactive": "Nieaktywna", + "policy": "Polityka", + "rules": "reguł", + "noRules": "Brak reguł w tym łańcuchu", + "noData": "Brak dostępnych danych zapory sieciowej", + "action": "Akcja", + "protocol": "Proto", + "port": "Port", + "source": "Źródło", + "anywhere": "Gdziekolwiek", + "chains": "łańcuchy" + }, + "loadAvg": "Obciążenie średnie", + "swap": "Swap", + "architecture": "Architektura", + "refresh": "Odśwież", + "retry": "Ponów", + "customize": "Dostosuj układ", + "reset": "Resetuj", + "tabLive": "Na żywo", + "editModeInstructions": "Przeciągnij karty, aby zmienić kolejność, przeciągnij dolną krawędź, aby zmienić wysokość, a przyciskiem szerokości zmień szerokość karty. Dodawaj lub usuwaj karty poniżej.", + "managers": { + "services": "Usługi", + "processInspector": "Inspektor procesów", + "logViewer": "Przeglądarka logów", + "cron": "Zadania cron", + "packages": "Pakiety", + "ssl": "Certyfikaty SSL", + "firewall": "Zapora sieciowa", + "users": "Użytkownicy i uprawnienia", + "healthCheck": "Kontrole stanu", + "diskBreakdown": "Podział dysku", + "systemdTimers": "Timery", + "topMemory": "Wg pamięci", + "noData": "Brak danych", + "sudoHint": "Ustaw hasło sudo dla tego hosta w edytorze hosta, aby włączyć akcje uprzywilejowane.", + "filter": "Filtr...", + "start": "Start", + "stop": "Zatrzymaj", + "restart": "Uruchom ponownie", + "actionDone": "Zaktualizowano {{name}}", + "actionFailed": "Akcja nie powiodła się", + "signalSent": "Sygnał wysłany do PID {{pid}}", + "killHint": "Kliknięcie: zakończ (SIGTERM). Kliknięcie prawym przyciskiem myszy: wymuś zakończenie (SIGKILL).", + "working": "Przetwarzanie...", + "update": "Aktualizuj", + "upgradeAll": "Uaktualnij wszystko", + "allUpToDate": "Wszystko jest aktualne", + "save": "Zapisz", + "command": "Polecenie", + "enabled": "Włączone", + "cronSaved": "Zaktualizowano crontab", + "clients": "Klienci", + "dryRun": "Symulacja", + "renew": "Odnów", + "noAcmeClient": "Nie znaleziono klienta ACME (certbot lub acme.sh) na tym hoście.", + "addInputRule": "Dodaj regułę INPUT", + "firewallWarning": "Zmiany działają tylko do restartu, dopóki nie zostaną utrwalone. Uważaj, aby nie odciąć sobie dostępu.", + "ruleApplied": "Zastosowano regułę", + "invalidPort": "Wprowadź prawidłowy port (1-65535)", + "newUsername": "Nowa nazwa użytkownika", + "addUser": "Dodaj", + "deleteUser": "Usuń użytkownika", + "noHealthChecks": "Nie skonfigurowano jeszcze żadnych kontroli stanu.", + "follow": "Śledź", + "noLogData": "Brak wyjścia logu.", + "tree": "Drzewo", + "enableDisable": "Włącz/wyłącz przy starcie systemu", + "grantSudo": "Przyznaj sudo", + "revokeSudo": "Odwołaj sudo", + "sslIssueCert": "Wystaw certyfikat", + "sslExpired": "Wygasły", + "sslInDays": "za {{days}} dni", + "sslNeedDomain": "Wprowadź co najmniej jedną domenę", + "sslIssued": "Wystawiono certyfikat", + "sslDomainsPlaceholder": "example.com, www.example.com", + "sslHttpStandalone": "HTTP (samodzielny)", + "sslHttpWebroot": "HTTP (webroot)", + "sslDns": "DNS", + "sslDnsProvider": "Dostawca DNS (np. Cloudflare)", + "sslIssueHint": "Poświadczenia dostawcy DNS muszą być już skonfigurowane na hoście.", + "sslRevoke": "Unieważnij certyfikat", + "sslRevoked": "Unieważniono certyfikat", + "sslRevokeConfirm": "Unieważnić i usunąć certyfikat „{{name}}”? Tego nie można cofnąć.", + "healthRun": "Uruchom", + "healthName": "Nazwa", + "healthTarget": "Host / adres", + "healthAddCheck": "Dodaj kontrolę", + "healthSaved": "Zapisano kontrole stanu", + "healthMissingFields": "Każda kontrola wymaga nazwy i celu", + "logFile": "Plik", + "logUnit": "Unit", + "logCustomPath": "Ścieżka niestandardowa w /var/log (opcjonalnie)", + "logGrep": "Filtruj wiersze...", + "firewallPersist": "Utrwal reguły", + "firewallPersisted": "Utrwalono reguły zapory", + "wireguard": "WireGuard", + "tailscale": "Tailscale", + "wgNotInstalled": "WireGuard nie jest zainstalowany na tym hoście", + "wgNoInterfaces": "Brak skonfigurowanych interfejsów WireGuard", + "wgInterfaceUp": "Podnieś", + "wgInterfaceDown": "Wyłącz", + "wgBringingUp": "Podnoszenie {{name}}...", + "wgBringingDown": "Wyłączanie {{name}}...", + "wgInterfaceUpDone": "{{name}} jest podniesiony", + "wgInterfaceDownDone": "{{name}} jest wyłączony", + "wgListenPort": "Port", + "wgPublicKey": "Klucz publiczny", + "wgEndpoint": "Punkt końcowy", + "wgAllowedIPs": "Dozwolone adresy IP", + "wgLastHandshake": "Ostatni handshake", + "wgHandshakeNever": "Nigdy", + "wgTransfer": "Transfer", + "tsNotInstalled": "Tailscale nie jest zainstalowany na tym hoście", + "tsRunning": "Działa", + "tsStopped": "Zatrzymany", + "tsEnable": "Połącz", + "tsDisable": "Odłącz", + "tsEnabling": "Łączenie z Tailscale...", + "tsDisabling": "Rozłączanie z Tailscale...", + "tsEnabled": "Tailscale połączony", + "tsDisabled": "Tailscale rozłączony", + "tsIPs": "Adresy IP Tailscale", + "tsPeers": "Peery", + "tsOnline": "Online", + "tsOffline": "Offline", + "tsExitNode": "Węzeł wyjściowy", + "tsExitNodeActive": "Węzeł wyjściowy aktywny", + "tsHostname": "Nazwa hosta" + } + }, + "metricsHistory": { + "title": "Historia metryk", + "historySuffix": "Historia", + "cpuMemoryDisk": "Procesor / Pamięć / Dysk", + "network": "Sieć", + "download": "RX", + "upload": "TX", + "noData": "Brak dostępnych danych historycznych dla tego przedziału czasu.", + "custom": "Niestandardowy", + "to": "do", + "apply": "Zastosuj", + "viewHistory": "Wyświetl historię" + }, + "proxmoxStats": { + "tabTitle": "Statystyki Proxmox", + "cpuUsage": "Wykorzystanie procesora", + "memoryUsage": "Wykorzystanie pamięci", + "diskUsage": "Wykorzystanie dysku", + "networkInterfaces": "Interfejsy sieciowe", + "uptime": "Czas działania", + "systemInfo": "Informacje o systemie", + "guestsSummary": "Goście", + "storagePools": "Pule magazynowe", + "clusterHealth": "Kondycja klastra", + "cpuCores_one": "{{count}} rdzeń", + "cpuCores_other": "{{count}} rdzeni", + "used": "Użyte", + "total": "Łącznie", + "hostname": "Nazwa hosta", + "kernel": "Jądro", + "pveVersion": "Wersja PVE", + "name": "Nazwa", + "status": "Status", + "type": "Typ", + "cpu": "Procesor", + "mem": "Pamięć", + "disk": "Dysk", + "running": "Działa", + "stopped": "Zatrzymany", + "guestCounts": "{{running}}/{{total}} działa", + "inactive": "Nieaktywny", + "notClustered": "Samodzielny węzeł (nie jest częścią klastra)", + "quorate": "Kworum osiągnięte", + "notQuorate": "Brak kworum", + "nodeOnline": "Online", + "nodeOffline": "Offline", + "noHostSelected": "Nie wybrano hosta", + "pveshNotFound": "Nie znaleziono pvesh. Czy to węzeł Proxmox?", + "nodeDetectionFailed": "Nie można ustalić prawidłowej nazwy węzła Proxmox", + "connecting": "Łączenie...", + "connectionFailed": "Nie udało się połączyć z węzłem Proxmox", + "refresh": "Odśwież", + "searchGuests": "Wyszukaj gości...", + "filterAll": "Wszystkie", + "filterVm": "VM", + "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." + }, + "nav": { + "hostMetrics": "Metryki hosta" + }, + "hosts": { + "tabHostMetrics": "Metryki hosta", + "enableProxmoxStats": "Włącz statystyki Proxmox", + "enableProxmoxStatsDesc": "Pokaż kartę statystyk Proxmox dla tego hosta z bieżącymi statystykami węzła, gości, magazynu i klastra zbieranymi przez SSH.", + "proxmoxStatsPollInterval": "Interwał sondowania (sekundy)", + "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", + "metricsCollectionLabel": "Zbieranie metryk", + "enableMetricsLabel": "Włącz metryki", + "enableMetricsDesc": "Zbieraj dane o procesorze, pamięci RAM, dysku i inne metryki z tego hosta", + "useGlobalMetrics": "Użyj interwału globalnego", + "useGlobalMetricsDesc": "Użyj globalnego interwału zbierania metryk", + "metricsIntervalS": "Interwał metryk (s)", + "metricsIntervalDesc2": "Sekundy między migawkami metryk", + "excludedMountsLabel": "Wykluczone montowania", + "monitoredMountsLabel": "Niestandardowe monitorowane ścieżki", + "monitoredMountsDesc": "Dodaj ścieżki, które nie są udostępniane jako osobne montowania, w tym ścieżki Home Assistant montowane przez bind, takie jak /config.", + "monitoredMountPathPlaceholder": "Ścieżka (/config, /mnt/data)", + "monitoredMountLabelPlaceholder": "Etykieta (opcjonalnie)", + "addMonitoredMount": "Dodaj ścieżkę", + "excludedMountsDesc": "Ukryj określone punkty montowania lub typy systemów plików (np. nfs, cifs) w informacjach o wykorzystaniu dysku i alertach dla tego hosta.", + "excludedMountsPlaceholder": "Ścieżka montowania (/mnt/nas) lub typ systemu plików (nfs, cifs)", + "excludedMountsEmpty": "Brak wykluczonych montowań. Wyświetlane są wszystkie wykryte systemy plików.", + "addExcludedMount": "Dodaj", + "visibleWidgets": "Widoczne widżety", + "widgetsMovedToHostMetrics": "Karty dodaje się, układa i skaluje bezpośrednio na karcie „Metryki hosta”. Otwórz Metryki hosta dla tego hosta i użyj opcji „Dostosuj”, aby wybrać wyświetlane karty.", + "quickActionsLabel": "Szybkie akcje", + "quickActionsToolbar": "Szybkie akcje pojawiają się jako przyciski na pasku narzędzi Metryki hosta, umożliwiając wykonanie polecenia jednym kliknięciem.", + "noQuickActions": "Brak szybkich akcji.", + "buttonLabel": "Etykieta przycisku", + "selectSnippetPlaceholder": "Wybierz snippet...", + "addActionBtn": "Dodaj akcję" + }, + "onboarding": { + "feature_metrics": "Metryki i alerty", + "feature_metrics_desc": "Śledź procesor, pamięć i dysk w czasie i otrzymuj alerty, gdy przekroczą próg." + }, + "admin": { + "metricsHistoryRetention": "Przechowywanie historii metryk", + "metricsHistoryRetentionRange": "od 1 do 90 dni", + "days": "dni" + }, + "homepage": { + "noData": "Brak dostępnych danych", + "showCurrentValue": "Pokaż wartość bieżącą", + "chartMetric": "Metryka", + "metricRange": "Zakres" + } +} diff --git a/plugins/host-metrics/locales/translated/pt_BR.json b/plugins/host-metrics/locales/translated/pt_BR.json new file mode 100644 index 000000000..300ab399f --- /dev/null +++ b/plugins/host-metrics/locales/translated/pt_BR.json @@ -0,0 +1,313 @@ +{ + "hostMetrics": { + "cpu": "CPU", + "memory": "Memória", + "disk": "Disco", + "network": "Rede", + "uptime": "Tempo de atividade", + "processes": "Processos", + "available": "Disponível", + "free": "Livre", + "connecting": "Conectando...", + "connectionFailed": "Falha ao conectar-se ao servidor", + "naCpus": "N/A CPU(s)", + "cpuCores_one": "{{count}} Núcleo", + "cpuCores_other": "{{count}} Núcleos", + "cpuUsage": "Utilização da CPU", + "memoryUsage": "Uso de memória", + "diskUsage": "Utilização do disco", + "selectFilesystem": "Selecione o sistema de arquivos", + "temperature": "Temperatura", + "highestTemperature": "Temperatura mais alta", + "primaryTemperatureSensor": "Sensor primário", + "gpu": { + "title": "GPU", + "noDevice": "Nenhuma GPU NVIDIA detectada. Instale o driver da NVIDIA (que fornece o nvidia-smi) para visualizar as métricas da GPU.", + "driver": "Motorista {{version}}", + "utilization": "Utilização", + "memory": "VRAM", + "temperature": "Temp", + "power": "Poder", + "fan": "Fã", + "processes": "processos da GPU", + "noProcesses": "Nenhum processo está utilizando a GPU." + }, + "failedToFetchHostConfig": "Falha ao obter a configuração do host", + "serverOffline": "Servidor offline", + "cannotFetchMetrics": "Não foi possível obter métricas do servidor offline.", + "totpFailed": "A verificação TOTP falhou.", + "noneAuthNotSupported": "O Host Metrics não suporta o tipo de autenticação 'nenhum'.", + "noHostSelected": "Nenhum host selecionado", + "load": "Carregar", + "systemInfo": "Informações do sistema", + "hostname": "Nome do host", + "operatingSystem": "Sistema operacional", + "kernel": "Kernel", + "seconds": "segundos", + "networkInterfaces": "Interfaces de rede", + "noInterfacesFound": "Nenhuma interface de rede encontrada", + "noProcessesFound": "Nenhum processo encontrado", + "processesTotal": "total", + "processesRunning": "correndo", + "loginStats": "Estatísticas de login SSH", + "noRecentLoginData": "Nenhum dado de login recente", + "executingQuickAction": "Executando {{name}}...", + "quickActionSuccess": "{{name}} concluído com sucesso", + "quickActionFailed": "{{name}} falhou", + "quickActionError": "Falha ao executar {{name}}", + "ports": { + "title": "Portas de escuta", + "protocol": "Protocolo", + "port": "Porta", + "address": "Endereço", + "process": "Processo", + "search": "Portas de pesquisa...", + "allProtocols": "Todos", + "noData": "Sem dados de portas de escuta" + }, + "firewall": { + "title": "Firewall", + "inactive": "Inativo", + "policy": "Política", + "rules": "regras", + "noRules": "Não há regras nesta corrente.", + "noData": "Não há dados de firewall disponíveis.", + "action": "Ação", + "protocol": "Proto", + "port": "Porta", + "source": "Fonte", + "anywhere": "Em qualquer lugar", + "chains": "correntes" + }, + "loadAvg": "Carga média", + "swap": "Trocar", + "architecture": "Arquitetura", + "refresh": "Atualizar", + "retry": "Tentar novamente", + "customize": "Personalizar layout", + "reset": "Reiniciar", + "tabLive": "Ao vivo", + "editModeInstructions": "Arraste os cartões para reorganizá-los, arraste a borda inferior para redimensioná-los e use o botão de largura para alterar a extensão de um cartão. Adicione ou remova cartões abaixo.", + "managers": { + "services": "Serviços", + "processInspector": "Inspetor de Processos", + "logViewer": "Visualizador de Logs", + "cron": "Tarefas agendadas", + "packages": "Pacotes", + "ssl": "Certificados SSL", + "firewall": "Firewall", + "users": "Usuários e permissões", + "healthCheck": "Exames de saúde", + "diskBreakdown": "Avaria do disco", + "systemdTimers": "Temporizadores", + "topMemory": "Melhor por memória", + "noData": "Sem dados", + "sudoHint": "Defina uma senha sudo para este host no editor de hosts para habilitar ações privilegiadas.", + "filter": "Filtro...", + "start": "Começar", + "stop": "Parar", + "restart": "Reiniciar", + "actionDone": "{{name}} atualizado", + "actionFailed": "A ação falhou", + "signalSent": "Sinal enviado para PID {{pid}}", + "killHint": "Clique: encerrar (SIGTERM). Clique com o botão direito: forçar o encerramento (SIGKILL).", + "working": "Trabalhando...", + "update": "Atualizar", + "upgradeAll": "Atualizar tudo", + "allUpToDate": "Tudo está atualizado.", + "save": "Salvar", + "command": "Comando", + "enabled": "Habilitado", + "cronSaved": "Crontab atualizado", + "clients": "Clientes", + "dryRun": "Ensaio geral", + "renew": "Renovar", + "noAcmeClient": "Nenhum cliente ACME (certbot ou acme.sh) foi encontrado neste host.", + "addInputRule": "Adicionar regra de ENTRADA", + "firewallWarning": "As alterações são válidas apenas em tempo de execução até serem persistidas. Tenha cuidado para não bloquear o seu próprio acesso.", + "ruleApplied": "Regra aplicada", + "invalidPort": "Digite uma porta válida (1-65535)", + "newUsername": "Novo nome de usuário", + "addUser": "Adicionar", + "deleteUser": "Excluir usuário", + "noHealthChecks": "Nenhuma verificação de integridade configurada ainda.", + "follow": "Seguir", + "noLogData": "Nenhuma saída de log.", + "tree": "Árvore", + "enableDisable": "Ativar/desativar na inicialização", + "grantSudo": "Conceder sudo", + "revokeSudo": "Revogar sudo", + "sslIssueCert": "Emitir certificado", + "sslExpired": "Expirado", + "sslInDays": "em {{days}}d", + "sslNeedDomain": "Insira pelo menos um domínio.", + "sslIssued": "Certificado emitido", + "sslDomainsPlaceholder": "exemplo.com, www.exemplo.com", + "sslHttpStandalone": "HTTP (autônomo)", + "sslHttpWebroot": "HTTP (raiz da web)", + "sslDns": "DNS", + "sslDnsProvider": "provedor de DNS (ex: Cloudflare)", + "sslIssueHint": "As credenciais do provedor de DNS já devem estar configuradas no host.", + "sslRevoke": "Revogar certificado", + "sslRevoked": "Certificado revogado", + "sslRevokeConfirm": "Revogar e remover o certificado \"{{name}}\"? Isso não pode ser desfeito.", + "healthRun": "Correr", + "healthName": "Nome", + "healthTarget": "Endereço do host", + "healthAddCheck": "Adicionar verificação", + "healthSaved": "Exames de saúde salvos", + "healthMissingFields": "Cada verificação precisa de um nome e um alvo.", + "logFile": "Arquivo", + "logUnit": "Unidade", + "logCustomPath": "Caminho personalizado em /var/log (opcional)", + "logGrep": "Linhas de filtro...", + "firewallPersist": "Regras persistentes", + "firewallPersisted": "As regras do firewall persistiram.", + "wireguard": "WireGuard", + "tailscale": "Escama da cauda", + "wgNotInstalled": "O WireGuard não está instalado neste host.", + "wgNoInterfaces": "Nenhuma interface WireGuard configurada", + "wgInterfaceUp": "Levantar a questão", + "wgInterfaceDown": "Derrubem", + "wgBringingUp": "Trazendo {{name}} para cima...", + "wgBringingDown": "Derrubando {{name}}...", + "wgInterfaceUpDone": "{{name}} está ativo", + "wgInterfaceDownDone": "{{name}} está inativo", + "wgListenPort": "Porta", + "wgPublicKey": "Chave pública", + "wgEndpoint": "Ponto final", + "wgAllowedIPs": "IPs permitidos", + "wgLastHandshake": "Último aperto de mãos", + "wgHandshakeNever": "Nunca", + "wgTransfer": "Transferir", + "tsNotInstalled": "O Tailscale não está instalado neste host.", + "tsRunning": "Correndo", + "tsStopped": "Parou", + "tsEnable": "Conectar", + "tsDisable": "Desconectar", + "tsEnabling": "Conectando-se à Tailscale...", + "tsDisabling": "Desconectando-se do Tailscale...", + "tsEnabled": "Escama de cauda conectada", + "tsDisabled": "Escama de cauda desconectada", + "tsIPs": "IPs da Tailscale", + "tsPeers": "Pares", + "tsOnline": "On-line", + "tsOffline": "Offline", + "tsExitNode": "Nó de saída", + "tsExitNodeActive": "Nó de saída ativo", + "tsHostname": "Nome do host" + } + }, + "metricsHistory": { + "title": "Histórico de métricas", + "historySuffix": "História", + "cpuMemoryDisk": "CPU / Memória / Disco", + "network": "Rede", + "download": "RX", + "upload": "TX", + "noData": "Não há dados históricos disponíveis para este período.", + "custom": "Personalizado", + "to": "para", + "apply": "Aplicar", + "viewHistory": "Ver histórico" + }, + "proxmoxStats": { + "tabTitle": "Estatísticas do Proxmox", + "cpuUsage": "Utilização da CPU", + "memoryUsage": "Uso de memória", + "diskUsage": "Utilização do disco", + "networkInterfaces": "Interfaces de rede", + "uptime": "Tempo de atividade", + "systemInfo": "Informações do sistema", + "guestsSummary": "Convidados", + "storagePools": "Piscinas de armazenamento", + "clusterHealth": "Cluster Health", + "cpuCores_one": "{{count}} Núcleo", + "cpuCores_other": "{{count}} Núcleos", + "used": "Usado", + "total": "Total", + "hostname": "Nome do host", + "kernel": "Kernel", + "pveVersion": "Versão PvE", + "name": "Nome", + "status": "Status", + "type": "Tipo", + "cpu": "CPU", + "mem": "Membro", + "disk": "Disco", + "running": "Correndo", + "stopped": "Parou", + "guestCounts": "{{running}}/{{total}} em execução", + "inactive": "Inativo", + "notClustered": "Nó independente (não faz parte de um cluster)", + "quorate": "Quorate", + "notQuorate": "Sem quórum", + "nodeOnline": "On-line", + "nodeOffline": "Offline", + "noHostSelected": "Nenhum host selecionado", + "pveshNotFound": "pvesh não encontrado - este é um nó Proxmox?", + "nodeDetectionFailed": "Não foi possível determinar um nome de nó Proxmox válido.", + "connecting": "Conectando...", + "connectionFailed": "Falha ao conectar-se ao nó Proxmox", + "refresh": "Atualizar", + "searchGuests": "Pesquisar hóspedes...", + "filterAll": "Todos", + "filterVm": "VM", + "filterLxc": "LXC", + "noGuests": "Nenhuma máquina virtual ou contêiner LXC foi encontrado neste nó.", + "noGuestsMatch": "Nenhum hóspede corresponde aos filtros atuais." + }, + "nav": { + "hostMetrics": "Métricas do host" + }, + "hosts": { + "tabHostMetrics": "Métricas do host", + "enableProxmoxStats": "Ativar estatísticas do Proxmox", + "enableProxmoxStatsDesc": "Exibe a aba de Estatísticas do Proxmox para este host com estatísticas em tempo real de nós, máquinas virtuais, armazenamento e cluster, coletadas via SSH.", + "proxmoxStatsPollInterval": "Intervalo de sondagem (segundos)", + "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", + "metricsCollectionLabel": "Coleta de métricas", + "enableMetricsLabel": "Ativar métricas", + "enableMetricsDesc": "Coletar métricas de CPU, RAM, disco e outras deste host.", + "useGlobalMetrics": "Usar intervalo global", + "useGlobalMetricsDesc": "Substituir pelo intervalo de métricas de todo o servidor", + "metricsIntervalS": "Intervalo de métricas (s)", + "metricsIntervalDesc2": "Segundos entre instantâneos de métricas", + "excludedMountsLabel": "Suportes excluídos", + "monitoredMountsLabel": "Caminhos monitorados personalizados", + "monitoredMountsDesc": "Adicione caminhos que não estejam expostos como montagens separadas, incluindo caminhos do Home Assistant montados via bind, como /config.", + "monitoredMountPathPlaceholder": "Caminho (/config, /mnt/data)", + "monitoredMountLabelPlaceholder": "Rótulo (opcional)", + "addMonitoredMount": "Adicionar caminho", + "excludedMountsDesc": "Oculte pontos de montagem ou tipos de sistema de arquivos específicos (por exemplo, NFS, CIFS) do uso de disco e dos alertas para este host.", + "excludedMountsPlaceholder": "Caminho de montagem (/mnt/nas) ou tipo de sistema de arquivos (nfs, cifs)", + "excludedMountsEmpty": "Nenhuma montagem excluída. Todos os sistemas de arquivos detectados são exibidos.", + "addExcludedMount": "Adicionar", + "visibleWidgets": "Widgets Visíveis", + "widgetsMovedToHostMetrics": "Agora, os cartões podem ser adicionados, organizados e redimensionados diretamente na guia Métricas do Host. Abra as Métricas do Host para este host e use a opção Personalizar para escolher quais cartões serão exibidos.", + "quickActionsLabel": "Ações rápidas", + "quickActionsToolbar": "As ações rápidas aparecem como botões na barra de ferramentas do Host Metrics para execução de comandos com um único clique.", + "noQuickActions": "Nenhuma ação imediata ainda.", + "buttonLabel": "Rótulo do botão", + "selectSnippetPlaceholder": "Selecione o trecho...", + "addActionBtn": "Adicionar ação" + }, + "onboarding": { + "feature_metrics": "Métricas e alertas", + "feature_metrics_desc": "Monitore o uso de CPU, memória e disco ao longo do tempo e receba alertas quando apresentarem problemas." + }, + "admin": { + "metricsHistoryRetention": "Retenção do histórico de métricas", + "metricsHistoryRetentionRange": "1 a 90 dias", + "days": "dias" + }, + "homepage": { + "noData": "Não há dados disponíveis.", + "showCurrentValue": "Mostrar valor atual", + "chartMetric": "Métrica", + "metricRange": "Faixa" + } +} diff --git a/plugins/host-metrics/locales/translated/pt_PT.json b/plugins/host-metrics/locales/translated/pt_PT.json new file mode 100644 index 000000000..6cef9aa23 --- /dev/null +++ b/plugins/host-metrics/locales/translated/pt_PT.json @@ -0,0 +1,313 @@ +{ + "hostMetrics": { + "cpu": "CPU", + "memory": "Memória", + "disk": "Disco", + "network": "Rede", + "uptime": "Tempo de atividade", + "processes": "Processos", + "available": "Disponível", + "free": "Livre", + "connecting": "A ligar...", + "connectionFailed": "Falha ao ligar ao servidor", + "naCpus": "N/D CPU(s)", + "cpuCores_one": "{{count}} Núcleo", + "cpuCores_other": "{{count}} Núcleos", + "cpuUsage": "Utilização da CPU", + "memoryUsage": "Utilização da memória", + "diskUsage": "Utilização do disco", + "selectFilesystem": "Selecione o sistema de ficheiros", + "temperature": "Temperatura", + "highestTemperature": "Temperatura máxima", + "primaryTemperatureSensor": "Sensor primário", + "gpu": { + "title": "GPU", + "noDevice": "Nenhuma GPU NVIDIA detetada. Instale o controlador da NVIDIA (que fornece o nvidia-smi) para visualizar as métricas da GPU.", + "driver": "Motorista {{version}}", + "utilization": "Utilização", + "memory": "VRAM", + "temperature": "Temp", + "power": "Poder", + "fan": "Fã", + "processes": "processos da GPU", + "noProcesses": "Nenhum processo está a utilizar a GPU." + }, + "failedToFetchHostConfig": "Falha ao obter a configuração do servidor", + "serverOffline": "Servidor offline", + "cannotFetchMetrics": "Não é possível obter métricas do servidor offline", + "totpFailed": "Falha na verificação TOTP", + "noneAuthNotSupported": "Host Metrics não suporta o tipo de autenticação 'none'.", + "noHostSelected": "Nenhum host selecionado", + "load": "Carga", + "systemInfo": "Informação do Sistema", + "hostname": "Nome do host", + "operatingSystem": "Sistema Operativo", + "kernel": "Kernel", + "seconds": "segundos", + "networkInterfaces": "Interfaces de Rede", + "noInterfacesFound": "Nenhuma interface de rede encontrada", + "noProcessesFound": "Nenhum processo encontrado", + "processesTotal": "total", + "processesRunning": "em execução", + "loginStats": "Estatísticas de início de sessão SSH", + "noRecentLoginData": "Sem dados de início de sessão recentes", + "executingQuickAction": "A executar {{name}}...", + "quickActionSuccess": "{{name}} concluído com sucesso", + "quickActionFailed": "{{name}} falhou", + "quickActionError": "Falha ao executar {{name}}", + "ports": { + "title": "Portas em escuta", + "protocol": "Protocolo", + "port": "Porta", + "address": "Endereço", + "process": "Processo", + "search": "Pesquisar portas...", + "allProtocols": "Todos", + "noData": "Sem dados de portas em escuta" + }, + "firewall": { + "title": "Firewall", + "inactive": "Inativo", + "policy": "Política", + "rules": "regras", + "noRules": "Sem regras nesta cadeia", + "noData": "Sem dados de firewall disponíveis", + "action": "Ação", + "protocol": "Proto", + "port": "Porta", + "source": "Origem", + "anywhere": "Qualquer lugar", + "chains": "cadeias" + }, + "loadAvg": "Carga Média", + "swap": "Swap", + "architecture": "Arquitetura", + "refresh": "Atualizar", + "retry": "Tentar novamente", + "customize": "Personalizar layout", + "reset": "Redefinir", + "tabLive": "Ao Vivo", + "editModeInstructions": "Arraste os cartões para reorganizar, arraste a borda inferior para redimensionar e use o botão de largura para alterar a largura do cartão. Adicione ou remova cartões abaixo.", + "managers": { + "services": "Serviços", + "processInspector": "Inspetor de Processos", + "logViewer": "Visualizador de Registos", + "cron": "Tarefas Cron", + "packages": "Pacotes", + "ssl": "Certificados SSL", + "firewall": "Firewall", + "users": "Utilizadores e Permissões", + "healthCheck": "Verificações de Estado", + "diskBreakdown": "Análise de Disco", + "systemdTimers": "Temporizadores", + "topMemory": "Top por Memória", + "noData": "Sem dados", + "sudoHint": "Defina uma palavra-passe sudo para este host no editor de hosts para ativar ações privilegiadas.", + "filter": "Filtrar...", + "start": "Iniciar", + "stop": "Parar", + "restart": "Reiniciar", + "actionDone": "{{name}} atualizado", + "actionFailed": "A ação falhou", + "signalSent": "Sinal enviado para o PID {{pid}}", + "killHint": "Clique: terminar (SIGTERM). Clique direito: forçar encerramento (SIGKILL).", + "working": "A trabalhar...", + "update": "Atualizar", + "upgradeAll": "Atualizar tudo", + "allUpToDate": "Tudo está atualizado", + "save": "Guardar", + "command": "Comando", + "enabled": "Ativado", + "cronSaved": "Crontab atualizado", + "clients": "Clientes", + "dryRun": "Simulação", + "renew": "Renovar", + "noAcmeClient": "Nenhum cliente ACME (certbot ou acme.sh) encontrado neste servidor.", + "addInputRule": "Adicionar regra INPUT", + "firewallWarning": "As alterações são efetuadas apenas em execução até serem guardadas. Tenha cuidado para não ficar bloqueado.", + "ruleApplied": "Regra aplicada", + "invalidPort": "Introduza uma porta válida (1-65535)", + "newUsername": "Novo nome de utilizador", + "addUser": "Adicionar", + "deleteUser": "Eliminar utilizador", + "noHealthChecks": "Nenhuma verificação de estado configurada ainda.", + "follow": "Seguir", + "noLogData": "Sem saída de registo.", + "tree": "Árvore", + "enableDisable": "Ativar / desativar no arranque", + "grantSudo": "Conceder sudo", + "revokeSudo": "Revogar sudo", + "sslIssueCert": "Emitir certificado", + "sslExpired": "Expirado", + "sslInDays": "em {{days}}d", + "sslNeedDomain": "Introduza pelo menos um domínio", + "sslIssued": "Certificado emitido", + "sslDomainsPlaceholder": "example.com, www.example.com", + "sslHttpStandalone": "HTTP (autónomo)", + "sslHttpWebroot": "HTTP (webroot)", + "sslDns": "DNS", + "sslDnsProvider": "Fornecedor DNS (ex. cloudflare)", + "sslIssueHint": "As credenciais do fornecedor DNS já devem estar configuradas no host.", + "sslRevoke": "Revogar certificado", + "sslRevoked": "Certificado revogado", + "sslRevokeConfirm": "Revogar e remover o certificado \"{{name}}\"? Esta ação não pode ser anulada.", + "healthRun": "Executar", + "healthName": "Nome", + "healthTarget": "Host / endereço", + "healthAddCheck": "Adicionar verificação", + "healthSaved": "Verificações de saúde guardadas", + "healthMissingFields": "Cada verificação necessita de um nome e um destino", + "logFile": "Ficheiro", + "logUnit": "Unidade", + "logCustomPath": "Caminho personalizado em /var/log (opcional)", + "logGrep": "Filtrar linhas...", + "firewallPersist": "Persistir regras", + "firewallPersisted": "Regras de firewall persistidas", + "wireguard": "WireGuard", + "tailscale": "Tailscale", + "wgNotInstalled": "O WireGuard não está instalado neste host", + "wgNoInterfaces": "Nenhuma interface WireGuard configurada", + "wgInterfaceUp": "Ativar", + "wgInterfaceDown": "Desativar", + "wgBringingUp": "A ativar {{name}}...", + "wgBringingDown": "A desativar {{name}}...", + "wgInterfaceUpDone": "{{name}} está ativada", + "wgInterfaceDownDone": "{{name}} está desativada", + "wgListenPort": "Porta", + "wgPublicKey": "Chave pública", + "wgEndpoint": "Endpoint", + "wgAllowedIPs": "IPs permitidos", + "wgLastHandshake": "Último handshake", + "wgHandshakeNever": "Nunca", + "wgTransfer": "Transferência", + "tsNotInstalled": "O Tailscale não está instalado neste host", + "tsRunning": "A executar", + "tsStopped": "Parado", + "tsEnable": "Ligar", + "tsDisable": "Desligar", + "tsEnabling": "A ligar ao Tailscale...", + "tsDisabling": "A desligar do Tailscale...", + "tsEnabled": "Tailscale ligado", + "tsDisabled": "Tailscale desligado", + "tsIPs": "IPs do Tailscale", + "tsPeers": "Pares", + "tsOnline": "Online", + "tsOffline": "Offline", + "tsExitNode": "Nó de saída", + "tsExitNodeActive": "Nó de saída ativo", + "tsHostname": "Nome do host" + } + }, + "metricsHistory": { + "title": "Histórico de Métricas", + "historySuffix": "Histórico", + "cpuMemoryDisk": "CPU / Memória / Disco", + "network": "Rede", + "download": "RX", + "upload": "TX", + "noData": "Sem dados de histórico disponíveis para este intervalo de tempo.", + "custom": "Personalizado", + "to": "a", + "apply": "Aplicar", + "viewHistory": "Ver Histórico" + }, + "proxmoxStats": { + "tabTitle": "Estatísticas do Proxmox", + "cpuUsage": "Utilização da CPU", + "memoryUsage": "Uso de memória", + "diskUsage": "Utilização do disco", + "networkInterfaces": "Interfaces de rede", + "uptime": "Tempo de atividade", + "systemInfo": "Informações do sistema", + "guestsSummary": "Convidados", + "storagePools": "Piscinas de armazenamento", + "clusterHealth": "Saúde em grupo", + "cpuCores_one": "{{count}} Núcleo", + "cpuCores_other": "{{count}} Núcleos", + "used": "Usado", + "total": "Total", + "hostname": "Nome do host", + "kernel": "Kernel", + "pveVersion": "Versão PvE", + "name": "Nome", + "status": "Estatuto", + "type": "Tipo", + "cpu": "CPU", + "mem": "Membro", + "disk": "Disco", + "running": "Corrida", + "stopped": "Parou", + "guestCounts": "{{running}}/{{total}} em execução", + "inactive": "Inativo", + "notClustered": "Nó independente (não faz parte de um cluster)", + "quorate": "Quorate", + "notQuorate": "Sem quórum", + "nodeOnline": "Online", + "nodeOffline": "Offline", + "noHostSelected": "Nenhum host selecionado", + "pveshNotFound": "pvesh não encontrado - este é um nó Proxmox?", + "nodeDetectionFailed": "Não foi possível determinar um nome de nó Proxmox válido.", + "connecting": "Ligando...", + "connectionFailed": "Falha ao ligar ao nó Proxmox", + "refresh": "Atualizar", + "searchGuests": "Pesquisar hóspedes...", + "filterAll": "Tudo", + "filterVm": "VM", + "filterLxc": "LXC", + "noGuests": "Nenhuma máquina virtual ou contentor LXC foi encontrado neste nó.", + "noGuestsMatch": "Nenhum hóspede corresponde aos filtros atuais." + }, + "nav": { + "hostMetrics": "Métricas do Servidor" + }, + "hosts": { + "tabHostMetrics": "Métricas do Host", + "enableProxmoxStats": "Ativar estatísticas do Proxmox", + "enableProxmoxStatsDesc": "Apresenta o separador Estatísticas do Proxmox para este host com estatísticas em tempo real dos nós, máquinas virtuais, armazenamento e cluster, recolhidas via SSH.", + "proxmoxStatsPollInterval": "Intervalo de sondagem (segundos)", + "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", + "metricsCollectionLabel": "Recolha de Métricas", + "enableMetricsLabel": "Ativar Métricas", + "enableMetricsDesc": "Recolher métricas de CPU, RAM, disco e outras deste host", + "useGlobalMetrics": "Usar Intervalo Global", + "useGlobalMetricsDesc": "Substituir pelo intervalo de métricas global do servidor", + "metricsIntervalS": "Intervalo de Métricas (s)", + "metricsIntervalDesc2": "Segundos entre cada registo de métricas", + "excludedMountsLabel": "Suportes excluídos", + "monitoredMountsLabel": "Caminhos monitorizados personalizados", + "monitoredMountsDesc": "Adicione caminhos que não estejam expostos como montagens separadas, incluindo caminhos do Home Assistant montados através de bind, como /config.", + "monitoredMountPathPlaceholder": "Caminho (/config, /mnt/data)", + "monitoredMountLabelPlaceholder": "Rótulo (opcional)", + "addMonitoredMount": "Adicionar caminho", + "excludedMountsDesc": "Ocultar pontos de montagem ou tipos de sistema de ficheiros específicos (por exemplo, NFS, CIFS) da utilização do disco e dos alertas para este host.", + "excludedMountsPlaceholder": "Caminho de montagem (/mnt/nas) ou tipo de sistema de ficheiros (nfs, cifs)", + "excludedMountsEmpty": "Nenhuma montagem excluída. Todos os sistemas de ficheiros detetados são apresentados.", + "addExcludedMount": "Adicionar", + "visibleWidgets": "Widgets Visíveis", + "widgetsMovedToHostMetrics": "Os cartões são agora adicionados, organizados e redimensionados diretamente no separador Métricas do Host. Abra as Métricas do Host para este host e use Personalizar para escolher quais os cartões a mostrar.", + "quickActionsLabel": "Ações Rápidas", + "quickActionsToolbar": "As ações rápidas aparecem como botões na barra de ferramentas de Métricas do Host para execução de comandos com um clique.", + "noQuickActions": "Ainda não existem ações rápidas.", + "buttonLabel": "Texto do botão", + "selectSnippetPlaceholder": "Selecionar snippet...", + "addActionBtn": "Adicionar Ação" + }, + "onboarding": { + "feature_metrics": "Métricas e alertas", + "feature_metrics_desc": "Monitorize a utilização de CPU, memória e disco ao longo do tempo e receba alertas quando apresentam problemas." + }, + "admin": { + "metricsHistoryRetention": "Retenção do histórico de métricas", + "metricsHistoryRetentionRange": "1 a 90 dias", + "days": "dias" + }, + "homepage": { + "noData": "Sem dados disponíveis", + "showCurrentValue": "Mostrar valor atual", + "chartMetric": "Métrica", + "metricRange": "Intervalo" + } +} diff --git a/plugins/host-metrics/locales/translated/ro_RO.json b/plugins/host-metrics/locales/translated/ro_RO.json new file mode 100644 index 000000000..56f656ce6 --- /dev/null +++ b/plugins/host-metrics/locales/translated/ro_RO.json @@ -0,0 +1,313 @@ +{ + "hostMetrics": { + "cpu": "CPU", + "memory": "Memorie", + "disk": "Disc", + "network": "Reţea", + "uptime": "Timp de funcționare", + "processes": "Procese", + "available": "Disponibil", + "free": "Gratuit", + "connecting": "Se conectează...", + "connectionFailed": "Conectarea la server a eșuat", + "naCpus": "N/A CPU(uri)", + "cpuCores_one": "{{count}} Nucleu", + "cpuCores_other": "{{count}} Nuclee", + "cpuUsage": "Utilizarea procesorului", + "memoryUsage": "Utilizarea memoriei", + "diskUsage": "Utilizarea discului", + "selectFilesystem": "Selectați sistemul de fișiere", + "temperature": "Temperatură", + "highestTemperature": "Cea mai ridicată temperatură", + "primaryTemperatureSensor": "Senzor principal", + "gpu": { + "title": "GPU", + "noDevice": "Nu a fost detectată nicio placă grafică NVIDIA. Instalați driverul NVIDIA (acesta oferă nvidia-smi) pentru a vedea valorile GPU.", + "driver": "Șofer {{version}}", + "utilization": "Utilizare", + "memory": "VRAM", + "temperature": "Temperatura", + "power": "Putere", + "fan": "Ventilator", + "processes": "Procese GPU", + "noProcesses": "Niciun proces nu folosește GPU-ul" + }, + "failedToFetchHostConfig": "Nu s-a putut prelua configurația gazdei", + "serverOffline": "Serverul este offline", + "cannotFetchMetrics": "Nu se pot prelua valori de pe serverul offline", + "totpFailed": "Verificarea TOTP a eșuat", + "noneAuthNotSupported": "Metricile gazdei nu acceptă tipul de autentificare „none”.", + "noHostSelected": "Nicio gazdă selectată", + "load": "Încărca", + "systemInfo": "Informații despre sistem", + "hostname": "Nume gazdă", + "operatingSystem": "Sistem de operare", + "kernel": "Nucleu", + "seconds": "secunde", + "networkInterfaces": "Interfețe de rețea", + "noInterfacesFound": "Nu s-au găsit interfețe de rețea", + "noProcessesFound": "Nu s-au găsit procese", + "processesTotal": "total", + "processesRunning": "funcţionare", + "loginStats": "Statistici de conectare SSH", + "noRecentLoginData": "Nu există date de conectare recente", + "executingQuickAction": "Se execută {{name}}...", + "quickActionSuccess": "{{name}} finalizat cu succes", + "quickActionFailed": "{{name}} a eșuat", + "quickActionError": "Executarea {{name}} a eșuat", + "ports": { + "title": "Porturi de ascultare", + "protocol": "Protocol", + "port": "Port", + "address": "Adresa", + "process": "Proces", + "search": "Căutați porturi...", + "allProtocols": "Toate", + "noData": "Nu există date despre porturile de ascultare" + }, + "firewall": { + "title": "Firewall", + "inactive": "Inactiv", + "policy": "Politică", + "rules": "reguli", + "noRules": "Nicio regulă în acest lanț", + "noData": "Nu sunt disponibile date despre firewall", + "action": "Acţiune", + "protocol": "Proto", + "port": "Port", + "source": "Sursă", + "anywhere": "Oriunde", + "chains": "lanţuri" + }, + "loadAvg": "Încărcare medie", + "swap": "Schimb", + "architecture": "Arhitectură", + "refresh": "Reîmprospăta", + "retry": "Reîncercați", + "customize": "Personalizați aspectul", + "reset": "Resetare", + "tabLive": "Trăi", + "editModeInstructions": "Trageți cărțile pentru a le rearanja, trageți marginea de jos pentru a o redimensiona și folosiți butonul de lățime pentru a modifica întinderea unei cărți. Adăugați sau eliminați cărți mai jos.", + "managers": { + "services": "Servicii", + "processInspector": "Inspector de procese", + "logViewer": "Vizualizator de jurnal", + "cron": "Lucrări cron", + "packages": "Pachete", + "ssl": "Certificate SSL", + "firewall": "Firewall", + "users": "Utilizatori și permisiuni", + "healthCheck": "Verificări medicale", + "diskBreakdown": "Defalcarea discului", + "systemdTimers": "Cronometre", + "topMemory": "Top după memorie", + "noData": "Fără date", + "sudoHint": "Setați o parolă sudo pentru această gazdă în editorul de gazde pentru a activa acțiuni privilegiate.", + "filter": "Filtra...", + "start": "Început", + "stop": "Stop", + "restart": "Repornire", + "actionDone": "{{name}} actualizat", + "actionFailed": "Acțiunea a eșuat", + "signalSent": "Semnal trimis către PID {{pid}}", + "killHint": "Clic: terminare (SIGTERM). Clic dreapta: închidere forțată (SIGKILL).", + "working": "Lucru...", + "update": "Actualizare", + "upgradeAll": "Actualizați toate", + "allUpToDate": "Totul este la zi", + "save": "Salva", + "command": "Comanda", + "enabled": "Activat", + "cronSaved": "Crontab actualizat", + "clients": "Clienți", + "dryRun": "Sesizare de uzură", + "renew": "Reînnoi", + "noAcmeClient": "Nu a fost găsit niciun client ACME (certbot sau acme.sh) pe această gazdă.", + "addInputRule": "Adăugați regula INPUT", + "firewallWarning": "Modificările sunt disponibile doar în timpul execuției până când sunt persistente. Aveți grijă să nu vă blocați accesul.", + "ruleApplied": "Regula aplicată", + "invalidPort": "Introduceți un port valid (1-65535)", + "newUsername": "Nume de utilizator nou", + "addUser": "Adăuga", + "deleteUser": "Șterge utilizatorul", + "noHealthChecks": "Nu au fost configurate încă verificări de stare.", + "follow": "Urmărește", + "noLogData": "Nicio ieșire de jurnal.", + "tree": "Copac", + "enableDisable": "Activare / dezactivare la pornire", + "grantSudo": "Acordă sudo", + "revokeSudo": "Revocați comanda sudo", + "sslIssueCert": "Emite certificat", + "sslExpired": "Expirat", + "sslInDays": "în {{days}}d", + "sslNeedDomain": "Introduceți cel puțin un domeniu", + "sslIssued": "Certificat emis", + "sslDomainsPlaceholder": "exemplu.com, www.exemplu.com", + "sslHttpStandalone": "HTTP (independent)", + "sslHttpWebroot": "HTTP (webroot)", + "sslDns": "DNS", + "sslDnsProvider": "Furnizor DNS (de exemplu, Cloudflare)", + "sslIssueHint": "Acreditările furnizorului DNS trebuie să fie deja configurate pe gazdă.", + "sslRevoke": "Revocați certificatul", + "sslRevoked": "Certificat revocat", + "sslRevokeConfirm": "Revocați și eliminați certificatul „{{name}}”? Această acțiune nu poate fi anulată.", + "healthRun": "Aleargă", + "healthName": "Nume", + "healthTarget": "Gazdă / adresă", + "healthAddCheck": "Adăugați cec", + "healthSaved": "Verificările de sănătate salvate", + "healthMissingFields": "Fiecare verificare necesită un nume și o țintă", + "logFile": "Fişier", + "logUnit": "Unitate", + "logCustomPath": "Cale personalizată sub /var/log (opțional)", + "logGrep": "Linii de filtrare...", + "firewallPersist": "Reguli persistente", + "firewallPersisted": "Regulile firewall-ului au persistat", + "wireguard": "WireGuard", + "tailscale": "Scară de coadă", + "wgNotInstalled": "WireGuard nu este instalat pe această gazdă", + "wgNoInterfaces": "Nicio interfață WireGuard configurată", + "wgInterfaceUp": "A menționa", + "wgInterfaceDown": "Doborâți", + "wgBringingUp": "Se afișează {{name}}...", + "wgBringingDown": "Se coboară {{name}}...", + "wgInterfaceUpDone": "{{name}} este activ", + "wgInterfaceDownDone": "{{name}} este nefuncțional", + "wgListenPort": "Port", + "wgPublicKey": "Cheie publică", + "wgEndpoint": "Punct final", + "wgAllowedIPs": "IP-uri permise", + "wgLastHandshake": "Ultima strângere de mână", + "wgHandshakeNever": "Nu", + "wgTransfer": "Transfer", + "tsNotInstalled": "Tailscale nu este instalat pe această gazdă", + "tsRunning": "Funcţionare", + "tsStopped": "Oprit", + "tsEnable": "Conectează-te", + "tsDisable": "Deconecta", + "tsEnabling": "Conectare la Tailscale...", + "tsDisabling": "Deconectare de la Tailscale...", + "tsEnabled": "Scală de coadă conectată", + "tsDisabled": "Scală detașată", + "tsIPs": "IP-uri la scară mică", + "tsPeers": "Colegi", + "tsOnline": "Online", + "tsOffline": "Offline", + "tsExitNode": "Nod de ieșire", + "tsExitNodeActive": "Nod de ieșire activ", + "tsHostname": "Nume gazdă" + } + }, + "metricsHistory": { + "title": "Istoricul metricilor", + "historySuffix": "Istorie", + "cpuMemoryDisk": "CPU / Memorie / Disc", + "network": "Reţea", + "download": "RX", + "upload": "TX", + "noData": "Nu sunt disponibile date istorice pentru acest interval de timp.", + "custom": "Personalizat", + "to": "la", + "apply": "Aplică", + "viewHistory": "Vizualizați istoricul" + }, + "proxmoxStats": { + "tabTitle": "Statistici Proxmox", + "cpuUsage": "Utilizarea procesorului", + "memoryUsage": "Utilizarea memoriei", + "diskUsage": "Utilizarea discului", + "networkInterfaces": "Interfețe de rețea", + "uptime": "Timp de funcționare", + "systemInfo": "Informații despre sistem", + "guestsSummary": "Oaspeți", + "storagePools": "Bazine de stocare", + "clusterHealth": "Sănătatea clusterului", + "cpuCores_one": "{{count}} Nucleu", + "cpuCores_other": "{{count}} Nuclee", + "used": "Folosit", + "total": "Total", + "hostname": "Nume gazdă", + "kernel": "Nucleu", + "pveVersion": "Versiunea PVE", + "name": "Nume", + "status": "Stare", + "type": "Tip", + "cpu": "CPU", + "mem": "Mem", + "disk": "Disc", + "running": "Funcţionare", + "stopped": "Oprit", + "guestCounts": "{{running}}/{{total}} rulează", + "inactive": "Inactiv", + "notClustered": "Nod independent (nu face parte dintr-un cluster)", + "quorate": "Cvoat", + "notQuorate": "Fără cvorum", + "nodeOnline": "Online", + "nodeOffline": "Offline", + "noHostSelected": "Nicio gazdă selectată", + "pveshNotFound": "pvesh nu a fost găsit - este acesta un nod Proxmox?", + "nodeDetectionFailed": "Nu se poate determina un nume de nod Proxmox valid", + "connecting": "Se conectează...", + "connectionFailed": "Conectarea la nodul Proxmox nu a reușit.", + "refresh": "Reîmprospăta", + "searchGuests": "Caută invitați...", + "filterAll": "Toate", + "filterVm": "Mașină virtuală", + "filterLxc": "LXC", + "noGuests": "Nu s-au găsit mașini virtuale sau containere LXC pe acest nod.", + "noGuestsMatch": "Niciun invitat nu corespunde filtrelor actuale." + }, + "nav": { + "hostMetrics": "Metrici ale gazdei" + }, + "hosts": { + "tabHostMetrics": "Metrici ale gazdei", + "enableProxmoxStats": "Activează statisticile Proxmox", + "enableProxmoxStatsDesc": "Afișează o filă Statistici Proxmox pentru această gazdă cu statistici live despre noduri, invitați, stocare și cluster, colectate prin SSH.", + "proxmoxStatsPollInterval": "Interval de sondaj (secunde)", + "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ă", + "metricsCollectionLabel": "Colecție de metrici", + "enableMetricsLabel": "Activați metricile", + "enableMetricsDesc": "Colectați valori pentru CPU, RAM, disc și alte valori de la această gazdă", + "useGlobalMetrics": "Utilizați intervalul global", + "useGlobalMetricsDesc": "Suprascriere cu intervalul de metrici la nivel de server", + "metricsIntervalS": "Interval (s) de metrică", + "metricsIntervalDesc2": "Secunde între instantaneele metricelor", + "excludedMountsLabel": "Monturi excluse", + "monitoredMountsLabel": "Căi monitorizate personalizate", + "monitoredMountsDesc": "Adăugați căi care nu sunt expuse ca monturi separate, inclusiv căi Home Assistant montate prin bind, cum ar fi /config.", + "monitoredMountPathPlaceholder": "Cale (/config, /mnt/data)", + "monitoredMountLabelPlaceholder": "Etichetă (opțional)", + "addMonitoredMount": "Adăugați o cale", + "excludedMountsDesc": "Ascunde anumite puncte de montare sau tipuri de sisteme de fișiere (de exemplu, nfs, cifs) de utilizarea discului și de alertele pentru această gazdă.", + "excludedMountsPlaceholder": "Calea de montare (/mnt/nas) sau tipul sistemului de fișiere (nfs, cifs)", + "excludedMountsEmpty": "Nicio montare exclusă. Sunt afișate toate sistemele de fișiere detectate.", + "addExcludedMount": "Adăuga", + "visibleWidgets": "Widgeturi vizibile", + "widgetsMovedToHostMetrics": "Cardurile sunt acum adăugate, aranjate și redimensionate direct în fila Indicatori gazdă. Deschideți Indicatori gazdă pentru această gazdă și utilizați Personalizare pentru a alege ce carduri sunt afișate.", + "quickActionsLabel": "Acțiuni rapide", + "quickActionsToolbar": "Acțiunile rapide apar sub formă de butoane în bara de instrumente Host Metrics pentru executarea comenzilor cu un singur clic.", + "noQuickActions": "Nicio acțiune rapidă încă.", + "buttonLabel": "Etichetă buton", + "selectSnippetPlaceholder": "Selectați fragmentul...", + "addActionBtn": "Adăugați o acțiune" + }, + "onboarding": { + "feature_metrics": "Metrici și alerte", + "feature_metrics_desc": "Urmărește procesorul, memoria și discul în timp și primește alerte când acestea se defectează." + }, + "admin": { + "metricsHistoryRetention": "Păstrarea istoricului metricilor", + "metricsHistoryRetentionRange": "1 până la 90 de zile", + "days": "zile" + }, + "homepage": { + "noData": "Nu sunt disponibile date", + "showCurrentValue": "Afișează valoarea curentă", + "chartMetric": "Metric", + "metricRange": "Gamă" + } +} diff --git a/plugins/host-metrics/locales/translated/ru_RU.json b/plugins/host-metrics/locales/translated/ru_RU.json new file mode 100644 index 000000000..aa3ac157a --- /dev/null +++ b/plugins/host-metrics/locales/translated/ru_RU.json @@ -0,0 +1,313 @@ +{ + "hostMetrics": { + "cpu": "ЦП", + "memory": "Память", + "disk": "Диск", + "network": "Сеть", + "uptime": "Время работы", + "processes": "Процессы", + "available": "Доступно", + "free": "Свободно", + "connecting": "Подключение...", + "connectionFailed": "Не удалось подключиться к серверу", + "naCpus": "Н/Д ЦП", + "cpuCores_one": "{{count}} ядро", + "cpuCores_other": "{{count}} ядер", + "cpuUsage": "Использование ЦП", + "memoryUsage": "Использование памяти", + "diskUsage": "Использование диска", + "selectFilesystem": "Выберите файловую систему", + "temperature": "Температура", + "highestTemperature": "Максимальная температура", + "primaryTemperatureSensor": "Основной датчик", + "gpu": { + "title": "GPU", + "noDevice": "Графический процессор NVIDIA не обнаружен. Установите драйвер NVIDIA (он включает nvidia-smi), чтобы увидеть показатели графического процессора.", + "driver": "Водитель {{version}}", + "utilization": "Использование", + "memory": "ВПМ", + "temperature": "Температура", + "power": "Власть", + "fan": "Вентилятор", + "processes": "процессы графического процессора", + "noProcesses": "Никакие процессы не используют графический процессор." + }, + "failedToFetchHostConfig": "Не удалось получить конфигурацию хоста", + "serverOffline": "Сервер недоступен", + "cannotFetchMetrics": "Не удалось загрузить метрики с недоступного сервера", + "totpFailed": "Проверка TOTP не пройдена", + "noneAuthNotSupported": "Host Metrics не поддерживает тип аутентификации 'none'.", + "noHostSelected": "Хост не выбран", + "load": "Нагрузка", + "systemInfo": "Информация о системе", + "hostname": "Имя хоста", + "operatingSystem": "Операционная система", + "kernel": "Ядро", + "seconds": "секунды", + "networkInterfaces": "Сетевые интерфейсы", + "noInterfacesFound": "Сетевые интерфейсы не найдены", + "noProcessesFound": "Процессы не найдены", + "processesTotal": "всего", + "processesRunning": "выполняется", + "loginStats": "Статистика входов SSH", + "noRecentLoginData": "Нет данных о недавних входах", + "executingQuickAction": "Выполняется {{name}}...", + "quickActionSuccess": "{{name}} успешно завершено", + "quickActionFailed": "{{name}} не удалось", + "quickActionError": "Не удалось выполнить {{name}}", + "ports": { + "title": "Прослушиваемые порты", + "protocol": "Протокол", + "port": "Порт", + "address": "Адрес", + "process": "Процесс", + "search": "Поиск портов...", + "allProtocols": "Все", + "noData": "Нет данных о прослушиваемых портах" + }, + "firewall": { + "title": "Брандмауэр", + "inactive": "Неактивен", + "policy": "Политика", + "rules": "правила", + "noRules": "Нет правил в этой цепочке", + "noData": "Нет данных о брандмауэре", + "action": "Действие", + "protocol": "Протокол", + "port": "Порт", + "source": "Источник", + "anywhere": "Любое", + "chains": "цепочки" + }, + "loadAvg": "Средняя нагрузка", + "swap": "Своп", + "architecture": "Архитектура", + "refresh": "Обновить", + "retry": "Повторить", + "customize": "Настроить макет", + "reset": "Сбросить", + "tabLive": "Онлайн", + "editModeInstructions": "Перетаскивайте карточки для изменения порядка, перетаскивайте нижний край для изменения размера и используйте кнопку ширины, чтобы изменить занимаемое пространство. Добавляйте или удаляйте карточки ниже.", + "managers": { + "services": "Службы", + "processInspector": "Инспектор процессов", + "logViewer": "Просмотр журналов", + "cron": "Задания Cron", + "packages": "Пакеты", + "ssl": "SSL-сертификаты", + "firewall": "Брандмауэр", + "users": "Пользователи и разрешения", + "healthCheck": "Проверки состояния", + "diskBreakdown": "Разбивка дисков", + "systemdTimers": "Таймеры", + "topMemory": "Топ по памяти", + "noData": "Нет данных", + "sudoHint": "Установите пароль sudo для этого хоста в редакторе хостов, чтобы включить привилегированные действия.", + "filter": "Фильтр...", + "start": "Запустить", + "stop": "Остановить", + "restart": "Перезапустить", + "actionDone": "{{name}} обновлено", + "actionFailed": "Действие не удалось", + "signalSent": "Сигнал отправлен PID {{pid}}", + "killHint": "Нажмите: завершить (SIGTERM). Правый клик: принудительно завершить (SIGKILL).", + "working": "Выполняется...", + "update": "Обновить", + "upgradeAll": "Обновить всё", + "allUpToDate": "Всё актуально", + "save": "Сохранить", + "command": "Команда", + "enabled": "Включено", + "cronSaved": "Crontab обновлён", + "clients": "Клиенты", + "dryRun": "Пробный запуск", + "renew": "Продлить", + "noAcmeClient": "На этом хосте не найден ACME-клиент (certbot или acme.sh).", + "addInputRule": "Добавить правило INPUT", + "firewallWarning": "Изменения действуют только до перезагрузки, пока не сохранены. Будьте осторожны, чтобы не заблокировать себе доступ.", + "ruleApplied": "Правило применено", + "invalidPort": "Введите допустимый порт (1–65535)", + "newUsername": "Новое имя пользователя", + "addUser": "Добавить", + "deleteUser": "Удалить пользователя", + "noHealthChecks": "Проверки работоспособности ещё не настроены.", + "follow": "Следить", + "noLogData": "Нет данных журнала.", + "tree": "Дерево", + "enableDisable": "Включить/отключить при загрузке", + "grantSudo": "Предоставить sudo", + "revokeSudo": "Отозвать sudo", + "sslIssueCert": "Выпустить сертификат", + "sslExpired": "Истёк", + "sslInDays": "через {{days}}д", + "sslNeedDomain": "Введите хотя бы один домен", + "sslIssued": "Сертификат выпущен", + "sslDomainsPlaceholder": "example.com, www.example.com", + "sslHttpStandalone": "HTTP (автономный)", + "sslHttpWebroot": "HTTP (webroot)", + "sslDns": "DNS", + "sslDnsProvider": "DNS-провайдер (например, cloudflare)", + "sslIssueHint": "Учетные данные DNS-провайдера должны быть уже настроены на хосте.", + "sslRevoke": "Отозвать сертификат", + "sslRevoked": "Сертификат отозван", + "sslRevokeConfirm": "Отозвать и удалить сертификат \"{{name}}\"? Это действие нельзя отменить.", + "healthRun": "Запустить", + "healthName": "Название", + "healthTarget": "Хост / адрес", + "healthAddCheck": "Добавить проверку", + "healthSaved": "Проверки работоспособности сохранены", + "healthMissingFields": "Для каждой проверки нужны название и цель", + "logFile": "Файл", + "logUnit": "Юнит", + "logCustomPath": "Произвольный путь в /var/log (необязательно)", + "logGrep": "Фильтр строк...", + "firewallPersist": "Сохранить правила", + "firewallPersisted": "Правила брандмауэра сохранены", + "wireguard": "WireGuard", + "tailscale": "Tailscale", + "wgNotInstalled": "WireGuard не установлен на этом хосте", + "wgNoInterfaces": "Не настроено ни одного интерфейса WireGuard", + "wgInterfaceUp": "Поднять", + "wgInterfaceDown": "Отключить", + "wgBringingUp": "Поднимается {{name}}...", + "wgBringingDown": "Отключается {{name}}...", + "wgInterfaceUpDone": "{{name}} поднят", + "wgInterfaceDownDone": "{{name}} отключен", + "wgListenPort": "Порт", + "wgPublicKey": "Открытый ключ", + "wgEndpoint": "Конечная точка", + "wgAllowedIPs": "Разрешенные IP-адреса", + "wgLastHandshake": "Последнее рукопожатие", + "wgHandshakeNever": "Никогда", + "wgTransfer": "Передано", + "tsNotInstalled": "Tailscale не установлен на этом хосте", + "tsRunning": "Запущен", + "tsStopped": "Остановлен", + "tsEnable": "Подключить", + "tsDisable": "Отключить", + "tsEnabling": "Подключение к Tailscale...", + "tsDisabling": "Отключение от Tailscale...", + "tsEnabled": "Tailscale подключён", + "tsDisabled": "Tailscale отключён", + "tsIPs": "IP-адреса Tailscale", + "tsPeers": "Пиры", + "tsOnline": "Онлайн", + "tsOffline": "Офлайн", + "tsExitNode": "Выходной узел", + "tsExitNodeActive": "Выходной узел активен", + "tsHostname": "Имя хоста" + } + }, + "metricsHistory": { + "title": "История метрик", + "historySuffix": "История", + "cpuMemoryDisk": "ЦП / Память / Диск", + "network": "Сеть", + "download": "RX", + "upload": "TX", + "noData": "Нет исторических данных за этот период.", + "custom": "Пользовательский", + "to": "по", + "apply": "Применить", + "viewHistory": "Просмотреть историю" + }, + "proxmoxStats": { + "tabTitle": "Статистика Proxmox", + "cpuUsage": "Использование ЦП", + "memoryUsage": "Использование памяти", + "diskUsage": "Использование диска", + "networkInterfaces": "Сетевые интерфейсы", + "uptime": "Время безотказной работы", + "systemInfo": "Информация о системе", + "guestsSummary": "Гости", + "storagePools": "Бассейны для хранения", + "clusterHealth": "Здоровье кластера", + "cpuCores_one": "{{count}} Ядро", + "cpuCores_other": "{{count}} Ядра", + "used": "Использовал", + "total": "Общий", + "hostname": "Имя хоста", + "kernel": "Ядро", + "pveVersion": "Версия для PVE", + "name": "Имя", + "status": "Статус", + "type": "Тип", + "cpu": "Процессор", + "mem": "Мем", + "disk": "Диск", + "running": "Бег", + "stopped": "Остановлено", + "guestCounts": "{{running}}/{{total}} бежит", + "inactive": "Неактивный", + "notClustered": "Автономный узел (не входящий в кластер)", + "quorate": "Цитата", + "notQuorate": "Кворум не соблюден", + "nodeOnline": "Онлайн", + "nodeOffline": "Офлайн", + "noHostSelected": "Хост не выбран", + "pveshNotFound": "pvesh не найден — это узел Proxmox?", + "nodeDetectionFailed": "Не удалось определить допустимое имя узла Proxmox.", + "connecting": "Подключение...", + "connectionFailed": "Не удалось подключиться к узлу Proxmox.", + "refresh": "Обновить", + "searchGuests": "Поиск гостей...", + "filterAll": "Все", + "filterVm": "VM", + "filterLxc": "ЛХС", + "noGuests": "На этом узле не обнаружено виртуальных машин или контейнеров LXC.", + "noGuestsMatch": "Ни один из гостей не соответствует текущим фильтрам." + }, + "nav": { + "hostMetrics": "Метрики хоста" + }, + "hosts": { + "tabHostMetrics": "Метрики хоста", + "enableProxmoxStats": "Включить статистику Proxmox", + "enableProxmoxStatsDesc": "Отобразить вкладку Proxmox Stats для этого хоста с актуальными статистическими данными по узлам, гостевым системам, хранилищу и кластеру, собранными по SSH.", + "proxmoxStatsPollInterval": "Интервал опроса (секунды)", + "proxmoxStatsPollIntervalDesc": "Минимум 15 секунд. Как часто обновлять статистику узлов Proxmox.", + "proxmoxStatsNodeOverride": "Переопределение имени узла", + "proxmoxStatsNodeOverrideDesc": "Отключить автоматическое определение имени узла Proxmox (по умолчанию определяется по имени хоста).", + "proxmoxStatsNodeOverridePlaceholder": "Автоматически определено по имени хоста", + "metricsCollectionLabel": "Сбор метрик", + "enableMetricsLabel": "Включить метрики", + "enableMetricsDesc": "Собирать метрики ЦП, ОЗУ, диска и другие с этого хоста", + "useGlobalMetrics": "Использовать глобальный интервал", + "useGlobalMetricsDesc": "Переопределить глобальным интервалом сбора метрик сервера", + "metricsIntervalS": "Интервал сбора метрик (с)", + "metricsIntervalDesc2": "Секунд между снимками метрик", + "excludedMountsLabel": "Исключенные крепления", + "monitoredMountsLabel": "Пользовательские контролируемые пути", + "monitoredMountsDesc": "Добавьте пути, которые не отображаются как отдельные точки монтирования, включая пути Home Assistant, смонтированные с помощью bind-mount, например, /config.", + "monitoredMountPathPlaceholder": "Путь (/config, /mnt/data)", + "monitoredMountLabelPlaceholder": "Этикетка (необязательно)", + "addMonitoredMount": "Добавить путь", + "excludedMountsDesc": "Скрыть определенные точки монтирования или типы файловых систем (например, nfs, cifs) от информации об использовании диска и оповещений для этого хоста.", + "excludedMountsPlaceholder": "Путь монтирования (/mnt/nas) или тип файловой системы (nfs, cifs)", + "excludedMountsEmpty": "Исключены все точки монтирования. Отображаются все обнаруженные файловые системы.", + "addExcludedMount": "Добавлять", + "visibleWidgets": "Видимые виджеты", + "widgetsMovedToHostMetrics": "Карточки теперь добавляются, упорядочиваются и изменяются в размере непосредственно на вкладке «Метрики хоста». Откройте метрики для этого хоста и используйте «Настроить», чтобы выбрать отображаемые карточки.", + "quickActionsLabel": "Быстрые действия", + "quickActionsToolbar": "Быстрые действия отображаются в виде кнопок на панели инструментов метрик хоста для выполнения команд в один клик.", + "noQuickActions": "Пока нет быстрых действий.", + "buttonLabel": "Надпись кнопки", + "selectSnippetPlaceholder": "Выбрать сниппет...", + "addActionBtn": "Добавить действие" + }, + "onboarding": { + "feature_metrics": "Метрики и оповещения", + "feature_metrics_desc": "Отслеживайте состояние процессора, памяти и диска с течением времени и получайте оповещения при возникновении неполадок." + }, + "admin": { + "metricsHistoryRetention": "Срок хранения метрик", + "metricsHistoryRetentionRange": "от 1 до 90 дней", + "days": "дней" + }, + "homepage": { + "noData": "Нет данных", + "showCurrentValue": "Показать текущее значение", + "chartMetric": "Метрика", + "metricRange": "Диапазон" + } +} diff --git a/plugins/host-metrics/locales/translated/sr_SP.json b/plugins/host-metrics/locales/translated/sr_SP.json new file mode 100644 index 000000000..9334e8c94 --- /dev/null +++ b/plugins/host-metrics/locales/translated/sr_SP.json @@ -0,0 +1,313 @@ +{ + "hostMetrics": { + "cpu": "Процесор", + "memory": "Памћење", + "disk": "Диск", + "network": "Мрежа", + "uptime": "Време непрекидног рада", + "processes": "Процеси", + "available": "Доступно", + "free": "Бесплатно", + "connecting": "Повезивање...", + "connectionFailed": "Повезивање са сервером није успело", + "naCpus": "Н/Д процесор(и)", + "cpuCores_one": "{{count}} Језгро", + "cpuCores_other": "{{count}} Језгра", + "cpuUsage": "Искоришћеност процесора", + "memoryUsage": "Коришћење меморије", + "diskUsage": "Искоришћеност диска", + "selectFilesystem": "Изаберите фајл систем", + "temperature": "Температура", + "highestTemperature": "Највиша температура", + "primaryTemperatureSensor": "Примарни сензор", + "gpu": { + "title": "ГПУ", + "noDevice": "Није детектована NVIDIA GPU. Инсталирајте NVIDIA драјвер (пружа nvidia-smi) да бисте видели метрике GPU-а.", + "driver": "Возач {{version}}", + "utilization": "Коришћење", + "memory": "Видео меморија", + "temperature": "Температура", + "power": "Моћ", + "fan": "Вентилатор", + "processes": "Процеси графичког процесора (GPU)", + "noProcesses": "Ниједан процес не користи ГПУ" + }, + "failedToFetchHostConfig": "Није успело преузимање конфигурације хоста", + "serverOffline": "Сервер ван мреже", + "cannotFetchMetrics": "Није могуће преузети метрике са офлајн сервера", + "totpFailed": "Верификација TOTP-а није успела", + "noneAuthNotSupported": "Метрике хоста не подржавају тип аутентификације „ниједан“.", + "noHostSelected": "Није изабран домаћин", + "load": "Учитај", + "systemInfo": "Системске информације", + "hostname": "Име хоста", + "operatingSystem": "Оперативни систем", + "kernel": "Језгро", + "seconds": "секунде", + "networkInterfaces": "Мрежни интерфејси", + "noInterfacesFound": "Није пронађен ниједан мрежни интерфејс", + "noProcessesFound": "Није пронађен ниједан процес", + "processesTotal": "укупно", + "processesRunning": "трчање", + "loginStats": "Статистика SSH пријава", + "noRecentLoginData": "Нема скорашњих података за пријављивање", + "executingQuickAction": "Извршава се {{name}}...", + "quickActionSuccess": "{{name}} успешно завршено", + "quickActionFailed": "{{name}} није успело", + "quickActionError": "Није успело извршавање {{name}}", + "ports": { + "title": "Портови за слушање", + "protocol": "Протокол", + "port": "Лука", + "address": "Адреса", + "process": "Процес", + "search": "Претражи портове...", + "allProtocols": "Сви", + "noData": "Нема података о портовима за слушање" + }, + "firewall": { + "title": "Заштитни зид (фајервол)", + "inactive": "Неактивно", + "policy": "Политика", + "rules": "правила", + "noRules": "Нема правила у овом ланцу", + "noData": "Нема доступних података о заштитном зиду", + "action": "Акција", + "protocol": "Прото", + "port": "Лука", + "source": "Извор", + "anywhere": "Било где", + "chains": "ланци" + }, + "loadAvg": "Учитај просек", + "swap": "Замена", + "architecture": "Архитектура", + "refresh": "Освежи", + "retry": "Покушај поново", + "customize": "Прилагоди распоред", + "reset": "Ресетуј", + "tabLive": "Уживо", + "editModeInstructions": "Превуците картице да бисте преуредили, превуците доњу ивицу да бисте променили величину и користите дугме за ширину да бисте променили распон картице. Додајте или уклоните картице испод.", + "managers": { + "services": "Услуге", + "processInspector": "Инспектор процеса", + "logViewer": "Прегледач дневника", + "cron": "Cron послови", + "packages": "Пакети", + "ssl": "SSL сертификати", + "firewall": "Заштитни зид (фајервол)", + "users": "Корисници и дозволе", + "healthCheck": "Здравствени прегледи", + "diskBreakdown": "Распад диска", + "systemdTimers": "Тајмери", + "topMemory": "Најбоље по сећању", + "noData": "Нема података", + "sudoHint": "Поставите sudo лозинку за овај хост у уређивачу хостова да бисте омогућили привилеговане акције.", + "filter": "Филтер...", + "start": "Почетак", + "stop": "Заустави", + "restart": "Поново покрени", + "actionDone": "{{name}} ажурирано", + "actionFailed": "Акција није успела", + "signalSent": "Сигнал послат на ПИД {{pid}}", + "killHint": "Кликните: прекините (SIGTERM). Кликните десним тастером миша: присилно зауставите (SIGKILL).", + "working": "Ради се...", + "update": "Ажурирање", + "upgradeAll": "Надогради све", + "allUpToDate": "Све је ажурирано", + "save": "Сачувај", + "command": "Команда", + "enabled": "Омогућено", + "cronSaved": "Кронтаб је ажуриран", + "clients": "Клијенти", + "dryRun": "Пробни рад", + "renew": "Обнови", + "noAcmeClient": "Није пронађен ACME клијент (certbot или acme.sh) на овом хосту.", + "addInputRule": "Додај INPUT правило", + "firewallWarning": "Промене су само за време извршавања док се не сачувају. Пазите да се не закључате.", + "ruleApplied": "Правило је примењено", + "invalidPort": "Унесите важећи порт (1-65535)", + "newUsername": "Ново корисничко име", + "addUser": "Додај", + "deleteUser": "Обриши корисника", + "noHealthChecks": "Још увек нису конфигурисане провере исправности.", + "follow": "Прати", + "noLogData": "Нема излаза лог-а.", + "tree": "Дрво", + "enableDisable": "Омогући/онемогући при покретању", + "grantSudo": "Додели судо", + "revokeSudo": "Поништи sudo", + "sslIssueCert": "Издај сертификат", + "sslExpired": "Истекло", + "sslInDays": "у {{days}}д", + "sslNeedDomain": "Унесите барем један домен", + "sslIssued": "Издат сертификат", + "sslDomainsPlaceholder": "example.com, www.example.com", + "sslHttpStandalone": "HTTP (самостални)", + "sslHttpWebroot": "HTTP (вебрут)", + "sslDns": "ДНС", + "sslDnsProvider": "DNS провајдер (нпр. cloudflare)", + "sslIssueHint": "Акредитиви DNS провајдера морају већ бити конфигурисани на хосту.", + "sslRevoke": "Поништи сертификат", + "sslRevoked": "Сертификат опозван", + "sslRevokeConfirm": "Поништити и уклонити сертификат „{{name}}“? Ово се не може поништити.", + "healthRun": "Трчи", + "healthName": "Име", + "healthTarget": "Домаћин / адреса", + "healthAddCheck": "Додај чек", + "healthSaved": "Провере здравственог стања сачуване", + "healthMissingFields": "Свака провера захтева име и циљ", + "logFile": "Датотека", + "logUnit": "Јединица", + "logCustomPath": "Прилагођена путања у /var/log (опционо)", + "logGrep": "Филтерске линије...", + "firewallPersist": "Правила трајања", + "firewallPersisted": "Правила заштитног зида су опстала", + "wireguard": "ВајерГард", + "tailscale": "Репна скала", + "wgNotInstalled": "WireGuard није инсталиран на овом хосту", + "wgNoInterfaces": "Није конфигурисан ниједан WireGuard интерфејс", + "wgInterfaceUp": "Поведи", + "wgInterfaceDown": "Срушити", + "wgBringingUp": "Доводи се {{name}} горе...", + "wgBringingDown": "Спуштање {{name}}...", + "wgInterfaceUpDone": "{{name}} је горе", + "wgInterfaceDownDone": "{{name}} је неактиван", + "wgListenPort": "Лука", + "wgPublicKey": "Јавни кључ", + "wgEndpoint": "Крајња тачка", + "wgAllowedIPs": "Дозвољене IP адресе", + "wgLastHandshake": "Последње руковање", + "wgHandshakeNever": "Никад", + "wgTransfer": "Пренос", + "tsNotInstalled": "Tailscale није инсталиран на овом хосту", + "tsRunning": "Трчање", + "tsStopped": "Заустављено", + "tsEnable": "Повежи се", + "tsDisable": "Прекини везу", + "tsEnabling": "Повезивање са Tailscale-ом...", + "tsDisabling": "Искључивање из мреже Tailscale...", + "tsEnabled": "Повезана је задња скала", + "tsDisabled": "Реалскала је искључена", + "tsIPs": "ИП адресе Tailscale-а", + "tsPeers": "Вршњаци", + "tsOnline": "Онлајн", + "tsOffline": "Офлајн", + "tsExitNode": "Излазни чвор", + "tsExitNodeActive": "Излазни чвор је активан", + "tsHostname": "Име хоста" + } + }, + "metricsHistory": { + "title": "Историја метрика", + "historySuffix": "Историја", + "cpuMemoryDisk": "Процесор / Меморија / Диск", + "network": "Мрежа", + "download": "Рецепт", + "upload": "Тексас", + "noData": "Нема доступних историјских података за овај временски опсег.", + "custom": "Прилагођено", + "to": "до", + "apply": "Примени", + "viewHistory": "Прикажи историју" + }, + "proxmoxStats": { + "tabTitle": "Proxmox статистика", + "cpuUsage": "Искоришћеност процесора", + "memoryUsage": "Коришћење меморије", + "diskUsage": "Искоришћеност диска", + "networkInterfaces": "Мрежни интерфејси", + "uptime": "Време непрекидног рада", + "systemInfo": "Системске информације", + "guestsSummary": "Гости", + "storagePools": "Складишни базени", + "clusterHealth": "Здравље кластера", + "cpuCores_one": "{{count}} Језгро", + "cpuCores_other": "{{count}} Језгра", + "used": "Коришћено", + "total": "Укупно", + "hostname": "Име хоста", + "kernel": "Језгро", + "pveVersion": "ПВЕ верзија", + "name": "Име", + "status": "Статус", + "type": "Тип", + "cpu": "Процесор", + "mem": "Мем", + "disk": "Диск", + "running": "Трчање", + "stopped": "Заустављено", + "guestCounts": "{{running}}/{{total}} трчи", + "inactive": "Неактивно", + "notClustered": "Самостални чвор (није део кластера)", + "quorate": "Кворат", + "notQuorate": "Није кворум", + "nodeOnline": "Онлајн", + "nodeOffline": "Офлајн", + "noHostSelected": "Није изабран домаћин", + "pveshNotFound": "pvesh није пронађен - да ли је ово Proxmox чвор?", + "nodeDetectionFailed": "Није могуће утврдити важеће име Proxmox чвора", + "connecting": "Повезивање...", + "connectionFailed": "Повезивање са Proxmox чвором није успело", + "refresh": "Освежи", + "searchGuests": "Претражи госте...", + "filterAll": "Сви", + "filterVm": "Виртуелна машина", + "filterLxc": "LXC", + "noGuests": "На овом чвору нису пронађене виртуелне машине или LXC контејнери.", + "noGuestsMatch": "Ниједан гост не одговара тренутним филтерима." + }, + "nav": { + "hostMetrics": "Метрике хоста" + }, + "hosts": { + "tabHostMetrics": "Метрике хоста", + "enableProxmoxStats": "Омогући Proxmox статистику", + "enableProxmoxStatsDesc": "Прикажи картицу Proxmox Stats за овај хост са статистикама уживо чвора, госта, складишта и кластера прикупљеним преко SSH-а.", + "proxmoxStatsPollInterval": "Интервал анкете (секунде)", + "proxmoxStatsPollIntervalDesc": "Минимум 15 секунди. Колико често освежавати статистику Proxmox чвора.", + "proxmoxStatsNodeOverride": "Замена имена чвора", + "proxmoxStatsNodeOverrideDesc": "Поништи аутоматско откривање имена Proxmox чвора (подразумевано се открива преко имена хоста).", + "proxmoxStatsNodeOverridePlaceholder": "Аутоматски детектовано на основу имена хоста", + "metricsCollectionLabel": "Колекција метрика", + "enableMetricsLabel": "Омогући метрике", + "enableMetricsDesc": "Прикупљајте метрику процесора, RAM-а, диска и друге показатеље са овог хоста", + "useGlobalMetrics": "Користи глобални интервал", + "useGlobalMetricsDesc": "Замени интервалом метрика на нивоу сервера", + "metricsIntervalS": "Интервал(и) метрика", + "metricsIntervalDesc2": "Секунде између снимака метрика", + "excludedMountsLabel": "Искључени носачи", + "monitoredMountsLabel": "Прилагођене праћене путање", + "monitoredMountsDesc": "Додајте путање које нису изложене као засебне монтиране верзије, укључујући путање за Home Assistant монтиране помоћу повезивања, као што је /config.", + "monitoredMountPathPlaceholder": "Путања (/config, /mnt/data)", + "monitoredMountLabelPlaceholder": "Ознака (опционо)", + "addMonitoredMount": "Додај путању", + "excludedMountsDesc": "Сакријте одређене тачке монтирања или типове фајл система (нпр. nfs, cifs) од коришћења диска и упозорења за овај хост.", + "excludedMountsPlaceholder": "Путања монтирања (/mnt/nas) или тип фајл система (nfs, cifs)", + "excludedMountsEmpty": "Није искључено ниједно монтирање. Приказани су сви откривени фајл системи.", + "addExcludedMount": "Додај", + "visibleWidgets": "Видљиви виџети", + "widgetsMovedToHostMetrics": "Картице се сада додају, распоређују и мењају им се величина директно на картици „Host Metrics“. Отворите „Host Metrics“ за овог хоста и користите „Customize“ да бисте изабрали које ће картице бити приказане.", + "quickActionsLabel": "Брзе акције", + "quickActionsToolbar": "Брзе акције се појављују као дугмад у траци са алаткама Host Metrics за извршавање команди једним кликом.", + "noQuickActions": "Још нема брзих акција.", + "buttonLabel": "Ознака дугмета", + "selectSnippetPlaceholder": "Изаберите исечак...", + "addActionBtn": "Додај акцију" + }, + "onboarding": { + "feature_metrics": "Метрике и упозорења", + "feature_metrics_desc": "Пратите процесор, меморију и диск током времена и добијајте обавештења када дође до квара." + }, + "admin": { + "metricsHistoryRetention": "Чување историје метрика", + "metricsHistoryRetentionRange": "Од 1 до 90 дана", + "days": "дана" + }, + "homepage": { + "noData": "Нема доступних података", + "showCurrentValue": "Прикажи тренутну вредност", + "chartMetric": "Метрика", + "metricRange": "Домет" + } +} diff --git a/plugins/host-metrics/locales/translated/sv_SE.json b/plugins/host-metrics/locales/translated/sv_SE.json new file mode 100644 index 000000000..820eff233 --- /dev/null +++ b/plugins/host-metrics/locales/translated/sv_SE.json @@ -0,0 +1,313 @@ +{ + "hostMetrics": { + "cpu": "CPU", + "memory": "Minne", + "disk": "Disk", + "network": "Nätverk", + "uptime": "Drifttid", + "processes": "Processer", + "available": "Tillgänglig", + "free": "Gratis", + "connecting": "Ansluter...", + "connectionFailed": "Misslyckades med att ansluta till servern", + "naCpus": "Ej tillämpligt CPU(er)", + "cpuCores_one": "{{count}} Kärna", + "cpuCores_other": "{{count}} Kärnor", + "cpuUsage": "CPU-användning", + "memoryUsage": "Minnesanvändning", + "diskUsage": "Diskanvändning", + "selectFilesystem": "Välj filsystem", + "temperature": "Temperatur", + "highestTemperature": "Högsta temperatur", + "primaryTemperatureSensor": "Primär sensor", + "gpu": { + "title": "GPU", + "noDevice": "Ingen NVIDIA GPU hittades. Installera NVIDIA-drivrutinen (den tillhandahåller nvidia-smi) för att se GPU-statistik.", + "driver": "Förare {{version}}", + "utilization": "Utnyttjande", + "memory": "VRAM", + "temperature": "Temp", + "power": "Driva", + "fan": "Fläkt", + "processes": "GPU-processer", + "noProcesses": "Inga processer använder GPU:n" + }, + "failedToFetchHostConfig": "Misslyckades med att hämta värdkonfigurationen", + "serverOffline": "Servern är offline", + "cannotFetchMetrics": "Kan inte hämta mätvärden från offlineservern", + "totpFailed": "TOTP-verifiering misslyckades", + "noneAuthNotSupported": "Host Metrics stöder inte autentiseringstypen 'ingen'.", + "noHostSelected": "Ingen värd vald", + "load": "Ladda", + "systemInfo": "Systeminformation", + "hostname": "Värdnamn", + "operatingSystem": "Operativsystem", + "kernel": "Kärna", + "seconds": "sekunder", + "networkInterfaces": "Nätverksgränssnitt", + "noInterfacesFound": "Inga nätverksgränssnitt hittades", + "noProcessesFound": "Inga processer hittades", + "processesTotal": "total", + "processesRunning": "spring", + "loginStats": "SSH-inloggningsstatistik", + "noRecentLoginData": "Inga aktuella inloggningsuppgifter", + "executingQuickAction": "Kör {{name}}...", + "quickActionSuccess": "{{name}} slutfört", + "quickActionFailed": "{{name}} misslyckades", + "quickActionError": "Misslyckades med att köra {{name}}", + "ports": { + "title": "Lyssningsportar", + "protocol": "Protokoll", + "port": "Hamn", + "address": "Adress", + "process": "Behandla", + "search": "Sök portar...", + "allProtocols": "Alla", + "noData": "Inga lyssningsportdata" + }, + "firewall": { + "title": "Brandvägg", + "inactive": "Inaktiv", + "policy": "Politik", + "rules": "regler", + "noRules": "Inga regler i den här kedjan", + "noData": "Ingen brandväggsdata tillgänglig", + "action": "Handling", + "protocol": "Proto", + "port": "Hamn", + "source": "Källa", + "anywhere": "Någonstans", + "chains": "kedjor" + }, + "loadAvg": "Ladda genomsnitt", + "swap": "Byta", + "architecture": "Arkitektur", + "refresh": "Uppdatera", + "retry": "Försöka igen", + "customize": "Anpassa layouten", + "reset": "Återställa", + "tabLive": "Bo", + "editModeInstructions": "Dra kort för att ordna om, dra i den nedre kanten för att ändra storlek och använd breddknappen för att ändra ett korts längd. Lägg till eller ta bort kort nedan.", + "managers": { + "services": "Tjänster", + "processInspector": "Processinspektör", + "logViewer": "Loggvisare", + "cron": "Cron-jobb", + "packages": "Paket", + "ssl": "SSL-certifikat", + "firewall": "Brandvägg", + "users": "Användare och behörigheter", + "healthCheck": "Hälsokontroller", + "diskBreakdown": "Diskuppdelning", + "systemdTimers": "Timers", + "topMemory": "Topp av Memory", + "noData": "Inga uppgifter", + "sudoHint": "Ange ett sudo-lösenord för den här värden i värdredigeraren för att aktivera privilegierade åtgärder.", + "filter": "Filtrera...", + "start": "Start", + "stop": "Stopp", + "restart": "Starta om", + "actionDone": "{{name}} uppdaterad", + "actionFailed": "Åtgärden misslyckades", + "signalSent": "Signal skickad till PID {{pid}}", + "killHint": "Klicka: avsluta (SIGTERM). Högerklicka: tvinga bort (SIGKILL).", + "working": "Arbetssätt...", + "update": "Uppdatera", + "upgradeAll": "Uppgradera alla", + "allUpToDate": "Allt är uppdaterat", + "save": "Spara", + "command": "Kommando", + "enabled": "Aktiverad", + "cronSaved": "Crontab uppdaterad", + "clients": "klienter", + "dryRun": "Torrkörning", + "renew": "Förnya", + "noAcmeClient": "Ingen ACME-klient (certbot eller acme.sh) hittades på den här värden.", + "addInputRule": "Lägg till INPUT-regel", + "firewallWarning": "Ändringarna gäller endast under körning tills de sparas. Var försiktig så att du inte låser dig ute.", + "ruleApplied": "Regel tillämpad", + "invalidPort": "Ange en giltig port (1-65535)", + "newUsername": "Nytt användarnamn", + "addUser": "Tillägga", + "deleteUser": "Ta bort användare", + "noHealthChecks": "Inga hälsokontroller har konfigurerats ännu.", + "follow": "Följa", + "noLogData": "Ingen loggutgång.", + "tree": "Träd", + "enableDisable": "Aktivera/avaktivera vid start", + "grantSudo": "Bevilja sudo", + "revokeSudo": "Återkalla sudo", + "sslIssueCert": "Utfärdande av certifikat", + "sslExpired": "Utgången", + "sslInDays": "i {{days}}d", + "sslNeedDomain": "Ange minst en domän", + "sslIssued": "Certifikat utfärdat", + "sslDomainsPlaceholder": "exempel.com, www.example.com", + "sslHttpStandalone": "HTTP (fristående)", + "sslHttpWebroot": "HTTP (webbrot)", + "sslDns": "DNS", + "sslDnsProvider": "DNS-leverantör (t.ex. Cloudflare)", + "sslIssueHint": "DNS-leverantörens inloggningsuppgifter måste redan vara konfigurerade på värden.", + "sslRevoke": "Återkalla certifikat", + "sslRevoked": "Certifikat återkallat", + "sslRevokeConfirm": "Återkalla och ta bort certifikatet \"{{name}}\"? Detta kan inte ångras.", + "healthRun": "Sikt", + "healthName": "Namn", + "healthTarget": "Värd / adress", + "healthAddCheck": "Lägg till check", + "healthSaved": "Hälsokontroller sparade", + "healthMissingFields": "Varje kontroll behöver ett namn och ett mål", + "logFile": "Fil", + "logUnit": "Enhet", + "logCustomPath": "Anpassad sökväg under /var/log (valfritt)", + "logGrep": "Filtrera rader...", + "firewallPersist": "Bevara regler", + "firewallPersisted": "Brandväggsreglerna bibehölls", + "wireguard": "WireGuard", + "tailscale": "Svansskala", + "wgNotInstalled": "WireGuard är inte installerat på den här värddatorn", + "wgNoInterfaces": "Inga WireGuard-gränssnitt konfigurerade", + "wgInterfaceUp": "Få upp", + "wgInterfaceDown": "Sänka", + "wgBringingUp": "Tar upp {{name}}...", + "wgBringingDown": "Att fälla {{name}}...", + "wgInterfaceUpDone": "{{name}} är uppe", + "wgInterfaceDownDone": "{{name}} är nere", + "wgListenPort": "Hamn", + "wgPublicKey": "Offentlig nyckel", + "wgEndpoint": "Slutpunkt", + "wgAllowedIPs": "Tillåtna IP-adresser", + "wgLastHandshake": "Sista handskakningen", + "wgHandshakeNever": "Aldrig", + "wgTransfer": "Överföra", + "tsNotInstalled": "Tailscale är inte installerat på den här värddatorn", + "tsRunning": "Spring", + "tsStopped": "Stoppad", + "tsEnable": "Ansluta", + "tsDisable": "Koppla från", + "tsEnabling": "Ansluter till Tailscale...", + "tsDisabling": "Kopplar från Tailscale...", + "tsEnabled": "Svanskalan ansluten", + "tsDisabled": "Svanskalan frånkopplad", + "tsIPs": "Tailskala-IP-adresser", + "tsPeers": "Kamrater", + "tsOnline": "Online", + "tsOffline": "Off-line", + "tsExitNode": "Utgångsnod", + "tsExitNodeActive": "Avslutsnod aktiv", + "tsHostname": "Värdnamn" + } + }, + "metricsHistory": { + "title": "Statistikhistorik", + "historySuffix": "Historia", + "cpuMemoryDisk": "CPU / Minne / Disk", + "network": "Nätverk", + "download": "RX", + "upload": "TX", + "noData": "Ingen historikdata tillgänglig för detta tidsintervall.", + "custom": "Beställnings", + "to": "till", + "apply": "Tillämpas", + "viewHistory": "Visa historik" + }, + "proxmoxStats": { + "tabTitle": "Proxmox-statistik", + "cpuUsage": "CPU-användning", + "memoryUsage": "Minnesanvändning", + "diskUsage": "Diskanvändning", + "networkInterfaces": "Nätverksgränssnitt", + "uptime": "Drifttid", + "systemInfo": "Systeminformation", + "guestsSummary": "Gäster", + "storagePools": "Lagringspooler", + "clusterHealth": "Klusterhälsa", + "cpuCores_one": "{{count}} Kärna", + "cpuCores_other": "{{count}} Kärnor", + "used": "Begagnad", + "total": "Total", + "hostname": "Värdnamn", + "kernel": "Kärna", + "pveVersion": "PVE-version", + "name": "Namn", + "status": "Status", + "type": "Typ", + "cpu": "CPU", + "mem": "Mem", + "disk": "Disk", + "running": "Spring", + "stopped": "Stoppad", + "guestCounts": "{{running}}/{{total}} springer", + "inactive": "Inaktiv", + "notClustered": "Fristående nod (inte en del av ett kluster)", + "quorate": "Kvorat", + "notQuorate": "Inte kvoriöst", + "nodeOnline": "Online", + "nodeOffline": "Off-line", + "noHostSelected": "Ingen värd vald", + "pveshNotFound": "pvesh hittades inte - är detta en Proxmox-nod?", + "nodeDetectionFailed": "Det gick inte att fastställa ett giltigt Proxmox-nodnamn", + "connecting": "Ansluter...", + "connectionFailed": "Misslyckades med att ansluta till Proxmox-noden", + "refresh": "Uppdatera", + "searchGuests": "Sök gäster...", + "filterAll": "Alla", + "filterVm": "VM", + "filterLxc": "LXC", + "noGuests": "Inga virtuella maskiner eller LXC-behållare hittades på den här noden.", + "noGuestsMatch": "Inga gäster matchar de aktuella filtren." + }, + "nav": { + "hostMetrics": "Värdstatistik" + }, + "hosts": { + "tabHostMetrics": "Värdstatistik", + "enableProxmoxStats": "Aktivera Proxmox-statistik", + "enableProxmoxStatsDesc": "Visa en Proxmox-statistikflik för den här värden med live-nod-, gäst-, lagrings- och klusterstatistik insamlad via SSH.", + "proxmoxStatsPollInterval": "Undersökningsintervall (sekunder)", + "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", + "metricsCollectionLabel": "Metriksamling", + "enableMetricsLabel": "Aktivera mätvärden", + "enableMetricsDesc": "Samla in CPU, RAM, disk och andra mätvärden från den här värden", + "useGlobalMetrics": "Använd globalt intervall", + "useGlobalMetricsDesc": "Åsidosätt med det serveromfattande mätintervallet", + "metricsIntervalS": "Mätintervall (s)", + "metricsIntervalDesc2": "Sekunder mellan mätvärdesbilder", + "excludedMountsLabel": "Undantagna fästen", + "monitoredMountsLabel": "Anpassade övervakade sökvägar", + "monitoredMountsDesc": "Lägg till sökvägar som inte exponeras som separata monteringar, inklusive bindningsmonterade Home Assistant-sökvägar som /config.", + "monitoredMountPathPlaceholder": "Sökväg (/config, /mnt/data)", + "monitoredMountLabelPlaceholder": "Etikett (valfritt)", + "addMonitoredMount": "Lägg till sökväg", + "excludedMountsDesc": "Dölj specifika monteringspunkter eller filsystemtyper (t.ex. nfs, cifs) från diskanvändning och aviseringar för den här värden.", + "excludedMountsPlaceholder": "Monteringssökväg (/mnt/nas) eller filsystemtyp (nfs, cifs)", + "excludedMountsEmpty": "Inga monteringar är undantagna. Alla upptäckta filsystem visas.", + "addExcludedMount": "Tillägga", + "visibleWidgets": "Synliga widgetar", + "widgetsMovedToHostMetrics": "Kort läggs nu till, ordnas och ändras i storlek direkt på fliken Värdstatistik. Öppna Värdstatistik för den här värden och använd Anpassa för att välja vilka kort som visas.", + "quickActionsLabel": "Snabbåtgärder", + "quickActionsToolbar": "Snabbåtgärder visas som knappar i verktygsfältet Host Metrics för att köra kommandon med ett klick.", + "noQuickActions": "Inga snabba åtgärder ännu.", + "buttonLabel": "Knappetikett", + "selectSnippetPlaceholder": "Välj utdrag...", + "addActionBtn": "Lägg till åtgärd" + }, + "onboarding": { + "feature_metrics": "Mätvärden och varningar", + "feature_metrics_desc": "Spåra CPU, minne och disk över tid och få en avisering när de blir dåliga." + }, + "admin": { + "metricsHistoryRetention": "Bevarande av mätvärdenas historik", + "metricsHistoryRetentionRange": "1 till 90 dagar", + "days": "dagar" + }, + "homepage": { + "noData": "Inga data tillgängliga", + "showCurrentValue": "Visa aktuellt värde", + "chartMetric": "Metrisk", + "metricRange": "Räckvidd" + } +} diff --git a/plugins/host-metrics/locales/translated/th_TH.json b/plugins/host-metrics/locales/translated/th_TH.json new file mode 100644 index 000000000..08874a42f --- /dev/null +++ b/plugins/host-metrics/locales/translated/th_TH.json @@ -0,0 +1,313 @@ +{ + "hostMetrics": { + "cpu": "ซีพียู", + "memory": "หน่วยความจำ", + "disk": "ดิสก์", + "network": "เครือข่าย", + "uptime": "เวลาใช้งาน", + "processes": "กระบวนการ", + "available": "มีอยู่", + "free": "ฟรี", + "connecting": "กำลังเชื่อมต่อ...", + "connectionFailed": "ไม่สามารถเชื่อมต่อกับเซิร์ฟเวอร์ได้", + "naCpus": "ไม่มีข้อมูล CPU", + "cpuCores_one": "{{count}} แกนหลัก", + "cpuCores_other": "{{count}} คอร์", + "cpuUsage": "การใช้งาน CPU", + "memoryUsage": "การใช้งานหน่วยความจำ", + "diskUsage": "การใช้งานดิสก์", + "selectFilesystem": "เลือกไฟล์ระบบ", + "temperature": "อุณหภูมิ", + "highestTemperature": "อุณหภูมิสูงสุด", + "primaryTemperatureSensor": "เซ็นเซอร์หลัก", + "gpu": { + "title": "จีพี", + "noDevice": "ไม่พบการ์ดจอ NVIDIA โปรดติดตั้งไดรเวอร์ NVIDIA (ซึ่งมีโปรแกรม nvidia-smi ให้ใช้งาน) เพื่อดูข้อมูลการทำงานของ GPU", + "driver": "คนขับ {{version}}", + "utilization": "การใช้ประโยชน์", + "memory": "วีแรม", + "temperature": "อุณหภูมิ", + "power": "พลัง", + "fan": "พัดลม", + "processes": "การประมวลผล GPU", + "noProcesses": "ไม่มีกระบวนการใดกำลังใช้งาน GPU อยู่" + }, + "failedToFetchHostConfig": "ไม่สามารถดึงข้อมูลการกำหนดค่าโฮสต์ได้", + "serverOffline": "เซิร์ฟเวอร์ออฟไลน์", + "cannotFetchMetrics": "ไม่สามารถดึงข้อมูลเมตริกจากเซิร์ฟเวอร์ออฟไลน์ได้", + "totpFailed": "การตรวจสอบ TOTP ล้มเหลว", + "noneAuthNotSupported": "Host Metrics ไม่รองรับประเภทการตรวจสอบสิทธิ์แบบ 'none'", + "noHostSelected": "ไม่ได้เลือกโฮสต์", + "load": "โหลด", + "systemInfo": "ข้อมูลระบบ", + "hostname": "ชื่อโฮสต์", + "operatingSystem": "ระบบปฏิบัติการ", + "kernel": "เคอร์เนล", + "seconds": "วินาที", + "networkInterfaces": "อินเทอร์เฟซเครือข่าย", + "noInterfacesFound": "ไม่พบอินเทอร์เฟซเครือข่าย", + "noProcessesFound": "ไม่พบกระบวนการใดๆ", + "processesTotal": "ทั้งหมด", + "processesRunning": "วิ่ง", + "loginStats": "สถิติการเข้าสู่ระบบ SSH", + "noRecentLoginData": "ไม่มีข้อมูลการเข้าสู่ระบบล่าสุด", + "executingQuickAction": "กำลังดำเนินการ {{name}}...", + "quickActionSuccess": "{{name}} เสร็จสมบูรณ์เรียบร้อยแล้ว", + "quickActionFailed": "{{name}} ล้มเหลว", + "quickActionError": "ไม่สามารถดำเนินการ {{name}} ได้", + "ports": { + "title": "พอร์ตรับฟัง", + "protocol": "โปรโตคอล", + "port": "ท่าเรือ", + "address": "ที่อยู่", + "process": "กระบวนการ", + "search": "ค้นหาพอร์ต...", + "allProtocols": "ทั้งหมด", + "noData": "ไม่มีข้อมูลพอร์ตการฟัง" + }, + "firewall": { + "title": "ไฟร์วอลล์", + "inactive": "ไม่ใช้งาน", + "policy": "นโยบาย", + "rules": "กฎ", + "noRules": "ไม่มีกฎเกณฑ์ใดๆ ในห่วงโซ่นี้", + "noData": "ไม่มีข้อมูลไฟร์วอลล์ให้ใช้งาน", + "action": "การกระทำ", + "protocol": "โปรโต", + "port": "ท่าเรือ", + "source": "แหล่งที่มา", + "anywhere": "ทุกที่", + "chains": "โซ่" + }, + "loadAvg": "โหลดเฉลี่ย", + "swap": "แลกเปลี่ยน", + "architecture": "สถาปัตยกรรม", + "refresh": "รีเฟรช", + "retry": "ลองใหม่อีกครั้ง", + "customize": "ปรับแต่งเค้าโครง", + "reset": "รีเซ็ต", + "tabLive": "สด", + "editModeInstructions": "ลากการ์ดเพื่อจัดเรียงใหม่ ลากขอบด้านล่างเพื่อปรับขนาด และใช้ปุ่มความกว้างเพื่อเปลี่ยนความกว้างของการ์ด เพิ่มหรือลบการ์ดด้านล่าง", + "managers": { + "services": "บริการ", + "processInspector": "ผู้ตรวจสอบกระบวนการ", + "logViewer": "โปรแกรมดูบันทึก", + "cron": "งานครอน", + "packages": "แพ็คเกจ", + "ssl": "ใบรับรอง SSL", + "firewall": "ไฟร์วอลล์", + "users": "ผู้ใช้และสิทธิ์การเข้าถึง", + "healthCheck": "การตรวจสุขภาพ", + "diskBreakdown": "การแยกดิสก์", + "systemdTimers": "ตัวจับเวลา", + "topMemory": "อันดับแรกโดย Memory", + "noData": "ไม่มีข้อมูล", + "sudoHint": "ตั้งรหัสผ่าน sudo สำหรับโฮสต์นี้ในโปรแกรมแก้ไขโฮสต์เพื่อเปิดใช้งานการดำเนินการที่มีสิทธิ์พิเศษ", + "filter": "กรอง...", + "start": "เริ่ม", + "stop": "หยุด", + "restart": "เริ่มใหม่", + "actionDone": "{{name}} อัปเดตแล้ว", + "actionFailed": "การดำเนินการล้มเหลว", + "signalSent": "ส่งสัญญาณไปยัง PID {{pid}}", + "killHint": "คลิก: ยุติการทำงาน (SIGTERM) คลิกขวา: บังคับปิดการทำงาน (SIGKILL)", + "working": "การทำงาน...", + "update": "อัปเดต", + "upgradeAll": "อัปเกรดทั้งหมด", + "allUpToDate": "ทุกอย่างอัปเดตแล้ว", + "save": "บันทึก", + "command": "สั่งการ", + "enabled": "เปิดใช้งาน", + "cronSaved": "อัปเดต Crontab แล้ว", + "clients": "ลูกค้า", + "dryRun": "การทดลองซ้อม", + "renew": "ต่ออายุ", + "noAcmeClient": "ไม่พบไคลเอ็นต์ ACME (certbot หรือ acme.sh) บนโฮสต์นี้", + "addInputRule": "เพิ่มกฎ INPUT", + "firewallWarning": "การเปลี่ยนแปลงจะมีผลเฉพาะขณะรันไทม์จนกว่าจะบันทึกเสร็จสมบูรณ์ โปรดระวังอย่าล็อกตัวเองออกจากระบบ", + "ruleApplied": "กฎที่ใช้", + "invalidPort": "ป้อนหมายเลขพอร์ตที่ถูกต้อง (1-65535)", + "newUsername": "ชื่อผู้ใช้ใหม่", + "addUser": "เพิ่ม", + "deleteUser": "ลบผู้ใช้", + "noHealthChecks": "ยังไม่ได้ตั้งค่าการตรวจสอบสุขภาพใดๆ", + "follow": "ติดตาม", + "noLogData": "ไม่มีการแสดงผลบันทึกใดๆ", + "tree": "ต้นไม้", + "enableDisable": "เปิดใช้งาน/ปิดใช้งานเมื่อบูตเครื่อง", + "grantSudo": "ให้สิทธิ์ sudo", + "revokeSudo": "ยกเลิกสิทธิ์ sudo", + "sslIssueCert": "ออกใบรับรอง", + "sslExpired": "หมดอายุ", + "sslInDays": "ใน {{days}}d", + "sslNeedDomain": "ป้อนโดเมนอย่างน้อยหนึ่งโดเมน", + "sslIssued": "ออกใบรับรองแล้ว", + "sslDomainsPlaceholder": "example.com, www.example.com", + "sslHttpStandalone": "HTTP (แบบสแตนด์อโลน)", + "sslHttpWebroot": "HTTP (webroot)", + "sslDns": "เอ็นเอสดี", + "sslDnsProvider": "ผู้ให้บริการ DNS (เช่น Cloudflare)", + "sslIssueHint": "ต้องตั้งค่าข้อมูลประจำตัวของผู้ให้บริการ DNS บนโฮสต์ไว้แล้ว", + "sslRevoke": "เพิกถอนใบรับรอง", + "sslRevoked": "ใบรับรองถูกเพิกถอน", + "sslRevokeConfirm": "เพิกถอนและลบใบรับรอง \"{{name}}\"? การดำเนินการนี้ไม่สามารถย้อนกลับได้", + "healthRun": "วิ่ง", + "healthName": "ชื่อ", + "healthTarget": "โฮสต์ / ที่อยู่", + "healthAddCheck": "เพิ่มเช็ค", + "healthSaved": "บันทึกการตรวจสุขภาพ", + "healthMissingFields": "เช็คแต่ละใบต้องมีชื่อและเป้าหมาย", + "logFile": "ไฟล์", + "logUnit": "หน่วย", + "logCustomPath": "เส้นทางที่กำหนดเองภายใต้ /var/log (ไม่บังคับ)", + "logGrep": "กรองบรรทัด...", + "firewallPersist": "กฎการคงอยู่", + "firewallPersisted": "กฎไฟร์วอลล์ยังคงอยู่", + "wireguard": "ไวร์การ์ด", + "tailscale": "เกล็ดหาง", + "wgNotInstalled": "WireGuard ไม่ได้ติดตั้งอยู่ในเครื่องนี้", + "wgNoInterfaces": "ไม่มีการกำหนดค่าอินเทอร์เฟซ WireGuard", + "wgInterfaceUp": "นำมา", + "wgInterfaceDown": "นำมาลง", + "wgBringingUp": "กำลังนำ {{name}} ขึ้นมา...", + "wgBringingDown": "ล้มล้าง {{name}}...", + "wgInterfaceUpDone": "{{name}} พร้อมใช้งานแล้ว", + "wgInterfaceDownDone": "{{name}} ใช้งานไม่ได้แล้ว", + "wgListenPort": "ท่าเรือ", + "wgPublicKey": "กุญแจสาธารณะ", + "wgEndpoint": "จุดสิ้นสุด", + "wgAllowedIPs": "ที่อยู่ IP ที่อนุญาต", + "wgLastHandshake": "การจับมือครั้งสุดท้าย", + "wgHandshakeNever": "ไม่เคย", + "wgTransfer": "โอนย้าย", + "tsNotInstalled": "Tailscale ไม่ได้ติดตั้งอยู่ในเครื่องนี้", + "tsRunning": "วิ่ง", + "tsStopped": "หยุด", + "tsEnable": "เชื่อมต่อ", + "tsDisable": "ตัดการเชื่อมต่อ", + "tsEnabling": "กำลังเชื่อมต่อกับ Tailscale...", + "tsDisabling": "กำลังตัดการเชื่อมต่อจาก Tailscale...", + "tsEnabled": "เกล็ดหางเชื่อมต่อ", + "tsDisabled": "เกล็ดหางหลุด", + "tsIPs": "IP หาง", + "tsPeers": "เพื่อนร่วมงาน", + "tsOnline": "ออนไลน์", + "tsOffline": "ออฟไลน์", + "tsExitNode": "โหนดทางออก", + "tsExitNodeActive": "โหนดทางออกทำงานอยู่", + "tsHostname": "ชื่อโฮสต์" + } + }, + "metricsHistory": { + "title": "ประวัติการวัดผล", + "historySuffix": "ประวัติศาสตร์", + "cpuMemoryDisk": "ซีพียู / หน่วยความจำ / ดิสก์", + "network": "เครือข่าย", + "download": "อาร์ซี", + "upload": "เท็กซัส", + "noData": "ไม่มีข้อมูลประวัติสำหรับช่วงเวลานี้", + "custom": "กำหนดเอง", + "to": "ถึง", + "apply": "นำมาใช้", + "viewHistory": "ประวัติการดู" + }, + "proxmoxStats": { + "tabTitle": "สถิติ Proxmox", + "cpuUsage": "การใช้งาน CPU", + "memoryUsage": "การใช้งานหน่วยความจำ", + "diskUsage": "การใช้งานดิสก์", + "networkInterfaces": "อินเทอร์เฟซเครือข่าย", + "uptime": "เวลาใช้งาน", + "systemInfo": "ข้อมูลระบบ", + "guestsSummary": "แขก", + "storagePools": "สระเก็บน้ำ", + "clusterHealth": "สุขภาพคลัสเตอร์", + "cpuCores_one": "{{count}} แกนหลัก", + "cpuCores_other": "{{count}} คอร์", + "used": "ใช้แล้ว", + "total": "ทั้งหมด", + "hostname": "ชื่อโฮสต์", + "kernel": "เคอร์เนล", + "pveVersion": "เวอร์ชัน PVE", + "name": "ชื่อ", + "status": "สถานะ", + "type": "พิมพ์", + "cpu": "ซีพียู", + "mem": "เมม", + "disk": "ดิสก์", + "running": "วิ่ง", + "stopped": "หยุด", + "guestCounts": "{{running}}/{{total}} กำลังทำงาน", + "inactive": "ไม่ใช้งาน", + "notClustered": "โหนดแบบสแตนด์อโลน (ไม่ได้เป็นส่วนหนึ่งของคลัสเตอร์)", + "quorate": "ควอต", + "notQuorate": "องค์ประชุมไม่ครบ", + "nodeOnline": "ออนไลน์", + "nodeOffline": "ออฟไลน์", + "noHostSelected": "ไม่ได้เลือกโฮสต์", + "pveshNotFound": "ไม่พบ pvesh - นี่เป็นโหนด Proxmox หรือไม่?", + "nodeDetectionFailed": "ไม่สามารถระบุชื่อโหนด Proxmox ที่ถูกต้องได้", + "connecting": "กำลังเชื่อมต่อ...", + "connectionFailed": "ไม่สามารถเชื่อมต่อกับโหนด Proxmox ได้", + "refresh": "รีเฟรช", + "searchGuests": "ค้นหาผู้เข้าพัก...", + "filterAll": "ทั้งหมด", + "filterVm": "วีเอ็ม", + "filterLxc": "LXC", + "noGuests": "ไม่พบเครื่องเสมือน (VM) หรือคอนเทนเนอร์ LXC บนโหนดนี้", + "noGuestsMatch": "ไม่มีแขกท่านใดตรงกับตัวกรองที่มีอยู่ในขณะนี้" + }, + "nav": { + "hostMetrics": "เมตริกโฮสต์" + }, + "hosts": { + "tabHostMetrics": "เมตริกโฮสต์", + "enableProxmoxStats": "เปิดใช้งานสถิติ Proxmox", + "enableProxmoxStatsDesc": "แสดงแท็บสถิติ Proxmox สำหรับโฮสต์นี้ พร้อมสถิติแบบเรียลไทม์ของโหนด เกสต์ พื้นที่จัดเก็บ และคลัสเตอร์ที่รวบรวมผ่าน SSH", + "proxmoxStatsPollInterval": "ช่วงเวลาการสำรวจ (วินาที)", + "proxmoxStatsPollIntervalDesc": "อย่างน้อย 15 วินาที ความถี่ในการอัปเดตสถิติโหนด Proxmox", + "proxmoxStatsNodeOverride": "การแทนที่ชื่อโหนด", + "proxmoxStatsNodeOverrideDesc": "ยกเลิกการตรวจจับชื่อโหนด Proxmox อัตโนมัติ (โดยค่าเริ่มต้นจะตรวจจับผ่านชื่อโฮสต์)", + "proxmoxStatsNodeOverridePlaceholder": "ตรวจจับอัตโนมัติจากชื่อโฮสต์", + "metricsCollectionLabel": "การรวบรวมเมตริก", + "enableMetricsLabel": "เปิดใช้งานเมตริก", + "enableMetricsDesc": "รวบรวมข้อมูลการใช้งาน CPU, RAM, ดิสก์ และข้อมูลอื่นๆ จากโฮสต์นี้", + "useGlobalMetrics": "ใช้ช่วงเวลาทั่วโลก", + "useGlobalMetricsDesc": "แทนที่ด้วยช่วงเวลาการวัดเมตริกทั่วทั้งเซิร์ฟเวอร์", + "metricsIntervalS": "ช่วงเวลาการวัด (วินาที)", + "metricsIntervalDesc2": "จำนวนวินาทีระหว่างการบันทึกภาพเมตริก", + "excludedMountsLabel": "การติดตั้งที่ไม่รวมอยู่ในเงื่อนไข", + "monitoredMountsLabel": "เส้นทางการตรวจสอบแบบกำหนดเอง", + "monitoredMountsDesc": "เพิ่มพาธที่ไม่ถูกเปิดเผยเป็นเมานต์แยกต่างหาก รวมถึงพาธ Home Assistant ที่เชื่อมต่อแบบ bind-mount เช่น /config", + "monitoredMountPathPlaceholder": "เส้นทาง (/config, /mnt/data)", + "monitoredMountLabelPlaceholder": "ป้ายกำกับ (ไม่บังคับ)", + "addMonitoredMount": "เพิ่มเส้นทาง", + "excludedMountsDesc": "ซ่อนจุดเชื่อมต่อหรือประเภทระบบไฟล์เฉพาะ (เช่น nfs, cifs) จากการใช้งานดิสก์และการแจ้งเตือนสำหรับโฮสต์นี้", + "excludedMountsPlaceholder": "เส้นทางการเชื่อมต่อ (/mnt/nas) หรือประเภทระบบไฟล์ (nfs, cifs)", + "excludedMountsEmpty": "ไม่มีการยกเว้นการเมานต์ใดๆ ระบบไฟล์ที่ตรวจพบทั้งหมดจะแสดงขึ้น", + "addExcludedMount": "เพิ่ม", + "visibleWidgets": "วิดเจ็ตที่มองเห็นได้", + "widgetsMovedToHostMetrics": "ขณะนี้สามารถเพิ่ม จัดเรียง และปรับขนาดการ์ดได้โดยตรงในแท็บเมตริกโฮสต์ เปิดเมตริกโฮสต์สำหรับโฮสต์นี้แล้วใช้ ปรับแต่ง เพื่อเลือกการ์ดที่จะแสดง", + "quickActionsLabel": "การดำเนินการด่วน", + "quickActionsToolbar": "การดำเนินการด่วนจะปรากฏเป็นปุ่มในแถบเครื่องมือ Host Metrics เพื่อให้สามารถเรียกใช้คำสั่งได้ด้วยการคลิกเพียงครั้งเดียว", + "noQuickActions": "ยังไม่มีการดำเนินการใดๆ อย่างเร่งด่วนในขณะนี้", + "buttonLabel": "ป้ายกำกับปุ่ม", + "selectSnippetPlaceholder": "เลือกส่วนย่อย...", + "addActionBtn": "เพิ่มการดำเนินการ" + }, + "onboarding": { + "feature_metrics": "ตัวชี้วัดและการแจ้งเตือน", + "feature_metrics_desc": "ติดตามการทำงานของ CPU หน่วยความจำ และดิสก์อย่างต่อเนื่อง และรับการแจ้งเตือนเมื่ออุปกรณ์เหล่านั้นเริ่มมีปัญหา" + }, + "admin": { + "metricsHistoryRetention": "การเก็บรักษาประวัติเมตริก", + "metricsHistoryRetentionRange": "1 ถึง 90 วัน", + "days": "วัน" + }, + "homepage": { + "noData": "ไม่มีข้อมูล", + "showCurrentValue": "แสดงมูลค่าปัจจุบัน", + "chartMetric": "เมตริก", + "metricRange": "พิสัย" + } +} diff --git a/plugins/host-metrics/locales/translated/tr_TR.json b/plugins/host-metrics/locales/translated/tr_TR.json new file mode 100644 index 000000000..104aca7b0 --- /dev/null +++ b/plugins/host-metrics/locales/translated/tr_TR.json @@ -0,0 +1,313 @@ +{ + "hostMetrics": { + "cpu": "CPU", + "memory": "Bellek", + "disk": "Disk", + "network": "Ağ", + "uptime": "Çalışma Süresi", + "processes": "İşlemler", + "available": "Kullanılabilir", + "free": "Boş", + "connecting": "Bağlanıyor...", + "connectionFailed": "Sunucuya bağlanılamadı", + "naCpus": "CPU yok", + "cpuCores_one": "{{count}} Çekirdek", + "cpuCores_other": "{{count}} Çekirdek", + "cpuUsage": "CPU Kullanımı", + "memoryUsage": "Bellek Kullanımı", + "diskUsage": "Disk Kullanımı", + "selectFilesystem": "Dosya sistemini seçin", + "temperature": "Sıcaklık", + "highestTemperature": "En yüksek sıcaklık", + "primaryTemperatureSensor": "Birincil sensör", + "gpu": { + "title": "GPU", + "noDevice": "NVIDIA GPU algılanmadı. GPU ölçümlerini görmek için NVIDIA sürücüsünü (nvidia-smi içerir) yükleyin.", + "driver": "Sürücü {{version}}", + "utilization": "Kullanım", + "memory": "VRAM", + "temperature": "Geçici", + "power": "Güç", + "fan": "Fan", + "processes": "GPU işlemleri", + "noProcesses": "GPU'yu kullanan hiçbir işlem yok." + }, + "failedToFetchHostConfig": "Host yapılandırması alınamadı", + "serverOffline": "Sunucu Çevrimdışı", + "cannotFetchMetrics": "Çevrimdışı sunucudan ölçümler alınamaz", + "totpFailed": "TOTP doğrulaması başarısız", + "noneAuthNotSupported": "Sunucu Metrikleri 'none' kimlik doğrulama türünü desteklemiyor.", + "noHostSelected": "Sunucu seçilmedi", + "load": "Yük", + "systemInfo": "Sistem Bilgisi", + "hostname": "Sunucu Adı", + "operatingSystem": "İşletim Sistemi", + "kernel": "Çekirdek", + "seconds": "saniye", + "networkInterfaces": "Ağ Arayüzleri", + "noInterfacesFound": "Ağ arayüzleri bulunamadı", + "noProcessesFound": "Hiç işlem bulunamadı", + "processesTotal": "toplam", + "processesRunning": "çalışan", + "loginStats": "SSH Giriş İstatistikleri", + "noRecentLoginData": "Son giriş verisi yok", + "executingQuickAction": "{{name}} çalıştırılıyor...", + "quickActionSuccess": "{{name}} başarıyla tamamlandı", + "quickActionFailed": "{{name}} başarısız oldu", + "quickActionError": "{{name}} çalıştırılamadı", + "ports": { + "title": "Dinlenen Portlar", + "protocol": "Protokol", + "port": "Port", + "address": "Adres", + "process": "İşlem", + "search": "Portları ara...", + "allProtocols": "Tümü", + "noData": "Dinlenen port verisi yok" + }, + "firewall": { + "title": "Güvenlik Duvarı", + "inactive": "Etkin Değil", + "policy": "Politika", + "rules": "kurallar", + "noRules": "Bu zincirde kural yok", + "noData": "Güvenlik duvarı verisi bulunamadı", + "action": "Eylem", + "protocol": "Protokol", + "port": "Port", + "source": "Kaynak", + "anywhere": "Her yer", + "chains": "zincirler" + }, + "loadAvg": "Ortalama Yük", + "swap": "Takas", + "architecture": "Mimari", + "refresh": "Yenile", + "retry": "Yeniden dene", + "customize": "Düzeni özelleştir", + "reset": "Sıfırla", + "tabLive": "Canlı", + "editModeInstructions": "Kartları yeniden düzenlemek için sürükleyin, yeniden boyutlandırmak için alt kenarı sürükleyin ve bir kartın genişliğini değiştirmek için genişlik düğmesini kullanın. Aşağıdan kart ekleyin veya kaldırın.", + "managers": { + "services": "Hizmetler", + "processInspector": "İşlem Denetçisi", + "logViewer": "Günlük Görüntüleyici", + "cron": "Cron Görevleri", + "packages": "Paketler", + "ssl": "SSL Sertifikaları", + "firewall": "Güvenlik Duvarı", + "users": "Kullanıcılar ve İzinler", + "healthCheck": "Sağlık Kontrolleri", + "diskBreakdown": "Disk Dağılımı", + "systemdTimers": "Zamanlayıcılar", + "topMemory": "Bellek Sıralaması", + "noData": "Veri yok", + "sudoHint": "Ayrıcalıklı eylemleri etkinleştirmek için host düzenleyicisinde bu host için bir sudo parolası belirleyin.", + "filter": "Filtrele...", + "start": "Başlat", + "stop": "Durdur", + "restart": "Yeniden Başlat", + "actionDone": "{{name}} güncellendi", + "actionFailed": "Eylem başarısız oldu", + "signalSent": "PID {{pid}}'e sinyal gönderildi", + "killHint": "Tıklama: sonlandır (SIGTERM). Sağ tıklama: zorla sonlandır (SIGKILL).", + "working": "Çalışıyor...", + "update": "Güncelle", + "upgradeAll": "Tümünü yükselt", + "allUpToDate": "Her şey güncel", + "save": "Kaydet", + "command": "Komut", + "enabled": "Etkin", + "cronSaved": "Crontab güncellendi", + "clients": "İstemciler", + "dryRun": "Deneme çalıştırması", + "renew": "Yenile", + "noAcmeClient": "Bu sunucuda ACME istemcisi (certbot veya acme.sh) bulunamadı.", + "addInputRule": "INPUT kuralı ekle", + "firewallWarning": "Değişiklikler, kalıcı hale getirilene kadar yalnızca çalışma zamanında geçerlidir. Kendinizi kilitlememeye dikkat edin.", + "ruleApplied": "Kural uygulandı", + "invalidPort": "Geçerli bir bağlantı noktası girin (1-65535)", + "newUsername": "Yeni kullanıcı adı", + "addUser": "Ekle", + "deleteUser": "Kullanıcıyı sil", + "noHealthChecks": "Henüz yapılandırılmış bir sağlık denetimi yok.", + "follow": "Takip et", + "noLogData": "Günlük çıktısı yok.", + "tree": "Ağaç", + "enableDisable": "Önyüklemede etkinleştir / devre dışı bırak", + "grantSudo": "Sudo yetkisi ver", + "revokeSudo": "Sudo yetkisini kaldır", + "sslIssueCert": "Sertifika oluştur", + "sslExpired": "Süresi dolmuş", + "sslInDays": "{{days}} gün içinde", + "sslNeedDomain": "En az bir alan adı girin", + "sslIssued": "Sertifika oluşturuldu", + "sslDomainsPlaceholder": "example.com, www.example.com", + "sslHttpStandalone": "HTTP (bağımsız)", + "sslHttpWebroot": "HTTP (webroot)", + "sslDns": "DNS", + "sslDnsProvider": "DNS sağlayıcısı (örn. cloudflare)", + "sslIssueHint": "DNS sağlayıcı kimlik bilgileri sunucuda zaten yapılandırılmış olmalıdır.", + "sslRevoke": "Sertifikayı iptal et", + "sslRevoked": "Sertifika iptal edildi", + "sslRevokeConfirm": "\"{{name}}\" sertifikası iptal edilip kaldırılsın mı? Bu işlem geri alınamaz.", + "healthRun": "Çalıştır", + "healthName": "Ad", + "healthTarget": "Sunucu / adres", + "healthAddCheck": "Kontrol ekle", + "healthSaved": "Sağlık kontrolleri kaydedildi", + "healthMissingFields": "Her kontrol bir ad ve hedef gerektirir", + "logFile": "Dosya", + "logUnit": "Birim", + "logCustomPath": "/var/log altında özel yol (isteğe bağlı)", + "logGrep": "Satırları filtrele...", + "firewallPersist": "Kuralları kalıcı yap", + "firewallPersisted": "Güvenlik duvarı kuralları kalıcı hale getirildi", + "wireguard": "WireGuard", + "tailscale": "Tailscale", + "wgNotInstalled": "Bu sunucuda WireGuard yüklü değil", + "wgNoInterfaces": "Yapılandırılmış WireGuard arayüzü yok", + "wgInterfaceUp": "Başlat", + "wgInterfaceDown": "Durdur", + "wgBringingUp": "{{name}} başlatılıyor...", + "wgBringingDown": "{{name}} durduruluyor...", + "wgInterfaceUpDone": "{{name}} çalışıyor", + "wgInterfaceDownDone": "{{name}} çalışmıyor", + "wgListenPort": "Port", + "wgPublicKey": "Açık anahtar", + "wgEndpoint": "Uç nokta", + "wgAllowedIPs": "İzin verilen IP'ler", + "wgLastHandshake": "Son el sıkışma", + "wgHandshakeNever": "Hiçbir zaman", + "wgTransfer": "Transfer", + "tsNotInstalled": "Bu sunucuda Tailscale yüklü değil", + "tsRunning": "Çalışıyor", + "tsStopped": "Durduruldu", + "tsEnable": "Bağlan", + "tsDisable": "Bağlantıyı Kes", + "tsEnabling": "Tailscale'e bağlanıyor...", + "tsDisabling": "Tailscale bağlantısı kesiliyor...", + "tsEnabled": "Tailscale bağlandı", + "tsDisabled": "Tailscale bağlantısı kesildi", + "tsIPs": "Tailscale IP'leri", + "tsPeers": "Eşler", + "tsOnline": "Çevrimiçi", + "tsOffline": "Çevrimdışı", + "tsExitNode": "Çıkış düğümü", + "tsExitNodeActive": "Çıkış düğümü etkin", + "tsHostname": "Ana bilgisayar adı" + } + }, + "metricsHistory": { + "title": "Metrik Geçmişi", + "historySuffix": "Geçmiş", + "cpuMemoryDisk": "CPU / Bellek / Disk", + "network": "Ağ", + "download": "RX", + "upload": "TX", + "noData": "Bu zaman aralığı için geçmiş verisi yok.", + "custom": "Özel", + "to": "ile", + "apply": "Uygula", + "viewHistory": "Geçmişi Görüntüle" + }, + "proxmoxStats": { + "tabTitle": "Proxmox İstatistikleri", + "cpuUsage": "CPU Kullanımı", + "memoryUsage": "Bellek Kullanımı", + "diskUsage": "Disk Kullanımı", + "networkInterfaces": "Ağ Arayüzleri", + "uptime": "Çalışma süresi", + "systemInfo": "Sistem Bilgileri", + "guestsSummary": "Misafirler", + "storagePools": "Depolama Havuzları", + "clusterHealth": "Küme Sağlığı", + "cpuCores_one": "{{count}} Çekirdek", + "cpuCores_other": "{{count}} Çekirdekler", + "used": "Kullanılmış", + "total": "Toplam", + "hostname": "Ana bilgisayar adı", + "kernel": "Çekirdek", + "pveVersion": "PVE Sürümü", + "name": "İsim", + "status": "Durum", + "type": "Tip", + "cpu": "İşlemci", + "mem": "Mem", + "disk": "Disk", + "running": "Koşma", + "stopped": "Durduruldu", + "guestCounts": "{{running}}/{{total}} çalışıyor", + "inactive": "Etkin değil", + "notClustered": "Bağımsız düğüm (kümenin parçası olmayan)", + "quorate": "Quora", + "notQuorate": "Yeterli çoğunluğa sahip değil", + "nodeOnline": "Çevrimiçi", + "nodeOffline": "Çevrimdışı", + "noHostSelected": "Sunucu seçilmedi.", + "pveshNotFound": "pvesh bulunamadı - bu bir Proxmox düğümü mü?", + "nodeDetectionFailed": "Geçerli bir Proxmox düğüm adı belirlenemedi.", + "connecting": "Bağlanıyor...", + "connectionFailed": "Proxmox düğümüne bağlanılamadı.", + "refresh": "Yenile", + "searchGuests": "Misafirleri ara...", + "filterAll": "Tüm", + "filterVm": "Sanal makine", + "filterLxc": "LXC", + "noGuests": "Bu düğümde hiçbir sanal makine veya LXC kapsayıcısı bulunamadı.", + "noGuestsMatch": "Mevcut filtrelere uyan konuk bulunamadı." + }, + "nav": { + "hostMetrics": "Sunucu Metrikleri" + }, + "hosts": { + "tabHostMetrics": "Sunucu Metrikleri", + "enableProxmoxStats": "Proxmox İstatistiklerini Etkinleştir", + "enableProxmoxStatsDesc": "Bu sunucu için, SSH üzerinden toplanan canlı düğüm, sanal makine, depolama ve küme istatistiklerini içeren bir Proxmox İstatistikleri sekmesi gösterin.", + "proxmoxStatsPollInterval": "Anket aralığı (saniye)", + "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ı", + "metricsCollectionLabel": "Metrik Toplama", + "enableMetricsLabel": "Metrikleri Etkinleştir", + "enableMetricsDesc": "Bu sunucudan CPU, RAM, disk ve diğer metrikleri topla", + "useGlobalMetrics": "Genel Aralığı Kullan", + "useGlobalMetricsDesc": "Sunucu geneli metrik aralığını geçersiz kıl", + "metricsIntervalS": "Metrik Aralığı (sn)", + "metricsIntervalDesc2": "Metrik anlık görüntüleri arasındaki saniye", + "excludedMountsLabel": "Hariç Tutulan Montajlar", + "monitoredMountsLabel": "Özel olarak izlenen yollar", + "monitoredMountsDesc": "/config gibi Home Assistant'a bağlanan yollar da dahil olmak üzere, ayrı bağlama noktaları olarak gösterilmeyen yolları ekleyin.", + "monitoredMountPathPlaceholder": "Yol (/config, /mnt/data)", + "monitoredMountLabelPlaceholder": "Etiket (isteğe bağlı)", + "addMonitoredMount": "Yol ekle", + "excludedMountsDesc": "Bu sunucu için disk kullanımı ve uyarılarından belirli bağlama noktalarını veya dosya sistemi türlerini (örneğin nfs, cifs) gizleyin.", + "excludedMountsPlaceholder": "Bağlama yolu (/mnt/nas) veya dosya sistemi türü (nfs, cifs)", + "excludedMountsEmpty": "Hiçbir bağlama noktası hariç tutulmadı. Tespit edilen tüm dosya sistemleri gösteriliyor.", + "addExcludedMount": "Eklemek", + "visibleWidgets": "Görünür Widget'lar", + "widgetsMovedToHostMetrics": "Kartlar artık doğrudan Sunucu Metrikleri sekmesinde eklenir, düzenlenir ve yeniden boyutlandırılır. Bu sunucu için Sunucu Metrikleri'ni açın ve hangi kartların gösterileceğini seçmek için Özelleştir'i kullanın.", + "quickActionsLabel": "Hızlı Eylemler", + "quickActionsToolbar": "Hızlı eylemler, tek tıklamayla komut çalıştırmak için Ana Bilgisayar Metrikleri araç çubuğunda düğme olarak görünür.", + "noQuickActions": "Henüz hızlı eylem yok.", + "buttonLabel": "Düğme etiketi", + "selectSnippetPlaceholder": "Parçacık seç...", + "addActionBtn": "Eylem Ekle" + }, + "onboarding": { + "feature_metrics": "Ölçümler ve uyarılar", + "feature_metrics_desc": "İşlemci, bellek ve disk performansını zaman içinde takip edin ve arızalandıklarında uyarı alın." + }, + "admin": { + "metricsHistoryRetention": "Metrik Geçmişi Saklama", + "metricsHistoryRetentionRange": "1 ila 90 gün", + "days": "gün" + }, + "homepage": { + "noData": "Veri yok", + "showCurrentValue": "Geçerli Değeri Göster", + "chartMetric": "Metrik", + "metricRange": "Aralık" + } +} diff --git a/plugins/host-metrics/locales/translated/uk_UA.json b/plugins/host-metrics/locales/translated/uk_UA.json new file mode 100644 index 000000000..3b8efcb5e --- /dev/null +++ b/plugins/host-metrics/locales/translated/uk_UA.json @@ -0,0 +1,313 @@ +{ + "hostMetrics": { + "cpu": "Процесор", + "memory": "Пам'ять", + "disk": "Диск", + "network": "Мережа", + "uptime": "Час безперебійної роботи", + "processes": "Процеси", + "available": "Доступно", + "free": "Безкоштовно", + "connecting": "Підключення...", + "connectionFailed": "Не вдалося підключитися до сервера", + "naCpus": "Процесор(и) Немає даних", + "cpuCores_one": "{{count}} Ядро", + "cpuCores_other": "{{count}} Ядра", + "cpuUsage": "Використання процесора", + "memoryUsage": "Використання пам'яті", + "diskUsage": "Використання диска", + "selectFilesystem": "Виберіть файлову систему", + "temperature": "Температура", + "highestTemperature": "Найвища температура", + "primaryTemperatureSensor": "Первинний датчик", + "gpu": { + "title": "Графічний процесор", + "noDevice": "Графічний процесор NVIDIA не виявлено. Встановіть драйвер NVIDIA (він надає nvidia-smi), щоб переглянути показники графічного процесора.", + "driver": "Водій {{version}}", + "utilization": "Використання", + "memory": "відеопам'ять", + "temperature": "Темп", + "power": "Потужність", + "fan": "Вентилятор", + "processes": "Процеси графічного процесора", + "noProcesses": "Жоден процес не використовує графічний процесор" + }, + "failedToFetchHostConfig": "Не вдалося отримати конфігурацію хоста", + "serverOffline": "Сервер офлайн", + "cannotFetchMetrics": "Не вдається отримати показники з офлайн-сервера", + "totpFailed": "Не вдалося перевірити TOTP", + "noneAuthNotSupported": "Метрики хоста не підтримують тип автентифікації «немає».", + "noHostSelected": "Хост не вибрано", + "load": "Навантаження", + "systemInfo": "Інформація про систему", + "hostname": "Ім'я хоста", + "operatingSystem": "Операційна система", + "kernel": "Ядро", + "seconds": "секунди", + "networkInterfaces": "Мережеві інтерфейси", + "noInterfacesFound": "Мережевих інтерфейсів не знайдено", + "noProcessesFound": "Процесів не знайдено", + "processesTotal": "загальна сума", + "processesRunning": "біг", + "loginStats": "Статистика входу SSH", + "noRecentLoginData": "Немає останніх даних для входу", + "executingQuickAction": "Виконання {{name}}...", + "quickActionSuccess": "{{name}} успішно завершено", + "quickActionFailed": "{{name}} не вдалося", + "quickActionError": "Не вдалося виконати {{name}}", + "ports": { + "title": "Порти прослуховування", + "protocol": "Протокол", + "port": "Порт", + "address": "Адреса", + "process": "Процес", + "search": "Пошук портів...", + "allProtocols": "Усі", + "noData": "Немає даних про порти прослуховування" + }, + "firewall": { + "title": "Брандмауер", + "inactive": "Неактивний", + "policy": "Політика", + "rules": "правила", + "noRules": "У цьому ланцюжку немає правил", + "noData": "Дані брандмауера недоступні", + "action": "Дія", + "protocol": "Прото", + "port": "Порт", + "source": "Джерело", + "anywhere": "Будь-де", + "chains": "ланцюги" + }, + "loadAvg": "Середнє навантаження", + "swap": "Обмін", + "architecture": "Архітектура", + "refresh": "Оновити", + "retry": "Повторити спробу", + "customize": "Налаштувати макет", + "reset": "Скинути", + "tabLive": "Живий", + "editModeInstructions": "Перетягуйте картки, щоб змінити порядок, перетягуйте нижній край, щоб змінити розмір, і скористайтеся кнопкою ширини, щоб змінити ширину картки. Додавайте або видаляйте картки нижче.", + "managers": { + "services": "Послуги", + "processInspector": "Інспектор процесів", + "logViewer": "Переглядач журналів", + "cron": "Cron-завдання", + "packages": "Пакети", + "ssl": "SSL-сертифікати", + "firewall": "Брандмауер", + "users": "Користувачі та дозволи", + "healthCheck": "Перевірки здоров'я", + "diskBreakdown": "Поломка диска", + "systemdTimers": "Таймери", + "topMemory": "Найкраще за пам'яттю", + "noData": "Немає даних", + "sudoHint": "Встановіть пароль sudo для цього хоста в редакторі хостів, щоб увімкнути привілейовані дії.", + "filter": "Фільтр...", + "start": "Початок", + "stop": "СТІЙ", + "restart": "Перезавантажити", + "actionDone": "{{name}} оновлено", + "actionFailed": "Дія не вдалася", + "signalSent": "Сигнал, що надсилається до ПІД-регулятора {{pid}}", + "killHint": "Клацніть: завершити (SIGTERM). Клацніть правою кнопкою миші: примусово завершити (SIGKILL).", + "working": "Працюємо...", + "update": "Оновлення", + "upgradeAll": "Оновити все", + "allUpToDate": "Все актуально", + "save": "Зберегти", + "command": "Команда", + "enabled": "Увімкнено", + "cronSaved": "Кронтаб оновлено", + "clients": "Клієнти", + "dryRun": "Сухий пробіг", + "renew": "Поновити", + "noAcmeClient": "На цьому хості не знайдено клієнта ACME (certbot або acme.sh).", + "addInputRule": "Додати правило INPUT", + "firewallWarning": "Зміни дійсні лише під час виконання, доки не будуть збережені. Будьте обережні, щоб не заблокувати себе.", + "ruleApplied": "Правило застосовано", + "invalidPort": "Введіть дійсний порт (1-65535)", + "newUsername": "Нове ім'я користувача", + "addUser": "Додати", + "deleteUser": "Видалити користувача", + "noHealthChecks": "Перевірки справності ще не налаштовано.", + "follow": "Стежити", + "noLogData": "Немає виводу журналу.", + "tree": "Дерево", + "enableDisable": "Увімкнути/вимкнути під час завантаження", + "grantSudo": "Грант sudo", + "revokeSudo": "Скасувати sudo", + "sslIssueCert": "Випуск сертифіката", + "sslExpired": "Термін дії минув", + "sslInDays": "у {{days}}днях", + "sslNeedDomain": "Введіть принаймні один домен", + "sslIssued": "Сертифікат видано", + "sslDomainsPlaceholder": "example.com, www.example.com", + "sslHttpStandalone": "HTTP (автономний)", + "sslHttpWebroot": "HTTP (корінь веб-сайту)", + "sslDns": "ДНС", + "sslDnsProvider": "DNS-провайдер (наприклад, cloudflare)", + "sslIssueHint": "Облікові дані постачальника DNS вже мають бути налаштовані на хості.", + "sslRevoke": "Скасувати сертифікат", + "sslRevoked": "Сертифікат анульовано", + "sslRevokeConfirm": "Скасувати та видалити сертифікат \"{{name}}\"? Цю дію неможливо скасувати.", + "healthRun": "Бігти", + "healthName": "Ім'я", + "healthTarget": "Хост / адреса", + "healthAddCheck": "Додати чек", + "healthSaved": "Перевірки стану збережено", + "healthMissingFields": "Кожній перевірці потрібні ім'я та ціль", + "logFile": "Файл", + "logUnit": "Одиниця", + "logCustomPath": "Власний шлях до /var/log (необов'язково)", + "logGrep": "Фільтрувальні лінії...", + "firewallPersist": "Зберегти правила", + "firewallPersisted": "Правила брандмауера збереглися", + "wireguard": "WireGuard", + "tailscale": "Хвостова шкала", + "wgNotInstalled": "WireGuard не встановлено на цьому хості", + "wgNoInterfaces": "Немає налаштованих інтерфейсів WireGuard", + "wgInterfaceUp": "Підніміть", + "wgInterfaceDown": "Збити", + "wgBringingUp": "Викликаємо {{name}}...", + "wgBringingDown": "Зниження {{name}}...", + "wgInterfaceUpDone": "{{name}} активовано", + "wgInterfaceDownDone": "{{name}} не працює", + "wgListenPort": "Порт", + "wgPublicKey": "Відкритий ключ", + "wgEndpoint": "Кінцева точка", + "wgAllowedIPs": "Дозволені IP-адреси", + "wgLastHandshake": "Останнє рукостискання", + "wgHandshakeNever": "Ніколи", + "wgTransfer": "Переказ", + "tsNotInstalled": "Tailscale не встановлено на цьому хості", + "tsRunning": "Біг", + "tsStopped": "Зупинено", + "tsEnable": "Підключитися", + "tsDisable": "Відключитися", + "tsEnabling": "Підключення до Tailscale...", + "tsDisabling": "Відключення від Tailscale...", + "tsEnabled": "Підключено хвостову шкалу", + "tsDisabled": "Хвостова шкала відключена", + "tsIPs": "IP-адреси Tailscale", + "tsPeers": "Однолітки", + "tsOnline": "Онлайн", + "tsOffline": "Офлайн", + "tsExitNode": "Вихідний вузол", + "tsExitNodeActive": "Вихідний вузол активний", + "tsHostname": "Ім'я хоста" + } + }, + "metricsHistory": { + "title": "Історія показників", + "historySuffix": "Історія", + "cpuMemoryDisk": "Процесор / Пам'ять / Диск", + "network": "Мережа", + "download": "Рецепт", + "upload": "Техас", + "noData": "Для цього періоду часу немає історичних даних.", + "custom": "Користувацька", + "to": "до", + "apply": "Застосувати", + "viewHistory": "Переглянути історію" + }, + "proxmoxStats": { + "tabTitle": "Статистика Proxmox", + "cpuUsage": "Використання процесора", + "memoryUsage": "Використання пам'яті", + "diskUsage": "Використання диска", + "networkInterfaces": "Мережеві інтерфейси", + "uptime": "Час безперебійної роботи", + "systemInfo": "Інформація про систему", + "guestsSummary": "Гості", + "storagePools": "Пули зберігання", + "clusterHealth": "Кластерне здоров'я", + "cpuCores_one": "{{count}} Ядро", + "cpuCores_other": "{{count}} Ядра", + "used": "Використано", + "total": "Всього", + "hostname": "Ім'я хоста", + "kernel": "Ядро", + "pveVersion": "ПВЕ-версія", + "name": "Ім'я", + "status": "Статус", + "type": "Тип", + "cpu": "Процесор", + "mem": "Мем", + "disk": "Диск", + "running": "Біг", + "stopped": "Зупинено", + "guestCounts": "{{running}}/{{total}} бігає", + "inactive": "Неактивний", + "notClustered": "Автономний вузол (не є частиною кластера)", + "quorate": "Кворат", + "notQuorate": "Не має кворуму", + "nodeOnline": "Онлайн", + "nodeOffline": "Офлайн", + "noHostSelected": "Хост не вибрано", + "pveshNotFound": "pvesh не знайдено - це вузол Proxmox?", + "nodeDetectionFailed": "Не вдається визначити дійсну назву вузла Proxmox", + "connecting": "Підключення...", + "connectionFailed": "Не вдалося підключитися до вузла Proxmox", + "refresh": "Оновити", + "searchGuests": "Пошук гостей...", + "filterAll": "Усі", + "filterVm": "ВМ", + "filterLxc": "LXC", + "noGuests": "На цьому вузлі не знайдено віртуальних машин або контейнерів LXC.", + "noGuestsMatch": "Немає гостей, які відповідають поточним фільтрам." + }, + "nav": { + "hostMetrics": "Метрики хоста" + }, + "hosts": { + "tabHostMetrics": "Метрики хоста", + "enableProxmoxStats": "Увімкнути статистику Proxmox", + "enableProxmoxStatsDesc": "Показати вкладку статистики Proxmox для цього хоста зі статистикою вузла, гостьового сервера, сховища та кластера, зібраною через SSH.", + "proxmoxStatsPollInterval": "Інтервал опитування (секунди)", + "proxmoxStatsPollIntervalDesc": "Мінімум 15 секунд. Як часто оновлювати статистику вузла Proxmox.", + "proxmoxStatsNodeOverride": "Перевизначення назви вузла", + "proxmoxStatsNodeOverrideDesc": "Перевизначити автоматичне визначення імені вузла Proxmox (за замовчуванням визначається через ім'я хоста).", + "proxmoxStatsNodeOverridePlaceholder": "Автоматично визначено за назвою хоста", + "metricsCollectionLabel": "Колекція показників", + "enableMetricsLabel": "Увімкнути метрики", + "enableMetricsDesc": "Збирати показники процесора, оперативної пам'яті, дискового простору та інші показники з цього хоста", + "useGlobalMetrics": "Використовувати глобальний інтервал", + "useGlobalMetricsDesc": "Перевизначити інтервалом показників на рівні сервера", + "metricsIntervalS": "Інтервал показників (и)", + "metricsIntervalDesc2": "Секунди між знімками показників", + "excludedMountsLabel": "Виключені маунти", + "monitoredMountsLabel": "Користувацькі контрольовані шляхи", + "monitoredMountsDesc": "Додайте шляхи, які не відображаються як окремі монтування, включаючи шляхи Home Assistant, змонтовані за допомогою прив’язки, такі як /config.", + "monitoredMountPathPlaceholder": "Шлях (/config, /mnt/data)", + "monitoredMountLabelPlaceholder": "Мітка (необов'язково)", + "addMonitoredMount": "Додати шлях", + "excludedMountsDesc": "Приховати певні точки монтування або типи файлових систем (наприклад, nfs, cifs) від використання диска та сповіщень для цього хоста.", + "excludedMountsPlaceholder": "Шлях монтування (/mnt/nas) або тип файлової системи (nfs, cifs)", + "excludedMountsEmpty": "Монтування не виключено. Відображаються всі виявлені файлові системи.", + "addExcludedMount": "Додати", + "visibleWidgets": "Видимі віджети", + "widgetsMovedToHostMetrics": "Тепер картки додаються, упорядковуються та змінюються за розміром безпосередньо на вкладці «Метрики хоста». Відкрийте «Метрики хоста» для цього хоста та скористайтеся функцією «Налаштувати», щоб вибрати, які картки відображатимуться.", + "quickActionsLabel": "Швидкі дії", + "quickActionsToolbar": "Швидкі дії відображаються як кнопки на панелі інструментів «Метрики хоста» для виконання команд одним клацанням миші.", + "noQuickActions": "Поки що жодних швидких дій.", + "buttonLabel": "Мітка кнопки", + "selectSnippetPlaceholder": "Вибрати фрагмент...", + "addActionBtn": "Додати дію" + }, + "onboarding": { + "feature_metrics": "Метрики та сповіщення", + "feature_metrics_desc": "Відстежуйте роботу процесора, пам'яті та диска з плином часу та отримуйте сповіщення, коли вони виходять з ладу." + }, + "admin": { + "metricsHistoryRetention": "Збереження історії показників", + "metricsHistoryRetentionRange": "Від 1 до 90 днів", + "days": "дні" + }, + "homepage": { + "noData": "Дані недоступні", + "showCurrentValue": "Показати поточне значення", + "chartMetric": "Метрика", + "metricRange": "Діапазон" + } +} diff --git a/plugins/host-metrics/locales/translated/vi_VN.json b/plugins/host-metrics/locales/translated/vi_VN.json new file mode 100644 index 000000000..51fcbf837 --- /dev/null +++ b/plugins/host-metrics/locales/translated/vi_VN.json @@ -0,0 +1,313 @@ +{ + "hostMetrics": { + "cpu": "CPU", + "memory": "Bộ nhớ", + "disk": "Ổ đĩa", + "network": "Mạng", + "uptime": "Thời gian hoạt động", + "processes": "Tiến trình", + "available": "Khả dụng", + "free": "Trống", + "connecting": "Đang kết nối...", + "connectionFailed": "Kết nối máy chủ thất bại", + "naCpus": "N/A CPU", + "cpuCores_one": "{{count}} Lõi", + "cpuCores_other": "{{count}} Lõi", + "cpuUsage": "Mức sử dụng CPU", + "memoryUsage": "Mức sử dụng bộ nhớ", + "diskUsage": "Mức sử dụng ổ đĩa", + "selectFilesystem": "Chọn hệ thống tệp", + "temperature": "Nhiệt độ", + "highestTemperature": "Nhiệt độ cao nhất", + "primaryTemperatureSensor": "Cảm biến chính", + "gpu": { + "title": "GPU", + "noDevice": "Không phát hiện thấy GPU NVIDIA. Hãy cài đặt trình điều khiển NVIDIA (nó cung cấp lệnh nvidia-smi) để xem các thông số GPU.", + "driver": "Tài xế {{version}}", + "utilization": "Sử dụng", + "memory": "VRAM", + "temperature": "Nhiệt độ", + "power": "Quyền lực", + "fan": "Cái quạt", + "processes": "Các quy trình GPU", + "noProcesses": "Hiện không có tiến trình nào đang sử dụng GPU." + }, + "failedToFetchHostConfig": "Không tải được cấu hình máy chủ", + "serverOffline": "Máy chủ ngoại tuyến", + "cannotFetchMetrics": "Không thể tải số liệu từ máy chủ ngoại tuyến", + "totpFailed": "Xác minh TOTP thất bại", + "noneAuthNotSupported": "Host Metrics không hỗ trợ kiểu xác thực 'none'.", + "noHostSelected": "Chưa chọn máy chủ", + "load": "Tải", + "systemInfo": "Thông tin hệ thống", + "hostname": "Tên máy chủ", + "operatingSystem": "Hệ điều hành", + "kernel": "Nhân", + "seconds": "giây", + "networkInterfaces": "Giao diện mạng", + "noInterfacesFound": "Không tìm thấy giao diện mạng nào", + "noProcessesFound": "Không tìm thấy tiến trình nào", + "processesTotal": "Tổng", + "processesRunning": "đang chạy", + "loginStats": "Thống kê đăng nhập SSH", + "noRecentLoginData": "Không có dữ liệu đăng nhập gần đây", + "executingQuickAction": "Đang thực thi {{name}}...", + "quickActionSuccess": "{{name}} đã hoàn tất thành công", + "quickActionFailed": "{{name}} thất bại", + "quickActionError": "Thực thi {{name}} thất bại", + "ports": { + "title": "Cổng đang lắng nghe", + "protocol": "Giao thức", + "port": "Cổng", + "address": "Địa chỉ", + "process": "Tiến trình", + "search": "Tìm kiếm cổng...", + "allProtocols": "Tất cả", + "noData": "Không có dữ liệu cổng đang lắng nghe" + }, + "firewall": { + "title": "Tường lửa", + "inactive": "Không hoạt động", + "policy": "Chính sách", + "rules": "quy tắc", + "noRules": "Không có quy tắc nào trong chuỗi này", + "noData": "Không có dữ liệu tường lửa", + "action": "Hành động", + "protocol": "Giao thức", + "port": "Cổng", + "source": "Nguồn", + "anywhere": "Mọi nơi", + "chains": "chuỗi" + }, + "loadAvg": "Tải trung bình", + "swap": "Swap", + "architecture": "Kiến trúc", + "refresh": "Làm mới", + "retry": "Thử lại", + "customize": "Tùy chỉnh bố cục", + "reset": "Đặt lại", + "tabLive": "Trực tiếp", + "editModeInstructions": "Kéo thẻ để sắp xếp lại, kéo cạnh dưới để thay đổi kích thước, và dùng nút chiều rộng để thay đổi độ rộng thẻ. Thêm hoặc xóa thẻ bên dưới.", + "managers": { + "services": "Dịch vụ", + "processInspector": "Trình kiểm tra tiến trình", + "logViewer": "Trình xem nhật ký", + "cron": "Cron Jobs", + "packages": "Gói", + "ssl": "Chứng chỉ SSL", + "firewall": "Tường lửa", + "users": "Người dùng & Quyền", + "healthCheck": "Kiểm tra sức khỏe", + "diskBreakdown": "Phân tích ổ đĩa", + "systemdTimers": "Bộ hẹn giờ", + "topMemory": "Top theo bộ nhớ", + "noData": "Không có dữ liệu", + "sudoHint": "Đặt mật khẩu sudo cho máy chủ này trong trình chỉnh sửa máy chủ để kích hoạt các hành động đặc quyền.", + "filter": "Lọc...", + "start": "Khởi động", + "stop": "Dừng", + "restart": "Khởi động lại", + "actionDone": "{{name}} được cập nhật", + "actionFailed": "Hành động thất bại", + "signalSent": "Đã gửi tín hiệu đến PID {{pid}}", + "killHint": "Nhấp: kết thúc (SIGTERM). Nhấp chuột phải: buộc kết thúc (SIGKILL).", + "working": "Đang làm việc...", + "update": "Cập nhật", + "upgradeAll": "Nâng cấp tất cả", + "allUpToDate": "Tất cả đều mới nhất", + "save": "Lưu", + "command": "Lệnh", + "enabled": "Đã bật", + "cronSaved": "Đã cập nhật crontab", + "clients": "Máy khách", + "dryRun": "Chạy thử", + "renew": "Gia hạn", + "noAcmeClient": "Không tìm thấy máy khách ACME (certbot hoặc acme.sh) trên máy này.", + "addInputRule": "Thêm quy tắc INPUT", + "firewallWarning": "Thay đổi chỉ tạm thời, chưa được lưu vĩnh viễn. Cẩn thận kẻo tự khóa mình ra ngoài.", + "ruleApplied": "Quy tắc đã được áp dụng", + "invalidPort": "Nhập cổng hợp lệ (1-65535)", + "newUsername": "Tên người dùng mới", + "addUser": "Thêm", + "deleteUser": "Xóa người dùng", + "noHealthChecks": "Chưa có kiểm tra trạng thái nào được cấu hình.", + "follow": "Theo dõi", + "noLogData": "Không có dữ liệu nhật ký.", + "tree": "Dạng cây", + "enableDisable": "Bật / tắt khi khởi động", + "grantSudo": "Cấp quyền sudo", + "revokeSudo": "Thu hồi quyền sudo", + "sslIssueCert": "Cấp chứng chỉ", + "sslExpired": "Đã hết hạn", + "sslInDays": "trong {{days}}d", + "sslNeedDomain": "Nhập ít nhất một tên miền", + "sslIssued": "Đã cấp chứng chỉ", + "sslDomainsPlaceholder": "example.com, www.example.com", + "sslHttpStandalone": "HTTP (độc lập)", + "sslHttpWebroot": "HTTP (webroot)", + "sslDns": "DNS", + "sslDnsProvider": "Nhà cung cấp DNS (ví dụ: cloudflare)", + "sslIssueHint": "Thông tin xác thực nhà cung cấp DNS phải được cấu hình trên máy chủ.", + "sslRevoke": "Thu hồi chứng chỉ", + "sslRevoked": "Chứng chỉ đã bị thu hồi", + "sslRevokeConfirm": "Thu hồi và xóa chứng chỉ \"{{name}}\"? Hành động này không thể hoàn tác.", + "healthRun": "Chạy", + "healthName": "Tên", + "healthTarget": "Máy chủ / địa chỉ", + "healthAddCheck": "Thêm kiểm tra", + "healthSaved": "Đã lưu kiểm tra sức khỏe", + "healthMissingFields": "Mỗi kiểm tra cần có tên và mục tiêu", + "logFile": "Tệp", + "logUnit": "Đơn vị", + "logCustomPath": "Đường dẫn tùy chỉnh trong /var/log (tùy chọn)", + "logGrep": "Lọc dòng...", + "firewallPersist": "Lưu quy tắc", + "firewallPersisted": "Đã lưu quy tắc tường lửa", + "wireguard": "WireGuard", + "tailscale": "Tailscale", + "wgNotInstalled": "WireGuard chưa được cài đặt trên máy chủ này", + "wgNoInterfaces": "Chưa cấu hình giao diện WireGuard nào", + "wgInterfaceUp": "Khởi động", + "wgInterfaceDown": "Dừng", + "wgBringingUp": "Đang khởi động {{name}}...", + "wgBringingDown": "Đang dừng {{name}}...", + "wgInterfaceUpDone": "{{name}} đã hoạt động", + "wgInterfaceDownDone": "{{name}} đã dừng", + "wgListenPort": "Cổng", + "wgPublicKey": "Khóa công khai", + "wgEndpoint": "Điểm cuối", + "wgAllowedIPs": "IP được phép", + "wgLastHandshake": "Lần bắt tay cuối", + "wgHandshakeNever": "Chưa bao giờ", + "wgTransfer": "Truyền tải", + "tsNotInstalled": "Tailscale chưa được cài đặt trên máy chủ này", + "tsRunning": "Đang chạy", + "tsStopped": "Đã dừng", + "tsEnable": "Kết nối", + "tsDisable": "Ngắt kết nối", + "tsEnabling": "Đang kết nối đến Tailscale...", + "tsDisabling": "Đang ngắt kết nối khỏi Tailscale...", + "tsEnabled": "Đã kết nối Tailscale", + "tsDisabled": "Đã ngắt kết nối Tailscale", + "tsIPs": "IP Tailscale", + "tsPeers": "Các máy ngang hàng", + "tsOnline": "Trực tuyến", + "tsOffline": "Ngoại tuyến", + "tsExitNode": "Nút thoát", + "tsExitNodeActive": "Nút thoát đang hoạt động", + "tsHostname": "Tên máy chủ" + } + }, + "metricsHistory": { + "title": "Lịch sử chỉ số", + "historySuffix": "Lịch sử", + "cpuMemoryDisk": "CPU / Bộ nhớ / Ổ đĩa", + "network": "Mạng", + "download": "RX", + "upload": "TX", + "noData": "Không có dữ liệu lịch sử cho khoảng thời gian này.", + "custom": "Tùy chỉnh", + "to": "đến", + "apply": "Áp dụng", + "viewHistory": "Xem lịch sử" + }, + "proxmoxStats": { + "tabTitle": "Thống kê Proxmox", + "cpuUsage": "Mức sử dụng CPU", + "memoryUsage": "Mức sử dụng bộ nhớ", + "diskUsage": "Mức sử dụng ổ đĩa", + "networkInterfaces": "Giao diện mạng", + "uptime": "Thời gian hoạt động", + "systemInfo": "Thông tin hệ thống", + "guestsSummary": "Khách", + "storagePools": "Các bể chứa", + "clusterHealth": "Cluster Health", + "cpuCores_one": "{{count}} Lõi", + "cpuCores_other": "{{count}} Lõi", + "used": "Đã sử dụng", + "total": "Tổng cộng", + "hostname": "Tên máy chủ", + "kernel": "Hạt nhân", + "pveVersion": "Phiên bản PVE", + "name": "Tên", + "status": "Trạng thái", + "type": "Kiểu", + "cpu": "CPU", + "mem": "Mem", + "disk": "Đĩa", + "running": "Đang chạy", + "stopped": "Đã dừng lại", + "guestCounts": "{{running}}/{{total}} đang chạy", + "inactive": "Không hoạt động", + "notClustered": "Nút độc lập (không thuộc cụm máy chủ)", + "quorate": "Quorate", + "notQuorate": "Không đủ số lượng", + "nodeOnline": "Trực tuyến", + "nodeOffline": "Ngoại tuyến", + "noHostSelected": "Chưa chọn máy chủ nào", + "pveshNotFound": "Không tìm thấy pvesh - đây có phải là một node Proxmox không?", + "nodeDetectionFailed": "Không thể xác định tên nút Proxmox hợp lệ.", + "connecting": "Đang kết nối...", + "connectionFailed": "Không thể kết nối đến nút Proxmox.", + "refresh": "Làm cho khỏe lại", + "searchGuests": "Tìm kiếm khách...", + "filterAll": "Tất cả", + "filterVm": "Máy ảo", + "filterLxc": "LXC", + "noGuests": "Không tìm thấy máy ảo hoặc vùng chứa LXC nào trên nút này.", + "noGuestsMatch": "Hiện không có khách nào phù hợp với bộ lọc hiện tại." + }, + "nav": { + "hostMetrics": "Chỉ số máy chủ" + }, + "hosts": { + "tabHostMetrics": "Số liệu máy chủ", + "enableProxmoxStats": "Bật thống kê Proxmox", + "enableProxmoxStatsDesc": "Hiển thị tab Thống kê Proxmox cho máy chủ này với các số liệu thống kê trực tiếp về nút, máy ảo, bộ nhớ và cụm được thu thập qua SSH.", + "proxmoxStatsPollInterval": "Khoảng thời gian giữa các lần thăm dò (giây)", + "proxmoxStatsPollIntervalDesc": "Tối thiểu 15 giây. Tần suất làm mới số liệu thống kê của node Proxmox.", + "proxmoxStatsNodeOverride": "Ghi đè tên nút", + "proxmoxStatsNodeOverrideDesc": "Ghi đè tính năng tự động phát hiện tên nút Proxmox (mặc định được phát hiện thông qua tên máy chủ).", + "proxmoxStatsNodeOverridePlaceholder": "Tự động nhận diện từ tên máy chủ", + "metricsCollectionLabel": "Thu thập số liệu", + "enableMetricsLabel": "Bật thu thập số liệu", + "enableMetricsDesc": "Thu thập CPU, RAM, đĩa và các số liệu khác từ máy này", + "useGlobalMetrics": "Dùng khoảng thời gian toàn cục", + "useGlobalMetricsDesc": "Ghi đè bằng khoảng thời gian thu thập số liệu toàn máy chủ", + "metricsIntervalS": "Khoảng thu thập số liệu (giây)", + "metricsIntervalDesc2": "Số giây giữa các lần chụp số liệu", + "excludedMountsLabel": "Giá đỡ bị loại trừ", + "monitoredMountsLabel": "Đường dẫn được giám sát tùy chỉnh", + "monitoredMountsDesc": "Thêm các đường dẫn không được hiển thị dưới dạng các điểm gắn kết riêng biệt, bao gồm cả các đường dẫn Home Assistant được gắn kết bằng bind, chẳng hạn như /config.", + "monitoredMountPathPlaceholder": "Đường dẫn (/config, /mnt/data)", + "monitoredMountLabelPlaceholder": "Nhãn (tùy chọn)", + "addMonitoredMount": "Thêm đường dẫn", + "excludedMountsDesc": "Ẩn các điểm gắn kết hoặc loại hệ thống tập tin cụ thể (ví dụ: nfs, cifs) khỏi thông tin sử dụng ổ đĩa và cảnh báo cho máy chủ này.", + "excludedMountsPlaceholder": "Đường dẫn gắn kết (/mnt/nas) hoặc loại hệ thống tệp (nfs, cifs)", + "excludedMountsEmpty": "Không có điểm gắn kết nào bị loại trừ. Tất cả các hệ thống tập tin được phát hiện đều được hiển thị.", + "addExcludedMount": "Thêm vào", + "visibleWidgets": "Widget hiển thị", + "widgetsMovedToHostMetrics": "Các thẻ hiện được thêm, sắp xếp và thay đổi kích thước trực tiếp trong tab Số liệu máy. Mở Số liệu máy cho máy này và dùng Tùy chỉnh để chọn thẻ hiển thị.", + "quickActionsLabel": "Hành động nhanh", + "quickActionsToolbar": "Hành động nhanh xuất hiện dưới dạng nút trên thanh công cụ Chỉ số máy để thực thi lệnh một lần nhấp.", + "noQuickActions": "Chưa có hành động nhanh nào.", + "buttonLabel": "Nhãn nút", + "selectSnippetPlaceholder": "Chọn đoạn mã...", + "addActionBtn": "Thêm hành động" + }, + "onboarding": { + "feature_metrics": "Số liệu và cảnh báo", + "feature_metrics_desc": "Theo dõi hiệu năng CPU, bộ nhớ và ổ đĩa theo thời gian, và nhận cảnh báo khi chúng gặp sự cố." + }, + "admin": { + "metricsHistoryRetention": "Thời gian lưu trữ lịch sử số liệu", + "metricsHistoryRetentionRange": "1 đến 90 ngày", + "days": "ngày" + }, + "homepage": { + "noData": "Không có dữ liệu", + "showCurrentValue": "Hiển thị giá trị hiện tại", + "chartMetric": "Chỉ số", + "metricRange": "Phạm vi" + } +} diff --git a/plugins/host-metrics/locales/translated/zh_CN.json b/plugins/host-metrics/locales/translated/zh_CN.json new file mode 100644 index 000000000..a1c60c10c --- /dev/null +++ b/plugins/host-metrics/locales/translated/zh_CN.json @@ -0,0 +1,313 @@ +{ + "hostMetrics": { + "cpu": "CPU", + "memory": "内存", + "disk": "磁盘", + "network": "网络", + "uptime": "运行时间", + "processes": "进程", + "available": "可用", + "free": "空闲", + "connecting": "连接中...", + "connectionFailed": "连接服务器失败", + "naCpus": "N/A CPU", + "cpuCores_one": "{{count}} 核心", + "cpuCores_other": "{{count}} 核心", + "cpuUsage": "CPU 使用率", + "memoryUsage": "内存使用率", + "diskUsage": "磁盘使用率", + "selectFilesystem": "选择文件系统", + "temperature": "温度", + "highestTemperature": "最高温度", + "primaryTemperatureSensor": "主传感器", + "gpu": { + "title": "GPU", + "noDevice": "未检测到NVIDIA GPU。请安装NVIDIA驱动程序(它提供nvidia-smi)以查看GPU指标。", + "driver": "司机 {{version}}", + "utilization": "利用率", + "memory": "显存", + "temperature": "温度", + "power": "力量", + "fan": "扇子", + "processes": "GPU 进程", + "noProcesses": "没有进程正在使用 GPU" + }, + "failedToFetchHostConfig": "获取主机配置失败", + "serverOffline": "服务器离线", + "cannotFetchMetrics": "无法从离线服务器获取指标", + "totpFailed": "TOTP 验证失败", + "noneAuthNotSupported": "主机指标不支持 'none' 认证类型。", + "noHostSelected": "未选择主机", + "load": "负载", + "systemInfo": "系统信息", + "hostname": "主机名", + "operatingSystem": "操作系统", + "kernel": "内核", + "seconds": "秒", + "networkInterfaces": "网络接口", + "noInterfacesFound": "未找到网络接口", + "noProcessesFound": "未找到进程", + "processesTotal": "总计", + "processesRunning": "运行中", + "loginStats": "SSH 登录统计", + "noRecentLoginData": "无最近登录数据", + "executingQuickAction": "正在执行 {{name}}...", + "quickActionSuccess": "{{name}} 执行成功", + "quickActionFailed": "{{name}} 执行失败", + "quickActionError": "执行 {{name}} 失败", + "ports": { + "title": "监听端口", + "protocol": "协议", + "port": "端口", + "address": "地址", + "process": "进程", + "search": "搜索端口...", + "allProtocols": "全部", + "noData": "无监听端口数据" + }, + "firewall": { + "title": "防火墙", + "inactive": "未激活", + "policy": "策略", + "rules": "规则", + "noRules": "该链中无规则", + "noData": "无可用防火墙数据", + "action": "操作", + "protocol": "协议", + "port": "端口", + "source": "来源", + "anywhere": "任意", + "chains": "链" + }, + "loadAvg": "平均负载", + "swap": "交换空间", + "architecture": "架构", + "refresh": "刷新", + "retry": "重试", + "customize": "自定义布局", + "reset": "重置", + "tabLive": "实时", + "editModeInstructions": "拖动卡片可重新排序,拖动底部边缘可调整大小,使用宽度按钮可更改卡片的跨度。在下方添加或移除卡片。", + "managers": { + "services": "服务", + "processInspector": "进程查看器", + "logViewer": "日志查看器", + "cron": "定时任务", + "packages": "软件包", + "ssl": "SSL证书", + "firewall": "防火墙", + "users": "用户与权限", + "healthCheck": "健康检查", + "diskBreakdown": "磁盘详情", + "systemdTimers": "计时器", + "topMemory": "按内存占用排行", + "noData": "无数据", + "sudoHint": "在主机编辑器中为此主机设置 sudo 密码以启用特权操作。", + "filter": "筛选...", + "start": "启动", + "stop": "停止", + "restart": "重启", + "actionDone": "{{name}} 已更新", + "actionFailed": "操作失败", + "signalSent": "信号已发送至 PID {{pid}}", + "killHint": "单击:终止 (SIGTERM)。右键单击:强制终止 (SIGKILL)。", + "working": "处理中...", + "update": "更新", + "upgradeAll": "全部升级", + "allUpToDate": "所有内容均为最新", + "save": "保存", + "command": "命令", + "enabled": "已启用", + "cronSaved": "定时任务已更新", + "clients": "客户端", + "dryRun": "试运行", + "renew": "续期", + "noAcmeClient": "此主机上未找到 ACME 客户端 (certbot 或 acme.sh)。", + "addInputRule": "添加 INPUT 规则", + "firewallWarning": "更改仅在运行时有效,需持久化保存。小心不要将自己锁定在外。", + "ruleApplied": "规则已应用", + "invalidPort": "请输入有效端口 (1-65535)", + "newUsername": "新用户名", + "addUser": "添加", + "deleteUser": "删除用户", + "noHealthChecks": "尚未配置健康检查。", + "follow": "跟踪", + "noLogData": "无日志输出。", + "tree": "树形", + "enableDisable": "启用/禁用开机自启", + "grantSudo": "授予 sudo", + "revokeSudo": "撤销 sudo", + "sslIssueCert": "签发证书", + "sslExpired": "已过期", + "sslInDays": "{{days}} 天后", + "sslNeedDomain": "至少输入一个域名", + "sslIssued": "证书已签发", + "sslDomainsPlaceholder": "example.com, www.example.com", + "sslHttpStandalone": "HTTP (独立模式)", + "sslHttpWebroot": "HTTP (webroot)", + "sslDns": "DNS", + "sslDnsProvider": "DNS 提供商 (如 cloudflare)", + "sslIssueHint": "DNS 提供商凭据必须已在主机上配置。", + "sslRevoke": "吊销证书", + "sslRevoked": "证书已吊销", + "sslRevokeConfirm": "吊销并删除证书 \"{{name}}\"?此操作无法撤销。", + "healthRun": "运行", + "healthName": "名称", + "healthTarget": "主机 / 地址", + "healthAddCheck": "添加检查", + "healthSaved": "健康检查已保存", + "healthMissingFields": "每个检查都需要名称和目标", + "logFile": "文件", + "logUnit": "单元", + "logCustomPath": "自定义路径 (位于 /var/log 下,可选)", + "logGrep": "过滤行...", + "firewallPersist": "持久化规则", + "firewallPersisted": "防火墙规则已持久化", + "wireguard": "WireGuard", + "tailscale": "Tailscale", + "wgNotInstalled": "此主机未安装 WireGuard", + "wgNoInterfaces": "未配置 WireGuard 接口", + "wgInterfaceUp": "启用", + "wgInterfaceDown": "停用", + "wgBringingUp": "正在启用 {{name}}...", + "wgBringingDown": "正在停用 {{name}}...", + "wgInterfaceUpDone": "{{name}} 已启用", + "wgInterfaceDownDone": "{{name}} 已停用", + "wgListenPort": "端口", + "wgPublicKey": "公钥", + "wgEndpoint": "对端", + "wgAllowedIPs": "允许的 IP", + "wgLastHandshake": "上次握手", + "wgHandshakeNever": "从未", + "wgTransfer": "传输", + "tsNotInstalled": "此主机未安装 Tailscale", + "tsRunning": "运行中", + "tsStopped": "已停止", + "tsEnable": "连接", + "tsDisable": "断开连接", + "tsEnabling": "正在连接到 Tailscale...", + "tsDisabling": "正在断开 Tailscale 连接...", + "tsEnabled": "Tailscale 已连接", + "tsDisabled": "Tailscale 已断开连接", + "tsIPs": "Tailscale IP", + "tsPeers": "节点", + "tsOnline": "在线", + "tsOffline": "离线", + "tsExitNode": "出口节点", + "tsExitNodeActive": "出口节点活跃", + "tsHostname": "主机名" + } + }, + "metricsHistory": { + "title": "指标历史", + "historySuffix": "历史", + "cpuMemoryDisk": "CPU / 内存 / 磁盘", + "network": "网络", + "download": "RX", + "upload": "TX", + "noData": "此时间范围内没有可用的历史数据。", + "custom": "自定义", + "to": "至", + "apply": "应用", + "viewHistory": "查看历史" + }, + "proxmoxStats": { + "tabTitle": "Proxmox 统计数据", + "cpuUsage": "CPU 使用率", + "memoryUsage": "内存使用情况", + "diskUsage": "磁盘使用情况", + "networkInterfaces": "网络接口", + "uptime": "正常运行时间", + "systemInfo": "系统信息", + "guestsSummary": "客户主机", + "storagePools": "存储池", + "clusterHealth": "集群健康", + "cpuCores_one": "{{count}} 核", + "cpuCores_other": "{{count}} 核", + "used": "已用", + "total": "总计", + "hostname": "主机名", + "kernel": "内核", + "pveVersion": "PVE 版本", + "name": "名称", + "status": "状态", + "type": "类型", + "cpu": "CPU", + "mem": "内存", + "disk": "磁盘", + "running": "运行中", + "stopped": "停止", + "guestCounts": "{{running}}/{{total}} 运行中", + "inactive": "未激活", + "notClustered": "独立节点(非集群的一部分)", + "quorate": "达到法定节点数量", + "notQuorate": "未达到法定节点数量", + "nodeOnline": "在线", + "nodeOffline": "离线", + "noHostSelected": "未选择主机", + "pveshNotFound": "未找到 pvesh - 这是 Proxmox 节点吗?", + "nodeDetectionFailed": "无法确定有效的 Proxmox 节点名称", + "connecting": "正在连接...", + "connectionFailed": "连接到 Proxmox 节点失败", + "refresh": "刷新", + "searchGuests": "搜索客户主机...", + "filterAll": "全部", + "filterVm": "虚拟机", + "filterLxc": "LXC", + "noGuests": "此节点上未找到虚拟机或 LXC 容器。", + "noGuestsMatch": "没有符合当前筛选条件的客户主机。" + }, + "nav": { + "hostMetrics": "主机指标" + }, + "hosts": { + "tabHostMetrics": "主机指标", + "enableProxmoxStats": "启用 Proxmox 统计信息", + "enableProxmoxStatsDesc": "显示此主机的 Proxmox 统计信息标签页,其中包含通过 SSH 收集的实时节点、客户机、存储和集群统计信息。", + "proxmoxStatsPollInterval": "轮询间隔(秒)", + "proxmoxStatsPollIntervalDesc": "最短间隔 15 秒。Proxmox 节点统计信息刷新频率。", + "proxmoxStatsNodeOverride": "覆盖节点名称", + "proxmoxStatsNodeOverrideDesc": "覆盖自动检测的 Proxmox 节点名称(默认情况下通过主机名检测)。", + "proxmoxStatsNodeOverridePlaceholder": "从主机名自动检测", + "metricsCollectionLabel": "指标收集", + "enableMetricsLabel": "启用指标", + "enableMetricsDesc": "从此主机收集 CPU、RAM、磁盘和其他指标", + "useGlobalMetrics": "使用全局间隔", + "useGlobalMetricsDesc": "使用服务器范围的指标间隔覆盖", + "metricsIntervalS": "指标间隔(秒)", + "metricsIntervalDesc2": "指标快照之间的秒数", + "excludedMountsLabel": "排除的挂载点", + "monitoredMountsLabel": "自定义监控路径", + "monitoredMountsDesc": "添加未作为单独挂载点公开的路径,包括绑定挂载的 Home Assistant 路径,例如 /config。", + "monitoredMountPathPlaceholder": "路径(/config,/mnt/data)", + "monitoredMountLabelPlaceholder": "标签(可选)", + "addMonitoredMount": "添加路径", + "excludedMountsDesc": "隐藏此主机磁盘使用情况和警报中的特定挂载点或文件系统类型(例如 nfs、cifs)。", + "excludedMountsPlaceholder": "挂载路径(/mnt/nas)或文件系统类型(nfs、cifs)", + "excludedMountsEmpty": "未排除任何挂载点。显示所有检测到的文件系统。", + "addExcludedMount": "添加", + "visibleWidgets": "可见小部件", + "widgetsMovedToHostMetrics": "卡片现在可在“主机指标”选项卡中直接添加、排列和调整大小。打开此主机的“主机指标”,使用“自定义”选择要显示的卡片。", + "quickActionsLabel": "快速操作", + "quickActionsToolbar": "快速操作以按钮形式显示在主机指标工具栏中,以便一键执行命令。", + "noQuickActions": "尚无快速操作。", + "buttonLabel": "按钮标签", + "selectSnippetPlaceholder": "选择代码片段...", + "addActionBtn": "添加操作" + }, + "onboarding": { + "feature_metrics": "指标与告警", + "feature_metrics_desc": "跟踪 CPU、内存和磁盘的运行情况,并在它们出现故障时发出告警。" + }, + "admin": { + "metricsHistoryRetention": "指标历史保留", + "metricsHistoryRetentionRange": "1 到 90 天", + "days": "天" + }, + "homepage": { + "noData": "暂无数据", + "showCurrentValue": "显示当前值", + "chartMetric": "指标", + "metricRange": "范围" + } +} diff --git a/plugins/host-metrics/locales/translated/zh_TW.json b/plugins/host-metrics/locales/translated/zh_TW.json new file mode 100644 index 000000000..0a09152da --- /dev/null +++ b/plugins/host-metrics/locales/translated/zh_TW.json @@ -0,0 +1,313 @@ +{ + "hostMetrics": { + "cpu": "CPU", + "memory": "記憶體", + "disk": "磁碟", + "network": "網路", + "uptime": "運作時間", + "processes": "程序", + "available": "可用", + "free": "可用", + "connecting": "連線中...", + "connectionFailed": "無法連線至伺服器", + "naCpus": "N/A CPU", + "cpuCores_one": "{{count}} 核心", + "cpuCores_other": "{{count}} 核心", + "cpuUsage": "CPU 使用率", + "memoryUsage": "記憶體使用率", + "diskUsage": "磁碟使用率", + "selectFilesystem": "選擇檔案系統", + "temperature": "溫度", + "highestTemperature": "最高溫度", + "primaryTemperatureSensor": "主感應器", + "gpu": { + "title": "GPU", + "noDevice": "未偵測到NVIDIA GPU。請安裝NVIDIA驅動程式(它提供nvidia-smi)以查看GPU指標。", + "driver": "司機 {{version}}", + "utilization": "使用率", + "memory": "顯存", + "temperature": "溫度", + "power": "力量", + "fan": "扇子", + "processes": "GPU 行程", + "noProcesses": "沒有進程正在使用 GPU" + }, + "failedToFetchHostConfig": "無法取得主機設定", + "serverOffline": "伺服器離線", + "cannotFetchMetrics": "無法從離線伺服器取得指標", + "totpFailed": "TOTP 驗證失敗", + "noneAuthNotSupported": "主機指標不支援 'none' 驗證類型。", + "noHostSelected": "未選擇主機", + "load": "負載", + "systemInfo": "系統資訊", + "hostname": "主機名稱", + "operatingSystem": "作業系統", + "kernel": "核心", + "seconds": "秒", + "networkInterfaces": "網路介面", + "noInterfacesFound": "找不到網路介面", + "noProcessesFound": "找不到程序", + "processesTotal": "總計", + "processesRunning": "執行中", + "loginStats": "SSH 登入統計資訊", + "noRecentLoginData": "沒有最近的登入資料", + "executingQuickAction": "正在執行 {{name}}...", + "quickActionSuccess": "{{name}} 已成功完成", + "quickActionFailed": "{{name}} 失敗", + "quickActionError": "無法執行 {{name}}", + "ports": { + "title": "監聽中的連接埠", + "protocol": "通訊協定", + "port": "連接埠", + "address": "位址", + "process": "程序", + "search": "搜尋連接埠...", + "allProtocols": "全部", + "noData": "無監聽連接埠資料" + }, + "firewall": { + "title": "防火牆", + "inactive": "未啟用", + "policy": "原則", + "rules": "規則", + "noRules": "此鏈中無規則", + "noData": "無防火牆資料可用", + "action": "動作", + "protocol": "通訊協定", + "port": "連接埠", + "source": "來源", + "anywhere": "任意位置", + "chains": "鏈" + }, + "loadAvg": "平均負載", + "swap": "交換空間", + "architecture": "架構", + "refresh": "重新整理", + "retry": "重試", + "customize": "自訂版面配置", + "reset": "重設", + "tabLive": "即時", + "editModeInstructions": "拖曳卡片以重新排列,拖曳底部邊緣以調整大小,並使用寬度按鈕變更卡片跨度。於下方新增或移除卡片。", + "managers": { + "services": "服務", + "processInspector": "程序檢查器", + "logViewer": "日誌檢視器", + "cron": "Cron 工作", + "packages": "套件", + "ssl": "SSL 憑證", + "firewall": "防火牆", + "users": "使用者與權限", + "healthCheck": "健康檢查", + "diskBreakdown": "磁碟明細", + "systemdTimers": "計時器", + "topMemory": "記憶體用量排行", + "noData": "無資料", + "sudoHint": "在主機編輯器中為此主機設定 sudo 密碼,以啟用特權操作。", + "filter": "篩選...", + "start": "啟動", + "stop": "停止", + "restart": "重新啟動", + "actionDone": "{{name}} 已更新", + "actionFailed": "操作失敗", + "signalSent": "訊號已傳送至 PID {{pid}}", + "killHint": "按一下:終止 (SIGTERM)。按右鍵:強制終止 (SIGKILL)。", + "working": "處理中...", + "update": "更新", + "upgradeAll": "全部升級", + "allUpToDate": "所有項目皆為最新", + "save": "儲存", + "command": "指令", + "enabled": "已啟用", + "cronSaved": "Crontab 已更新", + "clients": "客戶端", + "dryRun": "試執行", + "renew": "續期", + "noAcmeClient": "此主機上找不到 ACME 用戶端 (certbot 或 acme.sh)。", + "addInputRule": "新增 INPUT 規則", + "firewallWarning": "變更僅在執行階段有效,儲存後才會永久生效。小心切勿將自己鎖定在外。", + "ruleApplied": "規則已套用", + "invalidPort": "輸入有效的連接埠 (1-65535)", + "newUsername": "新使用者名稱", + "addUser": "新增", + "deleteUser": "刪除使用者", + "noHealthChecks": "尚未設定健康檢查。", + "follow": "追蹤", + "noLogData": "無日誌輸出。", + "tree": "樹狀", + "enableDisable": "開機時啟用 / 停用", + "grantSudo": "授予 sudo 權限", + "revokeSudo": "撤銷 sudo 權限", + "sslIssueCert": "頒發憑證", + "sslExpired": "已過期", + "sslInDays": "{{days}} 天內", + "sslNeedDomain": "至少輸入一個網域", + "sslIssued": "憑證已頒發", + "sslDomainsPlaceholder": "example.com, www.example.com", + "sslHttpStandalone": "HTTP (獨立模式)", + "sslHttpWebroot": "HTTP (webroot)", + "sslDns": "DNS", + "sslDnsProvider": "DNS 提供者 (例如 cloudflare)", + "sslIssueHint": "DNS 提供者的憑證必須已在主機上設定。", + "sslRevoke": "撤銷憑證", + "sslRevoked": "憑證已撤銷", + "sslRevokeConfirm": "撤銷並移除憑證「{{name}}」?此操作無法復原。", + "healthRun": "執行", + "healthName": "名稱", + "healthTarget": "主機 / 位址", + "healthAddCheck": "新增檢查", + "healthSaved": "健康檢查已儲存", + "healthMissingFields": "每個檢查都需要名稱和目標", + "logFile": "檔案", + "logUnit": "單元", + "logCustomPath": "/var/log 下的自訂路徑 (選用)", + "logGrep": "篩選行...", + "firewallPersist": "永久儲存規則", + "firewallPersisted": "防火牆規則已永久儲存", + "wireguard": "WireGuard", + "tailscale": "Tailscale", + "wgNotInstalled": "此主機上未安裝 WireGuard", + "wgNoInterfaces": "未設定任何 WireGuard 介面", + "wgInterfaceUp": "啟用", + "wgInterfaceDown": "停用", + "wgBringingUp": "正在啟用 {{name}}...", + "wgBringingDown": "正在停用 {{name}}...", + "wgInterfaceUpDone": "{{name}} 已啟用", + "wgInterfaceDownDone": "{{name}} 已停用", + "wgListenPort": "連接埠", + "wgPublicKey": "公開金鑰", + "wgEndpoint": "端點", + "wgAllowedIPs": "允許的 IP", + "wgLastHandshake": "上次交握", + "wgHandshakeNever": "從未", + "wgTransfer": "傳輸", + "tsNotInstalled": "此主機上未安裝 Tailscale", + "tsRunning": "執行中", + "tsStopped": "已停止", + "tsEnable": "連線", + "tsDisable": "中斷連線", + "tsEnabling": "正在連線至 Tailscale...", + "tsDisabling": "正在中斷 Tailscale 連線...", + "tsEnabled": "Tailscale 已連線", + "tsDisabled": "Tailscale 已中斷連線", + "tsIPs": "Tailscale IP", + "tsPeers": "對等節點", + "tsOnline": "線上", + "tsOffline": "離線", + "tsExitNode": "出口節點", + "tsExitNodeActive": "出口節點作用中", + "tsHostname": "主機名稱" + } + }, + "metricsHistory": { + "title": "指標歷史記錄", + "historySuffix": "歷史記錄", + "cpuMemoryDisk": "CPU / 記憶體 / 磁碟", + "network": "網路", + "download": "RX", + "upload": "TX", + "noData": "此時間範圍內沒有可用的歷史資料。", + "custom": "自訂", + "to": "至", + "apply": "套用", + "viewHistory": "檢視歷史記錄" + }, + "proxmoxStats": { + "tabTitle": "Proxmox 統計數據", + "cpuUsage": "CPU 使用率", + "memoryUsage": "記憶體使用情況", + "diskUsage": "磁碟使用情況", + "networkInterfaces": "網路介面", + "uptime": "正常運作時間", + "systemInfo": "系統資訊", + "guestsSummary": "賓客", + "storagePools": "儲水池", + "clusterHealth": "集群健康", + "cpuCores_one": "{{count}} 核心", + "cpuCores_other": "{{count}} 核心", + "used": "用過的", + "total": "全部的", + "hostname": "主機名稱", + "kernel": "核心", + "pveVersion": "PVE 版本", + "name": "姓名", + "status": "地位", + "type": "類型", + "cpu": "中央處理器", + "mem": "記憶", + "disk": "磁碟", + "running": "跑步", + "stopped": "停止", + "guestCounts": "{{running}}/{{total}} 運作中", + "inactive": "非活躍狀態", + "notClustered": "獨立節點(非叢集的一部分)", + "quorate": "法定人數", + "notQuorate": "未達法定人數", + "nodeOnline": "在線的", + "nodeOffline": "離線", + "noHostSelected": "未選擇主機", + "pveshNotFound": "找不到 pvesh - 這是 Proxmox 節點嗎?", + "nodeDetectionFailed": "無法確定有效的 Proxmox 節點名稱", + "connecting": "正在連接...", + "connectionFailed": "連線到 Proxmox 節點失敗", + "refresh": "重新整理", + "searchGuests": "搜尋賓客...", + "filterAll": "全部", + "filterVm": "虛擬機", + "filterLxc": "LXC", + "noGuests": "此節點上未發現虛擬機器或 LXC 容器。", + "noGuestsMatch": "沒有符合目前篩選條件的客人。" + }, + "nav": { + "hostMetrics": "主機指標" + }, + "hosts": { + "tabHostMetrics": "主機指標", + "enableProxmoxStats": "啟用 Proxmox 統計訊息", + "enableProxmoxStatsDesc": "顯示此主機的 Proxmox 統計資料標籤,其中包含透過 SSH 收集的即時節點、客戶機、儲存和叢集統計資訊。", + "proxmoxStatsPollInterval": "輪詢間隔(秒)", + "proxmoxStatsPollIntervalDesc": "最短間隔 15 秒。 Proxmox 節點統計資訊刷新頻率。", + "proxmoxStatsNodeOverride": "節點名稱覆蓋", + "proxmoxStatsNodeOverrideDesc": "覆蓋 Proxmox 節點名稱的自動偵測(預設透過主機名稱偵測)。", + "proxmoxStatsNodeOverridePlaceholder": "從主機名稱自動偵測", + "metricsCollectionLabel": "指標收集", + "enableMetricsLabel": "啟用指標", + "enableMetricsDesc": "從此主機收集 CPU、記憶體、磁碟和其他指標", + "useGlobalMetrics": "使用全域間隔", + "useGlobalMetricsDesc": "以伺服器範圍的指標間隔覆寫", + "metricsIntervalS": "指標間隔(秒)", + "metricsIntervalDesc2": "每次指標快照之間的秒數", + "excludedMountsLabel": "排除的安裝", + "monitoredMountsLabel": "自訂監控路徑", + "monitoredMountsDesc": "新增未以單獨掛載點公開的路徑,包括綁定掛載的 Home Assistant 路徑,例如 /config。", + "monitoredMountPathPlaceholder": "路徑(/config,/mnt/data)", + "monitoredMountLabelPlaceholder": "標籤(可選)", + "addMonitoredMount": "新增路徑", + "excludedMountsDesc": "隱藏此主機磁碟使用情況和警報中的特定掛載點或檔案系統類型(例如 nfs、cifs)。", + "excludedMountsPlaceholder": "掛載路徑(/mnt/nas)或檔案系統類型(nfs、cifs)", + "excludedMountsEmpty": "未排除任何掛載點。顯示所有偵測到的檔案系統。", + "addExcludedMount": "添加", + "visibleWidgets": "可見的小工具", + "widgetsMovedToHostMetrics": "現在卡片可直接在主機指標分頁中新增、排列和調整大小。開啟此主機的主機指標,然後使用自訂功能選擇要顯示的卡片。", + "quickActionsLabel": "快速動作", + "quickActionsToolbar": "快速動作會以按鈕形式顯示在主機計量工具列上,可一鍵執行指令。", + "noQuickActions": "尚無快速動作。", + "buttonLabel": "按鈕標籤", + "selectSnippetPlaceholder": "選取程式碼片段...", + "addActionBtn": "新增動作" + }, + "onboarding": { + "feature_metrics": "指標和警報", + "feature_metrics_desc": "追蹤 CPU、記憶體和磁碟的運作情況,並在它們出現故障時發出警報。" + }, + "admin": { + "metricsHistoryRetention": "指標歷史保留", + "metricsHistoryRetentionRange": "1 至 90 天", + "days": "天" + }, + "homepage": { + "noData": "無可用資料", + "showCurrentValue": "顯示目前值", + "chartMetric": "指標", + "metricRange": "範圍" + } +} diff --git a/plugins/host-metrics/manifest.json b/plugins/host-metrics/manifest.json index 4dcae9f5b..e976e3464 100644 --- a/plugins/host-metrics/manifest.json +++ b/plugins/host-metrics/manifest.json @@ -33,8 +33,23 @@ "titleKey": "nav.hostMetrics", "icon": "Activity", "openFrom": ["host-context-menu", "palette"] + }, + { + "id": "proxmox-stats", + "titleKey": "nav.proxmoxStats", + "icon": "HardDrive", + "openFrom": ["host-context-menu", "palette"] } - ] + ], + "settings": { + "admin": [ + { + "key": "historyRetention", + "type": "custom", + "component": "retention" + } + ] + } }, "locales": "locales", "platforms": ["linux", "win32", "darwin"] diff --git a/src/ui/sidebar/HostEditorStatsTab.tsx b/plugins/host-metrics/src/frontend/HostEditorStatsTab.tsx similarity index 99% rename from src/ui/sidebar/HostEditorStatsTab.tsx rename to plugins/host-metrics/src/frontend/HostEditorStatsTab.tsx index cdf004057..066d311d0 100644 --- a/src/ui/sidebar/HostEditorStatsTab.tsx +++ b/plugins/host-metrics/src/frontend/HostEditorStatsTab.tsx @@ -1,5 +1,5 @@ import { useState } from "react"; -import { useTranslation } from "react-i18next"; +import { useTranslation } from "@termix/plugin-sdk/frontend"; import { Activity, HardDrive, @@ -13,7 +13,7 @@ import { import { Button } from "@/components/button"; import { Input } from "@/components/input"; import { SectionCard, SettingRow, FakeSwitch } from "@/components/section-card"; -import type { HostEditorForm } from "./HostEditorData"; +import type { HostEditorForm } from "@/sidebar/HostEditorData"; import { Select2 } from "@/components/select2"; type SetHostField = ( diff --git a/plugins/host-metrics/src/frontend/HostMetricsApp.tsx b/plugins/host-metrics/src/frontend/HostMetricsApp.tsx index 18ac2f35f..70b75b07a 100644 --- a/plugins/host-metrics/src/frontend/HostMetricsApp.tsx +++ b/plugins/host-metrics/src/frontend/HostMetricsApp.tsx @@ -1,5 +1,5 @@ import React from "react"; -import { useTranslation } from "react-i18next"; +import { useTranslation } from "@termix/plugin-sdk/frontend"; import { HostMetricsTab } from "./HostMetricsTab.tsx"; import { FullScreenAppWrapper } from "@/features/FullScreenAppWrapper.tsx"; import { ConnectionScreen } from "@/components/connection/ConnectionScreen.tsx"; diff --git a/plugins/host-metrics/src/frontend/HostMetricsTab.tsx b/plugins/host-metrics/src/frontend/HostMetricsTab.tsx index 817369d0f..725e57f10 100644 --- a/plugins/host-metrics/src/frontend/HostMetricsTab.tsx +++ b/plugins/host-metrics/src/frontend/HostMetricsTab.tsx @@ -23,7 +23,7 @@ import { hasSnippetInputs } from "@/lib/snippet-variables.ts"; import type { Snippet } from "@/types/ui-types.ts"; import { TOTPDialog } from "@/ssh/dialogs/TOTPDialog.tsx"; import { useTabsSafe } from "@/shell/TabContext.tsx"; -import { useTranslation } from "react-i18next"; +import { useTranslation } from "@termix/plugin-sdk/frontend"; import { toast } from "sonner"; import { type StatsConfig, diff --git a/src/ui/features/homepage/dialogs/MetricsChartEditForm.tsx b/plugins/host-metrics/src/frontend/MetricsChartEditForm.tsx similarity index 98% rename from src/ui/features/homepage/dialogs/MetricsChartEditForm.tsx rename to plugins/host-metrics/src/frontend/MetricsChartEditForm.tsx index d8cc07405..89f0501cd 100644 --- a/src/ui/features/homepage/dialogs/MetricsChartEditForm.tsx +++ b/plugins/host-metrics/src/frontend/MetricsChartEditForm.tsx @@ -1,5 +1,5 @@ import { useEffect, useState } from "react"; -import { useTranslation } from "react-i18next"; +import { useTranslation } from "@termix/plugin-sdk/frontend"; import type { MetricsChartConfig, MetricsChartMetric, diff --git a/src/ui/features/homepage/widgets/MetricsChartWidget.tsx b/plugins/host-metrics/src/frontend/MetricsChartWidget.tsx similarity index 92% rename from src/ui/features/homepage/widgets/MetricsChartWidget.tsx rename to plugins/host-metrics/src/frontend/MetricsChartWidget.tsx index 372a6c040..19eb5fb4b 100644 --- a/src/ui/features/homepage/widgets/MetricsChartWidget.tsx +++ b/plugins/host-metrics/src/frontend/MetricsChartWidget.tsx @@ -1,20 +1,18 @@ import { useEffect, useState, useRef } from "react"; import { TrendingUp } from "lucide-react"; -import { useTranslation } from "react-i18next"; -import { registerWidget } from "./WidgetRegistry"; +import { useTranslation } from "@termix/plugin-sdk/frontend"; +import { MetricsChartEditForm } from "./MetricsChartEditForm"; import type { MetricsChartConfig, MetricsChartMetric, WidgetComponentProps, + WidgetTypeDefinition, } from "@/types/homepage-types"; import { GRID_SIZE } from "@/types/homepage-types"; -import { - getMetricsHistory, - type MetricsHistoryRow, -} from "@/api/host-metrics-api"; +import { getMetricsHistory, type MetricsHistoryRow } from "./host-metrics-api"; import { getSSHHosts } from "@/api/ssh-host-management-api"; -import { WidgetTitle } from "./WidgetTitle"; -import { runVisibleInterval } from "../use-visible-interval"; +import { WidgetTitle } from "@/features/homepage/widgets/WidgetTitle"; +import { runVisibleInterval } from "@/features/homepage/use-visible-interval"; function getAccentColor(): string { return ( @@ -234,7 +232,8 @@ function MetricsChartWidget({ ); } -registerWidget({ +/** Registered by the plugin while it runs. */ +export const metricsChartWidget: WidgetTypeDefinition = { id: "metrics_chart", name: "Metrics Chart", description: "Historical CPU, memory, disk, or network chart for a host", @@ -249,6 +248,7 @@ registerWidget({ defaultSize: { w: GRID_SIZE * 12, h: GRID_SIZE * 6 }, minSize: { w: GRID_SIZE * 6, h: GRID_SIZE * 4 }, component: MetricsChartWidget, -}); + editFormComponent: MetricsChartEditForm, +}; export { MetricsChartWidget }; diff --git a/plugins/host-metrics/src/frontend/MetricsRetentionSetting.tsx b/plugins/host-metrics/src/frontend/MetricsRetentionSetting.tsx new file mode 100644 index 000000000..6ac2a3ac3 --- /dev/null +++ b/plugins/host-metrics/src/frontend/MetricsRetentionSetting.tsx @@ -0,0 +1,73 @@ +import { useEffect, useState } from "react"; +import { useToast, useTranslation } from "@termix/plugin-sdk/frontend"; +import { Button, Input } from "@termix/plugin-sdk/ui"; +import { + getMetricsHistoryRetention, + saveMetricsHistoryRetention, +} from "./host-metrics-api"; + +/** + * How long metrics history is kept. Lives in the metrics backend's own + * setting, so it saves with its own button rather than the page's. + */ +export function MetricsRetentionSetting() { + const { t } = useTranslation(); + const toast = useToast(); + const [days, setDays] = useState("7"); + + useEffect(() => { + let cancelled = false; + getMetricsHistoryRetention() + .then((value) => { + if (!cancelled) setDays(String(value)); + }) + .catch(() => {}); + return () => { + cancelled = true; + }; + }, []); + + const save = async () => { + const value = Number.parseInt(days, 10); + if (Number.isNaN(value) || value < 1 || value > 90) { + toast.error(t("admin.metricsHistoryRetentionRange")); + return; + } + try { + await saveMetricsHistoryRetention(value); + toast.success(t("admin.monitoringSaved")); + } catch { + toast.error(t("admin.monitoringSaveFailed")); + } + }; + + return ( +
+ +
+ setDays(event.target.value)} + className="w-20 text-sm" + /> + {t("admin.days")} + +
+ + {t("admin.metricsHistoryRetentionRange")} + +
+ ); +} diff --git a/plugins/host-metrics/src/frontend/cards/CardTimeTabs.tsx b/plugins/host-metrics/src/frontend/cards/CardTimeTabs.tsx index 1d9c17832..fbd0f88ec 100644 --- a/plugins/host-metrics/src/frontend/cards/CardTimeTabs.tsx +++ b/plugins/host-metrics/src/frontend/cards/CardTimeTabs.tsx @@ -1,5 +1,5 @@ import { cn } from "@/lib/utils"; -import { useTranslation } from "react-i18next"; +import { useTranslation } from "@termix/plugin-sdk/frontend"; export type HistoryTab = "live" | "1h" | "6h" | "24h" | "7d"; diff --git a/plugins/host-metrics/src/frontend/cards/CpuCard.tsx b/plugins/host-metrics/src/frontend/cards/CpuCard.tsx index ad29b1e44..01b280505 100644 --- a/plugins/host-metrics/src/frontend/cards/CpuCard.tsx +++ b/plugins/host-metrics/src/frontend/cards/CpuCard.tsx @@ -1,14 +1,11 @@ import { useState, useEffect } from "react"; import { Cpu } from "lucide-react"; -import { useTranslation } from "react-i18next"; +import { useTranslation } from "@termix/plugin-sdk/frontend"; import type { ServerMetrics } from "@/main-axios"; import { RadialGauge, Sparkline, MiniStat } from "@/components/charts"; import { MetricCard } from "@/components/metric-card"; import { LineChart, type LineChartSeries } from "@/components/charts/LineChart"; -import { - getMetricsHistory, - type MetricsHistoryRow, -} from "@/api/host-metrics-api"; +import { getMetricsHistory, type MetricsHistoryRow } from "../host-metrics-api"; import { CardTimeTabs, type HistoryTab } from "./CardTimeTabs"; function computeChartData(rows: MetricsHistoryRow[]) { diff --git a/plugins/host-metrics/src/frontend/cards/DiskCard.tsx b/plugins/host-metrics/src/frontend/cards/DiskCard.tsx index 976427581..c1bb8ca0b 100644 --- a/plugins/host-metrics/src/frontend/cards/DiskCard.tsx +++ b/plugins/host-metrics/src/frontend/cards/DiskCard.tsx @@ -1,15 +1,12 @@ import { useState, useEffect, useMemo } from "react"; import { HardDrive } from "lucide-react"; -import { useTranslation } from "react-i18next"; +import { useTranslation } from "@termix/plugin-sdk/frontend"; import type { ServerMetrics } from "@/main-axios"; import { FilesystemPicker } from "./FilesystemPicker"; import { RadialGauge, Sparkline, MiniStat } from "@/components/charts"; import { MetricCard } from "@/components/metric-card"; import { LineChart, type LineChartSeries } from "@/components/charts/LineChart"; -import { - getMetricsHistory, - type MetricsHistoryRow, -} from "@/api/host-metrics-api"; +import { getMetricsHistory, type MetricsHistoryRow } from "../host-metrics-api"; import { CardTimeTabs, type HistoryTab } from "./CardTimeTabs"; export function DiskCard({ diff --git a/plugins/host-metrics/src/frontend/cards/FilesystemPicker.tsx b/plugins/host-metrics/src/frontend/cards/FilesystemPicker.tsx index e0b6ea464..243b43cb9 100644 --- a/plugins/host-metrics/src/frontend/cards/FilesystemPicker.tsx +++ b/plugins/host-metrics/src/frontend/cards/FilesystemPicker.tsx @@ -1,5 +1,5 @@ import { ChevronDown, Check } from "lucide-react"; -import { useTranslation } from "react-i18next"; +import { useTranslation } from "@termix/plugin-sdk/frontend"; import type { DiskFilesystem } from "@/main-axios"; import { cn } from "@/lib/utils"; import { diff --git a/plugins/host-metrics/src/frontend/cards/FirewallCard.tsx b/plugins/host-metrics/src/frontend/cards/FirewallCard.tsx index a21229fe2..337fd942d 100644 --- a/plugins/host-metrics/src/frontend/cards/FirewallCard.tsx +++ b/plugins/host-metrics/src/frontend/cards/FirewallCard.tsx @@ -1,5 +1,5 @@ import { ShieldCheck } from "lucide-react"; -import { useTranslation } from "react-i18next"; +import { useTranslation } from "@termix/plugin-sdk/frontend"; import type { ServerMetrics } from "@/main-axios"; import { MetricCard } from "@/components/metric-card"; diff --git a/plugins/host-metrics/src/frontend/cards/GpuCard.tsx b/plugins/host-metrics/src/frontend/cards/GpuCard.tsx index 7a53588bb..97192aa1c 100644 --- a/plugins/host-metrics/src/frontend/cards/GpuCard.tsx +++ b/plugins/host-metrics/src/frontend/cards/GpuCard.tsx @@ -1,6 +1,6 @@ import { useId } from "react"; import { Gpu } from "lucide-react"; -import { useTranslation } from "react-i18next"; +import { useTranslation } from "@termix/plugin-sdk/frontend"; import type { ServerMetrics } from "@/main-axios"; import type { GpuDevice, GpuProcess } from "@/types/stats-widgets"; import { MiniStat, RadialGauge, Sparkline, StatRow } from "@/components/charts"; diff --git a/plugins/host-metrics/src/frontend/cards/LoginStatsCard.tsx b/plugins/host-metrics/src/frontend/cards/LoginStatsCard.tsx index fdd659b2d..a221d6686 100644 --- a/plugins/host-metrics/src/frontend/cards/LoginStatsCard.tsx +++ b/plugins/host-metrics/src/frontend/cards/LoginStatsCard.tsx @@ -1,5 +1,5 @@ import { UserCheck, UserX } from "lucide-react"; -import { useTranslation } from "react-i18next"; +import { useTranslation } from "@termix/plugin-sdk/frontend"; import type { ServerMetrics } from "@/main-axios"; import { MetricCard } from "@/components/metric-card"; diff --git a/plugins/host-metrics/src/frontend/cards/MemoryCard.tsx b/plugins/host-metrics/src/frontend/cards/MemoryCard.tsx index fee2e4502..65d9766e4 100644 --- a/plugins/host-metrics/src/frontend/cards/MemoryCard.tsx +++ b/plugins/host-metrics/src/frontend/cards/MemoryCard.tsx @@ -1,14 +1,11 @@ import { useState, useEffect } from "react"; import { MemoryStick } from "lucide-react"; -import { useTranslation } from "react-i18next"; +import { useTranslation } from "@termix/plugin-sdk/frontend"; import type { ServerMetrics } from "@/main-axios"; import { RadialGauge, Sparkline, MiniStat } from "@/components/charts"; import { MetricCard } from "@/components/metric-card"; import { LineChart, type LineChartSeries } from "@/components/charts/LineChart"; -import { - getMetricsHistory, - type MetricsHistoryRow, -} from "@/api/host-metrics-api"; +import { getMetricsHistory, type MetricsHistoryRow } from "../host-metrics-api"; import { CardTimeTabs, type HistoryTab } from "./CardTimeTabs"; export function MemoryCard({ diff --git a/plugins/host-metrics/src/frontend/cards/NetworkCard.tsx b/plugins/host-metrics/src/frontend/cards/NetworkCard.tsx index f595f85fb..cd9696395 100644 --- a/plugins/host-metrics/src/frontend/cards/NetworkCard.tsx +++ b/plugins/host-metrics/src/frontend/cards/NetworkCard.tsx @@ -1,13 +1,10 @@ import { useState, useEffect } from "react"; import { Cable, Container, Network, Wifi, WifiOff } from "lucide-react"; -import { useTranslation } from "react-i18next"; +import { useTranslation } from "@termix/plugin-sdk/frontend"; import type { ServerMetrics } from "@/main-axios"; import { MetricCard } from "@/components/metric-card"; import { LineChart, type LineChartSeries } from "@/components/charts/LineChart"; -import { - getMetricsHistory, - type MetricsHistoryRow, -} from "@/api/host-metrics-api"; +import { getMetricsHistory, type MetricsHistoryRow } from "../host-metrics-api"; import { CardTimeTabs, type HistoryTab } from "./CardTimeTabs"; function ifaceIcon(name: string) { diff --git a/plugins/host-metrics/src/frontend/cards/PortsCard.tsx b/plugins/host-metrics/src/frontend/cards/PortsCard.tsx index 9e41b3fd4..d898ffe92 100644 --- a/plugins/host-metrics/src/frontend/cards/PortsCard.tsx +++ b/plugins/host-metrics/src/frontend/cards/PortsCard.tsx @@ -1,6 +1,6 @@ import { useMemo, useState } from "react"; import { Unplug, Search } from "lucide-react"; -import { useTranslation } from "react-i18next"; +import { useTranslation } from "@termix/plugin-sdk/frontend"; import type { ServerMetrics, ListeningPort } from "@/main-axios"; import { MetricCard } from "@/components/metric-card"; import { Select2 } from "@/components/select2"; diff --git a/plugins/host-metrics/src/frontend/cards/ProcessesCard.tsx b/plugins/host-metrics/src/frontend/cards/ProcessesCard.tsx index cb3f834a8..51b93e889 100644 --- a/plugins/host-metrics/src/frontend/cards/ProcessesCard.tsx +++ b/plugins/host-metrics/src/frontend/cards/ProcessesCard.tsx @@ -1,5 +1,5 @@ import { Cpu } from "lucide-react"; -import { useTranslation } from "react-i18next"; +import { useTranslation } from "@termix/plugin-sdk/frontend"; import type { ServerMetrics } from "@/main-axios"; import { StatRow } from "@/components/charts"; import { MetricCard } from "@/components/metric-card"; diff --git a/plugins/host-metrics/src/frontend/cards/SystemCard.tsx b/plugins/host-metrics/src/frontend/cards/SystemCard.tsx index 9cbda0872..78e452183 100644 --- a/plugins/host-metrics/src/frontend/cards/SystemCard.tsx +++ b/plugins/host-metrics/src/frontend/cards/SystemCard.tsx @@ -1,5 +1,5 @@ import { Server } from "lucide-react"; -import { useTranslation } from "react-i18next"; +import { useTranslation } from "@termix/plugin-sdk/frontend"; import type { ServerMetrics } from "@/main-axios"; import { StatRow } from "@/components/charts"; import { MetricCard } from "@/components/metric-card"; diff --git a/plugins/host-metrics/src/frontend/cards/TemperatureCard.tsx b/plugins/host-metrics/src/frontend/cards/TemperatureCard.tsx index 974ee7716..dce1d9384 100644 --- a/plugins/host-metrics/src/frontend/cards/TemperatureCard.tsx +++ b/plugins/host-metrics/src/frontend/cards/TemperatureCard.tsx @@ -1,5 +1,5 @@ import { Thermometer } from "lucide-react"; -import { useTranslation } from "react-i18next"; +import { useTranslation } from "@termix/plugin-sdk/frontend"; import type { ServerMetrics } from "@/main-axios"; import { StatRow } from "@/components/charts"; import { MetricCard } from "@/components/metric-card"; diff --git a/plugins/host-metrics/src/frontend/cards/UptimeCard.tsx b/plugins/host-metrics/src/frontend/cards/UptimeCard.tsx index 47c9b4d3c..d3c3dea4e 100644 --- a/plugins/host-metrics/src/frontend/cards/UptimeCard.tsx +++ b/plugins/host-metrics/src/frontend/cards/UptimeCard.tsx @@ -1,5 +1,5 @@ import { Clock } from "lucide-react"; -import { useTranslation } from "react-i18next"; +import { useTranslation } from "@termix/plugin-sdk/frontend"; import type { ServerMetrics } from "@/main-axios"; import { MetricCard } from "@/components/metric-card"; diff --git a/plugins/host-metrics/src/frontend/cards/managers/CronManagerCard.tsx b/plugins/host-metrics/src/frontend/cards/managers/CronManagerCard.tsx index 2e44f5127..87a22f79a 100644 --- a/plugins/host-metrics/src/frontend/cards/managers/CronManagerCard.tsx +++ b/plugins/host-metrics/src/frontend/cards/managers/CronManagerCard.tsx @@ -1,9 +1,9 @@ import { useEffect, useMemo, useState } from "react"; import { Clock4, Plus, Trash2, Save } from "lucide-react"; -import { useTranslation } from "react-i18next"; +import { useTranslation } from "@termix/plugin-sdk/frontend"; import { toast } from "sonner"; import { Button } from "@/components/button"; -import { managerPost } from "@/main-axios"; +import { managerPost } from "../../host-metrics-api"; import { useManagerData, extractError } from "./useManagerData"; import { ManagerCardShell } from "./ManagerCardShell"; import { ManagerSearch } from "./ManagerToolbar"; diff --git a/plugins/host-metrics/src/frontend/cards/managers/FirewallManagerCard.tsx b/plugins/host-metrics/src/frontend/cards/managers/FirewallManagerCard.tsx index 07de05585..351f66b1c 100644 --- a/plugins/host-metrics/src/frontend/cards/managers/FirewallManagerCard.tsx +++ b/plugins/host-metrics/src/frontend/cards/managers/FirewallManagerCard.tsx @@ -1,9 +1,10 @@ import { useMemo, useState } from "react"; import { ShieldCheck, Plus, Trash2, Save } from "lucide-react"; -import { useTranslation } from "react-i18next"; +import { useTranslation } from "@termix/plugin-sdk/frontend"; import { toast } from "sonner"; import { Button } from "@/components/button"; -import { managerPost, type FirewallChain } from "@/main-axios"; +import { type FirewallChain } from "@/main-axios"; +import { managerPost } from "../../host-metrics-api"; import { useManagerData, extractError } from "./useManagerData"; import { ManagerCardShell } from "./ManagerCardShell"; import { ManagerSearch } from "./ManagerToolbar"; diff --git a/plugins/host-metrics/src/frontend/cards/managers/HealthCheckCard.tsx b/plugins/host-metrics/src/frontend/cards/managers/HealthCheckCard.tsx index edb3f6681..0c5add399 100644 --- a/plugins/host-metrics/src/frontend/cards/managers/HealthCheckCard.tsx +++ b/plugins/host-metrics/src/frontend/cards/managers/HealthCheckCard.tsx @@ -8,11 +8,11 @@ import { Play, Pencil, } from "lucide-react"; -import { useTranslation } from "react-i18next"; +import { useTranslation } from "@termix/plugin-sdk/frontend"; import { toast } from "sonner"; import { Button } from "@/components/button"; import { Sparkline } from "@/components/charts"; -import { managerPost } from "@/main-axios"; +import { managerPost } from "../../host-metrics-api"; import { useManagerData, extractError } from "./useManagerData"; import { ManagerCardShell } from "./ManagerCardShell"; import { Select2 } from "@/components/select2"; diff --git a/plugins/host-metrics/src/frontend/cards/managers/LogViewerCard.tsx b/plugins/host-metrics/src/frontend/cards/managers/LogViewerCard.tsx index c8afaedeb..e175c5d18 100644 --- a/plugins/host-metrics/src/frontend/cards/managers/LogViewerCard.tsx +++ b/plugins/host-metrics/src/frontend/cards/managers/LogViewerCard.tsx @@ -1,7 +1,7 @@ import { useCallback, useEffect, useMemo, useRef, useState } from "react"; import { ScrollText } from "lucide-react"; -import { useTranslation } from "react-i18next"; -import { managerGet, managerGetSub } from "@/main-axios"; +import { useTranslation } from "@termix/plugin-sdk/frontend"; +import { managerGet, managerGetSub } from "../../host-metrics-api"; import { extractError } from "./useManagerData"; import { ManagerCardShell } from "./ManagerCardShell"; import { useAdaptivePolling } from "@/hooks/use-adaptive-polling"; diff --git a/plugins/host-metrics/src/frontend/cards/managers/ManagerCardShell.tsx b/plugins/host-metrics/src/frontend/cards/managers/ManagerCardShell.tsx index 3a3099a1b..a55e1ef36 100644 --- a/plugins/host-metrics/src/frontend/cards/managers/ManagerCardShell.tsx +++ b/plugins/host-metrics/src/frontend/cards/managers/ManagerCardShell.tsx @@ -1,6 +1,6 @@ import type { ReactNode } from "react"; import { RefreshCw, AlertTriangle } from "lucide-react"; -import { useTranslation } from "react-i18next"; +import { useTranslation } from "@termix/plugin-sdk/frontend"; import { Button } from "@/components/button"; import { MetricCard } from "@/components/metric-card"; import type { ManagerError } from "./useManagerData"; diff --git a/plugins/host-metrics/src/frontend/cards/managers/ManagerToolbar.tsx b/plugins/host-metrics/src/frontend/cards/managers/ManagerToolbar.tsx index c98ee85c5..fd63a2780 100644 --- a/plugins/host-metrics/src/frontend/cards/managers/ManagerToolbar.tsx +++ b/plugins/host-metrics/src/frontend/cards/managers/ManagerToolbar.tsx @@ -1,6 +1,6 @@ import type { ReactNode } from "react"; import { Search } from "lucide-react"; -import { useTranslation } from "react-i18next"; +import { useTranslation } from "@termix/plugin-sdk/frontend"; /** * Compact search row shared by manager cards. Optional `extra` renders to the diff --git a/plugins/host-metrics/src/frontend/cards/managers/PackageManagerCard.tsx b/plugins/host-metrics/src/frontend/cards/managers/PackageManagerCard.tsx index 525680941..7b9d77a66 100644 --- a/plugins/host-metrics/src/frontend/cards/managers/PackageManagerCard.tsx +++ b/plugins/host-metrics/src/frontend/cards/managers/PackageManagerCard.tsx @@ -1,9 +1,9 @@ import { useMemo, useState } from "react"; import { Package, ArrowUpCircle } from "lucide-react"; -import { useTranslation } from "react-i18next"; +import { useTranslation } from "@termix/plugin-sdk/frontend"; import { toast } from "sonner"; import { Button } from "@/components/button"; -import { managerPost } from "@/main-axios"; +import { managerPost } from "../../host-metrics-api"; import { useManagerData, extractError } from "./useManagerData"; import { ManagerCardShell } from "./ManagerCardShell"; import { ManagerSearch } from "./ManagerToolbar"; diff --git a/plugins/host-metrics/src/frontend/cards/managers/ProcessInspectorCard.tsx b/plugins/host-metrics/src/frontend/cards/managers/ProcessInspectorCard.tsx index ab4f14bb9..d828bb922 100644 --- a/plugins/host-metrics/src/frontend/cards/managers/ProcessInspectorCard.tsx +++ b/plugins/host-metrics/src/frontend/cards/managers/ProcessInspectorCard.tsx @@ -1,8 +1,8 @@ import { useMemo, useState } from "react"; import { ListTree, X, Skull } from "lucide-react"; -import { useTranslation } from "react-i18next"; +import { useTranslation } from "@termix/plugin-sdk/frontend"; import { toast } from "sonner"; -import { managerPost } from "@/main-axios"; +import { managerPost } from "../../host-metrics-api"; import { useManagerData, extractError } from "./useManagerData"; import { ManagerCardShell } from "./ManagerCardShell"; import { ManagerSearch } from "./ManagerToolbar"; diff --git a/plugins/host-metrics/src/frontend/cards/managers/ServiceManagerCard.tsx b/plugins/host-metrics/src/frontend/cards/managers/ServiceManagerCard.tsx index c3c1fa35a..1442adc9c 100644 --- a/plugins/host-metrics/src/frontend/cards/managers/ServiceManagerCard.tsx +++ b/plugins/host-metrics/src/frontend/cards/managers/ServiceManagerCard.tsx @@ -1,8 +1,8 @@ import { useMemo, useState } from "react"; import { Cog, Play, Square, RotateCw, Power } from "lucide-react"; -import { useTranslation } from "react-i18next"; +import { useTranslation } from "@termix/plugin-sdk/frontend"; import { toast } from "sonner"; -import { managerPost } from "@/main-axios"; +import { managerPost } from "../../host-metrics-api"; import { useManagerData, extractError } from "./useManagerData"; import { ManagerCardShell } from "./ManagerCardShell"; import { ManagerSearch } from "./ManagerToolbar"; diff --git a/plugins/host-metrics/src/frontend/cards/managers/SimpleManagerCards.tsx b/plugins/host-metrics/src/frontend/cards/managers/SimpleManagerCards.tsx index 09b43c5f1..2cfa220fc 100644 --- a/plugins/host-metrics/src/frontend/cards/managers/SimpleManagerCards.tsx +++ b/plugins/host-metrics/src/frontend/cards/managers/SimpleManagerCards.tsx @@ -1,6 +1,6 @@ import { useMemo, useState } from "react"; import { MemoryStick, Timer, HardDrive } from "lucide-react"; -import { useTranslation } from "react-i18next"; +import { useTranslation } from "@termix/plugin-sdk/frontend"; import { BarSeries, StatRow } from "@/components/charts"; import { useManagerData } from "./useManagerData"; import { ManagerCardShell } from "./ManagerCardShell"; diff --git a/plugins/host-metrics/src/frontend/cards/managers/SslManagerCard.tsx b/plugins/host-metrics/src/frontend/cards/managers/SslManagerCard.tsx index 8cded679c..db632155e 100644 --- a/plugins/host-metrics/src/frontend/cards/managers/SslManagerCard.tsx +++ b/plugins/host-metrics/src/frontend/cards/managers/SslManagerCard.tsx @@ -1,8 +1,8 @@ import { useMemo, useState } from "react"; import { ShieldCheck, RefreshCw, Plus, X, Trash2 } from "lucide-react"; -import { useTranslation } from "react-i18next"; +import { useTranslation } from "@termix/plugin-sdk/frontend"; import { Button } from "@/components/button"; -import { managerPost } from "@/main-axios"; +import { managerPost } from "../../host-metrics-api"; import { useManagerData, useManagerAction, diff --git a/plugins/host-metrics/src/frontend/cards/managers/TailscaleManagerCard.tsx b/plugins/host-metrics/src/frontend/cards/managers/TailscaleManagerCard.tsx index 1cbdb0ab1..63bece758 100644 --- a/plugins/host-metrics/src/frontend/cards/managers/TailscaleManagerCard.tsx +++ b/plugins/host-metrics/src/frontend/cards/managers/TailscaleManagerCard.tsx @@ -1,6 +1,6 @@ import { useState } from "react"; import { Power } from "lucide-react"; -import { useTranslation } from "react-i18next"; +import { useTranslation } from "@termix/plugin-sdk/frontend"; import { useManagerData, useManagerAction } from "./useManagerData"; import { ManagerCardShell } from "./ManagerCardShell"; import { ManagerSearch } from "./ManagerToolbar"; diff --git a/plugins/host-metrics/src/frontend/cards/managers/UserManagerCard.tsx b/plugins/host-metrics/src/frontend/cards/managers/UserManagerCard.tsx index ab7404d2e..f1f577056 100644 --- a/plugins/host-metrics/src/frontend/cards/managers/UserManagerCard.tsx +++ b/plugins/host-metrics/src/frontend/cards/managers/UserManagerCard.tsx @@ -1,9 +1,9 @@ import { useMemo, useState } from "react"; import { Users, Plus, Trash2, ShieldCheck, Shield } from "lucide-react"; -import { useTranslation } from "react-i18next"; +import { useTranslation } from "@termix/plugin-sdk/frontend"; import { toast } from "sonner"; import { Button } from "@/components/button"; -import { managerPost } from "@/main-axios"; +import { managerPost } from "../../host-metrics-api"; import { useManagerData, extractError } from "./useManagerData"; import { ManagerCardShell } from "./ManagerCardShell"; import { ManagerSearch } from "./ManagerToolbar"; diff --git a/plugins/host-metrics/src/frontend/cards/managers/WireGuardManagerCard.tsx b/plugins/host-metrics/src/frontend/cards/managers/WireGuardManagerCard.tsx index 9a62d4367..0a235c607 100644 --- a/plugins/host-metrics/src/frontend/cards/managers/WireGuardManagerCard.tsx +++ b/plugins/host-metrics/src/frontend/cards/managers/WireGuardManagerCard.tsx @@ -6,7 +6,7 @@ import { ArrowUp, ArrowDown, } from "lucide-react"; -import { useTranslation } from "react-i18next"; +import { useTranslation } from "@termix/plugin-sdk/frontend"; import { useManagerData, useManagerAction } from "./useManagerData"; import { ManagerCardShell } from "./ManagerCardShell"; diff --git a/plugins/host-metrics/src/frontend/cards/managers/useManagerData.ts b/plugins/host-metrics/src/frontend/cards/managers/useManagerData.ts index 67d92f8fb..56bc03057 100644 --- a/plugins/host-metrics/src/frontend/cards/managers/useManagerData.ts +++ b/plugins/host-metrics/src/frontend/cards/managers/useManagerData.ts @@ -1,6 +1,6 @@ import { useCallback, useEffect, useState } from "react"; import { toast } from "sonner"; -import { managerGet, managerPost } from "@/main-axios"; +import { managerGet, managerPost } from "../../host-metrics-api"; interface ManagerError { message: string; diff --git a/plugins/host-metrics/src/frontend/hooks/useHostMetricsPreferences.ts b/plugins/host-metrics/src/frontend/hooks/useHostMetricsPreferences.ts index 2462d5483..e42f99984 100644 --- a/plugins/host-metrics/src/frontend/hooks/useHostMetricsPreferences.ts +++ b/plugins/host-metrics/src/frontend/hooks/useHostMetricsPreferences.ts @@ -1,5 +1,8 @@ import { useCallback, useEffect, useRef, useState } from "react"; -import { getHostMetricsLayout, saveHostMetricsLayout } from "@/main-axios"; +import { + getHostMetricsLayout, + saveHostMetricsLayout, +} from "../host-metrics-api"; import type { HostMetricsLayout } from "@/types/host-metrics"; const SAVE_DEBOUNCE_MS = 800; diff --git a/src/ui/api/host-metrics-api.ts b/plugins/host-metrics/src/frontend/host-metrics-api.ts similarity index 100% rename from src/ui/api/host-metrics-api.ts rename to plugins/host-metrics/src/frontend/host-metrics-api.ts diff --git a/plugins/host-metrics/src/frontend/index.mjs b/plugins/host-metrics/src/frontend/index.mjs deleted file mode 100644 index 9234c1c39..000000000 --- a/plugins/host-metrics/src/frontend/index.mjs +++ /dev/null @@ -1,49 +0,0 @@ -/** - * Frontend half of the host-metrics plugin. - * - * Registers the Host Metrics tab through the existing extension seams - * (registerRailItem / registerTabComponent), the same way ssh-terminal's and - * docker's frontend do. - * - * HostEditorStatsTab itself stays in src/ui/sidebar/HostEditorStatsTab.tsx - * rather than moving into this plugin: it takes the same {form, setField} - * pair every other host editor tab does, and those types (HostEditorForm, - * the setField signature) are core types HostEditor.tsx owns -- the same - * reason docker leaves HostDockerTab in core. - * - * register() is called when the plugin is enabled, unregister() when it is - * disabled. As of this change neither is actually invoked anywhere yet, the - * same as ssh-terminal's and docker's frontend entries -- there is no - * frontend plugin loader yet. This file follows the same shape so it is - * ready the moment that loader exists. - */ - -export const id = "host-metrics"; -export const tabId = "host-metrics"; - -export async function register({ - registerRailItem, - registerTabComponent, - icons, -}) { - registerTabComponent(tabId, () => - import("./HostMetricsTab.tsx").then((m) => ({ - default: m.HostMetricsTab, - })), - ); - - registerRailItem({ - id: tabId, - icon: icons.Activity, - labelKey: "nav.hostMetrics", - kind: "tab", - }); -} - -export async function unregister({ - unregisterRailItem, - unregisterTabComponent, -}) { - unregisterRailItem(tabId); - unregisterTabComponent(tabId); -} diff --git a/plugins/host-metrics/src/frontend/index.tsx b/plugins/host-metrics/src/frontend/index.tsx new file mode 100644 index 000000000..61a5c813b --- /dev/null +++ b/plugins/host-metrics/src/frontend/index.tsx @@ -0,0 +1,161 @@ +import type { ComponentType } from "react"; +import { Activity, HardDrive, Server } from "lucide-react"; +import type { + HomepageWidgetContribution, + HostEditorSectionProps, + StandaloneViewProps, + TabProps, + TermixApp, +} from "@termix/plugin-sdk/frontend"; +import type { SSHHost } from "@/types"; +import { HostMetricsTab } from "./HostMetricsTab"; +import HostMetricsApp from "./HostMetricsApp"; +import { HostStatsTab } from "./HostEditorStatsTab"; +import { metricsChartWidget } from "./MetricsChartWidget"; +import { MetricsRetentionSetting } from "./MetricsRetentionSetting"; +import { ProxmoxStatsTab } from "./proxmox-stats/ProxmoxStatsTab"; +import ProxmoxStatsApp from "./proxmox-stats/ProxmoxStatsApp"; +import { HostProxmoxStatsTab } from "./proxmox-stats/HostProxmoxStatsTab"; + +type SectionSetField = Parameters[0]["setField"]; + +function MetricsTab({ sshHost, label, isVisible }: TabProps) { + return ( + + ); +} + +function ProxmoxTab({ sshHost, label, isVisible }: TabProps) { + return ( + + ); +} + +function MetricsStandalone({ hostId }: StandaloneViewProps) { + return ; +} + +function ProxmoxStandalone({ hostId }: StandaloneViewProps) { + return ; +} + +function MetricsHostSection({ + form, + setField, + snippets, +}: HostEditorSectionProps) { + return ( + + ); +} + +/** Drawn inside the proxmox plugin's host editor tab, when it runs. */ +function ProxmoxStatsHostSection({ + form, + setField, +}: { + // eslint-disable-next-line @typescript-eslint/no-explicit-any + form: any; + setField: (key: string, value: unknown) => void; +}) { + return ( + + ); +} + +export function activate(app: TermixApp): void { + app.registerTab("host-metrics", MetricsTab, { + icon: Server, + titleKey: "nav.hostMetrics", + requiresHost: true, + noHostMessageKey: "hostMetrics.noHostSelected", + persistent: true, + activityTypes: ["server_stats"], + standalone: MetricsStandalone, + // Links copied before the rename still open. + standaloneViews: ["server-stats"], + preload: () => import("./HostMetricsTab"), + }); + + app.registerTab("proxmox-stats", ProxmoxTab, { + icon: HardDrive, + titleKey: "nav.proxmoxStats", + requiresHost: true, + noHostMessageKey: "proxmoxStats.noHostSelected", + standalone: ProxmoxStandalone, + preload: () => import("./proxmox-stats/ProxmoxStatsTab"), + }); + + app.registerHostAction({ + id: "host-metrics", + titleKey: "nav.hostMetrics", + icon: Server, + kind: "open", + order: 50, + tabType: "host-metrics", + copyUrlView: "host-metrics", + overview: true, + when: (host) => + !!host.enableSsh && + (host.statsConfig as { metricsEnabled?: boolean } | undefined) + ?.metricsEnabled !== false, + }); + + app.registerHostAction({ + id: "proxmox-stats", + titleKey: "nav.proxmoxStats", + icon: HardDrive, + kind: "open", + order: 60, + tabType: "proxmox-stats", + copyUrlView: "proxmox-stats", + when: (host) => host.enableProxmoxStats === true, + }); + + app.registerHostEditorSection({ + id: "host-metrics", + group: "ssh", + titleKey: "hosts.tabHostMetrics", + icon: Activity, + order: 70, + component: MetricsHostSection, + }); + + app.registerSlotContribution("proxmox.hostEditor", { + actionId: "host-metrics.proxmoxStats", + titleKey: "nav.proxmoxStats", + kind: "component", + component: ProxmoxStatsHostSection as unknown as ComponentType< + Record + >, + }); + + app.registerHomepageWidget( + metricsChartWidget as unknown as HomepageWidgetContribution, + ); + + app.registerSettingsComponent("retention", MetricsRetentionSetting); + + app.registerSlotContribution("onboarding.features", { + actionId: "host-metrics.feature", + titleKey: "onboarding.feature_metrics", + descriptionKey: "onboarding.feature_metrics_desc", + icon: Activity as ComponentType<{ className?: string }>, + }); +} diff --git a/src/ui/features/proxmox-stats/GuestTable.tsx b/plugins/host-metrics/src/frontend/proxmox-stats/GuestTable.tsx similarity index 99% rename from src/ui/features/proxmox-stats/GuestTable.tsx rename to plugins/host-metrics/src/frontend/proxmox-stats/GuestTable.tsx index bf252e978..23ea3cd6f 100644 --- a/src/ui/features/proxmox-stats/GuestTable.tsx +++ b/plugins/host-metrics/src/frontend/proxmox-stats/GuestTable.tsx @@ -1,5 +1,5 @@ import { useMemo, useState } from "react"; -import { useTranslation } from "react-i18next"; +import { useTranslation } from "@termix/plugin-sdk/frontend"; import { Box, Search, Server as ServerIcon } from "lucide-react"; import { cn } from "@/lib/utils"; import { Input } from "@/components/input"; diff --git a/plugins/host-metrics/src/frontend/proxmox-stats/HostProxmoxStatsTab.tsx b/plugins/host-metrics/src/frontend/proxmox-stats/HostProxmoxStatsTab.tsx new file mode 100644 index 000000000..e923af753 --- /dev/null +++ b/plugins/host-metrics/src/frontend/proxmox-stats/HostProxmoxStatsTab.tsx @@ -0,0 +1,79 @@ +import { useTranslation } from "@termix/plugin-sdk/frontend"; +import { Server } from "lucide-react"; +import { Input } from "@/components/input"; +import { SectionCard, SettingRow, FakeSwitch } from "@/components/section-card"; +import type { HostEditorForm } from "@/sidebar/HostEditorData"; + +type SetHostField = ( + key: K, + value: HostEditorForm[K], +) => void; + +export function HostProxmoxStatsTab({ + form, + setField, +}: { + form: HostEditorForm; + setField: SetHostField; +}) { + const { t } = useTranslation(); + + return ( + } + > +
+ + setField("enableProxmoxStats", v)} + /> + + {form.enableProxmoxStats && ( + <> + + + setField("proxmoxStatsConfig", { + ...form.proxmoxStatsConfig, + pollInterval: Math.max( + 15, + Number.parseInt(e.target.value || "60", 10), + ), + }) + } + /> + + + + setField("proxmoxStatsConfig", { + ...form.proxmoxStatsConfig, + nodeName: e.target.value || null, + }) + } + /> + + + )} +
+
+ ); +} diff --git a/src/ui/features/proxmox-stats/NodeSummaryStrip.tsx b/plugins/host-metrics/src/frontend/proxmox-stats/NodeSummaryStrip.tsx similarity index 98% rename from src/ui/features/proxmox-stats/NodeSummaryStrip.tsx rename to plugins/host-metrics/src/frontend/proxmox-stats/NodeSummaryStrip.tsx index 57985ee38..b04f82c51 100644 --- a/src/ui/features/proxmox-stats/NodeSummaryStrip.tsx +++ b/plugins/host-metrics/src/frontend/proxmox-stats/NodeSummaryStrip.tsx @@ -1,4 +1,4 @@ -import { useTranslation } from "react-i18next"; +import { useTranslation } from "@termix/plugin-sdk/frontend"; import { Cpu, MemoryStick, HardDrive, Clock, Server } from "lucide-react"; import { cn } from "@/lib/utils"; import type { ProxmoxNodeStats } from "@/types/proxmox"; diff --git a/src/ui/features/proxmox-stats/ProxmoxStatsApp.tsx b/plugins/host-metrics/src/frontend/proxmox-stats/ProxmoxStatsApp.tsx similarity index 91% rename from src/ui/features/proxmox-stats/ProxmoxStatsApp.tsx rename to plugins/host-metrics/src/frontend/proxmox-stats/ProxmoxStatsApp.tsx index 77bf5705b..36805316a 100644 --- a/src/ui/features/proxmox-stats/ProxmoxStatsApp.tsx +++ b/plugins/host-metrics/src/frontend/proxmox-stats/ProxmoxStatsApp.tsx @@ -1,6 +1,6 @@ import React from "react"; -import { useTranslation } from "react-i18next"; -import { ProxmoxStatsTab } from "@/features/proxmox-stats/ProxmoxStatsTab.tsx"; +import { useTranslation } from "@termix/plugin-sdk/frontend"; +import { ProxmoxStatsTab } from "./ProxmoxStatsTab"; import { FullScreenAppWrapper } from "@/features/FullScreenAppWrapper.tsx"; import { ConnectionScreen } from "@/components/connection/ConnectionScreen.tsx"; diff --git a/src/ui/features/proxmox-stats/ProxmoxStatsTab.tsx b/plugins/host-metrics/src/frontend/proxmox-stats/ProxmoxStatsTab.tsx similarity index 98% rename from src/ui/features/proxmox-stats/ProxmoxStatsTab.tsx rename to plugins/host-metrics/src/frontend/proxmox-stats/ProxmoxStatsTab.tsx index c329aea5f..e46e9b790 100644 --- a/src/ui/features/proxmox-stats/ProxmoxStatsTab.tsx +++ b/plugins/host-metrics/src/frontend/proxmox-stats/ProxmoxStatsTab.tsx @@ -1,16 +1,16 @@ /* eslint-disable react-hooks/exhaustive-deps */ import React from "react"; import { Button } from "@/components/button.tsx"; +import { getSSHHosts } from "@/main-axios"; import { getProxmoxStats, startProxmoxStatsPolling, stopProxmoxStatsPolling, sendProxmoxStatsHeartbeat, - getSSHHosts, -} from "@/main-axios.ts"; +} from "./proxmox-stats-api"; import type { ProxmoxStatsSnapshot } from "@/types/proxmox"; import type { ProxmoxStatsConfig } from "@/types"; -import { useTranslation } from "react-i18next"; +import { useTranslation } from "@termix/plugin-sdk/frontend"; import { RefreshCw, Server } from "lucide-react"; import { NodeSummaryStrip } from "./NodeSummaryStrip"; import { GuestTable } from "./GuestTable"; diff --git a/src/ui/features/proxmox-stats/cards/ClusterHealthCard.tsx b/plugins/host-metrics/src/frontend/proxmox-stats/cards/ClusterHealthCard.tsx similarity index 97% rename from src/ui/features/proxmox-stats/cards/ClusterHealthCard.tsx rename to plugins/host-metrics/src/frontend/proxmox-stats/cards/ClusterHealthCard.tsx index 8c0620f58..a480ec4f3 100644 --- a/src/ui/features/proxmox-stats/cards/ClusterHealthCard.tsx +++ b/plugins/host-metrics/src/frontend/proxmox-stats/cards/ClusterHealthCard.tsx @@ -1,5 +1,5 @@ import { Network } from "lucide-react"; -import { useTranslation } from "react-i18next"; +import { useTranslation } from "@termix/plugin-sdk/frontend"; import type { ProxmoxStatsSnapshot } from "@/types/proxmox"; import { cn } from "@/lib/utils"; import { MetricCard } from "@/components/metric-card"; diff --git a/src/ui/features/proxmox-stats/cards/NodeNetworkCard.tsx b/plugins/host-metrics/src/frontend/proxmox-stats/cards/NodeNetworkCard.tsx similarity index 94% rename from src/ui/features/proxmox-stats/cards/NodeNetworkCard.tsx rename to plugins/host-metrics/src/frontend/proxmox-stats/cards/NodeNetworkCard.tsx index e48ed4ce2..0b4a590a8 100644 --- a/src/ui/features/proxmox-stats/cards/NodeNetworkCard.tsx +++ b/plugins/host-metrics/src/frontend/proxmox-stats/cards/NodeNetworkCard.tsx @@ -1,5 +1,5 @@ import { Network } from "lucide-react"; -import { useTranslation } from "react-i18next"; +import { useTranslation } from "@termix/plugin-sdk/frontend"; import type { ProxmoxStatsSnapshot } from "@/types/proxmox"; import { StatRow } from "@/components/charts"; import { MetricCard } from "@/components/metric-card"; diff --git a/src/ui/features/proxmox-stats/cards/StoragePoolsCard.tsx b/plugins/host-metrics/src/frontend/proxmox-stats/cards/StoragePoolsCard.tsx similarity index 97% rename from src/ui/features/proxmox-stats/cards/StoragePoolsCard.tsx rename to plugins/host-metrics/src/frontend/proxmox-stats/cards/StoragePoolsCard.tsx index 21c8f6f39..c79356014 100644 --- a/src/ui/features/proxmox-stats/cards/StoragePoolsCard.tsx +++ b/plugins/host-metrics/src/frontend/proxmox-stats/cards/StoragePoolsCard.tsx @@ -1,5 +1,5 @@ import { Database } from "lucide-react"; -import { useTranslation } from "react-i18next"; +import { useTranslation } from "@termix/plugin-sdk/frontend"; import type { ProxmoxStatsSnapshot } from "@/types/proxmox"; import { MetricCard } from "@/components/metric-card"; diff --git a/src/ui/api/proxmox-stats-api.ts b/plugins/host-metrics/src/frontend/proxmox-stats/proxmox-stats-api.ts similarity index 100% rename from src/ui/api/proxmox-stats-api.ts rename to plugins/host-metrics/src/frontend/proxmox-stats/proxmox-stats-api.ts diff --git a/plugins/host-metrics/tests/frontend/activate.test.tsx b/plugins/host-metrics/tests/frontend/activate.test.tsx new file mode 100644 index 000000000..814097280 --- /dev/null +++ b/plugins/host-metrics/tests/frontend/activate.test.tsx @@ -0,0 +1,53 @@ +import { afterEach, describe, expect, it } from "vitest"; +import { + renderWithApp, + type RenderedPluginApp, +} from "@termix/plugin-sdk/testing"; +import type { PluginManifest } from "@termix/plugin-sdk/manifest"; +import * as plugin from "../../src/frontend/index"; +import manifestJson from "../../manifest.json"; +import locales from "../../locales/en.json"; + +const manifest = manifestJson as unknown as PluginManifest; + +const declared = (views?: Array<{ id: string }>) => + (views ?? []).map((view) => view.id).sort(); + +let rendered: RenderedPluginApp | null = null; + +afterEach(async () => { + await rendered?.deactivate(); + rendered = null; +}); + +describe(`${manifest.id} activate`, () => { + it("activates and registers only views its manifest declares", async () => { + rendered = await renderWithApp(plugin, { manifest, locales }); + const contributes = manifest.contributes as unknown as Record< + string, + Array<{ id: string }> | undefined + >; + const tabs = declared(contributes.tabs); + // A rail panel may reuse one of the plugin's tab ids. + const panels = [...declared(contributes.panels), ...tabs]; + const cards = declared(contributes.dashboardCards); + for (const id of rendered.registered.tabs()) expect(tabs).toContain(id); + for (const id of rendered.registered.panels()) expect(panels).toContain(id); + for (const id of rendered.registered.dashboardCards()) { + expect(cards).toContain(id); + } + }); + + it("removes everything it registered on deactivate", async () => { + const app = await renderWithApp(plugin, { manifest, locales }); + await app.deactivate(); + expect(app.registered.tabs()).toEqual([]); + expect(app.registered.panels()).toEqual([]); + expect(app.registered.railItems()).toEqual([]); + expect(app.registered.hostActions()).toEqual([]); + expect(app.registered.hostEditorSections()).toEqual([]); + expect(app.registered.dashboardCards()).toEqual([]); + expect(app.registered.settingsComponents()).toEqual([]); + expect(app.registered.actions()).toEqual([]); + }); +}); diff --git a/plugins/network-topology/locales/en.json b/plugins/network-topology/locales/en.json index 0967ef424..c7c1395bd 100644 --- a/plugins/network-topology/locales/en.json +++ b/plugins/network-topology/locales/en.json @@ -1 +1,60 @@ -{} +{ + "networkGraph": { + "addHost": "Add Host", + "addGroup": "Add Group", + "addLink": "Add Link", + "zoomIn": "Zoom In", + "zoomOut": "Zoom Out", + "resetView": "Reset View", + "selectHost": "Select Host", + "chooseHost": "Choose a host...", + "parentGroup": "Parent Group", + "noGroup": "No Group", + "groupName": "Group Name", + "color": "Color", + "source": "Source", + "target": "Target", + "moveToGroup": "Move to Group", + "selectGroup": "Select group...", + "addConnection": "Add Connection", + "hostDetails": "Host Details", + "removeFromGroup": "Remove from Group", + "addHostHere": "Add Host Here", + "editGroup": "Edit Group", + "delete": "Delete", + "add": "Add", + "create": "Create", + "move": "Move", + "connect": "Connect", + "createGroup": "Create Group", + "selectSourcePlaceholder": "Select Source...", + "selectTargetPlaceholder": "Select Target...", + "invalidFile": "Invalid File", + "hostAlreadyExists": "Host is already in the topology", + "connectionExists": "Connection already exists", + "unknown": "Unknown", + "name": "Name", + "ip": "IP", + "status": "Status", + "failedToAddNode": "Failed to add node", + "sourceDifferentFromTarget": "Source and target must be different", + "exportJSON": "Export JSON", + "importJSON": "Import JSON", + "terminal": "Terminal", + "fileManager": "File Manager", + "tunnel": "Tunnel", + "docker": "Docker", + "serverStats": "Host Metrics", + "hostMetrics": "Host Metrics", + "noNodes": "No nodes yet" + }, + "nav": { + "networkGraph": "Network Graph" + }, + "dashboard": { + "networkGraph": "Network Graph" + }, + "dashboardTab": { + "nodes": "{{count}} nodes" + } +} diff --git a/plugins/network-topology/locales/translated/af_ZA.json b/plugins/network-topology/locales/translated/af_ZA.json new file mode 100644 index 000000000..e7c2b95b1 --- /dev/null +++ b/plugins/network-topology/locales/translated/af_ZA.json @@ -0,0 +1,60 @@ +{ + "networkGraph": { + "addHost": "Voeg gasheer by", + "addGroup": "Voeg Groep by", + "addLink": "Voeg skakel by", + "zoomIn": "Inzoem", + "zoomOut": "Uitzoom", + "resetView": "Herstel aansig", + "selectHost": "Kies gasheer", + "chooseHost": "Kies 'n gasheer...", + "parentGroup": "Ouergroep", + "noGroup": "Geen Groep", + "groupName": "Groepnaam", + "color": "Kleur", + "source": "Bron", + "target": "Teiken", + "moveToGroup": "Skuif na Groep", + "selectGroup": "Kies groep...", + "addConnection": "Voeg verbinding by", + "hostDetails": "Gasheerbesonderhede", + "removeFromGroup": "Verwyder uit Groep", + "addHostHere": "Voeg gasheer hier by", + "editGroup": "Wysig Groep", + "delete": "Vee uit", + "add": "Voeg by", + "create": "Skep", + "move": "Beweeg", + "connect": "Verbind", + "createGroup": "Skep Groep", + "selectSourcePlaceholder": "Kies Bron...", + "selectTargetPlaceholder": "Kies Teiken...", + "invalidFile": "Ongeldige lêer", + "hostAlreadyExists": "Gasheer is reeds in die topologie", + "connectionExists": "Verbinding bestaan reeds", + "unknown": "Onbekend", + "name": "Naam", + "ip": "IP-adres", + "status": "Status", + "failedToAddNode": "Kon nie nodus byvoeg nie", + "sourceDifferentFromTarget": "Bron en teiken moet verskillend wees", + "exportJSON": "Voer JSON uit", + "importJSON": "Voer JSON in", + "terminal": "Terminaal", + "fileManager": "Lêerbestuurder", + "tunnel": "Tonnel", + "docker": "Docker", + "serverStats": "Gasheermetrieke", + "hostMetrics": "Gasheermetrieke", + "noNodes": "Geen nodusse nog nie" + }, + "nav": { + "networkGraph": "Netwerkgrafiek" + }, + "dashboard": { + "networkGraph": "Netwerkgrafiek" + }, + "dashboardTab": { + "nodes": "{{count}} nodusse" + } +} diff --git a/plugins/network-topology/locales/translated/ar_SA.json b/plugins/network-topology/locales/translated/ar_SA.json new file mode 100644 index 000000000..2f158ae5a --- /dev/null +++ b/plugins/network-topology/locales/translated/ar_SA.json @@ -0,0 +1,60 @@ +{ + "networkGraph": { + "addHost": "إضافة مضيف", + "addGroup": "إضافة مجموعة", + "addLink": "إضافة رابط", + "zoomIn": "تكبير", + "zoomOut": "تصغير", + "resetView": "إعادة ضبط العرض", + "selectHost": "تحديد مضيف", + "chooseHost": "اختر مضيفًا...", + "parentGroup": "المجموعة الأم", + "noGroup": "بدون مجموعة", + "groupName": "اسم المجموعة", + "color": "اللون", + "source": "المصدر", + "target": "الهدف", + "moveToGroup": "نقل إلى مجموعة", + "selectGroup": "تحديد مجموعة...", + "addConnection": "إضافة اتصال", + "hostDetails": "تفاصيل المضيف", + "removeFromGroup": "إزالة من المجموعة", + "addHostHere": "إضافة مضيف هنا", + "editGroup": "تعديل المجموعة", + "delete": "حذف", + "add": "إضافة", + "create": "إنشاء", + "move": "نقل", + "connect": "اتصل", + "createGroup": "إنشاء مجموعة", + "selectSourcePlaceholder": "تحديد المصدر...", + "selectTargetPlaceholder": "تحديد الهدف...", + "invalidFile": "ملف غير صالح", + "hostAlreadyExists": "المضيف موجود بالفعل في الطوبولوجيا", + "connectionExists": "الاتصال موجود بالفعل", + "unknown": "غير معروف", + "name": "الاسم", + "ip": "IP", + "status": "الحالة", + "failedToAddNode": "فشل في إضافة العقدة", + "sourceDifferentFromTarget": "يجب أن يكون المصدر والهدف مختلفين", + "exportJSON": "تصدير JSON", + "importJSON": "استيراد JSON", + "terminal": "الطرفية", + "fileManager": "مدير الملفات", + "tunnel": "نفق", + "docker": "Docker", + "serverStats": "مقاييس المضيف", + "hostMetrics": "مقاييس المضيف", + "noNodes": "لا توجد عُقد بعد" + }, + "nav": { + "networkGraph": "رسم بياني للشبكة" + }, + "dashboard": { + "networkGraph": "الرسم البياني للشبكة" + }, + "dashboardTab": { + "nodes": "{{count}} عقدة" + } +} diff --git a/plugins/network-topology/locales/translated/bg_BG.json b/plugins/network-topology/locales/translated/bg_BG.json new file mode 100644 index 000000000..d35506d4c --- /dev/null +++ b/plugins/network-topology/locales/translated/bg_BG.json @@ -0,0 +1,60 @@ +{ + "networkGraph": { + "addHost": "Добавяне на хост", + "addGroup": "Добавяне на група", + "addLink": "Добавяне на връзка", + "zoomIn": "Увеличаване на мащаба", + "zoomOut": "Намаляване на мащаба", + "resetView": "Нулиране на изгледа", + "selectHost": "Изберете хост", + "chooseHost": "Изберете хост...", + "parentGroup": "Родителска група", + "noGroup": "Няма група", + "groupName": "Име на групата", + "color": "Цвят", + "source": "Източник", + "target": "Цел", + "moveToGroup": "Преместване в група", + "selectGroup": "Изберете група...", + "addConnection": "Добавяне на връзка", + "hostDetails": "Детайли за хоста", + "removeFromGroup": "Премахване от групата", + "addHostHere": "Добавете хост тук", + "editGroup": "Редактиране на група", + "delete": "Изтриване", + "add": "Добавяне", + "create": "Създаване", + "move": "Преместване", + "connect": "Свържете се", + "createGroup": "Създаване на група", + "selectSourcePlaceholder": "Изберете източник...", + "selectTargetPlaceholder": "Изберете цел...", + "invalidFile": "Невалиден файл", + "hostAlreadyExists": "Хостът вече е в топологията", + "connectionExists": "Връзката вече съществува", + "unknown": "Неизвестен", + "name": "Име", + "ip": "ИП", + "status": "Статус", + "failedToAddNode": "Добавянето на възел не бе успешно", + "sourceDifferentFromTarget": "Източникът и целта трябва да са различни", + "exportJSON": "Експортиране на JSON", + "importJSON": "Импортиране на JSON", + "terminal": "Терминал", + "fileManager": "Файлов мениджър", + "tunnel": "Тунел", + "docker": "Докер", + "serverStats": "Метрики на хоста", + "hostMetrics": "Метрики на хоста", + "noNodes": "Все още няма възли" + }, + "nav": { + "networkGraph": "Мрежова графика" + }, + "dashboard": { + "networkGraph": "Мрежова графика" + }, + "dashboardTab": { + "nodes": "{{count}} възли" + } +} diff --git a/plugins/network-topology/locales/translated/bn_BD.json b/plugins/network-topology/locales/translated/bn_BD.json new file mode 100644 index 000000000..105122add --- /dev/null +++ b/plugins/network-topology/locales/translated/bn_BD.json @@ -0,0 +1,60 @@ +{ + "networkGraph": { + "addHost": "হোস্ট যোগ করুন", + "addGroup": "গ্রুপ যোগ করুন", + "addLink": "লিঙ্ক যোগ করুন", + "zoomIn": "জুম ইন", + "zoomOut": "জুম আউট", + "resetView": "দৃশ্য রিসেট করুন", + "selectHost": "হোস্ট নির্বাচন করুন", + "chooseHost": "একজন হোস্ট বেছে নিন...", + "parentGroup": "অভিভাবক গোষ্ঠী", + "noGroup": "কোন গ্রুপ নেই", + "groupName": "গ্রুপের নাম", + "color": "রঙ", + "source": "উৎস", + "target": "লক্ষ্য", + "moveToGroup": "গ্রুপে যান", + "selectGroup": "দল নির্বাচন করুন...", + "addConnection": "সংযোগ যোগ করুন", + "hostDetails": "হোস্টের বিবরণ", + "removeFromGroup": "গ্রুপ থেকে অপসারণ করুন", + "addHostHere": "এখানে হোস্ট যোগ করুন", + "editGroup": "সম্পাদনা গ্রুপ", + "delete": "মুছে ফেলুন", + "add": "যোগ করুন", + "create": "তৈরি করুন", + "move": "স্থানান্তর", + "connect": "সংযোগ করুন", + "createGroup": "গ্রুপ তৈরি করুন", + "selectSourcePlaceholder": "উৎস নির্বাচন করুন...", + "selectTargetPlaceholder": "লক্ষ্য নির্বাচন করুন...", + "invalidFile": "অবৈধ ফাইল", + "hostAlreadyExists": "হোস্ট ইতিমধ্যে টপোলজিতে আছে", + "connectionExists": "সংযোগটি ইতিমধ্যেই বিদ্যমান আছে", + "unknown": "অজানা", + "name": "নাম", + "ip": "আইপি", + "status": "অবস্থা", + "failedToAddNode": "নোড যোগ করতে ব্যর্থ হয়েছে", + "sourceDifferentFromTarget": "উৎস এবং লক্ষ্য অবশ্যই ভিন্ন হতে হবে", + "exportJSON": "JSON রপ্তানি করুন", + "importJSON": "JSON আমদানি করুন", + "terminal": "টার্মিনাল", + "fileManager": "ফাইল ম্যানেজার", + "tunnel": "টানেল", + "docker": "ডকার", + "serverStats": "হোস্ট মেট্রিক্স", + "hostMetrics": "হোস্ট মেট্রিক্স", + "noNodes": "এখনো কোনো নোড নেই" + }, + "nav": { + "networkGraph": "নেটওয়ার্ক গ্রাফ" + }, + "dashboard": { + "networkGraph": "নেটওয়ার্ক গ্রাফ" + }, + "dashboardTab": { + "nodes": "{{count}} নোড" + } +} diff --git a/plugins/network-topology/locales/translated/ca_ES.json b/plugins/network-topology/locales/translated/ca_ES.json new file mode 100644 index 000000000..06757edb0 --- /dev/null +++ b/plugins/network-topology/locales/translated/ca_ES.json @@ -0,0 +1,60 @@ +{ + "networkGraph": { + "addHost": "Afegeix amfitrió", + "addGroup": "Afegeix un grup", + "addLink": "Afegeix un enllaç", + "zoomIn": "Ampliar zoom", + "zoomOut": "Allunyar", + "resetView": "Restableix la vista", + "selectHost": "Selecciona l'amfitrió", + "chooseHost": "Trieu un amfitrió...", + "parentGroup": "Grup de pares", + "noGroup": "Sense grup", + "groupName": "Nom del grup", + "color": "Color", + "source": "Font", + "target": "Objectiu", + "moveToGroup": "Moure al grup", + "selectGroup": "Selecciona el grup...", + "addConnection": "Afegeix una connexió", + "hostDetails": "Detalls de l'amfitrió", + "removeFromGroup": "Elimina del grup", + "addHostHere": "Afegeix l'amfitrió aquí", + "editGroup": "Edita el grup", + "delete": "Suprimeix", + "add": "Afegeix", + "create": "Crea", + "move": "Moure", + "connect": "Connecta", + "createGroup": "Crea un grup", + "selectSourcePlaceholder": "Selecciona la font...", + "selectTargetPlaceholder": "Selecciona l'objectiu...", + "invalidFile": "Fitxer no vàlid", + "hostAlreadyExists": "L'amfitrió ja és a la topologia", + "connectionExists": "La connexió ja existeix", + "unknown": "Desconegut", + "name": "Nom", + "ip": "IP", + "status": "Estat", + "failedToAddNode": "No s'ha pogut afegir el node", + "sourceDifferentFromTarget": "La font i la destinació han de ser diferents", + "exportJSON": "Exporta JSON", + "importJSON": "Importa JSON", + "terminal": "Terminal", + "fileManager": "Gestor de fitxers", + "tunnel": "Túnel", + "docker": "Docker", + "serverStats": "Mètriques de l'amfitrió", + "hostMetrics": "Mètriques de l'amfitrió", + "noNodes": "Encara no hi ha nodes" + }, + "nav": { + "networkGraph": "Gràfic de xarxa" + }, + "dashboard": { + "networkGraph": "Gràfic de xarxa" + }, + "dashboardTab": { + "nodes": "nodes {{count}}" + } +} diff --git a/plugins/network-topology/locales/translated/cs_CZ.json b/plugins/network-topology/locales/translated/cs_CZ.json new file mode 100644 index 000000000..ecd6d5f7b --- /dev/null +++ b/plugins/network-topology/locales/translated/cs_CZ.json @@ -0,0 +1,60 @@ +{ + "networkGraph": { + "addHost": "Přidat hostitele", + "addGroup": "Přidat skupinu", + "addLink": "Přidat odkaz", + "zoomIn": "Přiblížit", + "zoomOut": "Oddálit", + "resetView": "Obnovit zobrazení", + "selectHost": "Vyberte hostitele", + "chooseHost": "Vyberte si hostitele...", + "parentGroup": "Nadřazená skupina", + "noGroup": "Žádná skupina", + "groupName": "Název skupiny", + "color": "Barva", + "source": "Zdroj", + "target": "Cíl", + "moveToGroup": "Přesunout do skupiny", + "selectGroup": "Vyberte skupinu...", + "addConnection": "Přidat připojení", + "hostDetails": "Podrobnosti o hostiteli", + "removeFromGroup": "Odebrat ze skupiny", + "addHostHere": "Přidat hostitele zde", + "editGroup": "Upravit skupinu", + "delete": "Vymazat", + "add": "Přidat", + "create": "Vytvořit", + "move": "Pohyb", + "connect": "Připojit", + "createGroup": "Vytvořit skupinu", + "selectSourcePlaceholder": "Vyberte zdroj...", + "selectTargetPlaceholder": "Vyberte cíl...", + "invalidFile": "Neplatný soubor", + "hostAlreadyExists": "Hostitel je již v topologii", + "connectionExists": "Připojení již existuje", + "unknown": "Neznámý", + "name": "Jméno", + "ip": "IP adresa", + "status": "Postavení", + "failedToAddNode": "Nepodařilo se přidat uzel", + "sourceDifferentFromTarget": "Zdroj a cíl se musí lišit", + "exportJSON": "Exportovat JSON", + "importJSON": "Importovat JSON", + "terminal": "Terminál", + "fileManager": "Správce souborů", + "tunnel": "Tunel", + "docker": "Přístavní dělník", + "serverStats": "Metriky hostitele", + "hostMetrics": "Metriky hostitele", + "noNodes": "Zatím žádné uzly" + }, + "nav": { + "networkGraph": "Síťový graf" + }, + "dashboard": { + "networkGraph": "Síťový graf" + }, + "dashboardTab": { + "nodes": "{{count}} uzlů" + } +} diff --git a/plugins/network-topology/locales/translated/da_DK.json b/plugins/network-topology/locales/translated/da_DK.json new file mode 100644 index 000000000..dbd9f83a7 --- /dev/null +++ b/plugins/network-topology/locales/translated/da_DK.json @@ -0,0 +1,60 @@ +{ + "networkGraph": { + "addHost": "Tilføj vært", + "addGroup": "Tilføj gruppe", + "addLink": "Tilføj link", + "zoomIn": "Zoom ind", + "zoomOut": "Zoom ud", + "resetView": "Nulstil visning", + "selectHost": "Vælg vært", + "chooseHost": "Vælg en vært...", + "parentGroup": "Forældregruppe", + "noGroup": "Ingen gruppe", + "groupName": "Gruppenavn", + "color": "Farve", + "source": "Kilde", + "target": "Mål", + "moveToGroup": "Flyt til gruppe", + "selectGroup": "Vælg gruppe...", + "addConnection": "Tilføj forbindelse", + "hostDetails": "Værtsoplysninger", + "removeFromGroup": "Fjern fra gruppe", + "addHostHere": "Tilføj vært her", + "editGroup": "Rediger gruppe", + "delete": "Slet", + "add": "Tilføje", + "create": "Skabe", + "move": "Flytte", + "connect": "Forbinde", + "createGroup": "Opret gruppe", + "selectSourcePlaceholder": "Vælg kilde...", + "selectTargetPlaceholder": "Vælg mål...", + "invalidFile": "Ugyldig fil", + "hostAlreadyExists": "Værten er allerede i topologien", + "connectionExists": "Forbindelsen findes allerede", + "unknown": "Ukendt", + "name": "Navn", + "ip": "IP-adresse", + "status": "Status", + "failedToAddNode": "Kunne ikke tilføje node", + "sourceDifferentFromTarget": "Kilde og mål skal være forskellige", + "exportJSON": "Eksportér JSON", + "importJSON": "Importér JSON", + "terminal": "Terminal", + "fileManager": "Filhåndtering", + "tunnel": "Tunnel", + "docker": "Docker", + "serverStats": "Værtsmålinger", + "hostMetrics": "Værtsmålinger", + "noNodes": "Ingen noder endnu" + }, + "nav": { + "networkGraph": "Netværksgraf" + }, + "dashboard": { + "networkGraph": "Netværksgraf" + }, + "dashboardTab": { + "nodes": "{{count}} noder" + } +} diff --git a/plugins/network-topology/locales/translated/de_DE.json b/plugins/network-topology/locales/translated/de_DE.json new file mode 100644 index 000000000..4b4df93ec --- /dev/null +++ b/plugins/network-topology/locales/translated/de_DE.json @@ -0,0 +1,60 @@ +{ + "networkGraph": { + "addHost": "Host hinzufügen", + "addGroup": "Gruppe hinzufügen", + "addLink": "Link hinzufügen", + "zoomIn": "Vergrößern", + "zoomOut": "Verkleinern", + "resetView": "Ansicht zurücksetzen", + "selectHost": "Host auswählen", + "chooseHost": "Host auswählen...", + "parentGroup": "Übergeordnete Gruppe", + "noGroup": "Keine Gruppe", + "groupName": "Gruppenname", + "color": "Farbe", + "source": "Quelle", + "target": "Ziel", + "moveToGroup": "In Gruppe verschieben", + "selectGroup": "Gruppe auswählen...", + "addConnection": "Verbindung hinzufügen", + "hostDetails": "Host-Details", + "removeFromGroup": "Aus Gruppe entfernen", + "addHostHere": "Host hier hinzufügen", + "editGroup": "Gruppe bearbeiten", + "delete": "Löschen", + "add": "Hinzufügen", + "create": "Erstellen", + "move": "Verschieben", + "connect": "Verbinden", + "createGroup": "Gruppe erstellen", + "selectSourcePlaceholder": "Quelle auswählen...", + "selectTargetPlaceholder": "Ziel auswählen...", + "invalidFile": "Ungültige Datei", + "hostAlreadyExists": "Host ist bereits in der Topologie", + "connectionExists": "Verbindung ist bereits vorhanden", + "unknown": "Unbekannt", + "name": "Name", + "ip": "IP", + "status": "Status", + "failedToAddNode": "Knoten konnte nicht hinzugefügt werden", + "sourceDifferentFromTarget": "Quelle und Ziel müssen unterschiedlich sein", + "exportJSON": "JSON exportieren", + "importJSON": "JSON importieren", + "terminal": "Terminal", + "fileManager": "Dateimanager", + "tunnel": "Tunnel", + "docker": "Docker", + "serverStats": "Host-Metriken", + "hostMetrics": "Host-Metriken", + "noNodes": "Noch keine Knoten" + }, + "nav": { + "networkGraph": "Netzwerkdiagramm" + }, + "dashboard": { + "networkGraph": "Netzwerkdiagramm" + }, + "dashboardTab": { + "nodes": "{{count}} Knoten" + } +} diff --git a/plugins/network-topology/locales/translated/el_GR.json b/plugins/network-topology/locales/translated/el_GR.json new file mode 100644 index 000000000..20f323859 --- /dev/null +++ b/plugins/network-topology/locales/translated/el_GR.json @@ -0,0 +1,60 @@ +{ + "networkGraph": { + "addHost": "Προσθήκη κεντρικού υπολογιστή", + "addGroup": "Προσθήκη ομάδας", + "addLink": "Προσθήκη συνδέσμου", + "zoomIn": "Μεγέθυνση", + "zoomOut": "Σμίκρυνση", + "resetView": "Επαναφορά προβολής", + "selectHost": "Επιλέξτε κεντρικό υπολογιστή", + "chooseHost": "Επιλέξτε έναν οικοδεσπότη...", + "parentGroup": "Γονική ομάδα", + "noGroup": "Καμία ομάδα", + "groupName": "Όνομα ομάδας", + "color": "Χρώμα", + "source": "Πηγή", + "target": "Στόχος", + "moveToGroup": "Μετακίνηση σε ομάδα", + "selectGroup": "Επιλογή ομάδας...", + "addConnection": "Προσθήκη σύνδεσης", + "hostDetails": "Στοιχεία κεντρικού υπολογιστή", + "removeFromGroup": "Αφαίρεση από την ομάδα", + "addHostHere": "Προσθήκη κεντρικού υπολογιστή εδώ", + "editGroup": "Επεξεργασία ομάδας", + "delete": "Διαγράφω", + "add": "Προσθέτω", + "create": "Δημιουργώ", + "move": "Κίνηση", + "connect": "Συνδέω", + "createGroup": "Δημιουργία ομάδας", + "selectSourcePlaceholder": "Επιλογή Πηγής...", + "selectTargetPlaceholder": "Επιλογή Στόχου...", + "invalidFile": "Μη έγκυρο αρχείο", + "hostAlreadyExists": "Ο κεντρικός υπολογιστής βρίσκεται ήδη στην τοπολογία", + "connectionExists": "Η σύνδεση υπάρχει ήδη", + "unknown": "Αγνωστος", + "name": "Ονομα", + "ip": "Πνευματική Ιδιοκτησία", + "status": "Κατάσταση", + "failedToAddNode": "Αποτυχία προσθήκης κόμβου", + "sourceDifferentFromTarget": "Η πηγή και ο στόχος πρέπει να είναι διαφορετικοί", + "exportJSON": "Εξαγωγή JSON", + "importJSON": "Εισαγωγή JSON", + "terminal": "Τερματικό", + "fileManager": "Διαχειριστής αρχείων", + "tunnel": "Σήραγγα", + "docker": "Λιμενεργάτης", + "serverStats": "Μετρήσεις κεντρικού υπολογιστή", + "hostMetrics": "Μετρήσεις κεντρικού υπολογιστή", + "noNodes": "Δεν υπάρχουν ακόμη κόμβοι" + }, + "nav": { + "networkGraph": "Γράφημα δικτύου" + }, + "dashboard": { + "networkGraph": "Γράφημα δικτύου" + }, + "dashboardTab": { + "nodes": "{{count}} κόμβοι" + } +} diff --git a/plugins/network-topology/locales/translated/es_ES.json b/plugins/network-topology/locales/translated/es_ES.json new file mode 100644 index 000000000..a4b041cfa --- /dev/null +++ b/plugins/network-topology/locales/translated/es_ES.json @@ -0,0 +1,60 @@ +{ + "networkGraph": { + "addHost": "Añadir host", + "addGroup": "Añadir grupo", + "addLink": "Añadir enlace", + "zoomIn": "Acercar", + "zoomOut": "Alejar", + "resetView": "Restablecer vista", + "selectHost": "Seleccionar host", + "chooseHost": "Elegir un host...", + "parentGroup": "Grupo padre", + "noGroup": "Sin grupo", + "groupName": "Nombre del grupo", + "color": "Color", + "source": "Origen", + "target": "Destino", + "moveToGroup": "Mover al grupo", + "selectGroup": "Seleccionar grupo...", + "addConnection": "Añadir conexión", + "hostDetails": "Detalles del host", + "removeFromGroup": "Quitar del grupo", + "addHostHere": "Añadir host aquí", + "editGroup": "Editar grupo", + "delete": "Eliminar", + "add": "Añadir", + "create": "Crear", + "move": "Mover", + "connect": "Conectar", + "createGroup": "Crear grupo", + "selectSourcePlaceholder": "Seleccionar origen...", + "selectTargetPlaceholder": "Seleccionar destino...", + "invalidFile": "Archivo no válido", + "hostAlreadyExists": "El host ya está en la topología", + "connectionExists": "La conexión ya existe", + "unknown": "Desconocido", + "name": "Nombre", + "ip": "IP", + "status": "Estado", + "failedToAddNode": "Error al añadir nodo", + "sourceDifferentFromTarget": "El origen y el destino deben ser diferentes", + "exportJSON": "Exportar JSON", + "importJSON": "Importar JSON", + "terminal": "Terminal", + "fileManager": "Gestor de archivos", + "tunnel": "Túnel", + "docker": "Docker", + "serverStats": "Métricas del host", + "hostMetrics": "Métricas del host", + "noNodes": "Aún no hay nodos" + }, + "nav": { + "networkGraph": "Gráfico de red" + }, + "dashboard": { + "networkGraph": "Gráfico de red" + }, + "dashboardTab": { + "nodes": "{{count}} nodos" + } +} diff --git a/plugins/network-topology/locales/translated/fi_FI.json b/plugins/network-topology/locales/translated/fi_FI.json new file mode 100644 index 000000000..1cdf961eb --- /dev/null +++ b/plugins/network-topology/locales/translated/fi_FI.json @@ -0,0 +1,60 @@ +{ + "networkGraph": { + "addHost": "Lisää isäntä", + "addGroup": "Lisää ryhmä", + "addLink": "Lisää linkki", + "zoomIn": "Lähennä", + "zoomOut": "Loitonna", + "resetView": "Palauta näkymä", + "selectHost": "Valitse isäntä", + "chooseHost": "Valitse isäntä...", + "parentGroup": "Yläryhmä", + "noGroup": "Ei ryhmää", + "groupName": "Ryhmän nimi", + "color": "Väri", + "source": "Lähde", + "target": "Kohde", + "moveToGroup": "Siirrä ryhmään", + "selectGroup": "Valitse ryhmä...", + "addConnection": "Lisää yhteys", + "hostDetails": "Isännän tiedot", + "removeFromGroup": "Poista ryhmästä", + "addHostHere": "Lisää isäntä tähän", + "editGroup": "Muokkaa ryhmää", + "delete": "Poistaa", + "add": "Lisätä", + "create": "Luoda", + "move": "Liikkua", + "connect": "Yhdistä", + "createGroup": "Luo ryhmä", + "selectSourcePlaceholder": "Valitse lähde...", + "selectTargetPlaceholder": "Valitse kohde...", + "invalidFile": "Virheellinen tiedosto", + "hostAlreadyExists": "Isäntä on jo topologiassa", + "connectionExists": "Yhteys on jo olemassa", + "unknown": "Tuntematon", + "name": "Nimi", + "ip": "IP-osoite", + "status": "Status", + "failedToAddNode": "Solmun lisääminen epäonnistui", + "sourceDifferentFromTarget": "Lähteen ja kohteen on oltava eri", + "exportJSON": "Vie JSON", + "importJSON": "Tuo JSON", + "terminal": "Terminaali", + "fileManager": "Tiedostonhallinta", + "tunnel": "Tunneli", + "docker": "Satamatyöläinen", + "serverStats": "Isännän mittarit", + "hostMetrics": "Isännän mittarit", + "noNodes": "Ei vielä solmuja" + }, + "nav": { + "networkGraph": "Verkkokaavio" + }, + "dashboard": { + "networkGraph": "Verkkokaavio" + }, + "dashboardTab": { + "nodes": "{{count}} solmut" + } +} diff --git a/plugins/network-topology/locales/translated/fr_FR.json b/plugins/network-topology/locales/translated/fr_FR.json new file mode 100644 index 000000000..3865a5abc --- /dev/null +++ b/plugins/network-topology/locales/translated/fr_FR.json @@ -0,0 +1,60 @@ +{ + "networkGraph": { + "addHost": "Ajouter un hôte", + "addGroup": "Ajouter un groupe", + "addLink": "Ajouter un lien", + "zoomIn": "Zoom avant", + "zoomOut": "Zoom arrière", + "resetView": "Réinitialiser la vue", + "selectHost": "Sélectionner l'hôte", + "chooseHost": "Choisir un hôte...", + "parentGroup": "Groupe parent", + "noGroup": "Aucun groupe", + "groupName": "Nom du groupe", + "color": "Couleur", + "source": "Source", + "target": "Cible", + "moveToGroup": "Déplacer vers le groupe", + "selectGroup": "Sélectionner un groupe...", + "addConnection": "Ajouter une connexion", + "hostDetails": "Détails de l'hôte", + "removeFromGroup": "Retirer du groupe", + "addHostHere": "Ajouter un hôte ici", + "editGroup": "Modifier le groupe", + "delete": "Supprimer", + "add": "Ajouter", + "create": "Créer", + "move": "Déplacer", + "connect": "Connecter", + "createGroup": "Créer un groupe", + "selectSourcePlaceholder": "Sélectionner la source...", + "selectTargetPlaceholder": "Sélectionner la cible...", + "invalidFile": "Fichier non valide", + "hostAlreadyExists": "L'hôte est déjà dans la topologie", + "connectionExists": "La connexion existe déjà", + "unknown": "Inconnu", + "name": "Nom", + "ip": "IP", + "status": "Statut", + "failedToAddNode": "Échec de l'ajout du nœud", + "sourceDifferentFromTarget": "La source et la cible doivent être différentes", + "exportJSON": "Exporter JSON", + "importJSON": "Importer JSON", + "terminal": "Terminal", + "fileManager": "Gestionnaire de fichiers", + "tunnel": "Tunnel", + "docker": "Docker", + "serverStats": "Métriques de l'hôte", + "hostMetrics": "Métriques de l'hôte", + "noNodes": "Aucun nœud pour l'instant" + }, + "nav": { + "networkGraph": "Graphique réseau" + }, + "dashboard": { + "networkGraph": "Graphique réseau" + }, + "dashboardTab": { + "nodes": "{{count}} nœuds" + } +} diff --git a/plugins/network-topology/locales/translated/he_IL.json b/plugins/network-topology/locales/translated/he_IL.json new file mode 100644 index 000000000..c8a6c46f3 --- /dev/null +++ b/plugins/network-topology/locales/translated/he_IL.json @@ -0,0 +1,60 @@ +{ + "networkGraph": { + "addHost": "הוסף מארח", + "addGroup": "הוסף קבוצה", + "addLink": "הוסף קישור", + "zoomIn": "לְהִתְמַקֵד", + "zoomOut": "התקרבות", + "resetView": "איפוס תצוגה", + "selectHost": "בחר מארח", + "chooseHost": "בחר מארח...", + "parentGroup": "קבוצת הורים", + "noGroup": "אין קבוצה", + "groupName": "שם הקבוצה", + "color": "צֶבַע", + "source": "מָקוֹר", + "target": "יַעַד", + "moveToGroup": "העבר לקבוצה", + "selectGroup": "בחירת קבוצה...", + "addConnection": "הוסף חיבור", + "hostDetails": "פרטי המארח", + "removeFromGroup": "הסר מהקבוצה", + "addHostHere": "הוסף מארח כאן", + "editGroup": "עריכת קבוצה", + "delete": "לִמְחוֹק", + "add": "לְהוֹסִיף", + "create": "לִיצוֹר", + "move": "מַהֲלָך", + "connect": "לְחַבֵּר", + "createGroup": "צור קבוצה", + "selectSourcePlaceholder": "בחר מקור...", + "selectTargetPlaceholder": "בחר יעד...", + "invalidFile": "קובץ לא חוקי", + "hostAlreadyExists": "המארח כבר נמצא בטופולוגיה", + "connectionExists": "החיבור כבר קיים", + "unknown": "לֹא יְדוּעַ", + "name": "שֵׁם", + "ip": "IP", + "status": "סטָטוּס", + "failedToAddNode": "נכשל בהוספת הצומת", + "sourceDifferentFromTarget": "המקור והיעד חייבים להיות שונים", + "exportJSON": "ייצוא JSON", + "importJSON": "ייבוא JSON", + "terminal": "מָסוֹף", + "fileManager": "מנהל הקבצים", + "tunnel": "מִנהָרָה", + "docker": "דוקר", + "serverStats": "מדדי מארח", + "hostMetrics": "מדדי מארח", + "noNodes": "עדיין אין צמתים" + }, + "nav": { + "networkGraph": "גרף הרשת" + }, + "dashboard": { + "networkGraph": "גרף הרשת" + }, + "dashboardTab": { + "nodes": "צמתים {{count}}" + } +} diff --git a/plugins/network-topology/locales/translated/hi_IN.json b/plugins/network-topology/locales/translated/hi_IN.json new file mode 100644 index 000000000..0dc02c8c0 --- /dev/null +++ b/plugins/network-topology/locales/translated/hi_IN.json @@ -0,0 +1,60 @@ +{ + "networkGraph": { + "addHost": "होस्ट जोड़ें", + "addGroup": "समूह जोड़ें", + "addLink": "लिंक जोड़ें", + "zoomIn": "ज़ूम इन", + "zoomOut": "ज़ूम आउट", + "resetView": "रीसेट करें", + "selectHost": "होस्ट चुनें", + "chooseHost": "कोई होस्ट चुनें...", + "parentGroup": "मूल समूह", + "noGroup": "कोई समूह नहीं", + "groupName": "समूह का नाम", + "color": "रंग", + "source": "स्रोत", + "target": "लक्ष्य", + "moveToGroup": "समूह में ले जाएँ", + "selectGroup": "समूह चुनें...", + "addConnection": "कनेक्शन जोड़ें", + "hostDetails": "होस्ट विवरण", + "removeFromGroup": "समूह से निकालें", + "addHostHere": "यहाँ होस्ट जोड़ें", + "editGroup": "समूह संपादित करें", + "delete": "हटाएँ", + "add": "जोड़ें", + "create": "बनाएँ", + "move": "ले जाएँ", + "connect": "कनेक्ट करें", + "createGroup": "समूह बनाएँ", + "selectSourcePlaceholder": "स्रोत चुनें...", + "selectTargetPlaceholder": "लक्ष्य चुनें...", + "invalidFile": "अमान्य फ़ाइल", + "hostAlreadyExists": "होस्ट पहले से टोपोलॉजी में मौजूद है", + "connectionExists": "कनेक्शन पहले से मौजूद है", + "unknown": "अज्ञात", + "name": "नाम", + "ip": "IP", + "status": "स्थिति", + "failedToAddNode": "नोड जोड़ने में विफल", + "sourceDifferentFromTarget": "स्रोत और लक्ष्य भिन्न होने चाहिए", + "exportJSON": "JSON निर्यात करें", + "importJSON": "JSON आयात करें", + "terminal": "टर्मिनल", + "fileManager": "फ़ाइल प्रबंधक", + "tunnel": "टनल", + "docker": "Docker", + "serverStats": "होस्ट मेट्रिक्स", + "hostMetrics": "होस्ट मेट्रिक्स", + "noNodes": "अभी तक कोई नोड नहीं" + }, + "nav": { + "networkGraph": "नेटवर्क ग्राफ़" + }, + "dashboard": { + "networkGraph": "नेटवर्क ग्राफ़" + }, + "dashboardTab": { + "nodes": "{{count}} नोड्स" + } +} diff --git a/plugins/network-topology/locales/translated/hu_HU.json b/plugins/network-topology/locales/translated/hu_HU.json new file mode 100644 index 000000000..528ef2538 --- /dev/null +++ b/plugins/network-topology/locales/translated/hu_HU.json @@ -0,0 +1,60 @@ +{ + "networkGraph": { + "addHost": "Gazdagép hozzáadása", + "addGroup": "Csoport hozzáadása", + "addLink": "Link hozzáadása", + "zoomIn": "Nagyítás", + "zoomOut": "Kicsinyítés", + "resetView": "Nézet visszaállítása", + "selectHost": "Válasszon gazdagépet", + "chooseHost": "Válassz egy tárhelyszolgáltatót...", + "parentGroup": "Szülőcsoport", + "noGroup": "Nincs csoport", + "groupName": "Csoport neve", + "color": "Szín", + "source": "Forrás", + "target": "Cél", + "moveToGroup": "Áthelyezés csoportba", + "selectGroup": "Csoport kiválasztása...", + "addConnection": "Kapcsolat hozzáadása", + "hostDetails": "Gazdagép adatai", + "removeFromGroup": "Eltávolítás a csoportból", + "addHostHere": "Gazdagép hozzáadása ide", + "editGroup": "Csoport szerkesztése", + "delete": "Töröl", + "add": "Hozzáadás", + "create": "Teremt", + "move": "Mozog", + "connect": "Csatlakozás", + "createGroup": "Csoport létrehozása", + "selectSourcePlaceholder": "Forrás kiválasztása...", + "selectTargetPlaceholder": "Cél kiválasztása...", + "invalidFile": "Érvénytelen fájl", + "hostAlreadyExists": "A gazdagép már szerepel a topológiában", + "connectionExists": "A kapcsolat már létezik", + "unknown": "Ismeretlen", + "name": "Név", + "ip": "IP-cím", + "status": "Állapot", + "failedToAddNode": "Nem sikerült hozzáadni a csomópontot", + "sourceDifferentFromTarget": "A forrásnak és a célnak eltérőnek kell lennie", + "exportJSON": "JSON exportálása", + "importJSON": "JSON importálása", + "terminal": "Terminál", + "fileManager": "Fájlkezelő", + "tunnel": "Alagút", + "docker": "Dokkmunkás", + "serverStats": "Gazdagép-metrikák", + "hostMetrics": "Gazdagép-metrikák", + "noNodes": "Még nincsenek csomópontok" + }, + "nav": { + "networkGraph": "Hálózati gráf" + }, + "dashboard": { + "networkGraph": "Hálózati gráf" + }, + "dashboardTab": { + "nodes": "{{count}} csomópontok" + } +} diff --git a/plugins/network-topology/locales/translated/id_ID.json b/plugins/network-topology/locales/translated/id_ID.json new file mode 100644 index 000000000..6873a62fa --- /dev/null +++ b/plugins/network-topology/locales/translated/id_ID.json @@ -0,0 +1,60 @@ +{ + "networkGraph": { + "addHost": "Tambahkan Host", + "addGroup": "Tambahkan Grup", + "addLink": "Tambahkan Tautan", + "zoomIn": "Perbesar", + "zoomOut": "Perkecil tampilan", + "resetView": "Atur Ulang Tampilan", + "selectHost": "Pilih Host", + "chooseHost": "Pilih tuan rumah...", + "parentGroup": "Kelompok Orang Tua", + "noGroup": "Tidak Ada Grup", + "groupName": "Nama Grup", + "color": "Warna", + "source": "Sumber", + "target": "Target", + "moveToGroup": "Pindah ke Grup", + "selectGroup": "Pilih grup...", + "addConnection": "Tambahkan Koneksi", + "hostDetails": "Detail Tuan Rumah", + "removeFromGroup": "Hapus dari Grup", + "addHostHere": "Tambahkan Host di Sini", + "editGroup": "Grup Pengeditan", + "delete": "Menghapus", + "add": "Menambahkan", + "create": "Membuat", + "move": "Bergerak", + "connect": "Menghubungkan", + "createGroup": "Buat Grup", + "selectSourcePlaceholder": "Pilih Sumber...", + "selectTargetPlaceholder": "Pilih Target...", + "invalidFile": "Berkas tidak valid", + "hostAlreadyExists": "Host sudah ada dalam topologi.", + "connectionExists": "Koneksi sudah ada.", + "unknown": "Tidak dikenal", + "name": "Nama", + "ip": "AKU P", + "status": "Status", + "failedToAddNode": "Gagal menambahkan node", + "sourceDifferentFromTarget": "Sumber dan target harus berbeda.", + "exportJSON": "Ekspor JSON", + "importJSON": "Impor JSON", + "terminal": "Terminal", + "fileManager": "Pengelola File", + "tunnel": "Terowongan", + "docker": "Buruh pelabuhan", + "serverStats": "Metrik Host", + "hostMetrics": "Metrik Host", + "noNodes": "Belum ada node" + }, + "nav": { + "networkGraph": "Grafik Jaringan" + }, + "dashboard": { + "networkGraph": "Grafik Jaringan" + }, + "dashboardTab": { + "nodes": "{{count}} node" + } +} diff --git a/plugins/network-topology/locales/translated/it_IT.json b/plugins/network-topology/locales/translated/it_IT.json new file mode 100644 index 000000000..0eae51798 --- /dev/null +++ b/plugins/network-topology/locales/translated/it_IT.json @@ -0,0 +1,60 @@ +{ + "networkGraph": { + "addHost": "Aggiungi host", + "addGroup": "Aggiungi gruppo", + "addLink": "Aggiungi collegamento", + "zoomIn": "Ingrandisci", + "zoomOut": "Riduci", + "resetView": "Reimposta vista", + "selectHost": "Seleziona host", + "chooseHost": "Scegli un host...", + "parentGroup": "Gruppo padre", + "noGroup": "Nessun gruppo", + "groupName": "Nome gruppo", + "color": "Colore", + "source": "Origine", + "target": "Destinazione", + "moveToGroup": "Sposta nel gruppo", + "selectGroup": "Seleziona gruppo...", + "addConnection": "Aggiungi connessione", + "hostDetails": "Dettagli host", + "removeFromGroup": "Rimuovi dal gruppo", + "addHostHere": "Aggiungi host qui", + "editGroup": "Modifica gruppo", + "delete": "Elimina", + "add": "Aggiungi", + "create": "Crea", + "move": "Sposta", + "connect": "Connetti", + "createGroup": "Crea gruppo", + "selectSourcePlaceholder": "Seleziona origine...", + "selectTargetPlaceholder": "Seleziona destinazione...", + "invalidFile": "File non valido", + "hostAlreadyExists": "L'host è già presente nella topologia", + "connectionExists": "La connessione esiste già", + "unknown": "Sconosciuto", + "name": "Nome", + "ip": "IP", + "status": "Stato", + "failedToAddNode": "Impossibile aggiungere il nodo", + "sourceDifferentFromTarget": "Origine e destinazione devono essere diverse", + "exportJSON": "Esporta JSON", + "importJSON": "Importa JSON", + "terminal": "Terminale", + "fileManager": "Gestore file", + "tunnel": "Tunnel", + "docker": "Docker", + "serverStats": "Metriche host", + "hostMetrics": "Metriche host", + "noNodes": "Nessun nodo al momento" + }, + "nav": { + "networkGraph": "Grafico di rete" + }, + "dashboard": { + "networkGraph": "Grafico di rete" + }, + "dashboardTab": { + "nodes": "{{count}} nodi" + } +} diff --git a/plugins/network-topology/locales/translated/ja_JP.json b/plugins/network-topology/locales/translated/ja_JP.json new file mode 100644 index 000000000..ee8b9f0db --- /dev/null +++ b/plugins/network-topology/locales/translated/ja_JP.json @@ -0,0 +1,60 @@ +{ + "networkGraph": { + "addHost": "ホストを追加", + "addGroup": "グループを追加", + "addLink": "リンクを追加", + "zoomIn": "拡大", + "zoomOut": "縮小", + "resetView": "表示をリセット", + "selectHost": "ホストを選択", + "chooseHost": "ホストを選択...", + "parentGroup": "親グループ", + "noGroup": "グループなし", + "groupName": "グループ名", + "color": "色", + "source": "ソース", + "target": "ターゲット", + "moveToGroup": "グループに移動", + "selectGroup": "グループを選択...", + "addConnection": "接続を追加", + "hostDetails": "ホスト詳細", + "removeFromGroup": "グループから削除", + "addHostHere": "ここにホストを追加", + "editGroup": "グループを編集", + "delete": "削除", + "add": "追加", + "create": "作成", + "move": "移動", + "connect": "接続", + "createGroup": "グループを作成", + "selectSourcePlaceholder": "ソースを選択...", + "selectTargetPlaceholder": "ターゲットを選択...", + "invalidFile": "無効なファイル", + "hostAlreadyExists": "ホストはトポロジーに既に存在します", + "connectionExists": "接続は既に存在しています", + "unknown": "不明", + "name": "名前", + "ip": "IP", + "status": "ステータス", + "failedToAddNode": "ノードの追加に失敗しました", + "sourceDifferentFromTarget": "ソースとターゲットは異なる必要があります", + "exportJSON": "JSON エクスポート", + "importJSON": "JSON インポート", + "terminal": "ターミナル", + "fileManager": "ファイルマネージャー", + "tunnel": "トンネル", + "docker": "Docker", + "serverStats": "ホストメトリクス", + "hostMetrics": "ホストメトリクス", + "noNodes": "ノードはまだありません" + }, + "nav": { + "networkGraph": "ネットワークグラフ" + }, + "dashboard": { + "networkGraph": "ネットワークグラフ" + }, + "dashboardTab": { + "nodes": "{{count}} ノード" + } +} diff --git a/plugins/network-topology/locales/translated/ko_KR.json b/plugins/network-topology/locales/translated/ko_KR.json new file mode 100644 index 000000000..ede805526 --- /dev/null +++ b/plugins/network-topology/locales/translated/ko_KR.json @@ -0,0 +1,60 @@ +{ + "networkGraph": { + "addHost": "호스트 추가", + "addGroup": "그룹 추가", + "addLink": "링크 추가", + "zoomIn": "확대", + "zoomOut": "축소", + "resetView": "보기 초기화", + "selectHost": "호스트 선택", + "chooseHost": "호스트 선택...", + "parentGroup": "상위 그룹", + "noGroup": "그룹 없음", + "groupName": "그룹 이름", + "color": "색상", + "source": "소스", + "target": "대상", + "moveToGroup": "그룹으로 이동", + "selectGroup": "그룹 선택...", + "addConnection": "연결 추가", + "hostDetails": "호스트 세부 정보", + "removeFromGroup": "그룹에서 제거", + "addHostHere": "여기에 호스트 추가", + "editGroup": "그룹 편집", + "delete": "삭제", + "add": "추가", + "create": "생성", + "move": "이동", + "connect": "연결", + "createGroup": "그룹 생성", + "selectSourcePlaceholder": "소스 선택...", + "selectTargetPlaceholder": "대상 선택...", + "invalidFile": "잘못된 파일", + "hostAlreadyExists": "호스트가 이미 토폴로지에 있습니다.", + "connectionExists": "연결이 이미 존재합니다.", + "unknown": "알 수 없음", + "name": "이름", + "ip": "IP", + "status": "상태", + "failedToAddNode": "노드를 추가하지 못했습니다.", + "sourceDifferentFromTarget": "소스와 대상은 달라야 합니다.", + "exportJSON": "JSON 내보내기", + "importJSON": "JSON 가져오기", + "terminal": "터미널", + "fileManager": "파일 관리자", + "tunnel": "터널", + "docker": "Docker", + "serverStats": "호스트 메트릭", + "hostMetrics": "호스트 메트릭", + "noNodes": "아직 노드 없음" + }, + "nav": { + "networkGraph": "네트워크 그래프" + }, + "dashboard": { + "networkGraph": "네트워크 그래프" + }, + "dashboardTab": { + "nodes": "{{count}}개 노드" + } +} diff --git a/plugins/network-topology/locales/translated/nl_NL.json b/plugins/network-topology/locales/translated/nl_NL.json new file mode 100644 index 000000000..fe8845e27 --- /dev/null +++ b/plugins/network-topology/locales/translated/nl_NL.json @@ -0,0 +1,60 @@ +{ + "networkGraph": { + "addHost": "Voeg een host toe", + "addGroup": "Groep toevoegen", + "addLink": "Link toevoegen", + "zoomIn": "Inzoomen", + "zoomOut": "Uitzoomen", + "resetView": "Weergave opnieuw instellen", + "selectHost": "Selecteer host", + "chooseHost": "Kies een host...", + "parentGroup": "Oudergroep", + "noGroup": "Geen groep", + "groupName": "Groepsnaam", + "color": "Kleur", + "source": "Bron", + "target": "Doel", + "moveToGroup": "Verplaatsen naar groep", + "selectGroup": "Selecteer groep...", + "addConnection": "Verbinding toevoegen", + "hostDetails": "Gegevens van de gastheer", + "removeFromGroup": "Verwijderen uit groep", + "addHostHere": "Voeg hier de host toe", + "editGroup": "Groep bewerken", + "delete": "Verwijderen", + "add": "Toevoegen", + "create": "Creëren", + "move": "Beweging", + "connect": "Verbinden", + "createGroup": "Groep aanmaken", + "selectSourcePlaceholder": "Selecteer bron...", + "selectTargetPlaceholder": "Doel selecteren...", + "invalidFile": "Ongeldig bestand", + "hostAlreadyExists": "De host bevindt zich al in de topologie.", + "connectionExists": "De verbinding bestaat al", + "unknown": "Onbekend", + "name": "Naam", + "ip": "IP", + "status": "Status", + "failedToAddNode": "Het toevoegen van het knooppunt is mislukt.", + "sourceDifferentFromTarget": "Bron en doel moeten verschillend zijn.", + "exportJSON": "Exporteer JSON", + "importJSON": "JSON importeren", + "terminal": "Terminal", + "fileManager": "Bestandsbeheerder", + "tunnel": "Tunnel", + "docker": "Docker", + "serverStats": "Hoststatistieken", + "hostMetrics": "Hoststatistieken", + "noNodes": "Nog geen knooppunten" + }, + "nav": { + "networkGraph": "Netwerkgrafiek" + }, + "dashboard": { + "networkGraph": "Netwerkgrafiek" + }, + "dashboardTab": { + "nodes": "{{count}} knooppunten" + } +} diff --git a/plugins/network-topology/locales/translated/no_NO.json b/plugins/network-topology/locales/translated/no_NO.json new file mode 100644 index 000000000..d2e92f0f2 --- /dev/null +++ b/plugins/network-topology/locales/translated/no_NO.json @@ -0,0 +1,60 @@ +{ + "networkGraph": { + "addHost": "Legg til vert", + "addGroup": "Legg til gruppe", + "addLink": "Legg til lenke", + "zoomIn": "Zoom inn", + "zoomOut": "Zoom ut", + "resetView": "Tilbakestill visning", + "selectHost": "Velg vert", + "chooseHost": "Velg en vert...", + "parentGroup": "Foreldregruppe", + "noGroup": "Ingen gruppe", + "groupName": "Gruppenavn", + "color": "Farge", + "source": "Kilde", + "target": "Mål", + "moveToGroup": "Flytt til gruppe", + "selectGroup": "Velg gruppe...", + "addConnection": "Legg til tilkobling", + "hostDetails": "Vertsdetaljer", + "removeFromGroup": "Fjern fra gruppen", + "addHostHere": "Legg til vert her", + "editGroup": "Rediger gruppe", + "delete": "Slett", + "add": "Legge til", + "create": "Skape", + "move": "Flytte", + "connect": "Koble til", + "createGroup": "Opprett gruppe", + "selectSourcePlaceholder": "Velg kilde...", + "selectTargetPlaceholder": "Velg mål...", + "invalidFile": "Ugyldig fil", + "hostAlreadyExists": "Verten er allerede i topologien", + "connectionExists": "Tilkoblingen finnes allerede", + "unknown": "Ukjent", + "name": "Navn", + "ip": "IP-adresse", + "status": "Status", + "failedToAddNode": "Kunne ikke legge til node", + "sourceDifferentFromTarget": "Kilde og mål må være forskjellige", + "exportJSON": "Eksporter JSON", + "importJSON": "Importer JSON", + "terminal": "Terminal", + "fileManager": "Filbehandler", + "tunnel": "Tunnel", + "docker": "Dokker", + "serverStats": "Vertsmålinger", + "hostMetrics": "Vertsmålinger", + "noNodes": "Ingen noder ennå" + }, + "nav": { + "networkGraph": "Nettverksgraf" + }, + "dashboard": { + "networkGraph": "Nettverksgraf" + }, + "dashboardTab": { + "nodes": "{{count}} noder" + } +} diff --git a/plugins/network-topology/locales/translated/pl_PL.json b/plugins/network-topology/locales/translated/pl_PL.json new file mode 100644 index 000000000..d839f7608 --- /dev/null +++ b/plugins/network-topology/locales/translated/pl_PL.json @@ -0,0 +1,60 @@ +{ + "networkGraph": { + "addHost": "Dodaj hosta", + "addGroup": "Dodaj grupę", + "addLink": "Dodaj link", + "zoomIn": "Powiększ", + "zoomOut": "Oddal", + "resetView": "Resetuj widok", + "selectHost": "Wybierz hosta", + "chooseHost": "Wybierz hosta...", + "parentGroup": "Grupa nadrzędna", + "noGroup": "Brak grupy", + "groupName": "Nazwa grupy", + "color": "Kolor", + "source": "Źródło", + "target": "Cel", + "moveToGroup": "Przenieś do grupy", + "selectGroup": "Wybierz grupę...", + "addConnection": "Dodaj połączenie", + "hostDetails": "Szczegóły hosta", + "removeFromGroup": "Usuń z grupy", + "addHostHere": "Dodaj hosta tutaj", + "editGroup": "Edytuj grupę", + "delete": "Usuń", + "add": "Dodaj", + "create": "Utwórz", + "move": "Przenieś", + "connect": "Połącz", + "createGroup": "Utwórz grupę", + "selectSourcePlaceholder": "Wybierz źródło...", + "selectTargetPlaceholder": "Wybierz cel...", + "invalidFile": "Nieprawidłowy plik", + "hostAlreadyExists": "Host jest już w topologii", + "connectionExists": "Połączenie już istnieje", + "unknown": "Nieznany", + "name": "Nazwa", + "ip": "IP", + "status": "Status", + "failedToAddNode": "Nie udało się dodać węzła", + "sourceDifferentFromTarget": "Źródło i cel muszą być różne", + "exportJSON": "Eksportuj JSON", + "importJSON": "Importuj JSON", + "terminal": "Terminal", + "fileManager": "Menedżer plików", + "tunnel": "Tunel", + "docker": "Docker", + "serverStats": "Metryki hosta", + "hostMetrics": "Metryki hosta", + "noNodes": "Brak węzłów" + }, + "nav": { + "networkGraph": "Graf sieci" + }, + "dashboard": { + "networkGraph": "Graf sieci" + }, + "dashboardTab": { + "nodes": "{{count}} węzłów" + } +} diff --git a/plugins/network-topology/locales/translated/pt_BR.json b/plugins/network-topology/locales/translated/pt_BR.json new file mode 100644 index 000000000..4b43ca6ba --- /dev/null +++ b/plugins/network-topology/locales/translated/pt_BR.json @@ -0,0 +1,60 @@ +{ + "networkGraph": { + "addHost": "Adicionar host", + "addGroup": "Adicionar grupo", + "addLink": "Adicionar link", + "zoomIn": "Ampliar", + "zoomOut": "Diminuir o zoom", + "resetView": "Redefinir visualização", + "selectHost": "Selecione o host", + "chooseHost": "Escolha um anfitrião...", + "parentGroup": "Grupo de Pais", + "noGroup": "Nenhum grupo", + "groupName": "Nome do grupo", + "color": "Cor", + "source": "Fonte", + "target": "Alvo", + "moveToGroup": "Mover para o grupo", + "selectGroup": "Selecione o grupo...", + "addConnection": "Adicionar conexão", + "hostDetails": "Detalhes do anfitrião", + "removeFromGroup": "Remover do grupo", + "addHostHere": "Adicione o host aqui", + "editGroup": "Editar grupo", + "delete": "Excluir", + "add": "Adicionar", + "create": "Criar", + "move": "Mover", + "connect": "Conectar", + "createGroup": "Criar grupo", + "selectSourcePlaceholder": "Selecione a fonte...", + "selectTargetPlaceholder": "Selecione o alvo...", + "invalidFile": "Arquivo inválido", + "hostAlreadyExists": "O host já está na topologia.", + "connectionExists": "A conexão já existe.", + "unknown": "Desconhecido", + "name": "Nome", + "ip": "IP", + "status": "Status", + "failedToAddNode": "Falha ao adicionar nó", + "sourceDifferentFromTarget": "A origem e o destino devem ser diferentes.", + "exportJSON": "Exportar JSON", + "importJSON": "Importar JSON", + "terminal": "terminal", + "fileManager": "Gerenciador de arquivos", + "tunnel": "Túnel", + "docker": "Docker", + "serverStats": "Métricas do host", + "hostMetrics": "Métricas do host", + "noNodes": "Ainda não há nós." + }, + "nav": { + "networkGraph": "Gráfico de rede" + }, + "dashboard": { + "networkGraph": "Gráfico de rede" + }, + "dashboardTab": { + "nodes": "{{count}} nós" + } +} diff --git a/plugins/network-topology/locales/translated/pt_PT.json b/plugins/network-topology/locales/translated/pt_PT.json new file mode 100644 index 000000000..97bbce375 --- /dev/null +++ b/plugins/network-topology/locales/translated/pt_PT.json @@ -0,0 +1,60 @@ +{ + "networkGraph": { + "addHost": "Adicionar Host", + "addGroup": "Adicionar Grupo", + "addLink": "Adicionar Ligação", + "zoomIn": "Ampliar", + "zoomOut": "Reduzir", + "resetView": "Repor Vista", + "selectHost": "Selecionar Host", + "chooseHost": "Escolher um host...", + "parentGroup": "Grupo Pai", + "noGroup": "Nenhum grupo", + "groupName": "Nome do Grupo", + "color": "Cor", + "source": "Origem", + "target": "Destino", + "moveToGroup": "Mover para Grupo", + "selectGroup": "Selecionar grupo...", + "addConnection": "Adicionar Ligação", + "hostDetails": "Detalhes do Host", + "removeFromGroup": "Remover do Grupo", + "addHostHere": "Adicionar Host Aqui", + "editGroup": "Editar Grupo", + "delete": "Eliminar", + "add": "Adicionar", + "create": "Criar", + "move": "Mover", + "connect": "Ligar", + "createGroup": "Criar Grupo", + "selectSourcePlaceholder": "Selecionar Origem...", + "selectTargetPlaceholder": "Selecionar Destino...", + "invalidFile": "Ficheiro Inválido", + "hostAlreadyExists": "O host já está na topologia.", + "connectionExists": "A ligação já existe", + "unknown": "Desconhecido", + "name": "Nome", + "ip": "IP", + "status": "Estado", + "failedToAddNode": "Falha ao adicionar nó", + "sourceDifferentFromTarget": "A origem e o destino devem ser diferentes", + "exportJSON": "Exportar JSON", + "importJSON": "Importar JSON", + "terminal": "Terminal", + "fileManager": "Gestor de ficheiros", + "tunnel": "Túnel", + "docker": "Docker", + "serverStats": "Métricas do host", + "hostMetrics": "Métricas do host", + "noNodes": "Ainda sem nós" + }, + "nav": { + "networkGraph": "Gráfico de rede" + }, + "dashboard": { + "networkGraph": "Gráfico de Rede" + }, + "dashboardTab": { + "nodes": "{{count}} nós" + } +} diff --git a/plugins/network-topology/locales/translated/ro_RO.json b/plugins/network-topology/locales/translated/ro_RO.json new file mode 100644 index 000000000..0c220fc2a --- /dev/null +++ b/plugins/network-topology/locales/translated/ro_RO.json @@ -0,0 +1,60 @@ +{ + "networkGraph": { + "addHost": "Adăugați gazdă", + "addGroup": "Adăugați un grup", + "addLink": "Adăugați link", + "zoomIn": "Mărire", + "zoomOut": "Micșorare", + "resetView": "Resetare vizualizare", + "selectHost": "Selectați gazda", + "chooseHost": "Alege o gazdă...", + "parentGroup": "Grupul de părinți", + "noGroup": "Fără grup", + "groupName": "Numele grupului", + "color": "Culoare", + "source": "Sursă", + "target": "Ţintă", + "moveToGroup": "Mutare în grup", + "selectGroup": "Selectați grupul...", + "addConnection": "Adăugați o conexiune", + "hostDetails": "Detalii gazdă", + "removeFromGroup": "Eliminare din grup", + "addHostHere": "Adăugați gazda aici", + "editGroup": "Editați grupul", + "delete": "Şterge", + "add": "Adăuga", + "create": "Crea", + "move": "Mişcare", + "connect": "Conectează-te", + "createGroup": "Creare grup", + "selectSourcePlaceholder": "Selectați sursa...", + "selectTargetPlaceholder": "Selectați țintă...", + "invalidFile": "Fișier nevalid", + "hostAlreadyExists": "Gazda se află deja în topologie", + "connectionExists": "Conexiunea există deja", + "unknown": "Necunoscut", + "name": "Nume", + "ip": "IP-ul", + "status": "Stare", + "failedToAddNode": "Nu s-a putut adăuga nodul", + "sourceDifferentFromTarget": "Sursa și ținta trebuie să fie diferite", + "exportJSON": "Export JSON", + "importJSON": "Import JSON", + "terminal": "Terminal", + "fileManager": "Manager de fișiere", + "tunnel": "Tunel", + "docker": "Docher", + "serverStats": "Metrici ale gazdei", + "hostMetrics": "Metrici ale gazdei", + "noNodes": "Încă nu există noduri" + }, + "nav": { + "networkGraph": "Grafic de rețea" + }, + "dashboard": { + "networkGraph": "Grafic de rețea" + }, + "dashboardTab": { + "nodes": "noduri {{count}}" + } +} diff --git a/plugins/network-topology/locales/translated/ru_RU.json b/plugins/network-topology/locales/translated/ru_RU.json new file mode 100644 index 000000000..e21ea374d --- /dev/null +++ b/plugins/network-topology/locales/translated/ru_RU.json @@ -0,0 +1,60 @@ +{ + "networkGraph": { + "addHost": "Добавить хост", + "addGroup": "Добавить группу", + "addLink": "Добавить связь", + "zoomIn": "Приблизить", + "zoomOut": "Отдалить", + "resetView": "Сбросить вид", + "selectHost": "Выбрать хост", + "chooseHost": "Выберите хост...", + "parentGroup": "Родительская группа", + "noGroup": "Без группы", + "groupName": "Имя группы", + "color": "Цвет", + "source": "Источник", + "target": "Цель", + "moveToGroup": "Переместить в группу", + "selectGroup": "Выберите группу...", + "addConnection": "Добавить соединение", + "hostDetails": "Сведения о хосте", + "removeFromGroup": "Удалить из группы", + "addHostHere": "Добавить хост сюда", + "editGroup": "Редактировать группу", + "delete": "Удалить", + "add": "Добавить", + "create": "Создать", + "move": "Переместить", + "connect": "Соединить", + "createGroup": "Создать группу", + "selectSourcePlaceholder": "Выберите источник...", + "selectTargetPlaceholder": "Выберите цель...", + "invalidFile": "Неверный файл", + "hostAlreadyExists": "Хост уже присутствует в топологии", + "connectionExists": "Соединение уже существует", + "unknown": "Неизвестно", + "name": "Имя", + "ip": "IP", + "status": "Статус", + "failedToAddNode": "Не удалось добавить узел", + "sourceDifferentFromTarget": "Источник и цель должны различаться", + "exportJSON": "Экспорт JSON", + "importJSON": "Импорт JSON", + "terminal": "Терминал", + "fileManager": "Файловый менеджер", + "tunnel": "Туннель", + "docker": "Docker", + "serverStats": "Метрики хоста", + "hostMetrics": "Метрики хоста", + "noNodes": "Пока нет узлов" + }, + "nav": { + "networkGraph": "Сетевой график" + }, + "dashboard": { + "networkGraph": "Сетевой график" + }, + "dashboardTab": { + "nodes": "{{count}} узлов" + } +} diff --git a/plugins/network-topology/locales/translated/sr_SP.json b/plugins/network-topology/locales/translated/sr_SP.json new file mode 100644 index 000000000..d08230b39 --- /dev/null +++ b/plugins/network-topology/locales/translated/sr_SP.json @@ -0,0 +1,60 @@ +{ + "networkGraph": { + "addHost": "Додај хоста", + "addGroup": "Додај групу", + "addLink": "Додај линк", + "zoomIn": "Увећај", + "zoomOut": "Умањи", + "resetView": "Ресетуј приказ", + "selectHost": "Изаберите хост", + "chooseHost": "Изаберите домаћина...", + "parentGroup": "Матична група", + "noGroup": "Нема групе", + "groupName": "Назив групе", + "color": "Боја", + "source": "Извор", + "target": "Циљ", + "moveToGroup": "Премести у групу", + "selectGroup": "Изаберите групу...", + "addConnection": "Додај везу", + "hostDetails": "Детаљи домаћина", + "removeFromGroup": "Уклони из групе", + "addHostHere": "Додај хост овде", + "editGroup": "Уреди групу", + "delete": "Обриши", + "add": "Додај", + "create": "Креирај", + "move": "Помери", + "connect": "Повежи се", + "createGroup": "Направи групу", + "selectSourcePlaceholder": "Изаберите извор...", + "selectTargetPlaceholder": "Изаберите циљ...", + "invalidFile": "Неважећа датотека", + "hostAlreadyExists": "Хост је већ у топологији", + "connectionExists": "Веза већ постоји", + "unknown": "Непознато", + "name": "Име", + "ip": "ИП", + "status": "Статус", + "failedToAddNode": "Додавање чвора није успело", + "sourceDifferentFromTarget": "Извор и циљ морају бити различити", + "exportJSON": "Извези JSON", + "importJSON": "Увези JSON", + "terminal": "Терминал", + "fileManager": "Менаџер датотека", + "tunnel": "Тунел", + "docker": "Докер", + "serverStats": "Метрике хоста", + "hostMetrics": "Метрике хоста", + "noNodes": "Још нема чворова" + }, + "nav": { + "networkGraph": "Мрежни графикон" + }, + "dashboard": { + "networkGraph": "Мрежни графикон" + }, + "dashboardTab": { + "nodes": "{{count}} чворова" + } +} diff --git a/plugins/network-topology/locales/translated/sv_SE.json b/plugins/network-topology/locales/translated/sv_SE.json new file mode 100644 index 000000000..259924f1d --- /dev/null +++ b/plugins/network-topology/locales/translated/sv_SE.json @@ -0,0 +1,60 @@ +{ + "networkGraph": { + "addHost": "Lägg till värd", + "addGroup": "Lägg till grupp", + "addLink": "Lägg till länk", + "zoomIn": "Zooma in", + "zoomOut": "Zooma ut", + "resetView": "Återställ vy", + "selectHost": "Välj värd", + "chooseHost": "Välj en värd...", + "parentGroup": "Föräldragrupp", + "noGroup": "Ingen grupp", + "groupName": "Gruppnamn", + "color": "Färg", + "source": "Källa", + "target": "Mål", + "moveToGroup": "Flytta till grupp", + "selectGroup": "Välj grupp...", + "addConnection": "Lägg till anslutning", + "hostDetails": "Värduppgifter", + "removeFromGroup": "Ta bort från gruppen", + "addHostHere": "Lägg till värd här", + "editGroup": "Redigera grupp", + "delete": "Radera", + "add": "Tillägga", + "create": "Skapa", + "move": "Flytta", + "connect": "Ansluta", + "createGroup": "Skapa grupp", + "selectSourcePlaceholder": "Välj källa...", + "selectTargetPlaceholder": "Välj mål...", + "invalidFile": "Ogiltig fil", + "hostAlreadyExists": "Värden finns redan i topologin", + "connectionExists": "Anslutningen finns redan", + "unknown": "Okänd", + "name": "Namn", + "ip": "IP-adress", + "status": "Status", + "failedToAddNode": "Misslyckades med att lägga till nod", + "sourceDifferentFromTarget": "Källa och mål måste vara olika", + "exportJSON": "Exportera JSON", + "importJSON": "Importera JSON", + "terminal": "Terminal", + "fileManager": "Filhanteraren", + "tunnel": "Tunnel", + "docker": "Hamnarbetare", + "serverStats": "Värdstatistik", + "hostMetrics": "Värdstatistik", + "noNodes": "Inga noder ännu" + }, + "nav": { + "networkGraph": "Nätverksgraf" + }, + "dashboard": { + "networkGraph": "Nätverksgraf" + }, + "dashboardTab": { + "nodes": "{{count}} noder" + } +} diff --git a/plugins/network-topology/locales/translated/th_TH.json b/plugins/network-topology/locales/translated/th_TH.json new file mode 100644 index 000000000..b9a2b1d19 --- /dev/null +++ b/plugins/network-topology/locales/translated/th_TH.json @@ -0,0 +1,60 @@ +{ + "networkGraph": { + "addHost": "เพิ่มโฮสต์", + "addGroup": "เพิ่มกลุ่ม", + "addLink": "เพิ่มลิงก์", + "zoomIn": "ซูมเข้า", + "zoomOut": "ซูมออก", + "resetView": "รีเซ็ตมุมมอง", + "selectHost": "เลือกโฮสต์", + "chooseHost": "เลือกเจ้าภาพ...", + "parentGroup": "กลุ่มผู้ปกครอง", + "noGroup": "ไม่มีกลุ่ม", + "groupName": "ชื่อกลุ่ม", + "color": "สี", + "source": "แหล่งที่มา", + "target": "เป้า", + "moveToGroup": "ย้ายไปยังกลุ่ม", + "selectGroup": "เลือกกลุ่ม...", + "addConnection": "เพิ่มการเชื่อมต่อ", + "hostDetails": "รายละเอียดโฮสต์", + "removeFromGroup": "ลบออกจากกลุ่ม", + "addHostHere": "เพิ่มโฮสต์ที่นี่", + "editGroup": "แก้ไขกลุ่ม", + "delete": "ลบ", + "add": "เพิ่ม", + "create": "สร้าง", + "move": "เคลื่อนไหว", + "connect": "เชื่อมต่อ", + "createGroup": "สร้างกลุ่ม", + "selectSourcePlaceholder": "เลือกแหล่งที่มา...", + "selectTargetPlaceholder": "เลือกเป้าหมาย...", + "invalidFile": "ไฟล์ไม่ถูกต้อง", + "hostAlreadyExists": "โฮสต์อยู่ในโทโพโลยีแล้ว", + "connectionExists": "การเชื่อมต่อมีอยู่แล้ว", + "unknown": "ไม่ทราบ", + "name": "ชื่อ", + "ip": "ไอพี", + "status": "สถานะ", + "failedToAddNode": "ไม่สามารถเพิ่มโหนดได้", + "sourceDifferentFromTarget": "แหล่งที่มาและเป้าหมายต้องแตกต่างกัน", + "exportJSON": "ส่งออก JSON", + "importJSON": "นำเข้า JSON", + "terminal": "เทอร์มินัล", + "fileManager": "ตัวจัดการไฟล์", + "tunnel": "อุโมงค์", + "docker": "ด็อกเกอร์", + "serverStats": "เมตริกโฮสต์", + "hostMetrics": "เมตริกโฮสต์", + "noNodes": "ยังไม่มีโหนด" + }, + "nav": { + "networkGraph": "กราฟเครือข่าย" + }, + "dashboard": { + "networkGraph": "กราฟเครือข่าย" + }, + "dashboardTab": { + "nodes": "โหนด {{count}}" + } +} diff --git a/plugins/network-topology/locales/translated/tr_TR.json b/plugins/network-topology/locales/translated/tr_TR.json new file mode 100644 index 000000000..a2d9ed8cc --- /dev/null +++ b/plugins/network-topology/locales/translated/tr_TR.json @@ -0,0 +1,60 @@ +{ + "networkGraph": { + "addHost": "Sunucu Ekle", + "addGroup": "Grup Ekle", + "addLink": "Bağlantı Ekle", + "zoomIn": "Yakınlaştır", + "zoomOut": "Uzaklaştır", + "resetView": "Görünümü Sıfırla", + "selectHost": "Sunucu Seç", + "chooseHost": "Bir sunucu seçin...", + "parentGroup": "Üst Grup", + "noGroup": "Grup Yok", + "groupName": "Grup Adı", + "color": "Renk", + "source": "Kaynak", + "target": "Hedef", + "moveToGroup": "Gruba Taşı", + "selectGroup": "Grup seçin...", + "addConnection": "Bağlantı Ekle", + "hostDetails": "Sunucu Detayları", + "removeFromGroup": "Gruptan Kaldır", + "addHostHere": "Buraya Sunucu Ekle", + "editGroup": "Grubu Düzenle", + "delete": "Sil", + "add": "Ekle", + "create": "Oluştur", + "move": "Taşı", + "connect": "Bağlan", + "createGroup": "Grup Oluştur", + "selectSourcePlaceholder": "Kaynak Seçin...", + "selectTargetPlaceholder": "Hedef Seçin...", + "invalidFile": "Geçersiz Dosya", + "hostAlreadyExists": "Sunucu zaten topolojide var", + "connectionExists": "Bağlantı zaten var", + "unknown": "Bilinmiyor", + "name": "Ad", + "ip": "IP", + "status": "Durum", + "failedToAddNode": "Düğüm eklenemedi", + "sourceDifferentFromTarget": "Kaynak ve hedef farklı olmalıdır", + "exportJSON": "JSON Dışa Aktar", + "importJSON": "JSON İçe Aktar", + "terminal": "Terminal", + "fileManager": "Dosya Yöneticisi", + "tunnel": "Tünel", + "docker": "Docker", + "serverStats": "Sunucu Metrikleri", + "hostMetrics": "Sunucu Metrikleri", + "noNodes": "Henüz düğüm yok" + }, + "nav": { + "networkGraph": "Ağ Grafiği" + }, + "dashboard": { + "networkGraph": "Ağ Grafiği" + }, + "dashboardTab": { + "nodes": "{{count}} düğüm" + } +} diff --git a/plugins/network-topology/locales/translated/uk_UA.json b/plugins/network-topology/locales/translated/uk_UA.json new file mode 100644 index 000000000..452c1efe0 --- /dev/null +++ b/plugins/network-topology/locales/translated/uk_UA.json @@ -0,0 +1,60 @@ +{ + "networkGraph": { + "addHost": "Додати хоста", + "addGroup": "Додати групу", + "addLink": "Додати посилання", + "zoomIn": "Збільшити масштаб", + "zoomOut": "Зменшити масштаб", + "resetView": "Скинути вигляд", + "selectHost": "Виберіть хоста", + "chooseHost": "Виберіть хоста...", + "parentGroup": "Батьківська група", + "noGroup": "Без групи", + "groupName": "Назва групи", + "color": "Колір", + "source": "Джерело", + "target": "Ціль", + "moveToGroup": "Перемістити до групи", + "selectGroup": "Виберіть групу...", + "addConnection": "Додати підключення", + "hostDetails": "Деталі хоста", + "removeFromGroup": "Видалити з групи", + "addHostHere": "Додати хост тут", + "editGroup": "Редагувати групу", + "delete": "Видалити", + "add": "Додати", + "create": "Створити", + "move": "Перемістити", + "connect": "Підключитися", + "createGroup": "Створити групу", + "selectSourcePlaceholder": "Виберіть джерело...", + "selectTargetPlaceholder": "Виберіть ціль...", + "invalidFile": "Недійсний файл", + "hostAlreadyExists": "Хост вже є в топології", + "connectionExists": "З'єднання вже існує", + "unknown": "Невідомо", + "name": "Ім'я", + "ip": "ІП", + "status": "Статус", + "failedToAddNode": "Не вдалося додати вузол", + "sourceDifferentFromTarget": "Джерело та ціль мають бути різними", + "exportJSON": "Експорт JSON", + "importJSON": "Імпорт JSON", + "terminal": "Термінал", + "fileManager": "Файловий менеджер", + "tunnel": "Тунель", + "docker": "Докер", + "serverStats": "Метрики хоста", + "hostMetrics": "Метрики хоста", + "noNodes": "Поки що немає вузлів" + }, + "nav": { + "networkGraph": "Мережевий графік" + }, + "dashboard": { + "networkGraph": "Мережевий графік" + }, + "dashboardTab": { + "nodes": "{{count}} вузлів" + } +} diff --git a/plugins/network-topology/locales/translated/vi_VN.json b/plugins/network-topology/locales/translated/vi_VN.json new file mode 100644 index 000000000..ef5643515 --- /dev/null +++ b/plugins/network-topology/locales/translated/vi_VN.json @@ -0,0 +1,60 @@ +{ + "networkGraph": { + "addHost": "Thêm máy chủ", + "addGroup": "Thêm nhóm", + "addLink": "Thêm liên kết", + "zoomIn": "Phóng to", + "zoomOut": "Thu nhỏ", + "resetView": "Đặt lại khung nhìn", + "selectHost": "Chọn máy chủ", + "chooseHost": "Chọn một máy chủ...", + "parentGroup": "Nhóm cha", + "noGroup": "Không nhóm", + "groupName": "Tên nhóm", + "color": "Màu sắc", + "source": "Nguồn", + "target": "Đích", + "moveToGroup": "Di chuyển vào nhóm", + "selectGroup": "Chọn nhóm...", + "addConnection": "Thêm kết nối", + "hostDetails": "Chi tiết máy chủ", + "removeFromGroup": "Xóa khỏi nhóm", + "addHostHere": "Thêm máy chủ tại đây", + "editGroup": "Sửa nhóm", + "delete": "Xóa", + "add": "Thêm", + "create": "Tạo", + "move": "Di chuyển", + "connect": "Kết nối", + "createGroup": "Tạo nhóm", + "selectSourcePlaceholder": "Chọn nguồn...", + "selectTargetPlaceholder": "Chọn đích...", + "invalidFile": "Tệp không hợp lệ", + "hostAlreadyExists": "Máy chủ đã có trong cấu trúc liên kết", + "connectionExists": "Kết nối đã tồn tại", + "unknown": "Không xác định", + "name": "Tên", + "ip": "IP", + "status": "Trạng thái", + "failedToAddNode": "Không thể thêm nút", + "sourceDifferentFromTarget": "Nguồn và đích phải khác nhau", + "exportJSON": "Xuất JSON", + "importJSON": "Nhập JSON", + "terminal": "Terminal", + "fileManager": "Trình quản lý file", + "tunnel": "Đường hầm", + "docker": "Docker", + "serverStats": "Số liệu máy chủ", + "hostMetrics": "Số liệu máy chủ", + "noNodes": "Chưa có nút nào" + }, + "nav": { + "networkGraph": "Biểu đồ mạng" + }, + "dashboard": { + "networkGraph": "Biểu đồ Mạng" + }, + "dashboardTab": { + "nodes": "{{count}} node" + } +} diff --git a/plugins/network-topology/locales/translated/zh_CN.json b/plugins/network-topology/locales/translated/zh_CN.json new file mode 100644 index 000000000..623594b87 --- /dev/null +++ b/plugins/network-topology/locales/translated/zh_CN.json @@ -0,0 +1,60 @@ +{ + "networkGraph": { + "addHost": "添加主机", + "addGroup": "添加分组", + "addLink": "添加链接", + "zoomIn": "放大", + "zoomOut": "缩小", + "resetView": "重置视图", + "selectHost": "选择主机", + "chooseHost": "选择主机...", + "parentGroup": "父分组", + "noGroup": "无分组", + "groupName": "分组名称", + "color": "颜色", + "source": "源", + "target": "目标", + "moveToGroup": "移至分组", + "selectGroup": "选择分组...", + "addConnection": "添加连接", + "hostDetails": "主机详情", + "removeFromGroup": "移出群组", + "addHostHere": "在此添加主机", + "editGroup": "编辑群组", + "delete": "删除", + "add": "添加", + "create": "创建", + "move": "移动", + "connect": "连接", + "createGroup": "创建群组", + "selectSourcePlaceholder": "选择源...", + "selectTargetPlaceholder": "选择目标...", + "invalidFile": "无效文件", + "hostAlreadyExists": "主机已在拓扑中", + "connectionExists": "连接已存在", + "unknown": "未知", + "name": "名称", + "ip": "IP", + "status": "状态", + "failedToAddNode": "添加节点失败", + "sourceDifferentFromTarget": "源和目标必须不同", + "exportJSON": "导出 JSON", + "importJSON": "导入 JSON", + "terminal": "终端", + "fileManager": "文件管理器", + "tunnel": "隧道", + "docker": "Docker", + "serverStats": "主机指标", + "hostMetrics": "主机指标", + "noNodes": "尚无节点" + }, + "nav": { + "networkGraph": "网络拓扑图" + }, + "dashboard": { + "networkGraph": "网络图表" + }, + "dashboardTab": { + "nodes": "{{count}} 个节点" + } +} diff --git a/plugins/network-topology/locales/translated/zh_TW.json b/plugins/network-topology/locales/translated/zh_TW.json new file mode 100644 index 000000000..90d571430 --- /dev/null +++ b/plugins/network-topology/locales/translated/zh_TW.json @@ -0,0 +1,60 @@ +{ + "networkGraph": { + "addHost": "新增主機", + "addGroup": "新增群組", + "addLink": "新增連結", + "zoomIn": "放大", + "zoomOut": "縮小", + "resetView": "重置檢視", + "selectHost": "選取主機", + "chooseHost": "選擇主機...", + "parentGroup": "父群組", + "noGroup": "無群組", + "groupName": "群組名稱", + "color": "顏色", + "source": "來源", + "target": "目標", + "moveToGroup": "移至群組", + "selectGroup": "選取群組...", + "addConnection": "新增連線", + "hostDetails": "主機詳細資料", + "removeFromGroup": "從群組中移除", + "addHostHere": "在此新增主機", + "editGroup": "編輯群組", + "delete": "刪除", + "add": "新增", + "create": "建立", + "move": "移動", + "connect": "連線", + "createGroup": "建立群組", + "selectSourcePlaceholder": "選取來源...", + "selectTargetPlaceholder": "選取目標...", + "invalidFile": "無效的檔案", + "hostAlreadyExists": "主機已存在於拓撲中", + "connectionExists": "連線已存在", + "unknown": "未知", + "name": "名稱", + "ip": "IP", + "status": "狀態", + "failedToAddNode": "無法新增節點", + "sourceDifferentFromTarget": "來源與目標必須不同", + "exportJSON": "匯出 JSON", + "importJSON": "匯入 JSON", + "terminal": "終端機", + "fileManager": "檔案管理員", + "tunnel": "隧道", + "docker": "Docker", + "serverStats": "主機指標", + "hostMetrics": "主機指標", + "noNodes": "尚無節點" + }, + "nav": { + "networkGraph": "網路圖表" + }, + "dashboard": { + "networkGraph": "網路圖表" + }, + "dashboardTab": { + "nodes": "{{count}} 個節點" + } +} diff --git a/plugins/network-topology/manifest.json b/plugins/network-topology/manifest.json index 681e08316..d5f19fa1c 100644 --- a/plugins/network-topology/manifest.json +++ b/plugins/network-topology/manifest.json @@ -23,6 +23,13 @@ "icon": "Network", "openFrom": ["rail", "palette"] } + ], + "dashboardCards": [ + { + "id": "network_graph", + "titleKey": "dashboard.networkGraph", + "icon": "Network" + } ] }, "locales": "locales", diff --git a/plugins/network-topology/src/frontend/NetworkGraphCard.tsx b/plugins/network-topology/src/frontend/NetworkGraphCard.tsx index e0aef8642..cf60fc181 100644 --- a/plugins/network-topology/src/frontend/NetworkGraphCard.tsx +++ b/plugins/network-topology/src/frontend/NetworkGraphCard.tsx @@ -59,7 +59,7 @@ import { ArrowDownUp, Loader2, } from "lucide-react"; -import { useTranslation } from "react-i18next"; +import { useTranslation } from "@termix/plugin-sdk/frontend"; import { useTabsSafe } from "@/shell/TabContext"; import { cn } from "@/lib/utils"; import { readStatusColorScheme } from "@/hooks/use-status-color-scheme"; diff --git a/plugins/network-topology/src/frontend/index.mjs b/plugins/network-topology/src/frontend/index.mjs deleted file mode 100644 index e394d2be4..000000000 --- a/plugins/network-topology/src/frontend/index.mjs +++ /dev/null @@ -1,44 +0,0 @@ -/** - * Frontend half of the network-topology plugin. - * - * NetworkGraphCard renders in two modes: as a full tab (network_graph) and - * embedded as a dashboard card. Both usages are wired today through the - * existing tabUtils.tsx / DashboardTab.tsx switch statements the same way - * fleet-inventory's tab is, not through register() below -- per - * src/ui/shell/pluginLoader.ts's own comment, "there is no plugin loader - * yet" for the frontend half. - * - * register()/unregister() still follow the same shape every other plugin's - * frontend entry does, so this is ready the moment a real frontend plugin - * loader exists. - */ - -export const id = "network-topology"; -export const tabId = "network_graph"; - -export async function register({ - registerRailItem, - registerTabComponent, - icons, -}) { - registerTabComponent?.(tabId, () => - import("./NetworkGraphCard.tsx").then((m) => ({ - default: m.NetworkGraphCard, - })), - ); - - registerRailItem?.({ - id: tabId, - icon: icons.Network, - labelKey: "nav.networkGraph", - kind: "tab", - }); -} - -export async function unregister({ - unregisterRailItem, - unregisterTabComponent, -}) { - unregisterRailItem?.(tabId); - unregisterTabComponent?.(tabId); -} diff --git a/plugins/network-topology/src/frontend/index.tsx b/plugins/network-topology/src/frontend/index.tsx new file mode 100644 index 000000000..54a4d35a2 --- /dev/null +++ b/plugins/network-topology/src/frontend/index.tsx @@ -0,0 +1,47 @@ +import { Network } from "lucide-react"; +import type { + DashboardCardProps, + TabProps, + TermixApp, +} from "@termix/plugin-sdk/frontend"; +import { NetworkGraphCard } from "./NetworkGraphCard"; + +const VIEW_ID = "network_graph"; + +function GraphTab({ isVisible }: TabProps) { + return ; +} + +function GraphCard({ isVisible, shell }: DashboardCardProps) { + return ( + shell.openSingletonTab(VIEW_ID)} + /> + ); +} + +export function activate(app: TermixApp): void { + app.registerTab(VIEW_ID, GraphTab, { + icon: Network, + titleKey: "nav.networkGraph", + singleton: true, + hostless: true, + }); + + app.registerRailItem({ + id: VIEW_ID, + icon: Network, + titleKey: "nav.networkGraph", + kind: "tab", + after: "local-terminal", + }); + + app.registerDashboardCard({ + id: VIEW_ID, + titleKey: "dashboard.networkGraph", + defaultHeight: 350, + component: GraphCard, + }); +} diff --git a/plugins/network-topology/tests/frontend/activate.test.tsx b/plugins/network-topology/tests/frontend/activate.test.tsx new file mode 100644 index 000000000..814097280 --- /dev/null +++ b/plugins/network-topology/tests/frontend/activate.test.tsx @@ -0,0 +1,53 @@ +import { afterEach, describe, expect, it } from "vitest"; +import { + renderWithApp, + type RenderedPluginApp, +} from "@termix/plugin-sdk/testing"; +import type { PluginManifest } from "@termix/plugin-sdk/manifest"; +import * as plugin from "../../src/frontend/index"; +import manifestJson from "../../manifest.json"; +import locales from "../../locales/en.json"; + +const manifest = manifestJson as unknown as PluginManifest; + +const declared = (views?: Array<{ id: string }>) => + (views ?? []).map((view) => view.id).sort(); + +let rendered: RenderedPluginApp | null = null; + +afterEach(async () => { + await rendered?.deactivate(); + rendered = null; +}); + +describe(`${manifest.id} activate`, () => { + it("activates and registers only views its manifest declares", async () => { + rendered = await renderWithApp(plugin, { manifest, locales }); + const contributes = manifest.contributes as unknown as Record< + string, + Array<{ id: string }> | undefined + >; + const tabs = declared(contributes.tabs); + // A rail panel may reuse one of the plugin's tab ids. + const panels = [...declared(contributes.panels), ...tabs]; + const cards = declared(contributes.dashboardCards); + for (const id of rendered.registered.tabs()) expect(tabs).toContain(id); + for (const id of rendered.registered.panels()) expect(panels).toContain(id); + for (const id of rendered.registered.dashboardCards()) { + expect(cards).toContain(id); + } + }); + + it("removes everything it registered on deactivate", async () => { + const app = await renderWithApp(plugin, { manifest, locales }); + await app.deactivate(); + expect(app.registered.tabs()).toEqual([]); + expect(app.registered.panels()).toEqual([]); + expect(app.registered.railItems()).toEqual([]); + expect(app.registered.hostActions()).toEqual([]); + expect(app.registered.hostEditorSections()).toEqual([]); + expect(app.registered.dashboardCards()).toEqual([]); + expect(app.registered.settingsComponents()).toEqual([]); + expect(app.registered.actions()).toEqual([]); + }); +}); diff --git a/plugins/proxmox/locales/en.json b/plugins/proxmox/locales/en.json index 0967ef424..01df301dd 100644 --- a/plugins/proxmox/locales/en.json +++ b/plugins/proxmox/locales/en.json @@ -1 +1,53 @@ -{} +{ + "hosts": { + "tabProxmox": "Proxmox", + "authTypeStepca": "Step CA", + "proxmoxIntegration": "Proxmox Integration", + "enableProxmox": "Enable Proxmox", + "enableProxmoxDesc": "Mark this host as a Proxmox node. Enables guest discovery and import directly from this host.", + "proxmoxDefaultAuthType": "Default Auth Type", + "proxmoxDefaultAuthTypeDesc": "Authentication method applied to imported guest hosts. Choose the auth type that matches how you connect to your guests.", + "authTypePassword": "Password", + "authTypeKey": "SSH Key", + "authTypeCredential": "Credential", + "authTypeOpkssh": "OPKSSH", + "authTypeNone": "None", + "proxmoxDefaultCredential": "Default Credential", + "proxmoxDefaultCredentialDesc": "Credential used for imported guest hosts when auth type is set to Credential.", + "proxmoxWindowsDetection": "Windows / RDP detection", + "proxmoxWindowsDetectionDesc": "Comma-separated name patterns that trigger RDP instead of SSH (case-insensitive)", + "proxmoxDockerDetection": "Docker detection", + "proxmoxDockerDetectionDesc": "Comma-separated name patterns that enable Docker for matching guests", + "proxmoxPreferredRanges": "Preferred IP ranges", + "proxmoxPreferredRangesDesc": "Comma-separated prefixes in priority order for IP selection when a guest has multiple interfaces", + "proxmoxAutoSync": "Auto sync guests", + "proxmoxAutoSyncDesc": "Periodically discover this Proxmox node and create or update imported guest hosts while your session is unlocked.", + "proxmoxSyncInterval": "Sync interval (minutes)", + "proxmoxSyncIntervalDesc": "Minimum 5 minutes. The scheduler skips locked user sessions.", + "proxmoxMarkMissing": "Mark missing guests", + "proxmoxMarkMissingDesc": "Add a proxmox-missing tag when a previously imported guest disappears instead of deleting it.", + "proxmoxLastSync": "Last sync", + "proxmoxLastSyncNever": "Not synced yet", + "proxmoxLastSyncNoResult": "No result details", + "proxmoxLastSyncSummary": "{{created}} created, {{updated}} updated, {{markedMissing}} missing, {{skipped}} skipped", + "proxmoxLastSyncStatus": { + "error": "Failed", + "pending": "Pending" + }, + "proxmoxDiscoverAction": "Discover & import Proxmox guests", + "proxmoxImportTitle": "Import from Proxmox", + "proxmoxSelectHost": "Select a Proxmox host…", + "proxmoxDiscover": "Discover", + "proxmoxDiscovering": "Discovering…", + "proxmoxDiscoverGuests": "Discover guests", + "proxmoxSelectAll": "Select all", + "proxmoxDeselectAll": "Deselect all", + "proxmoxNoGuests": "No guests found on this Proxmox node.", + "proxmoxResultImported": "{{count}} imported", + "proxmoxResultUpdated": "{{count}} updated", + "proxmoxResultFailed": "{{count}} failed", + "proxmoxImportComplete": "Proxmox import complete: {{summary}}", + "proxmoxDiscoveryFailed": "Discovery failed", + "proxmoxImportFailed": "Import failed" + } +} diff --git a/plugins/proxmox/locales/translated/af_ZA.json b/plugins/proxmox/locales/translated/af_ZA.json new file mode 100644 index 000000000..7427416e1 --- /dev/null +++ b/plugins/proxmox/locales/translated/af_ZA.json @@ -0,0 +1,53 @@ +{ + "hosts": { + "tabProxmox": "Proxmox", + "authTypeStepca": "Stap CA", + "proxmoxIntegration": "Proxmox-integrasie", + "enableProxmox": "Aktiveer Proxmox", + "enableProxmoxDesc": "Merk hierdie gasheer as 'n Proxmox-nodus. Aktiveer gasontdekking en invoer direk vanaf hierdie gasheer.", + "proxmoxDefaultAuthType": "Standaardmagtigingtipe", + "proxmoxDefaultAuthTypeDesc": "Verifikasiemetode toegepas op ingevoerde gashere. Kies die verifikasietipe wat ooreenstem met hoe jy met jou gaste skakel.", + "authTypePassword": "Wagwoord", + "authTypeKey": "SSH-sleutel", + "authTypeCredential": "Geloofsbrief", + "authTypeOpkssh": "OPKSSH", + "authTypeNone": "Geen", + "proxmoxDefaultCredential": "Standaard geloofsbriewe", + "proxmoxDefaultCredentialDesc": "Geloofsbrief wat gebruik word vir ingevoerde gashere wanneer magtigingstipe op Geloofsbrief gestel is.", + "proxmoxWindowsDetection": "Windows / RDP-opsporing", + "proxmoxWindowsDetectionDesc": "Komma-geskeide naampatrone wat RDP in plaas van SSH aktiveer (ongesensitief vir hoofletters)", + "proxmoxDockerDetection": "Docker-opsporing", + "proxmoxDockerDetectionDesc": "Komma-geskeide naampatrone wat Docker in staat stel om gaste te pas", + "proxmoxPreferredRanges": "Voorkeur-IP-reekse", + "proxmoxPreferredRangesDesc": "Komma-geskeide voorvoegsels in prioriteitsvolgorde vir IP-keuse wanneer 'n gas verskeie koppelvlakke het", + "proxmoxAutoSync": "Outomatiese sinkronisering van gaste", + "proxmoxAutoSyncDesc": "Ontdek hierdie Proxmox-nodus gereeld en skep of werk ingevoerde gashere op terwyl jou sessie ontsluit is.", + "proxmoxSyncInterval": "Sinkronisasie-interval (minute)", + "proxmoxSyncIntervalDesc": "Minimum 5 minute. Die skeduleerder slaan geslote gebruikerssessies oor.", + "proxmoxMarkMissing": "Merk ontbrekende gaste", + "proxmoxMarkMissingDesc": "Voeg 'n proxmox-missing-etiket by wanneer 'n voorheen ingevoerde gas verdwyn in plaas daarvan om dit te verwyder.", + "proxmoxLastSync": "Laaste sinkronisasie", + "proxmoxLastSyncNever": "Nog nie gesinkroniseer nie", + "proxmoxLastSyncNoResult": "Geen resultaatbesonderhede nie", + "proxmoxLastSyncSummary": "{{created}} geskep, {{updated}} opgedateer, {{markedMissing}} ontbreek, {{skipped}} oorgeslaan", + "proxmoxLastSyncStatus": { + "error": "Misluk", + "pending": "Hangende" + }, + "proxmoxDiscoverAction": "Ontdek en invoer Proxmox-gaste", + "proxmoxImportTitle": "Invoer vanaf Proxmox", + "proxmoxSelectHost": "Kies 'n Proxmox-gasheer…", + "proxmoxDiscover": "Ontdek", + "proxmoxDiscovering": "Ontdek…", + "proxmoxDiscoverGuests": "Ontdek gaste", + "proxmoxSelectAll": "Kies alles", + "proxmoxDeselectAll": "Deselekteer alles", + "proxmoxNoGuests": "Geen gaste gevind op hierdie Proxmox-nodus nie.", + "proxmoxResultImported": "{{count}} ingevoer", + "proxmoxResultUpdated": "{{count}} opgedateer", + "proxmoxResultFailed": "{{count}} het misluk", + "proxmoxImportComplete": "Proxmox-invoer voltooi: {{summary}}", + "proxmoxDiscoveryFailed": "Ontdekking het misluk", + "proxmoxImportFailed": "Invoer het misluk" + } +} diff --git a/plugins/proxmox/locales/translated/ar_SA.json b/plugins/proxmox/locales/translated/ar_SA.json new file mode 100644 index 000000000..55cd949fc --- /dev/null +++ b/plugins/proxmox/locales/translated/ar_SA.json @@ -0,0 +1,53 @@ +{ + "hosts": { + "tabProxmox": "Proxmox", + "authTypeStepca": "الخطوة ج", + "proxmoxIntegration": "تكامل Proxmox", + "enableProxmox": "تمكين Proxmox", + "enableProxmoxDesc": "تعليم هذا المضيف كعقدة Proxmox. يُمكّن اكتشاف الضيوف واستيرادهم مباشرة من هذا المضيف.", + "proxmoxDefaultAuthType": "نوع المصادقة الافتراضي", + "proxmoxDefaultAuthTypeDesc": "طريقة المصادقة المطبقة على المضيفين الضيوف المستوردين. اختر نوع المصادقة الذي يتوافق مع طريقة اتصالك بالضيوف.", + "authTypePassword": "كلمة مرور", + "authTypeKey": "مفتاح SSH", + "authTypeCredential": "بيانات اعتماد", + "authTypeOpkssh": "OPKSSH", + "authTypeNone": "بلا", + "proxmoxDefaultCredential": "بيانات الاعتماد الافتراضية", + "proxmoxDefaultCredentialDesc": "بيانات الاعتماد المُستخدمة للأجهزة الضيفة المستوردة عند ضبط نوع المصادقة على 'بيانات الاعتماد'.", + "proxmoxWindowsDetection": "اكتشاف Windows / RDP", + "proxmoxWindowsDetectionDesc": "أنماط الأسماء مفصولة بفواصل تُشغّل RDP بدلاً من SSH (غير حسّاسة لحالة الأحرف)", + "proxmoxDockerDetection": "اكتشاف Docker", + "proxmoxDockerDetectionDesc": "أنماط الأسماء مفصولة بفواصل تُمكّن Docker للأجهزة الضيفة المطابقة", + "proxmoxPreferredRanges": "نطاقات IP المُفضّلة", + "proxmoxPreferredRangesDesc": "بادئات مفصولة بفواصل بترتيب الأولوية لاختيار IP عندما يكون للجهاز الضيف واجهات متعددة", + "proxmoxAutoSync": "مزامنة تلقائية للأجهزة الضيفة", + "proxmoxAutoSyncDesc": "اكتشاف عقدة Proxmox هذه بشكل دوري وإنشاء أو تحديث الأجهزة الضيفة المستوردة أثناء فتح جلستك.", + "proxmoxSyncInterval": "فترة المزامنة (بالدقائق)", + "proxmoxSyncIntervalDesc": "الحد الأدنى 5 دقائق. يتخطّى المجدول جلسات المستخدم المقفلة.", + "proxmoxMarkMissing": "تعليم الأجهزة الضيفة المفقودة", + "proxmoxMarkMissingDesc": "أضف وسم proxmox-missing عندما يختفي جهاز ضيف تم استيراده مسبقاً بدلاً من حذفه.", + "proxmoxLastSync": "آخر مزامنة", + "proxmoxLastSyncNever": "لم تتم المزامنة بعد", + "proxmoxLastSyncNoResult": "لا توجد تفاصيل للنتائج", + "proxmoxLastSyncSummary": "{{created}} مُنشأ، {{updated}} مُحدَّث، {{markedMissing}} مفقود، {{skipped}} مُتخطّى", + "proxmoxLastSyncStatus": { + "error": "فشل", + "pending": "قيد الانتظار" + }, + "proxmoxDiscoverAction": "اكتشاف واستيراد أجهزة Proxmox الضيفة", + "proxmoxImportTitle": "استيراد من Proxmox", + "proxmoxSelectHost": "اختر مضيف Proxmox…", + "proxmoxDiscover": "اكتشف", + "proxmoxDiscovering": "جارٍ الاكتشاف…", + "proxmoxDiscoverGuests": "اكتشف الأجهزة الضيفة", + "proxmoxSelectAll": "تحديد الكل", + "proxmoxDeselectAll": "إلغاء تحديد الكل", + "proxmoxNoGuests": "لم يتم العثور على أجهزة ضيفة على عقدة Proxmox هذه.", + "proxmoxResultImported": "{{count}} تم استيرادها", + "proxmoxResultUpdated": "{{count}} تم تحديثها", + "proxmoxResultFailed": "{{count}} فشلت", + "proxmoxImportComplete": "اكتمل استيراد Proxmox: {{summary}}", + "proxmoxDiscoveryFailed": "فشل الاكتشاف", + "proxmoxImportFailed": "فشل الاستيراد" + } +} diff --git a/plugins/proxmox/locales/translated/bg_BG.json b/plugins/proxmox/locales/translated/bg_BG.json new file mode 100644 index 000000000..3e216dae8 --- /dev/null +++ b/plugins/proxmox/locales/translated/bg_BG.json @@ -0,0 +1,53 @@ +{ + "hosts": { + "tabProxmox": "Проксмокс", + "authTypeStepca": "Стъпка CA", + "proxmoxIntegration": "Интеграция с Proxmox", + "enableProxmox": "Активиране на Proxmox", + "enableProxmoxDesc": "Маркирайте този хост като Proxmox възел. Активирайте откриването на гост и импортирането директно от този хост.", + "proxmoxDefaultAuthType": "Тип удостоверяване по подразбиране", + "proxmoxDefaultAuthTypeDesc": "Методът за удостоверяване е приложен към импортираните гост-хостове. Изберете типа удостоверяване, който съответства на начина, по който се свързвате с гостите си.", + "authTypePassword": "Парола", + "authTypeKey": "SSH ключ", + "authTypeCredential": "Пълномощия", + "authTypeOpkssh": "ОПКСШ", + "authTypeNone": "Няма", + "proxmoxDefaultCredential": "Подразбиращи се идентификационни данни", + "proxmoxDefaultCredentialDesc": "Идентификационни данни, използвани за импортирани гост хостове, когато типът удостоверяване е зададен на Идентификационни данни.", + "proxmoxWindowsDetection": "Откриване на Windows / RDP", + "proxmoxWindowsDetectionDesc": "Модели на имена, разделени със запетаи, които задействат RDP вместо SSH (без значение от главни и малки букви)", + "proxmoxDockerDetection": "Откриване на Докер", + "proxmoxDockerDetectionDesc": "Модели за имена, разделени със запетаи, които позволяват на Docker да съпоставя гости", + "proxmoxPreferredRanges": "Предпочитани IP диапазони", + "proxmoxPreferredRangesDesc": "Префикси, разделени със запетаи, подредени по приоритет за избор на IP адрес, когато гост има множество интерфейси", + "proxmoxAutoSync": "Автоматично синхронизиране на гости", + "proxmoxAutoSyncDesc": "Периодично откривайте този Proxmox възел и създавайте или актуализирайте импортирани гост хостове, докато сесията ви е отключена.", + "proxmoxSyncInterval": "Интервал на синхронизиране (минути)", + "proxmoxSyncIntervalDesc": "Минимум 5 минути. Планировчикът пропуска заключените потребителски сесии.", + "proxmoxMarkMissing": "Маркиране на липсващи гости", + "proxmoxMarkMissingDesc": "Добавете етикет proxmox-missing, когато предварително импортиран гост изчезне, вместо да го изтриете.", + "proxmoxLastSync": "Последна синхронизация", + "proxmoxLastSyncNever": "Все още не е синхронизирано", + "proxmoxLastSyncNoResult": "Няма подробности за резултата", + "proxmoxLastSyncSummary": "{{created}} създадено, {{updated}} актуализирано, {{markedMissing}} липсващо, {{skipped}} пропуснато", + "proxmoxLastSyncStatus": { + "error": "Неуспешно", + "pending": "В очакване" + }, + "proxmoxDiscoverAction": "Откриване и импортиране на гости на Proxmox", + "proxmoxImportTitle": "Импортиране от Proxmox", + "proxmoxSelectHost": "Изберете Proxmox хост…", + "proxmoxDiscover": "Открийте", + "proxmoxDiscovering": "Откриване…", + "proxmoxDiscoverGuests": "Открийте гостите", + "proxmoxSelectAll": "Избери всички", + "proxmoxDeselectAll": "Премахване на избора от всички", + "proxmoxNoGuests": "Няма намерени гости на този Proxmox възел.", + "proxmoxResultImported": "{{count}} импортирано", + "proxmoxResultUpdated": "{{count}} актуализирано", + "proxmoxResultFailed": "{{count}} неуспешно", + "proxmoxImportComplete": "Импортирането на Proxmox е завършено: {{summary}}", + "proxmoxDiscoveryFailed": "Откриването не беше успешно", + "proxmoxImportFailed": "Импортирането не бе успешно" + } +} diff --git a/plugins/proxmox/locales/translated/bn_BD.json b/plugins/proxmox/locales/translated/bn_BD.json new file mode 100644 index 000000000..cfb3d4a95 --- /dev/null +++ b/plugins/proxmox/locales/translated/bn_BD.json @@ -0,0 +1,53 @@ +{ + "hosts": { + "tabProxmox": "প্রক্সমক্স", + "authTypeStepca": "স্টেপ সিএ", + "proxmoxIntegration": "প্রক্সমক্স ইন্টিগ্রেশন", + "enableProxmox": "প্রক্সমক্স সক্রিয় করুন", + "enableProxmoxDesc": "এই হোস্টটিকে একটি প্রক্সমক্স নোড হিসেবে চিহ্নিত করুন। এর ফলে সরাসরি এই হোস্ট থেকে গেস্ট ডিসকভারি এবং ইম্পোর্ট করা যায়।", + "proxmoxDefaultAuthType": "ডিফল্ট প্রমাণীকরণ ধরণ", + "proxmoxDefaultAuthTypeDesc": "আমদানিকৃত গেস্ট হোস্টদের জন্য প্রযোজ্য প্রমাণীকরণ পদ্ধতি। আপনি আপনার গেস্টদের সাথে যেভাবে সংযোগ স্থাপন করেন, তার সাথে মেলে এমন প্রমাণীকরণের ধরণটি বেছে নিন।", + "authTypePassword": "পাসওয়ার্ড", + "authTypeKey": "SSH কী", + "authTypeCredential": "শংসাপত্র", + "authTypeOpkssh": "OPKSSH", + "authTypeNone": "কোনোটিই না", + "proxmoxDefaultCredential": "ডিফল্ট পরিচয়পত্র", + "proxmoxDefaultCredentialDesc": "যখন অথোরাইজেশন টাইপ 'ক্রেডেনশিয়াল' হিসেবে সেট করা থাকে, তখন ইম্পোর্ট করা গেস্ট হোস্টগুলির জন্য ব্যবহৃত ক্রেডেনশিয়াল।", + "proxmoxWindowsDetection": "উইন্ডোজ / আরডিপি সনাক্তকরণ", + "proxmoxWindowsDetectionDesc": "কমা দ্বারা পৃথক করা নামের প্যাটার্ন যা SSH-এর পরিবর্তে RDP চালু করে (কেস-ইনসেনসিটিভ)", + "proxmoxDockerDetection": "ডকার সনাক্তকরণ", + "proxmoxDockerDetectionDesc": "কমা দ্বারা পৃথক করা নামের প্যাটার্ন যা ডকারকে গেস্টদের মেলানোর জন্য সক্ষম করে", + "proxmoxPreferredRanges": "পছন্দের আইপি রেঞ্জ", + "proxmoxPreferredRangesDesc": "যখন কোনো গেস্টের একাধিক ইন্টারফেস থাকে, তখন আইপি নির্বাচনের জন্য অগ্রাধিকার ক্রমে কমা দ্বারা পৃথক করা প্রিফিক্সগুলো ব্যবহৃত হয়।", + "proxmoxAutoSync": "অতিথিদের স্বয়ংক্রিয়ভাবে সিঙ্ক করুন", + "proxmoxAutoSyncDesc": "আপনার সেশন আনলক থাকা অবস্থায় পর্যায়ক্রমে এই প্রক্সমক্স নোডটি আবিষ্কার করুন এবং ইম্পোর্ট করা গেস্ট হোস্টগুলি তৈরি বা আপডেট করুন।", + "proxmoxSyncInterval": "সিঙ্ক ব্যবধান (মিনিট)", + "proxmoxSyncIntervalDesc": "সর্বনিম্ন ৫ মিনিট। শিডিউলারটি লক করা ব্যবহারকারীর সেশনগুলো এড়িয়ে যায়।", + "proxmoxMarkMissing": "অনুপস্থিত অতিথিদের চিহ্নিত করুন", + "proxmoxMarkMissingDesc": "পূর্বে ইম্পোর্ট করা কোনো গেস্ট অদৃশ্য হয়ে গেলে, সেটিকে ডিলিট না করে একটি proxmox-missing ট্যাগ যোগ করুন।", + "proxmoxLastSync": "শেষ সিঙ্ক", + "proxmoxLastSyncNever": "এখনো সিঙ্ক হয়নি", + "proxmoxLastSyncNoResult": "ফলাফলের কোনো বিবরণ নেই", + "proxmoxLastSyncSummary": "{{created}} তৈরি করা হয়েছে, {{updated}} আপডেট করা হয়েছে, {{markedMissing}} অনুপস্থিত, {{skipped}} বাদ দেওয়া হয়েছে", + "proxmoxLastSyncStatus": { + "error": "ব্যর্থ", + "pending": "বিচারাধীন" + }, + "proxmoxDiscoverAction": "Proxmox গেস্টদের আবিষ্কার ও আমদানি করুন", + "proxmoxImportTitle": "প্রক্সমক্স থেকে আমদানি করুন", + "proxmoxSelectHost": "একটি প্রক্সমক্স হোস্ট নির্বাচন করুন…", + "proxmoxDiscover": "আবিষ্কার করুন", + "proxmoxDiscovering": "… আবিষ্কার করা", + "proxmoxDiscoverGuests": "অতিথিদের আবিষ্কার করুন", + "proxmoxSelectAll": "সবগুলো নির্বাচন করুন", + "proxmoxDeselectAll": "সবগুলো নির্বাচন বাতিল করুন", + "proxmoxNoGuests": "এই প্রক্সমক্স নোডে কোনো অতিথি পাওয়া যায়নি।", + "proxmoxResultImported": "{{count}} আমদানি করা হয়েছে", + "proxmoxResultUpdated": "{{count}} আপডেট করা হয়েছে", + "proxmoxResultFailed": "{{count}} ব্যর্থ হয়েছে", + "proxmoxImportComplete": "প্রক্সমক্স আমদানি সম্পন্ন: {{summary}}", + "proxmoxDiscoveryFailed": "আবিষ্কার ব্যর্থ হয়েছে", + "proxmoxImportFailed": "আমদানি ব্যর্থ হয়েছে" + } +} diff --git a/plugins/proxmox/locales/translated/ca_ES.json b/plugins/proxmox/locales/translated/ca_ES.json new file mode 100644 index 000000000..51c49076a --- /dev/null +++ b/plugins/proxmox/locales/translated/ca_ES.json @@ -0,0 +1,53 @@ +{ + "hosts": { + "tabProxmox": "Proxmox", + "authTypeStepca": "Pas CA", + "proxmoxIntegration": "Integració de Proxmox", + "enableProxmox": "Activa Proxmox", + "enableProxmoxDesc": "Marca aquest amfitrió com a node de Proxmox. Activa la detecció de convidats i la importació directament des d'aquest amfitrió.", + "proxmoxDefaultAuthType": "Tipus d'autorització per defecte", + "proxmoxDefaultAuthTypeDesc": "Mètode d'autenticació aplicat als amfitrions convidats importats. Trieu el tipus d'autenticació que coincideixi amb la manera com us connecteu als vostres convidats.", + "authTypePassword": "Contrasenya", + "authTypeKey": "Clau SSH", + "authTypeCredential": "Credencial", + "authTypeOpkssh": "OPKSSH", + "authTypeNone": "Cap", + "proxmoxDefaultCredential": "Credencial predeterminada", + "proxmoxDefaultCredentialDesc": "Credencial utilitzada per als amfitrions convidats importats quan el tipus d'autenticació està definit com a Credencial.", + "proxmoxWindowsDetection": "Detecció de Windows / RDP", + "proxmoxWindowsDetectionDesc": "Patrons de noms separats per comes que activen RDP en lloc de SSH (sense distinció entre majúscules i minúscules)", + "proxmoxDockerDetection": "Detecció de Docker", + "proxmoxDockerDetectionDesc": "Patrons de noms separats per comes que permeten a Docker utilitzar convidats coincidents", + "proxmoxPreferredRanges": "Intervals d'IP preferits", + "proxmoxPreferredRangesDesc": "Prefixos separats per comes en ordre de prioritat per a la selecció d'IP quan un convidat té diverses interfícies", + "proxmoxAutoSync": "Sincronitza automàticament els convidats", + "proxmoxAutoSyncDesc": "Descobreix periòdicament aquest node de Proxmox i crea o actualitza els hosts convidats importats mentre la sessió està desbloquejada.", + "proxmoxSyncInterval": "Interval de sincronització (minuts)", + "proxmoxSyncIntervalDesc": "Mínim 5 minuts. El planificador omet les sessions d'usuari bloquejades.", + "proxmoxMarkMissing": "Marca els convidats que falten", + "proxmoxMarkMissingDesc": "Afegeix una etiqueta proxmox-missing quan un convidat importat prèviament desapareix en comptes d'eliminar-lo.", + "proxmoxLastSync": "Darrera sincronització", + "proxmoxLastSyncNever": "Encara no sincronitzat", + "proxmoxLastSyncNoResult": "Sense detalls del resultat", + "proxmoxLastSyncSummary": "{{created}} creat, {{updated}} actualitzat, {{markedMissing}} no hi és, {{skipped}} omès", + "proxmoxLastSyncStatus": { + "error": "Fallat", + "pending": "Pendent" + }, + "proxmoxDiscoverAction": "Descobreix i importa convidats de Proxmox", + "proxmoxImportTitle": "Importar des de Proxmox", + "proxmoxSelectHost": "Seleccioneu un amfitrió de Proxmox…", + "proxmoxDiscover": "Descobreix", + "proxmoxDiscovering": "Descobrint…", + "proxmoxDiscoverGuests": "Descobreix convidats", + "proxmoxSelectAll": "Selecciona-ho tot", + "proxmoxDeselectAll": "Desselecciona-ho tot", + "proxmoxNoGuests": "No s'han trobat convidats en aquest node de Proxmox.", + "proxmoxResultImported": "{{count}} importat", + "proxmoxResultUpdated": "{{count}} actualitzat", + "proxmoxResultFailed": "{{count}} ha fallat", + "proxmoxImportComplete": "Importació de Proxmox completada: {{summary}}", + "proxmoxDiscoveryFailed": "El descobriment ha fallat", + "proxmoxImportFailed": "La importació ha fallat" + } +} diff --git a/plugins/proxmox/locales/translated/cs_CZ.json b/plugins/proxmox/locales/translated/cs_CZ.json new file mode 100644 index 000000000..327aff09e --- /dev/null +++ b/plugins/proxmox/locales/translated/cs_CZ.json @@ -0,0 +1,53 @@ +{ + "hosts": { + "tabProxmox": "Proxmox", + "authTypeStepca": "Krok CA", + "proxmoxIntegration": "Integrace Proxmoxu", + "enableProxmox": "Povolit Proxmox", + "enableProxmoxDesc": "Označit tento hostitel jako uzel Proxmox. Umožňuje vyhledávání hostů a import přímo z tohoto hostitele.", + "proxmoxDefaultAuthType": "Výchozí typ ověření", + "proxmoxDefaultAuthTypeDesc": "Metoda ověřování použitá na importované hostující hostitele. Vyberte typ ověřování, který odpovídá způsobu, jakým se připojujete k hostům.", + "authTypePassword": "Heslo", + "authTypeKey": "SSH klíč", + "authTypeCredential": "Pověření", + "authTypeOpkssh": "OPKSSH", + "authTypeNone": "Žádný", + "proxmoxDefaultCredential": "Výchozí přihlašovací údaje", + "proxmoxDefaultCredentialDesc": "Přihlašovací údaje používané pro importované hostující hostitele, pokud je typ ověření nastaven na Přihlašovací údaje.", + "proxmoxWindowsDetection": "Detekce Windows / RDP", + "proxmoxWindowsDetectionDesc": "Vzory názvů oddělené čárkami, které spouštějí RDP místo SSH (bez rozlišení velkých a malých písmen)", + "proxmoxDockerDetection": "Detekce Dockeru", + "proxmoxDockerDetectionDesc": "Vzory názvů oddělených čárkami, které Dockeru umožňují vyhledávání hostů", + "proxmoxPreferredRanges": "Preferované rozsahy IP adres", + "proxmoxPreferredRangesDesc": "Prefixy oddělené čárkami v pořadí priority pro výběr IP adresy, když má host více rozhraní", + "proxmoxAutoSync": "Automatická synchronizace hostů", + "proxmoxAutoSyncDesc": "Pravidelně vyhledávejte tento uzel Proxmox a vytvářejte nebo aktualizujte importované hostující hostitele, zatímco je vaše relace odemčená.", + "proxmoxSyncInterval": "Interval synchronizace (minuty)", + "proxmoxSyncIntervalDesc": "Minimálně 5 minut. Plánovač přeskakuje uzamčené uživatelské relace.", + "proxmoxMarkMissing": "Označte chybějící hosty", + "proxmoxMarkMissingDesc": "Přidat tag proxmox-missing, když dříve importovaný host zmizí, místo aby byl smazán.", + "proxmoxLastSync": "Poslední synchronizace", + "proxmoxLastSyncNever": "Zatím nesynchronizováno", + "proxmoxLastSyncNoResult": "Žádné podrobnosti o výsledcích", + "proxmoxLastSyncSummary": "{{created}} vytvořeno, {{updated}} aktualizováno, {{markedMissing}} chybí, {{skipped}} přeskočeno", + "proxmoxLastSyncStatus": { + "error": "Selhalo", + "pending": "Čeká na vyřízení" + }, + "proxmoxDiscoverAction": "Objevte a importujte hosty Proxmoxu", + "proxmoxImportTitle": "Import z Proxmoxu", + "proxmoxSelectHost": "Vyberte hostitele Proxmox…", + "proxmoxDiscover": "Objevit", + "proxmoxDiscovering": "Objevování…", + "proxmoxDiscoverGuests": "Objevte hosty", + "proxmoxSelectAll": "Vybrat vše", + "proxmoxDeselectAll": "Zrušit výběr všeho", + "proxmoxNoGuests": "Na tomto uzlu Proxmox nebyli nalezeni žádní hosté.", + "proxmoxResultImported": "{{count}} importováno", + "proxmoxResultUpdated": "{{count}} aktualizováno", + "proxmoxResultFailed": "{{count}} selhalo", + "proxmoxImportComplete": "Import Proxmoxu dokončen: {{summary}}", + "proxmoxDiscoveryFailed": "Objev selhal", + "proxmoxImportFailed": "Import se nezdařil" + } +} diff --git a/plugins/proxmox/locales/translated/da_DK.json b/plugins/proxmox/locales/translated/da_DK.json new file mode 100644 index 000000000..3e0625aeb --- /dev/null +++ b/plugins/proxmox/locales/translated/da_DK.json @@ -0,0 +1,53 @@ +{ + "hosts": { + "tabProxmox": "Proxmox", + "authTypeStepca": "Trin CA", + "proxmoxIntegration": "Proxmox-integration", + "enableProxmox": "Aktivér Proxmox", + "enableProxmoxDesc": "Marker denne vært som en Proxmox-node. Aktiverer gæsteopdagelse og import direkte fra denne vært.", + "proxmoxDefaultAuthType": "Standardgodkendelsestype", + "proxmoxDefaultAuthTypeDesc": "Godkendelsesmetode anvendt på importerede gæsteværter. Vælg den godkendelsestype, der matcher den måde, du opretter forbindelse til dine gæster.", + "authTypePassword": "Adgangskode", + "authTypeKey": "SSH-nøgle", + "authTypeCredential": "Legitimationsoplysninger", + "authTypeOpkssh": "OPKSSH", + "authTypeNone": "Ingen", + "proxmoxDefaultCredential": "Standardlegitimationsoplysninger", + "proxmoxDefaultCredentialDesc": "Legitimationsoplysninger, der bruges til importerede gæsteværter, når godkendelsestypen er indstillet til Legitimationsoplysninger.", + "proxmoxWindowsDetection": "Windows/RDP-detektion", + "proxmoxWindowsDetectionDesc": "Kommaseparerede navnemønstre, der udløser RDP i stedet for SSH (ikke-sanskel på store og små bogstaver)", + "proxmoxDockerDetection": "Docker-detektion", + "proxmoxDockerDetectionDesc": "Kommaseparerede navnemønstre, der gør det muligt for Docker at matche gæster", + "proxmoxPreferredRanges": "Foretrukne IP-intervaller", + "proxmoxPreferredRangesDesc": "Kommaseparerede præfikser i prioriteret rækkefølge for IP-valg, når en gæst har flere grænseflader", + "proxmoxAutoSync": "Automatisk synkronisering af gæster", + "proxmoxAutoSyncDesc": "Opdag periodisk denne Proxmox-node og opret eller opdater importerede gæsteværter, mens din session er låst op.", + "proxmoxSyncInterval": "Synkroniseringsinterval (minutter)", + "proxmoxSyncIntervalDesc": "Minimum 5 minutter. Planlæggeren springer låste brugersessioner over.", + "proxmoxMarkMissing": "Markér manglende gæster", + "proxmoxMarkMissingDesc": "Tilføj et proxmox-missing-tag, når en tidligere importeret gæst forsvinder, i stedet for at slette den.", + "proxmoxLastSync": "Sidste synkronisering", + "proxmoxLastSyncNever": "Ikke synkroniseret endnu", + "proxmoxLastSyncNoResult": "Ingen resultatdetaljer", + "proxmoxLastSyncSummary": "{{created}} oprettet, {{updated}} opdateret, {{markedMissing}} mangler, {{skipped}} sprunget over", + "proxmoxLastSyncStatus": { + "error": "Mislykkedes", + "pending": "Indtil" + }, + "proxmoxDiscoverAction": "Opdag og importer Proxmox-gæster", + "proxmoxImportTitle": "Importer fra Proxmox", + "proxmoxSelectHost": "Vælg en Proxmox-vært…", + "proxmoxDiscover": "Opdage", + "proxmoxDiscovering": "Opdager…", + "proxmoxDiscoverGuests": "Opdag gæster", + "proxmoxSelectAll": "Vælg alle", + "proxmoxDeselectAll": "Fravælg alle", + "proxmoxNoGuests": "Ingen gæster fundet på denne Proxmox-node.", + "proxmoxResultImported": "{{count}} importeret", + "proxmoxResultUpdated": "{{count}} opdateret", + "proxmoxResultFailed": "{{count}} mislykkedes", + "proxmoxImportComplete": "Proxmox-import fuldført: {{summary}}", + "proxmoxDiscoveryFailed": "Opdagelsen mislykkedes", + "proxmoxImportFailed": "Importen mislykkedes" + } +} diff --git a/plugins/proxmox/locales/translated/de_DE.json b/plugins/proxmox/locales/translated/de_DE.json new file mode 100644 index 000000000..36f8e6f22 --- /dev/null +++ b/plugins/proxmox/locales/translated/de_DE.json @@ -0,0 +1,53 @@ +{ + "hosts": { + "tabProxmox": "Proxmox", + "authTypeStepca": "Schritt CA", + "proxmoxIntegration": "Proxmox-Integration", + "enableProxmox": "Proxmox aktivieren", + "enableProxmoxDesc": "Diesen Host als Proxmox-Knoten markieren. Ermöglicht die Erkennung und den Import von Gästen direkt von diesem Host.", + "proxmoxDefaultAuthType": "Standard-Authentifizierungstyp", + "proxmoxDefaultAuthTypeDesc": "Authentifizierungsmethode, die auf importierte Gast-Hosts angewendet wird. Wählen Sie den Authentifizierungstyp, der Ihrer Verbindungsmethode zu den Gästen entspricht.", + "authTypePassword": "Passwort", + "authTypeKey": "SSH-Schlüssel", + "authTypeCredential": "Anmeldedaten", + "authTypeOpkssh": "OPKSSH", + "authTypeNone": "Keine", + "proxmoxDefaultCredential": "Standard-Anmeldedaten", + "proxmoxDefaultCredentialDesc": "Anmeldedaten, die für importierte Gastsysteme verwendet werden, wenn der Authentifizierungstyp auf Anmeldedaten gesetzt ist.", + "proxmoxWindowsDetection": "Windows-/RDP-Erkennung", + "proxmoxWindowsDetectionDesc": "Kommagetrennte Namensmuster, die RDP statt SSH auslösen (Groß-/Kleinschreibung wird nicht beachtet).", + "proxmoxDockerDetection": "Docker-Erkennung", + "proxmoxDockerDetectionDesc": "Kommagetrennte Namensmuster, die Docker für passende Gastsysteme aktivieren.", + "proxmoxPreferredRanges": "Bevorzugte IP-Bereiche", + "proxmoxPreferredRangesDesc": "Kommagetrennte Präfixe in Prioritätsreihenfolge für die IP-Auswahl, wenn ein Gastsystem mehrere Schnittstellen hat.", + "proxmoxAutoSync": "Gastsysteme automatisch synchronisieren", + "proxmoxAutoSyncDesc": "Diesen Proxmox-Knoten periodisch erkennen und importierte Gastsysteme erstellen oder aktualisieren, während Ihre Sitzung entsperrt ist.", + "proxmoxSyncInterval": "Synchronisierungsintervall (Minuten)", + "proxmoxSyncIntervalDesc": "Mindestens 5 Minuten. Der Scheduler überspringt gesperrte Benutzersitzungen.", + "proxmoxMarkMissing": "Fehlende Gastsysteme markieren", + "proxmoxMarkMissingDesc": "Ein proxmox-missing-Tag hinzufügen, wenn ein zuvor importiertes Gastsystem verschwindet, anstatt es zu löschen.", + "proxmoxLastSync": "Letzte Synchronisierung", + "proxmoxLastSyncNever": "Noch nicht synchronisiert", + "proxmoxLastSyncNoResult": "Keine Ergebnisdetails", + "proxmoxLastSyncSummary": "{{created}} erstellt, {{updated}} aktualisiert, {{markedMissing}} fehlend, {{skipped}} übersprungen", + "proxmoxLastSyncStatus": { + "error": "Fehlgeschlagen", + "pending": "Ausstehend" + }, + "proxmoxDiscoverAction": "Proxmox-Gastsysteme erkennen & importieren", + "proxmoxImportTitle": "Von Proxmox importieren", + "proxmoxSelectHost": "Proxmox-Host auswählen…", + "proxmoxDiscover": "Erkennen", + "proxmoxDiscovering": "Erkennen…", + "proxmoxDiscoverGuests": "Gastsysteme erkennen", + "proxmoxSelectAll": "Alle auswählen", + "proxmoxDeselectAll": "Alle abwählen", + "proxmoxNoGuests": "Keine Gastsysteme auf diesem Proxmox-Knoten gefunden.", + "proxmoxResultImported": "{{count}} importiert", + "proxmoxResultUpdated": "{{count}} aktualisiert", + "proxmoxResultFailed": "{{count}} fehlgeschlagen", + "proxmoxImportComplete": "Proxmox-Import abgeschlossen: {{summary}}", + "proxmoxDiscoveryFailed": "Erkennung fehlgeschlagen", + "proxmoxImportFailed": "Import fehlgeschlagen" + } +} diff --git a/plugins/proxmox/locales/translated/el_GR.json b/plugins/proxmox/locales/translated/el_GR.json new file mode 100644 index 000000000..dcdcbd643 --- /dev/null +++ b/plugins/proxmox/locales/translated/el_GR.json @@ -0,0 +1,53 @@ +{ + "hosts": { + "tabProxmox": "Proxmox", + "authTypeStepca": "Βήμα CA", + "proxmoxIntegration": "Ενσωμάτωση Proxmox", + "enableProxmox": "Ενεργοποίηση Proxmox", + "enableProxmoxDesc": "Σημειώστε αυτόν τον κεντρικό υπολογιστή ως κόμβο Proxmox. Επιτρέπει την ανακάλυψη επισκεπτών και την απευθείας εισαγωγή από αυτόν τον κεντρικό υπολογιστή.", + "proxmoxDefaultAuthType": "Προεπιλεγμένος τύπος εξουσιοδότησης", + "proxmoxDefaultAuthTypeDesc": "Μέθοδος ελέγχου ταυτότητας που εφαρμόστηκε στους εισαγόμενους φιλοξενούμενους οικοδεσπότες. Επιλέξτε τον τύπο ελέγχου ταυτότητας που ταιριάζει με τον τρόπο που συνδέεστε με τους επισκέπτες σας.", + "authTypePassword": "Σύνθημα", + "authTypeKey": "Κλειδί SSH", + "authTypeCredential": "Πιστοποιητικό", + "authTypeOpkssh": "OPKSSH", + "authTypeNone": "Κανένας", + "proxmoxDefaultCredential": "Προεπιλεγμένα διαπιστευτήρια", + "proxmoxDefaultCredentialDesc": "Διαπιστευτήριο που χρησιμοποιείται για εισαγόμενους φιλοξενούμενους οικοδεσπότες όταν ο τύπος εξουσιοδότησης έχει οριστεί σε Διαπιστευτήριο.", + "proxmoxWindowsDetection": "Ανίχνευση Windows / RDP", + "proxmoxWindowsDetectionDesc": "Μοτίβα ονομάτων διαχωρισμένα με κόμματα που ενεργοποιούν το RDP αντί για SSH (χωρίς διάκριση πεζών-κεφαλαίων)", + "proxmoxDockerDetection": "Ανίχνευση Docker", + "proxmoxDockerDetectionDesc": "Μοτίβα ονομάτων διαχωρισμένα με κόμματα που επιτρέπουν στο Docker να αντιστοιχίζει επισκέπτες", + "proxmoxPreferredRanges": "Προτιμώμενα εύρη IP", + "proxmoxPreferredRangesDesc": "Προθέματα διαχωρισμένα με κόμμα σε σειρά προτεραιότητας για την επιλογή IP όταν ένας επισκέπτης έχει πολλαπλές διεπαφές", + "proxmoxAutoSync": "Αυτόματος συγχρονισμός επισκεπτών", + "proxmoxAutoSyncDesc": "Εντοπίζετε περιοδικά αυτόν τον κόμβο Proxmox και δημιουργείτε ή ενημερώνετε εισαγόμενους φιλοξενούμενους υπολογιστές όσο η συνεδρία σας είναι ξεκλείδωτη.", + "proxmoxSyncInterval": "Διάστημα συγχρονισμού (λεπτά)", + "proxmoxSyncIntervalDesc": "Ελάχιστο 5 λεπτά. Ο προγραμματιστής παραλείπει τις κλειδωμένες συνεδρίες χρήστη.", + "proxmoxMarkMissing": "Ο Μαρκ λείπουν επισκέπτες.", + "proxmoxMarkMissingDesc": "Προσθέστε μια ετικέτα proxmox-missing όταν εξαφανιστεί ένας προηγουμένως εισαγόμενος επισκέπτης αντί να τον διαγράψετε.", + "proxmoxLastSync": "Τελευταίος συγχρονισμός", + "proxmoxLastSyncNever": "Δεν έχει συγχρονιστεί ακόμα", + "proxmoxLastSyncNoResult": "Δεν υπάρχουν λεπτομέρειες για το αποτέλεσμα", + "proxmoxLastSyncSummary": "{{created}} δημιουργήθηκε, {{updated}} ενημερώθηκε, {{markedMissing}} λείπει, {{skipped}} παραλείφθηκε", + "proxmoxLastSyncStatus": { + "error": "Αποτυχημένος", + "pending": "Εκκρεμής" + }, + "proxmoxDiscoverAction": "Ανακάλυψη και εισαγωγή επισκεπτών Proxmox", + "proxmoxImportTitle": "Εισαγωγή από το Proxmox", + "proxmoxSelectHost": "Επιλέξτε έναν κεντρικό υπολογιστή Proxmox…", + "proxmoxDiscover": "Ανακαλύπτω", + "proxmoxDiscovering": "Ανακαλύπτοντας…", + "proxmoxDiscoverGuests": "Ανακαλύψτε επισκέπτες", + "proxmoxSelectAll": "Επιλογή όλων", + "proxmoxDeselectAll": "Αποεπιλογή όλων", + "proxmoxNoGuests": "Δεν βρέθηκαν επισκέπτες σε αυτόν τον κόμβο Proxmox.", + "proxmoxResultImported": "{{count}} εισήχθη", + "proxmoxResultUpdated": "{{count}} ενημερώθηκε", + "proxmoxResultFailed": "{{count}} απέτυχε", + "proxmoxImportComplete": "Η εισαγωγή Proxmox ολοκληρώθηκε: {{summary}}", + "proxmoxDiscoveryFailed": "Η ανακάλυψη απέτυχε", + "proxmoxImportFailed": "Η εισαγωγή απέτυχε." + } +} diff --git a/plugins/proxmox/locales/translated/es_ES.json b/plugins/proxmox/locales/translated/es_ES.json new file mode 100644 index 000000000..611bc9e36 --- /dev/null +++ b/plugins/proxmox/locales/translated/es_ES.json @@ -0,0 +1,53 @@ +{ + "hosts": { + "tabProxmox": "Proxmox", + "authTypeStepca": "Paso CA", + "proxmoxIntegration": "Integración con Proxmox", + "enableProxmox": "Activar Proxmox", + "enableProxmoxDesc": "Marcar este host como un nodo Proxmox. Permite la detección e importación de invitados directamente desde este host.", + "proxmoxDefaultAuthType": "Tipo de autenticación predeterminado", + "proxmoxDefaultAuthTypeDesc": "Método de autenticación aplicado a los hosts invitados importados. Elija el tipo de autenticación que coincida con cómo se conecta a sus invitados.", + "authTypePassword": "Contraseña", + "authTypeKey": "Clave SSH", + "authTypeCredential": "Credencial", + "authTypeOpkssh": "OPKSSH", + "authTypeNone": "Ninguno", + "proxmoxDefaultCredential": "Credencial predeterminada", + "proxmoxDefaultCredentialDesc": "Credencial utilizada para los hosts invitados importados cuando el tipo de autenticación está configurado como Credencial.", + "proxmoxWindowsDetection": "Detección de Windows / RDP", + "proxmoxWindowsDetectionDesc": "Patrones de nombres separados por comas que activan RDP en lugar de SSH (sin distinción de mayúsculas/minúsculas)", + "proxmoxDockerDetection": "Detección de Docker", + "proxmoxDockerDetectionDesc": "Patrones de nombres separados por comas que habilitan Docker para los invitados coincidentes", + "proxmoxPreferredRanges": "Rangos de IP preferidos", + "proxmoxPreferredRangesDesc": "Prefijos separados por comas en orden de prioridad para la selección de IP cuando un invitado tiene múltiples interfaces", + "proxmoxAutoSync": "Sincronización automática de invitados", + "proxmoxAutoSyncDesc": "Descubrir periódicamente este nodo Proxmox y crear o actualizar los hosts invitados importados mientras la sesión está desbloqueada.", + "proxmoxSyncInterval": "Intervalo de sincronización (minutos)", + "proxmoxSyncIntervalDesc": "Mínimo 5 minutos. El planificador omite las sesiones de usuario bloqueadas.", + "proxmoxMarkMissing": "Marcar invitados faltantes", + "proxmoxMarkMissingDesc": "Añadir una etiqueta proxmox-missing cuando un invitado previamente importado desaparece en lugar de eliminarlo.", + "proxmoxLastSync": "Última sincronización", + "proxmoxLastSyncNever": "Aún no sincronizado", + "proxmoxLastSyncNoResult": "Sin detalles del resultado", + "proxmoxLastSyncSummary": "{{created}} creados, {{updated}} actualizados, {{markedMissing}} faltantes, {{skipped}} omitidos", + "proxmoxLastSyncStatus": { + "error": "Fallido", + "pending": "Pendiente" + }, + "proxmoxDiscoverAction": "Descubrir e importar invitados Proxmox", + "proxmoxImportTitle": "Importar desde Proxmox", + "proxmoxSelectHost": "Seleccionar un host Proxmox…", + "proxmoxDiscover": "Descubrir", + "proxmoxDiscovering": "Descubriendo…", + "proxmoxDiscoverGuests": "Descubrir invitados", + "proxmoxSelectAll": "Seleccionar todos", + "proxmoxDeselectAll": "Deseleccionar todos", + "proxmoxNoGuests": "No se encontraron invitados en este nodo Proxmox.", + "proxmoxResultImported": "{{count}} importados", + "proxmoxResultUpdated": "{{count}} actualizados", + "proxmoxResultFailed": "{{count}} fallidos", + "proxmoxImportComplete": "Importación de Proxmox completada: {{summary}}", + "proxmoxDiscoveryFailed": "Descubrimiento fallido", + "proxmoxImportFailed": "Importación fallida" + } +} diff --git a/plugins/proxmox/locales/translated/fi_FI.json b/plugins/proxmox/locales/translated/fi_FI.json new file mode 100644 index 000000000..c6679f666 --- /dev/null +++ b/plugins/proxmox/locales/translated/fi_FI.json @@ -0,0 +1,53 @@ +{ + "hosts": { + "tabProxmox": "Proxmox", + "authTypeStepca": "Vaihe CA", + "proxmoxIntegration": "Proxmox-integraatio", + "enableProxmox": "Ota Proxmox käyttöön", + "enableProxmoxDesc": "Merkitse tämä isäntä Proxmox-solmuksi. Mahdollistaa vieraslaitteiden etsinnän ja tuonnin suoraan tästä isännästä.", + "proxmoxDefaultAuthType": "Oletustodennustyyppi", + "proxmoxDefaultAuthTypeDesc": "Tuotuihin vieraspalvelimiin sovellettu todennustapa. Valitse todennustyyppi, joka vastaa tapaa, jolla muodostat yhteyden vieraisiin palvelimiin.", + "authTypePassword": "Salasana", + "authTypeKey": "SSH-avain", + "authTypeCredential": "Valtakirja", + "authTypeOpkssh": "OPKSSH", + "authTypeNone": "Ei mitään", + "proxmoxDefaultCredential": "Oletustunnistetiedot", + "proxmoxDefaultCredentialDesc": "Tuotujen vieraspalvelimien tunnistetiedot, kun todennustyypiksi on asetettu Tunnistetiedot.", + "proxmoxWindowsDetection": "Windowsin / RDP-tunnistus", + "proxmoxWindowsDetectionDesc": "Pilkuilla erotetut nimimallit, jotka käynnistävät RDP:n SSH:n sijaan (kirjainkokoa ei erotella)", + "proxmoxDockerDetection": "Docker-tunnistus", + "proxmoxDockerDetectionDesc": "Pilkuilla erotetut nimimallit, joiden avulla Docker löytää vieraat yhteensopiviksi", + "proxmoxPreferredRanges": "Suositellut IP-alueet", + "proxmoxPreferredRangesDesc": "Pilkuilla erotetut etuliitteet prioriteettijärjestyksessä IP-osoitteen valinnassa, kun vieraalla on useita rajapintoja", + "proxmoxAutoSync": "Synkronoi vieraat automaattisesti", + "proxmoxAutoSyncDesc": "Etsi tämä Proxmox-solmu säännöllisesti ja luo tai päivitä tuotuja vieraskomanteja istunnon ollessa lukitsematon.", + "proxmoxSyncInterval": "Synkronointiväli (minuuttia)", + "proxmoxSyncIntervalDesc": "Vähintään 5 minuuttia. Ajastin ohittaa lukitut käyttäjäistunnot.", + "proxmoxMarkMissing": "Merkitse puuttuvat vieraat", + "proxmoxMarkMissingDesc": "Lisää proxmox-missing-tunniste, kun aiemmin tuotu vieras katoaa sen poistamisen sijaan.", + "proxmoxLastSync": "Viimeisin synkronointi", + "proxmoxLastSyncNever": "Ei vielä synkronoitu", + "proxmoxLastSyncNoResult": "Ei tulostietoja", + "proxmoxLastSyncSummary": "{{created}} luotu, {{updated}} päivitetty, {{markedMissing}} puuttuu, {{skipped}} ohitettu", + "proxmoxLastSyncStatus": { + "error": "Epäonnistui", + "pending": "Odottaa" + }, + "proxmoxDiscoverAction": "Löydä ja tuo Proxmox-vieraita", + "proxmoxImportTitle": "Tuo Proxmoxista", + "proxmoxSelectHost": "Valitse Proxmox-isäntä…", + "proxmoxDiscover": "Tutustu", + "proxmoxDiscovering": "Löytöretkellä…", + "proxmoxDiscoverGuests": "Tutustu vieraisiin", + "proxmoxSelectAll": "Valitse kaikki", + "proxmoxDeselectAll": "Poista kaikkien valinta", + "proxmoxNoGuests": "Tältä Proxmox-solmulta ei löytynyt vieraita.", + "proxmoxResultImported": "{{count}} tuotu", + "proxmoxResultUpdated": "{{count}} päivitetty", + "proxmoxResultFailed": "{{count}} epäonnistui", + "proxmoxImportComplete": "Proxmox-tuonti valmis: {{summary}}", + "proxmoxDiscoveryFailed": "Löytö epäonnistui", + "proxmoxImportFailed": "Tuonti epäonnistui" + } +} diff --git a/plugins/proxmox/locales/translated/fr_FR.json b/plugins/proxmox/locales/translated/fr_FR.json new file mode 100644 index 000000000..bcf10b85a --- /dev/null +++ b/plugins/proxmox/locales/translated/fr_FR.json @@ -0,0 +1,53 @@ +{ + "hosts": { + "tabProxmox": "Proxmox", + "authTypeStepca": "Étape CA", + "proxmoxIntegration": "Intégration Proxmox", + "enableProxmox": "Activer Proxmox", + "enableProxmoxDesc": "Marquer cet hôte comme un nœud Proxmox. Permet la découverte et l'importation des invités directement depuis cet hôte.", + "proxmoxDefaultAuthType": "Type d'authentification par défaut", + "proxmoxDefaultAuthTypeDesc": "Méthode d'authentification appliquée aux hôtes invités importés. Choisissez le type d'authentification correspondant à votre méthode de connexion aux invités.", + "authTypePassword": "Mot de passe", + "authTypeKey": "Clé SSH", + "authTypeCredential": "Identifiants", + "authTypeOpkssh": "OPKSSH", + "authTypeNone": "Aucun", + "proxmoxDefaultCredential": "Identifiant par défaut", + "proxmoxDefaultCredentialDesc": "Identifiant utilisé pour les hôtes invités importés lorsque le type d'authentification est défini sur Identifiant.", + "proxmoxWindowsDetection": "Détection Windows / RDP", + "proxmoxWindowsDetectionDesc": "Liste de motifs de noms, séparés par des virgules, qui déclenchent RDP au lieu de SSH (insensible à la casse).", + "proxmoxDockerDetection": "Détection Docker", + "proxmoxDockerDetectionDesc": "Liste de motifs de noms, séparés par des virgules, qui activent Docker pour les invités correspondants.", + "proxmoxPreferredRanges": "Plages IP préférées", + "proxmoxPreferredRangesDesc": "Préfixes séparés par des virgules, par ordre de priorité, pour la sélection d'adresse IP lorsqu'un invité possède plusieurs interfaces.", + "proxmoxAutoSync": "Synchronisation automatique des invités", + "proxmoxAutoSyncDesc": "Découvre périodiquement ce nœud Proxmox et crée ou met à jour les hôtes invités importés tant que votre session est déverrouillée.", + "proxmoxSyncInterval": "Intervalle de synchronisation (minutes)", + "proxmoxSyncIntervalDesc": "Minimum 5 minutes. Le planificateur ignore les sessions utilisateur verrouillées.", + "proxmoxMarkMissing": "Marquer les invités manquants", + "proxmoxMarkMissingDesc": "Ajoute une étiquette proxmox-missing lorsqu'un invité précédemment importé disparaît, au lieu de le supprimer.", + "proxmoxLastSync": "Dernière synchronisation", + "proxmoxLastSyncNever": "Pas encore synchronisé", + "proxmoxLastSyncNoResult": "Aucun détail de résultat", + "proxmoxLastSyncSummary": "{{created}} créé(s), {{updated}} mis à jour, {{markedMissing}} manquant(s), {{skipped}} ignoré(s)", + "proxmoxLastSyncStatus": { + "error": "Échec", + "pending": "En attente" + }, + "proxmoxDiscoverAction": "Découvrir et importer les invités Proxmox", + "proxmoxImportTitle": "Importer depuis Proxmox", + "proxmoxSelectHost": "Sélectionner un hôte Proxmox…", + "proxmoxDiscover": "Découvrir", + "proxmoxDiscovering": "Découverte en cours…", + "proxmoxDiscoverGuests": "Découvrir les invités", + "proxmoxSelectAll": "Tout sélectionner", + "proxmoxDeselectAll": "Tout désélectionner", + "proxmoxNoGuests": "Aucun invité trouvé sur ce nœud Proxmox.", + "proxmoxResultImported": "{{count}} importés", + "proxmoxResultUpdated": "{{count}} mis à jour", + "proxmoxResultFailed": "{{count}} échoués", + "proxmoxImportComplete": "Importation Proxmox terminée : {{summary}}", + "proxmoxDiscoveryFailed": "Échec de la découverte", + "proxmoxImportFailed": "Échec de l'importation" + } +} diff --git a/plugins/proxmox/locales/translated/he_IL.json b/plugins/proxmox/locales/translated/he_IL.json new file mode 100644 index 000000000..24a28079f --- /dev/null +++ b/plugins/proxmox/locales/translated/he_IL.json @@ -0,0 +1,53 @@ +{ + "hosts": { + "tabProxmox": "פרוקסמוקס", + "authTypeStepca": "שלב CA", + "proxmoxIntegration": "אינטגרציה של פרוקסמוקס", + "enableProxmox": "הפעל את Proxmox", + "enableProxmoxDesc": "סמן מארח זה כצומת Proxmox. מאפשר גילוי אורחים וייבוא ישירות ממארח זה.", + "proxmoxDefaultAuthType": "סוג אימות ברירת מחדל", + "proxmoxDefaultAuthTypeDesc": "שיטת אימות הוחלת על מארחי אורחים מיובאים. בחר את סוג האימות שמתאים לאופן שבו אתה מתחבר לאורחים שלך.", + "authTypePassword": "סִיסמָה", + "authTypeKey": "מפתח SSH", + "authTypeCredential": "תְעוּדָה", + "authTypeOpkssh": "אופקש", + "authTypeNone": "אַף לֹא אֶחָד", + "proxmoxDefaultCredential": "אישור ברירת מחדל", + "proxmoxDefaultCredentialDesc": "אישור המשמש עבור מארחים אורחים מיובאים כאשר סוג האימות מוגדר לאישור.", + "proxmoxWindowsDetection": "זיהוי Windows / RDP", + "proxmoxWindowsDetectionDesc": "תבניות שמות מופרדות בפסיקים המפעילות RDP במקום SSH (לא תלויות רישיות)", + "proxmoxDockerDetection": "זיהוי דוקר", + "proxmoxDockerDetectionDesc": "תבניות שמות מופרדות בפסיקים המאפשרות ל-Docker להתאים אורחים", + "proxmoxPreferredRanges": "טווחי IP מועדפים", + "proxmoxPreferredRangesDesc": "קידומות מופרדות בפסיקים בסדר עדיפות לבחירת IP כאשר לאורח יש ממשקים מרובים", + "proxmoxAutoSync": "סנכרון אוטומטי של אורחים", + "proxmoxAutoSyncDesc": "גלה מעת לעת את צומת Proxmox הזה וצור או עדכן מארחי אורחים מיובאים בזמן שההפעלה שלך אינה נעולה.", + "proxmoxSyncInterval": "מרווח סנכרון (דקות)", + "proxmoxSyncIntervalDesc": "מינימום 5 דקות. המתזמן מדלג על סשנים נעולים של משתמשים.", + "proxmoxMarkMissing": "סמן אורחים חסרים", + "proxmoxMarkMissingDesc": "הוסף תג proxmox-missing כאשר אורח שיובא בעבר נעלם במקום למחוק אותו.", + "proxmoxLastSync": "סנכרון אחרון", + "proxmoxLastSyncNever": "עדיין לא מסונכרן", + "proxmoxLastSyncNoResult": "אין פרטי תוצאה", + "proxmoxLastSyncSummary": "{{created}} נוצר, {{updated}} עודכן, {{markedMissing}} חסר, {{skipped}} דילג", + "proxmoxLastSyncStatus": { + "error": "נִכשָׁל", + "pending": "תָלוּי וְעוֹמֵד" + }, + "proxmoxDiscoverAction": "גלה וייבא אורחי Proxmox", + "proxmoxImportTitle": "ייבוא מ-Proxmox", + "proxmoxSelectHost": "בחר מארח Proxmox…", + "proxmoxDiscover": "לְגַלוֹת", + "proxmoxDiscovering": "גילוי…", + "proxmoxDiscoverGuests": "גלה אורחים", + "proxmoxSelectAll": "בחר הכל", + "proxmoxDeselectAll": "בטל את הבחירה של הכל", + "proxmoxNoGuests": "לא נמצאו אורחים בצומת Proxmox זה.", + "proxmoxResultImported": "{{count}} מיובא", + "proxmoxResultUpdated": "{{count}} updated", + "proxmoxResultFailed": "{{count}} נכשל", + "proxmoxImportComplete": "ייבוא Proxmox הושלם: {{summary}}", + "proxmoxDiscoveryFailed": "הגילוי נכשל", + "proxmoxImportFailed": "הייבוא נכשל" + } +} diff --git a/plugins/proxmox/locales/translated/hi_IN.json b/plugins/proxmox/locales/translated/hi_IN.json new file mode 100644 index 000000000..2bb7d6999 --- /dev/null +++ b/plugins/proxmox/locales/translated/hi_IN.json @@ -0,0 +1,53 @@ +{ + "hosts": { + "tabProxmox": "Proxmox", + "authTypeStepca": "स्टेप सीए", + "proxmoxIntegration": "Proxmox एकीकरण", + "enableProxmox": "Proxmox सक्षम करें", + "enableProxmoxDesc": "इस होस्ट को Proxmox नोड के रूप में चिह्नित करें। इस होस्ट से सीधे अतिथि खोज और आयात सक्षम करता है।", + "proxmoxDefaultAuthType": "डिफ़ॉल्ट प्रमाणीकरण प्रकार", + "proxmoxDefaultAuthTypeDesc": "आयातित अतिथि होस्ट पर लागू प्रमाणीकरण विधि। वह प्रमाणीकरण प्रकार चुनें जो आपके अतिथियों से कनेक्ट करने के तरीके से मेल खाता हो।", + "authTypePassword": "पासवर्ड", + "authTypeKey": "SSH कुंजी", + "authTypeCredential": "क्रेडेंशियल", + "authTypeOpkssh": "OPKSSH", + "authTypeNone": "कोई नहीं", + "proxmoxDefaultCredential": "डिफ़ॉल्ट क्रेडेंशियल", + "proxmoxDefaultCredentialDesc": "जब प्रमाणीकरण प्रकार 'क्रेडेंशियल' पर सेट होता है तब आयातित अतिथि होस्ट के लिए उपयोग किया जाने वाला क्रेडेंशियल।", + "proxmoxWindowsDetection": "Windows / RDP पहचान", + "proxmoxWindowsDetectionDesc": "अल्पविराम से अलग नाम पैटर्न जो SSH के बजाय RDP ट्रिगर करते हैं (अक्षर-आकार असंवेदी)", + "proxmoxDockerDetection": "Docker पहचान", + "proxmoxDockerDetectionDesc": "अल्पविराम से अलग नाम पैटर्न जो मिलान वाले अतिथियों के लिए Docker सक्षम करते हैं", + "proxmoxPreferredRanges": "पसंदीदा IP श्रेणियाँ", + "proxmoxPreferredRangesDesc": "अतिथि के पास कई इंटरफ़ेस होने पर IP चयन के लिए प्राथमिकता क्रम में अल्पविराम से अलग उपसर्ग", + "proxmoxAutoSync": "अतिथि स्वतः सिंक", + "proxmoxAutoSyncDesc": "जब आपका सत्र अनलॉक हो तो समय-समय पर इस Proxmox नोड की खोज करें और आयातित अतिथि होस्ट बनाएँ या अपडेट करें।", + "proxmoxSyncInterval": "सिंक अंतराल (मिनट)", + "proxmoxSyncIntervalDesc": "न्यूनतम 5 मिनट। शेड्यूलर लॉक उपयोगकर्ता सत्रों को छोड़ देता है।", + "proxmoxMarkMissing": "गायब अतिथियों को चिह्नित करें", + "proxmoxMarkMissingDesc": "जब पहले से आयातित कोई अतिथि गायब हो जाए तो उसे हटाने के बजाय एक 'proxmox-missing' टैग जोड़ें।", + "proxmoxLastSync": "अंतिम सिंक", + "proxmoxLastSyncNever": "अभी तक सिंक नहीं हुआ", + "proxmoxLastSyncNoResult": "कोई परिणाम विवरण नहीं", + "proxmoxLastSyncSummary": "{{created}} बनाए गए, {{updated}} अपडेट किए गए, {{markedMissing}} गायब, {{skipped}} छोड़े गए", + "proxmoxLastSyncStatus": { + "error": "विफल", + "pending": "लंबित" + }, + "proxmoxDiscoverAction": "Proxmox अतिथियों की खोज करें और आयात करें", + "proxmoxImportTitle": "Proxmox से आयात करें", + "proxmoxSelectHost": "एक Proxmox होस्ट चुनें…", + "proxmoxDiscover": "खोजें", + "proxmoxDiscovering": "खोज रहा है…", + "proxmoxDiscoverGuests": "अतिथियों की खोज करें", + "proxmoxSelectAll": "सभी चुनें", + "proxmoxDeselectAll": "सभी अचयनित करें", + "proxmoxNoGuests": "इस Proxmox नोड पर कोई अतिथि नहीं मिला।", + "proxmoxResultImported": "{{count}} आयातित", + "proxmoxResultUpdated": "{{count}} अद्यतित", + "proxmoxResultFailed": "{{count}} विफल", + "proxmoxImportComplete": "Proxmox आयात पूर्ण: {{summary}}", + "proxmoxDiscoveryFailed": "डिस्कवरी विफल", + "proxmoxImportFailed": "आयात विफल" + } +} diff --git a/plugins/proxmox/locales/translated/hu_HU.json b/plugins/proxmox/locales/translated/hu_HU.json new file mode 100644 index 000000000..1f5c3061a --- /dev/null +++ b/plugins/proxmox/locales/translated/hu_HU.json @@ -0,0 +1,53 @@ +{ + "hosts": { + "tabProxmox": "Proxmox", + "authTypeStepca": "CA lépés", + "proxmoxIntegration": "Proxmox integráció", + "enableProxmox": "Proxmox engedélyezése", + "enableProxmoxDesc": "Jelölje meg ezt a gépet Proxmox csomópontként. Engedélyezi a vendégfelderítést és az importálást közvetlenül erről a gépről.", + "proxmoxDefaultAuthType": "Alapértelmezett hitelesítési típus", + "proxmoxDefaultAuthTypeDesc": "Hitelesítési módszer alkalmazva az importált vendéggazdagépekre. Válassza ki azt a hitelesítési típust, amelyik megfelel a vendéggazdagépekhez való csatlakozás módjának.", + "authTypePassword": "Jelszó", + "authTypeKey": "SSH-kulcs", + "authTypeCredential": "Hitelesítő adat", + "authTypeOpkssh": "OPKSSH", + "authTypeNone": "Egyik sem", + "proxmoxDefaultCredential": "Alapértelmezett hitelesítő adat", + "proxmoxDefaultCredentialDesc": "Az importált vendéggazdagépekhez használt hitelesítő adat, ha a hitelesítési típus Hitelesítő adatra van állítva.", + "proxmoxWindowsDetection": "Windows/RDP-észlelés", + "proxmoxWindowsDetectionDesc": "Vesszővel elválasztott névminták, amelyek RDP-t indítanak el SSH helyett (kis- és nagybetűket nem megkülönböztető)", + "proxmoxDockerDetection": "Docker-észlelés", + "proxmoxDockerDetectionDesc": "Vesszővel elválasztott névminták, amelyek lehetővé teszik a Docker számára a vendégek egyezését", + "proxmoxPreferredRanges": "Előnyben részesített IP-tartományok", + "proxmoxPreferredRangesDesc": "Vesszővel elválasztott előtagok prioritási sorrendben IP-cím kiválasztásához, ha egy vendégnek több interfésze van", + "proxmoxAutoSync": "Vendégek automatikus szinkronizálása", + "proxmoxAutoSyncDesc": "Rendszeresen fedezze fel ezt a Proxmox csomópontot, és hozzon létre vagy frissítsen importált vendéggazdagépeket, miközben a munkamenete fel van oldva.", + "proxmoxSyncInterval": "Szinkronizálási időköz (perc)", + "proxmoxSyncIntervalDesc": "Minimum 5 perc. Az ütemező kihagyja a zárolt felhasználói munkameneteket.", + "proxmoxMarkMissing": "Jelöld meg az eltűnt vendégeket", + "proxmoxMarkMissingDesc": "Hozzáad egy proxmox-missing címkét, amikor egy korábban importált vendég eltűnik, ahelyett, hogy törölné azt.", + "proxmoxLastSync": "Utolsó szinkronizálás", + "proxmoxLastSyncNever": "Még nincs szinkronizálva", + "proxmoxLastSyncNoResult": "Nincsenek találati részletek", + "proxmoxLastSyncSummary": "{{created}} létrehozva, {{updated}} frissítve, {{markedMissing}} hiányzik, {{skipped}} kihagyva", + "proxmoxLastSyncStatus": { + "error": "Sikertelen", + "pending": "Függőben levő" + }, + "proxmoxDiscoverAction": "Proxmox vendégek felfedezése és importálása", + "proxmoxImportTitle": "Importálás a Proxmoxból", + "proxmoxSelectHost": "Válasszon egy Proxmox hosztot…", + "proxmoxDiscover": "Felfedezés", + "proxmoxDiscovering": "Felfedezés…", + "proxmoxDiscoverGuests": "Fedezze fel a vendégeket", + "proxmoxSelectAll": "Összes kijelölése", + "proxmoxDeselectAll": "Összes kijelölés törlése", + "proxmoxNoGuests": "Nem találhatók vendégek ezen a Proxmox csomóponton.", + "proxmoxResultImported": "{{count}} importálva", + "proxmoxResultUpdated": "{{count}} frissítve", + "proxmoxResultFailed": "{{count}} sikertelen", + "proxmoxImportComplete": "Proxmox importálás kész: {{summary}}", + "proxmoxDiscoveryFailed": "A felfedezés sikertelen", + "proxmoxImportFailed": "Importálás sikertelen" + } +} diff --git a/plugins/proxmox/locales/translated/id_ID.json b/plugins/proxmox/locales/translated/id_ID.json new file mode 100644 index 000000000..d0fe9a35f --- /dev/null +++ b/plugins/proxmox/locales/translated/id_ID.json @@ -0,0 +1,53 @@ +{ + "hosts": { + "tabProxmox": "Proxmox", + "authTypeStepca": "Langkah CA", + "proxmoxIntegration": "Integrasi Proxmox", + "enableProxmox": "Aktifkan Proxmox", + "enableProxmoxDesc": "Tandai host ini sebagai node Proxmox. Memungkinkan penemuan dan impor guest langsung dari host ini.", + "proxmoxDefaultAuthType": "Jenis Otentikasi Default", + "proxmoxDefaultAuthTypeDesc": "Metode otentikasi yang diterapkan pada host tamu yang diimpor. Pilih jenis otentikasi yang sesuai dengan cara Anda terhubung ke tamu Anda.", + "authTypePassword": "Kata sandi", + "authTypeKey": "Kunci SSH", + "authTypeCredential": "Mandat", + "authTypeOpkssh": "OPKSSH", + "authTypeNone": "Tidak ada", + "proxmoxDefaultCredential": "Kredensial Default", + "proxmoxDefaultCredentialDesc": "Kredensial yang digunakan untuk host tamu yang diimpor ketika tipe otentikasi diatur ke Kredensial.", + "proxmoxWindowsDetection": "Deteksi Windows / RDP", + "proxmoxWindowsDetectionDesc": "Pola nama yang dipisahkan koma yang memicu RDP alih-alih SSH (tidak peka huruf besar/kecil)", + "proxmoxDockerDetection": "Deteksi Docker", + "proxmoxDockerDetectionDesc": "Pola nama yang dipisahkan koma yang memungkinkan Docker untuk mencocokkan mesin virtual.", + "proxmoxPreferredRanges": "Rentang IP yang disukai", + "proxmoxPreferredRangesDesc": "Awalan yang dipisahkan koma dalam urutan prioritas untuk pemilihan IP ketika tamu memiliki beberapa antarmuka.", + "proxmoxAutoSync": "Sinkronisasi otomatis tamu", + "proxmoxAutoSyncDesc": "Secara berkala, temukan node Proxmox ini dan buat atau perbarui host tamu yang diimpor saat sesi Anda tidak terkunci.", + "proxmoxSyncInterval": "Interval sinkronisasi (menit)", + "proxmoxSyncIntervalDesc": "Minimal 5 menit. Penjadwal akan melewati sesi pengguna yang terkunci.", + "proxmoxMarkMissing": "Tandai tamu yang hilang", + "proxmoxMarkMissingDesc": "Tambahkan tag proxmox-missing ketika tamu yang sebelumnya diimpor menghilang, alih-alih menghapusnya.", + "proxmoxLastSync": "Sinkronisasi terakhir", + "proxmoxLastSyncNever": "Belum disinkronkan", + "proxmoxLastSyncNoResult": "Tidak ada detail hasil.", + "proxmoxLastSyncSummary": "{{created}} dibuat, {{updated}} diperbarui, {{markedMissing}} hilang, {{skipped}} dilewati", + "proxmoxLastSyncStatus": { + "error": "Gagal", + "pending": "Tertunda" + }, + "proxmoxDiscoverAction": "Temukan & impor tamu Proxmox", + "proxmoxImportTitle": "Impor dari Proxmox", + "proxmoxSelectHost": "Pilih host Proxmox…", + "proxmoxDiscover": "Menemukan", + "proxmoxDiscovering": "Menemukan…", + "proxmoxDiscoverGuests": "Temukan tamu", + "proxmoxSelectAll": "Pilih semua", + "proxmoxDeselectAll": "Batalkan pilihan semua", + "proxmoxNoGuests": "Tidak ada tamu yang ditemukan di node Proxmox ini.", + "proxmoxResultImported": "{{count}} diimpor", + "proxmoxResultUpdated": "{{count}} diperbarui", + "proxmoxResultFailed": "{{count}} gagal", + "proxmoxImportComplete": "Impor Proxmox selesai: {{summary}}", + "proxmoxDiscoveryFailed": "Penemuan gagal", + "proxmoxImportFailed": "Impor gagal" + } +} diff --git a/plugins/proxmox/locales/translated/it_IT.json b/plugins/proxmox/locales/translated/it_IT.json new file mode 100644 index 000000000..7698f360f --- /dev/null +++ b/plugins/proxmox/locales/translated/it_IT.json @@ -0,0 +1,53 @@ +{ + "hosts": { + "tabProxmox": "Proxmox", + "authTypeStepca": "Passo CA", + "proxmoxIntegration": "Integrazione Proxmox", + "enableProxmox": "Abilita Proxmox", + "enableProxmoxDesc": "Contrassegna questo host come nodo Proxmox. Abilita il discovery e l'importazione di guest direttamente da questo host.", + "proxmoxDefaultAuthType": "Tipo di autenticazione predefinito", + "proxmoxDefaultAuthTypeDesc": "Metodo di autenticazione applicato agli host guest importati. Scegli il tipo di autenticazione corrispondente a come ti connetti ai tuoi guest.", + "authTypePassword": "Password", + "authTypeKey": "Chiave SSH", + "authTypeCredential": "Credenziale", + "authTypeOpkssh": "OPKSSH", + "authTypeNone": "Nessuno", + "proxmoxDefaultCredential": "Credenziale predefinita", + "proxmoxDefaultCredentialDesc": "Credenziale utilizzata per gli host guest importati quando il tipo di autenticazione è impostato su Credenziale.", + "proxmoxWindowsDetection": "Rilevamento Windows / RDP", + "proxmoxWindowsDetectionDesc": "Elenco di pattern di nomi separati da virgole che attivano RDP invece di SSH (case‑insensitive)", + "proxmoxDockerDetection": "Rilevamento Docker", + "proxmoxDockerDetectionDesc": "Elenco di pattern di nomi separati da virgole che abilitano Docker per i guest corrispondenti", + "proxmoxPreferredRanges": "Intervalli IP preferiti", + "proxmoxPreferredRangesDesc": "Prefissi separati da virgole in ordine di priorità per la selezione dell'IP quando un guest ha più interfacce", + "proxmoxAutoSync": "Sincronizzazione automatica dei guest", + "proxmoxAutoSyncDesc": "Scopri periodicamente questo nodo Proxmox e crea o aggiorna gli host guest importati mentre la sessione è sbloccata.", + "proxmoxSyncInterval": "Intervallo di sincronizzazione (minuti)", + "proxmoxSyncIntervalDesc": "Minimo 5 minuti. La pianificazione salta le sessioni utente bloccate.", + "proxmoxMarkMissing": "Segna i guest mancanti", + "proxmoxMarkMissingDesc": "Aggiungi un tag proxmox-missing quando un guest precedentemente importato scompare invece di eliminarlo.", + "proxmoxLastSync": "Ultima sincronizzazione", + "proxmoxLastSyncNever": "Non ancora sincronizzato", + "proxmoxLastSyncNoResult": "Nessun dettaglio del risultato", + "proxmoxLastSyncSummary": "{{created}} creati, {{updated}} aggiornati, {{markedMissing}} mancanti, {{skipped}} saltati", + "proxmoxLastSyncStatus": { + "error": "Fallita", + "pending": "In attesa" + }, + "proxmoxDiscoverAction": "Scopri e importa guest Proxmox", + "proxmoxImportTitle": "Importa da Proxmox", + "proxmoxSelectHost": "Seleziona un host Proxmox…", + "proxmoxDiscover": "Scopri", + "proxmoxDiscovering": "Scoperta in corso…", + "proxmoxDiscoverGuests": "Scopri guest", + "proxmoxSelectAll": "Seleziona tutto", + "proxmoxDeselectAll": "Deseleziona tutto", + "proxmoxNoGuests": "Nessun guest trovato su questo nodo Proxmox.", + "proxmoxResultImported": "{{count}} importati", + "proxmoxResultUpdated": "{{count}} aggiornati", + "proxmoxResultFailed": "{{count}} falliti", + "proxmoxImportComplete": "Importazione Proxmox completata: {{summary}}", + "proxmoxDiscoveryFailed": "Rilevamento non riuscito", + "proxmoxImportFailed": "Importazione non riuscita" + } +} diff --git a/plugins/proxmox/locales/translated/ja_JP.json b/plugins/proxmox/locales/translated/ja_JP.json new file mode 100644 index 000000000..5cd675ce4 --- /dev/null +++ b/plugins/proxmox/locales/translated/ja_JP.json @@ -0,0 +1,53 @@ +{ + "hosts": { + "tabProxmox": "Proxmox", + "authTypeStepca": "ステップCA", + "proxmoxIntegration": "Proxmox統合", + "enableProxmox": "Proxmoxを有効にする", + "enableProxmoxDesc": "このホストをProxmoxノードとしてマークします。ゲストの検出とインポートをこのホストから直接行えるようにします。", + "proxmoxDefaultAuthType": "デフォルト認証タイプ", + "proxmoxDefaultAuthTypeDesc": "インポートされたゲストホストに適用される認証方式です。ゲストへの接続方法に合わせて認証タイプを選択してください。", + "authTypePassword": "パスワード", + "authTypeKey": "SSH鍵", + "authTypeCredential": "クレデンシャル", + "authTypeOpkssh": "OPKSSH", + "authTypeNone": "なし", + "proxmoxDefaultCredential": "デフォルト認証情報", + "proxmoxDefaultCredentialDesc": "認証タイプが「Credential」に設定されている場合に、インポートされたゲストホストに使用される認証情報。", + "proxmoxWindowsDetection": "Windows / RDP 検出", + "proxmoxWindowsDetectionDesc": "SSH の代わりに RDP をトリガーする、カンマ区切りの名前パターン(大文字と小文字を区別しない)", + "proxmoxDockerDetection": "Docker 検出", + "proxmoxDockerDetectionDesc": "一致するゲストに対して Docker を有効にする、カンマ区切りの名前パターン", + "proxmoxPreferredRanges": "優先 IP 範囲", + "proxmoxPreferredRangesDesc": "ゲストが複数のインターフェースを持つ場合の IP 選択の優先順位で指定する、カンマ区切りのプレフィックス", + "proxmoxAutoSync": "ゲストの自動同期", + "proxmoxAutoSyncDesc": "セッションがロックされていないときに、この Proxmox ノードを定期的に検出し、インポートされたゲストホストを作成または更新します。", + "proxmoxSyncInterval": "同期間隔(分)", + "proxmoxSyncIntervalDesc": "最小 5 分。スケジューラーはロックされたユーザーセッションをスキップします。", + "proxmoxMarkMissing": "欠落ゲストをマーク", + "proxmoxMarkMissingDesc": "以前にインポートされたゲストが消えたときに、削除する代わりに proxmox-missing タグを追加します。", + "proxmoxLastSync": "最終同期", + "proxmoxLastSyncNever": "未同期", + "proxmoxLastSyncNoResult": "結果の詳細なし", + "proxmoxLastSyncSummary": "{{created}} 作成、{{updated}} 更新、{{markedMissing}} 欠落、{{skipped}} スキップ", + "proxmoxLastSyncStatus": { + "error": "失敗", + "pending": "保留中" + }, + "proxmoxDiscoverAction": "Proxmox ゲストの検出とインポート", + "proxmoxImportTitle": "Proxmox からインポート", + "proxmoxSelectHost": "Proxmox ホストを選択…", + "proxmoxDiscover": "検出", + "proxmoxDiscovering": "検出中…", + "proxmoxDiscoverGuests": "ゲストを検出", + "proxmoxSelectAll": "すべて選択", + "proxmoxDeselectAll": "すべて選択解除", + "proxmoxNoGuests": "この Proxmox ノードにゲストが見つかりません。", + "proxmoxResultImported": "{{count}} インポート済み", + "proxmoxResultUpdated": "{{count}} 更新済み", + "proxmoxResultFailed": "{{count}} 失敗", + "proxmoxImportComplete": "Proxmox インポート完了: {{summary}}", + "proxmoxDiscoveryFailed": "検出に失敗しました", + "proxmoxImportFailed": "インポートに失敗しました" + } +} diff --git a/plugins/proxmox/locales/translated/ko_KR.json b/plugins/proxmox/locales/translated/ko_KR.json new file mode 100644 index 000000000..4cb29bd55 --- /dev/null +++ b/plugins/proxmox/locales/translated/ko_KR.json @@ -0,0 +1,53 @@ +{ + "hosts": { + "tabProxmox": "Proxmox", + "authTypeStepca": "스텝 CA", + "proxmoxIntegration": "Proxmox 통합", + "enableProxmox": "Proxmox 활성화", + "enableProxmoxDesc": "이 호스트를 Proxmox 노드로 표시합니다. 이 호스트에서 직접 게스트를 검색하고 가져올 수 있도록 합니다.", + "proxmoxDefaultAuthType": "기본 인증 유형", + "proxmoxDefaultAuthTypeDesc": "가져온 게스트 호스트에 적용되는 인증 방법입니다. 게스트에 연결하는 방식에 맞는 인증 유형을 선택하세요.", + "authTypePassword": "비밀번호", + "authTypeKey": "SSH 키", + "authTypeCredential": "자격 증명", + "authTypeOpkssh": "OPKSSH", + "authTypeNone": "없음", + "proxmoxDefaultCredential": "기본 자격 증명", + "proxmoxDefaultCredentialDesc": "인증 유형이 자격 증명으로 설정된 경우 가져온 게스트 호스트에 사용되는 자격 증명입니다.", + "proxmoxWindowsDetection": "Windows / RDP 감지", + "proxmoxWindowsDetectionDesc": "SSH 대신 RDP를 트리거하는 쉼표로 구분된 이름 패턴(대소문자 구분 안 함)", + "proxmoxDockerDetection": "Docker 감지", + "proxmoxDockerDetectionDesc": "일치하는 게스트에 대해 Docker를 활성화하는 쉼표로 구분된 이름 패턴", + "proxmoxPreferredRanges": "선호하는 IP 범위", + "proxmoxPreferredRangesDesc": "게스트에 여러 인터페이스가 있을 때 IP 선택을 위한 우선 순위 순서의 쉼표로 구분된 접두사", + "proxmoxAutoSync": "게스트 자동 동기화", + "proxmoxAutoSyncDesc": "세션이 잠금 해제되어 있을 때 주기적으로 이 Proxmox 노드를 검색하고 가져온 게스트 호스트를 생성하거나 업데이트합니다.", + "proxmoxSyncInterval": "동기화 간격(분)", + "proxmoxSyncIntervalDesc": "최소 5분. 스케줄러는 잠긴 사용자 세션을 건너뜁니다.", + "proxmoxMarkMissing": "누락된 게스트 표시", + "proxmoxMarkMissingDesc": "이전에 가져온 게스트가 사라지면 삭제 대신 proxmox-missing 태그를 추가합니다.", + "proxmoxLastSync": "마지막 동기화", + "proxmoxLastSyncNever": "아직 동기화되지 않음", + "proxmoxLastSyncNoResult": "결과 세부 정보 없음", + "proxmoxLastSyncSummary": "생성 {{created}}개, 업데이트 {{updated}}개, 누락 {{markedMissing}}개, 건너뜀 {{skipped}}개", + "proxmoxLastSyncStatus": { + "error": "실패", + "pending": "보류 중" + }, + "proxmoxDiscoverAction": "Proxmox 게스트 검색 및 가져오기", + "proxmoxImportTitle": "Proxmox에서 가져오기", + "proxmoxSelectHost": "Proxmox 호스트 선택…", + "proxmoxDiscover": "검색", + "proxmoxDiscovering": "검색 중…", + "proxmoxDiscoverGuests": "게스트 검색", + "proxmoxSelectAll": "전체 선택", + "proxmoxDeselectAll": "전체 선택 취소", + "proxmoxNoGuests": "이 Proxmox 노드에서 게스트를 찾을 수 없습니다.", + "proxmoxResultImported": "{{count}}개 가져옴", + "proxmoxResultUpdated": "{{count}}개 업데이트됨", + "proxmoxResultFailed": "{{count}}개 실패", + "proxmoxImportComplete": "Proxmox 가져오기 완료: {{summary}}", + "proxmoxDiscoveryFailed": "검색 실패", + "proxmoxImportFailed": "가져오기 실패" + } +} diff --git a/plugins/proxmox/locales/translated/nl_NL.json b/plugins/proxmox/locales/translated/nl_NL.json new file mode 100644 index 000000000..8fa41ff6f --- /dev/null +++ b/plugins/proxmox/locales/translated/nl_NL.json @@ -0,0 +1,53 @@ +{ + "hosts": { + "tabProxmox": "Proxmox", + "authTypeStepca": "Stap CA", + "proxmoxIntegration": "Proxmox-integratie", + "enableProxmox": "Proxmox inschakelen", + "enableProxmoxDesc": "Markeer deze host als een Proxmox-node. Dit maakt het mogelijk om virtuele machines direct vanaf deze host te detecteren en te importeren.", + "proxmoxDefaultAuthType": "Standaard authenticatietype", + "proxmoxDefaultAuthTypeDesc": "Authenticatiemethode toegepast op geïmporteerde gasthosts. Kies het authenticatietype dat overeenkomt met de manier waarop u verbinding maakt met uw gasten.", + "authTypePassword": "Wachtwoord", + "authTypeKey": "SSH-sleutel", + "authTypeCredential": "Referentie", + "authTypeOpkssh": "OPKSSH", + "authTypeNone": "Geen", + "proxmoxDefaultCredential": "Standaard inloggegevens", + "proxmoxDefaultCredentialDesc": "De inloggegevens die worden gebruikt voor geïmporteerde gasthosts wanneer het authenticatietype is ingesteld op 'Inloggegevens'.", + "proxmoxWindowsDetection": "Windows-/RDP-detectie", + "proxmoxWindowsDetectionDesc": "Door komma's gescheiden naampatronen die RDP in plaats van SSH activeren (hoofdlettergevoeligheid speelt geen rol).", + "proxmoxDockerDetection": "Docker-detectie", + "proxmoxDockerDetectionDesc": "Door komma's gescheiden naampatronen waarmee Docker gastsystemen kan herkennen.", + "proxmoxPreferredRanges": "Voorkeurs-IP-bereiken", + "proxmoxPreferredRangesDesc": "Door komma's gescheiden voorvoegsels in prioriteitsvolgorde voor IP-selectie wanneer een gast meerdere interfaces heeft.", + "proxmoxAutoSync": "Automatische synchronisatie van gasten", + "proxmoxAutoSyncDesc": "Ontdek periodiek dit Proxmox-knooppunt en maak of update geïmporteerde gasthosts terwijl uw sessie ontgrendeld is.", + "proxmoxSyncInterval": "Synchronisatie-interval (minuten)", + "proxmoxSyncIntervalDesc": "Minimaal 5 minuten. De planner slaat vergrendelde gebruikerssessies over.", + "proxmoxMarkMissing": "Markeer ontbrekende gasten", + "proxmoxMarkMissingDesc": "Voeg een 'proxmox-missing'-tag toe wanneer een eerder geïmporteerde gast verdwijnt, in plaats van deze te verwijderen.", + "proxmoxLastSync": "Laatste synchronisatie", + "proxmoxLastSyncNever": "Nog niet gesynchroniseerd", + "proxmoxLastSyncNoResult": "Geen resultaatdetails", + "proxmoxLastSyncSummary": "{{created}} aangemaakt, {{updated}} bijgewerkt, {{markedMissing}} ontbreekt, {{skipped}} overgeslagen", + "proxmoxLastSyncStatus": { + "error": "Mislukt", + "pending": "In behandeling" + }, + "proxmoxDiscoverAction": "Ontdek en importeer Proxmox-gasten", + "proxmoxImportTitle": "Importeren vanuit Proxmox", + "proxmoxSelectHost": "Selecteer een Proxmox-host…", + "proxmoxDiscover": "Ontdekken", + "proxmoxDiscovering": "Ontdekken…", + "proxmoxDiscoverGuests": "Ontdek gasten", + "proxmoxSelectAll": "Alles selecteren", + "proxmoxDeselectAll": "Alles deselecteren", + "proxmoxNoGuests": "Er zijn geen gasten gevonden op dit Proxmox-knooppunt.", + "proxmoxResultImported": "{{count}} geïmporteerd", + "proxmoxResultUpdated": "{{count}} bijgewerkt", + "proxmoxResultFailed": "{{count}} mislukt", + "proxmoxImportComplete": "Proxmox-import voltooid: {{summary}}", + "proxmoxDiscoveryFailed": "Ontdekking mislukt", + "proxmoxImportFailed": "Importeren mislukt" + } +} diff --git a/plugins/proxmox/locales/translated/no_NO.json b/plugins/proxmox/locales/translated/no_NO.json new file mode 100644 index 000000000..1c16574f3 --- /dev/null +++ b/plugins/proxmox/locales/translated/no_NO.json @@ -0,0 +1,53 @@ +{ + "hosts": { + "tabProxmox": "Proxmox", + "authTypeStepca": "Trinn CA", + "proxmoxIntegration": "Proxmox-integrasjon", + "enableProxmox": "Aktiver Proxmox", + "enableProxmoxDesc": "Merk denne verten som en Proxmox-node. Aktiverer gjesteoppdagelse og import direkte fra denne verten.", + "proxmoxDefaultAuthType": "Standard autentiseringstype", + "proxmoxDefaultAuthTypeDesc": "Autentiseringsmetode brukt på importerte gjesteverter. Velg autentiseringstypen som samsvarer med hvordan du kobler til gjestene dine.", + "authTypePassword": "Passord", + "authTypeKey": "SSH-nøkkel", + "authTypeCredential": "Legitimasjon", + "authTypeOpkssh": "OPKSSH", + "authTypeNone": "Ingen", + "proxmoxDefaultCredential": "Standard legitimasjon", + "proxmoxDefaultCredentialDesc": "Legitimasjon som brukes for importerte gjesteverter når godkjenningstypen er satt til Legitimasjon.", + "proxmoxWindowsDetection": "Windows / RDP-deteksjon", + "proxmoxWindowsDetectionDesc": "Kommaseparerte navnemønstre som utløser RDP i stedet for SSH (ikke-skillende mellom store og små bokstaver)", + "proxmoxDockerDetection": "Docker-deteksjon", + "proxmoxDockerDetectionDesc": "Kommaseparerte navnemønstre som gjør det mulig for Docker å matche gjester", + "proxmoxPreferredRanges": "Foretrukne IP-områder", + "proxmoxPreferredRangesDesc": "Kommaseparerte prefikser i prioritert rekkefølge for IP-valg når en gjest har flere grensesnitt", + "proxmoxAutoSync": "Automatisk synkronisering av gjester", + "proxmoxAutoSyncDesc": "Oppdag denne Proxmox-noden med jevne mellomrom og opprett eller oppdater importerte gjesteverter mens økten din er ulåst.", + "proxmoxSyncInterval": "Synkroniseringsintervall (minutter)", + "proxmoxSyncIntervalDesc": "Minimum 5 minutter. Planleggeren hopper over låste brukerøkter.", + "proxmoxMarkMissing": "Merk manglende gjester", + "proxmoxMarkMissingDesc": "Legg til en proxmox-missing-tag når en tidligere importert gjest forsvinner i stedet for å slette den.", + "proxmoxLastSync": "Siste synkronisering", + "proxmoxLastSyncNever": "Ikke synkronisert ennå", + "proxmoxLastSyncNoResult": "Ingen resultatdetaljer", + "proxmoxLastSyncSummary": "{{created}} opprettet, {{updated}} oppdatert, {{markedMissing}} mangler, {{skipped}} hoppet over", + "proxmoxLastSyncStatus": { + "error": "Mislyktes", + "pending": "I påvente av" + }, + "proxmoxDiscoverAction": "Oppdag og importer Proxmox-gjester", + "proxmoxImportTitle": "Importer fra Proxmox", + "proxmoxSelectHost": "Velg en Proxmox-vert…", + "proxmoxDiscover": "Oppdage", + "proxmoxDiscovering": "Oppdager…", + "proxmoxDiscoverGuests": "Oppdag gjester", + "proxmoxSelectAll": "Velg alle", + "proxmoxDeselectAll": "Fjern merkingen av alt", + "proxmoxNoGuests": "Ingen gjester funnet på denne Proxmox-noden.", + "proxmoxResultImported": "{{count}} importert", + "proxmoxResultUpdated": "{{count}} oppdatert", + "proxmoxResultFailed": "{{count}} mislyktes", + "proxmoxImportComplete": "Proxmox-import fullført: {{summary}}", + "proxmoxDiscoveryFailed": "Oppdagelsen mislyktes", + "proxmoxImportFailed": "Importen mislyktes" + } +} diff --git a/plugins/proxmox/locales/translated/pl_PL.json b/plugins/proxmox/locales/translated/pl_PL.json new file mode 100644 index 000000000..7fe830de8 --- /dev/null +++ b/plugins/proxmox/locales/translated/pl_PL.json @@ -0,0 +1,53 @@ +{ + "hosts": { + "tabProxmox": "Proxmox", + "authTypeStepca": "Krok CA", + "proxmoxIntegration": "Integracja Proxmox", + "enableProxmox": "Włącz Proxmox", + "enableProxmoxDesc": "Oznacz ten host jako węzeł Proxmox. Umożliwia wykrywanie gości i importowanie bezpośrednio z tego hosta.", + "proxmoxDefaultAuthType": "Domyślny typ uwierzytelniania", + "proxmoxDefaultAuthTypeDesc": "Metoda uwierzytelniania stosowana do importowanych hostów gościnnych. Wybierz typ uwierzytelniania odpowiadający sposobowi, w jaki łączysz się z gośćmi.", + "authTypePassword": "Hasło", + "authTypeKey": "Klucz SSH", + "authTypeCredential": "Poświadczenie", + "authTypeOpkssh": "OPKSSH", + "authTypeNone": "Brak", + "proxmoxDefaultCredential": "Domyślne poświadczenie", + "proxmoxDefaultCredentialDesc": "Poświadczenie używane dla importowanych hostów gości, gdy typ uwierzytelniania to Poświadczenie.", + "proxmoxWindowsDetection": "Wykrywanie systemu Windows/RDP", + "proxmoxWindowsDetectionDesc": "Wzorce nazw rozdzielone przecinkami, które wyzwalają protokół RDP zamiast protokołu SSH (bez uwzględniania wielkości liter)", + "proxmoxDockerDetection": "Wykrywanie Dockera", + "proxmoxDockerDetectionDesc": "Wzorce nazw rozdzielone przecinkami, które włączają Docker dla pasujących gości", + "proxmoxPreferredRanges": "Preferowane zakresy adresów IP", + "proxmoxPreferredRangesDesc": "Prefiksy rozdzielone przecinkami w kolejności priorytetów wyboru adresu IP, gdy gość ma wiele interfejsów", + "proxmoxAutoSync": "Automatyczna synchronizacja gości", + "proxmoxAutoSyncDesc": "Okresowo wykrywaj ten węzeł Proxmox i twórz lub aktualizuj importowane hosty gości, dopóki Twoja sesja jest odblokowana.", + "proxmoxSyncInterval": "Interwał synchronizacji (minuty)", + "proxmoxSyncIntervalDesc": "Minimum 5 minut. Harmonogram pomija zablokowane sesje użytkowników.", + "proxmoxMarkMissing": "Oznacz brakujących gości", + "proxmoxMarkMissingDesc": "Dodaj tag proxmox-missing, gdy wcześniej zaimportowany gość zniknie, zamiast go usuwać.", + "proxmoxLastSync": "Ostatnia synchronizacja", + "proxmoxLastSyncNever": "Jeszcze nie zsynchronizowano", + "proxmoxLastSyncNoResult": "Brak szczegółów wyników", + "proxmoxLastSyncSummary": "utworzono {{created}}, zaktualizowano {{updated}}, brakujących {{markedMissing}}, pominięto {{skipped}}", + "proxmoxLastSyncStatus": { + "error": "Niepowodzenie", + "pending": "Oczekuje" + }, + "proxmoxDiscoverAction": "Wykryj i zaimportuj gości Proxmox", + "proxmoxImportTitle": "Import z Proxmox", + "proxmoxSelectHost": "Wybierz hosta Proxmox…", + "proxmoxDiscover": "Wykryj", + "proxmoxDiscovering": "Wykrywanie…", + "proxmoxDiscoverGuests": "Wykryj gości", + "proxmoxSelectAll": "Zaznacz wszystko", + "proxmoxDeselectAll": "Odznacz wszystko", + "proxmoxNoGuests": "Nie znaleziono gości na tym węźle Proxmox.", + "proxmoxResultImported": "{{count}} zaimportowano", + "proxmoxResultUpdated": "{{count}} zaktualizowano", + "proxmoxResultFailed": "{{count}} nie powiodło się", + "proxmoxImportComplete": "Zakończono importowanie Proxmox: {{summary}}", + "proxmoxDiscoveryFailed": "Wykrywanie nie powiodło się", + "proxmoxImportFailed": "Import nie powiódł się" + } +} diff --git a/plugins/proxmox/locales/translated/pt_BR.json b/plugins/proxmox/locales/translated/pt_BR.json new file mode 100644 index 000000000..b41db3204 --- /dev/null +++ b/plugins/proxmox/locales/translated/pt_BR.json @@ -0,0 +1,53 @@ +{ + "hosts": { + "tabProxmox": "Proxmox", + "authTypeStepca": "Etapa CA", + "proxmoxIntegration": "Integração Proxmox", + "enableProxmox": "Ativar Proxmox", + "enableProxmoxDesc": "Marque este host como um nó Proxmox. Isso permite a descoberta e importação de máquinas virtuais diretamente deste host.", + "proxmoxDefaultAuthType": "Tipo de autenticação padrão", + "proxmoxDefaultAuthTypeDesc": "Método de autenticação aplicado aos hosts convidados importados. Escolha o tipo de autenticação que corresponde à forma como você se conecta aos seus convidados.", + "authTypePassword": "Senha", + "authTypeKey": "Chave SSH", + "authTypeCredential": "Credencial", + "authTypeOpkssh": "OPKSSH", + "authTypeNone": "Nenhum", + "proxmoxDefaultCredential": "Credencial padrão", + "proxmoxDefaultCredentialDesc": "Credencial usada para hosts convidados importados quando o tipo de autenticação está definido como Credencial.", + "proxmoxWindowsDetection": "Detecção de Windows/RDP", + "proxmoxWindowsDetectionDesc": "Padrões de nomes separados por vírgulas que acionam o RDP em vez do SSH (sem distinção entre maiúsculas e minúsculas)", + "proxmoxDockerDetection": "Detecção de Docker", + "proxmoxDockerDetectionDesc": "Padrões de nomes separados por vírgulas que permitem ao Docker identificar máquinas virtuais.", + "proxmoxPreferredRanges": "Faixas de IP preferenciais", + "proxmoxPreferredRangesDesc": "Prefixos separados por vírgula em ordem de prioridade para seleção de IP quando um convidado possui múltiplas interfaces.", + "proxmoxAutoSync": "Sincronização automática de convidados", + "proxmoxAutoSyncDesc": "Descubra periodicamente este nó Proxmox e crie ou atualize hosts convidados importados enquanto sua sessão estiver desbloqueada.", + "proxmoxSyncInterval": "Intervalo de sincronização (minutos)", + "proxmoxSyncIntervalDesc": "Tempo mínimo de 5 minutos. O agendador ignora sessões de usuário bloqueadas.", + "proxmoxMarkMissing": "Marque os hóspedes ausentes", + "proxmoxMarkMissingDesc": "Adicione a tag proxmox-missing quando uma máquina virtual previamente importada desaparecer, em vez de excluí-la.", + "proxmoxLastSync": "Última sincronização", + "proxmoxLastSyncNever": "Ainda não sincronizado", + "proxmoxLastSyncNoResult": "Nenhum detalhe do resultado", + "proxmoxLastSyncSummary": "{{created}} criado, {{updated}} atualizado, {{markedMissing}} ausente, {{skipped}} ignorado", + "proxmoxLastSyncStatus": { + "error": "Fracassado", + "pending": "Pendente" + }, + "proxmoxDiscoverAction": "Descubra e importe hóspedes do Proxmox", + "proxmoxImportTitle": "Importar do Proxmox", + "proxmoxSelectHost": "Selecione um host Proxmox…", + "proxmoxDiscover": "Descobrir", + "proxmoxDiscovering": "Descobrindo…", + "proxmoxDiscoverGuests": "Descubra os hóspedes", + "proxmoxSelectAll": "Selecionar tudo", + "proxmoxDeselectAll": "Desmarque tudo", + "proxmoxNoGuests": "Nenhum convidado encontrado neste nó Proxmox.", + "proxmoxResultImported": "{{count}} importado", + "proxmoxResultUpdated": "{{count}} atualizado", + "proxmoxResultFailed": "{{count}} falhou", + "proxmoxImportComplete": "Importação do Proxmox concluída: {{summary}}", + "proxmoxDiscoveryFailed": "A descoberta falhou", + "proxmoxImportFailed": "A importação falhou" + } +} diff --git a/plugins/proxmox/locales/translated/pt_PT.json b/plugins/proxmox/locales/translated/pt_PT.json new file mode 100644 index 000000000..eb7cd4967 --- /dev/null +++ b/plugins/proxmox/locales/translated/pt_PT.json @@ -0,0 +1,53 @@ +{ + "hosts": { + "tabProxmox": "Proxmox", + "authTypeStepca": "Etapa CA", + "proxmoxIntegration": "Integração com Proxmox", + "enableProxmox": "Ativar Proxmox", + "enableProxmoxDesc": "Marcar este host como um nó Proxmox. Permite a descoberta e importação de convidados diretamente a partir deste host.", + "proxmoxDefaultAuthType": "Tipo de Autenticação Padrão", + "proxmoxDefaultAuthTypeDesc": "Método de autenticação aplicado aos hosts convidados importados. Escolha o tipo de autenticação que corresponde à forma como se liga aos seus convidados.", + "authTypePassword": "Palavra-passe", + "authTypeKey": "Chave SSH", + "authTypeCredential": "Credencial", + "authTypeOpkssh": "OPKSSH", + "authTypeNone": "Nenhum", + "proxmoxDefaultCredential": "Credencial padrão", + "proxmoxDefaultCredentialDesc": "Credencial usada para os convidados importados quando o tipo de autenticação é definido como Credencial.", + "proxmoxWindowsDetection": "Deteção de Windows / RDP", + "proxmoxWindowsDetectionDesc": "Padrões de nomes separados por vírgulas que acionam RDP em vez de SSH (sem distinção entre maiúsculas/minúsculas)", + "proxmoxDockerDetection": "Deteção de Docker", + "proxmoxDockerDetectionDesc": "Padrões de nomes separados por vírgulas que ativam o Docker nos convidados que correspondam.", + "proxmoxPreferredRanges": "Intervalos de IP preferenciais", + "proxmoxPreferredRangesDesc": "Prefixos separados por vírgulas em ordem de prioridade para seleção de IP quando um convidado tem várias interfaces.", + "proxmoxAutoSync": "Sincronização automática", + "proxmoxAutoSyncDesc": "Descobrir periodicamente este nó Proxmox e criar ou atualizar os convidados importados enquanto a sessão estiver desbloqueada.", + "proxmoxSyncInterval": "Intervalo de sincronização (minutos)", + "proxmoxSyncIntervalDesc": "Mínimo de 5 minutos. O agendador ignora sessões de utilizador bloqueadas.", + "proxmoxMarkMissing": "Marcar convidados em falta", + "proxmoxMarkMissingDesc": "Adicionar a etiqueta proxmox-missing quando um convidado previamente importado desaparecer, em vez de o eliminar.", + "proxmoxLastSync": "Última sincronização", + "proxmoxLastSyncNever": "Ainda não sincronizado", + "proxmoxLastSyncNoResult": "Sem detalhes do resultado", + "proxmoxLastSyncSummary": "{{created}} criados, {{updated}} atualizados, {{markedMissing}} em falta, {{skipped}} ignorados", + "proxmoxLastSyncStatus": { + "error": "Falhou", + "pending": "Pendente" + }, + "proxmoxDiscoverAction": "Descobrir e importar convidados", + "proxmoxImportTitle": "Importar do Proxmox", + "proxmoxSelectHost": "Selecionar um host Proxmox…", + "proxmoxDiscover": "Descobrir", + "proxmoxDiscovering": "A descobrir…", + "proxmoxDiscoverGuests": "Descobrir convidados", + "proxmoxSelectAll": "Selecionar todos", + "proxmoxDeselectAll": "Desmarcar todos", + "proxmoxNoGuests": "Nenhum convidado encontrado neste nó Proxmox.", + "proxmoxResultImported": "{{count}} importados", + "proxmoxResultUpdated": "{{count}} atualizados", + "proxmoxResultFailed": "{{count}} falhados", + "proxmoxImportComplete": "Importação Proxmox concluída: {{summary}}", + "proxmoxDiscoveryFailed": "Descoberta falhou", + "proxmoxImportFailed": "Importação falhou" + } +} diff --git a/plugins/proxmox/locales/translated/ro_RO.json b/plugins/proxmox/locales/translated/ro_RO.json new file mode 100644 index 000000000..497deb327 --- /dev/null +++ b/plugins/proxmox/locales/translated/ro_RO.json @@ -0,0 +1,53 @@ +{ + "hosts": { + "tabProxmox": "Proxmox", + "authTypeStepca": "Pasul CA", + "proxmoxIntegration": "Integrare Proxmox", + "enableProxmox": "Activează Proxmox", + "enableProxmoxDesc": "Marchează această gazdă ca nod Proxmox. Activează descoperirea și importul de informații de către oaspeți direct de pe această gazdă.", + "proxmoxDefaultAuthType": "Tip de autentificare implicit", + "proxmoxDefaultAuthTypeDesc": "Metoda de autentificare aplicată gazdelor invitate importate. Alegeți tipul de autentificare care corespunde modului în care vă conectați la invitați.", + "authTypePassword": "Parolă", + "authTypeKey": "Cheie SSH", + "authTypeCredential": "Acreditare", + "authTypeOpkssh": "OPKSSH", + "authTypeNone": "Nici unul", + "proxmoxDefaultCredential": "Acreditare implicită", + "proxmoxDefaultCredentialDesc": "Acreditare utilizată pentru gazdele invitate importate atunci când tipul de autentificare este setat la Acreditare.", + "proxmoxWindowsDetection": "Detectare Windows / RDP", + "proxmoxWindowsDetectionDesc": "Modele de nume separate prin virgulă care declanșează RDP în loc de SSH (fără sensibilitate la majuscule/minuscule)", + "proxmoxDockerDetection": "Detectarea Docker", + "proxmoxDockerDetectionDesc": "Modele de nume separate prin virgulă care activează Docker pentru invitații potriviți", + "proxmoxPreferredRanges": "Intervalele IP preferate", + "proxmoxPreferredRangesDesc": "Prefixe separate prin virgulă în ordinea priorității pentru selectarea adresei IP atunci când un oaspete are mai multe interfețe", + "proxmoxAutoSync": "Sincronizare automată a invitaților", + "proxmoxAutoSyncDesc": "Descoperiți periodic acest nod Proxmox și creați sau actualizați gazdele invitate importate în timp ce sesiunea este deblocată.", + "proxmoxSyncInterval": "Interval de sincronizare (minute)", + "proxmoxSyncIntervalDesc": "Minim 5 minute. Planificatorul omite sesiunile utilizatorilor blocate.", + "proxmoxMarkMissing": "Marchează oaspeții lipsă", + "proxmoxMarkMissingDesc": "Adăugați o etichetă proxmox-missing atunci când un invitat importat anterior dispare, în loc să îl ștergeți.", + "proxmoxLastSync": "Ultima sincronizare", + "proxmoxLastSyncNever": "Încă nesincronizat", + "proxmoxLastSyncNoResult": "Niciun detaliu al rezultatului", + "proxmoxLastSyncSummary": "{{created}} creat, {{updated}} actualizat, {{markedMissing}} lipsă, {{skipped}} omis", + "proxmoxLastSyncStatus": { + "error": "Eșuat", + "pending": "În așteptare" + }, + "proxmoxDiscoverAction": "Descoperiți și importați invitați Proxmox", + "proxmoxImportTitle": "Import din Proxmox", + "proxmoxSelectHost": "Selectați o gazdă Proxmox…", + "proxmoxDiscover": "Descoperi", + "proxmoxDiscovering": "Descoperind…", + "proxmoxDiscoverGuests": "Descoperă oaspeți", + "proxmoxSelectAll": "Selectați tot", + "proxmoxDeselectAll": "Deselectați tot", + "proxmoxNoGuests": "Nu s-au găsit invitați pe acest nod Proxmox.", + "proxmoxResultImported": "{{count}} importat", + "proxmoxResultUpdated": "{{count}} actualizat", + "proxmoxResultFailed": "{{count}} a eșuat", + "proxmoxImportComplete": "Import Proxmox finalizat: {{summary}}", + "proxmoxDiscoveryFailed": "Descoperirea a eșuat", + "proxmoxImportFailed": "Importul a eșuat" + } +} diff --git a/plugins/proxmox/locales/translated/ru_RU.json b/plugins/proxmox/locales/translated/ru_RU.json new file mode 100644 index 000000000..ca110d5ac --- /dev/null +++ b/plugins/proxmox/locales/translated/ru_RU.json @@ -0,0 +1,53 @@ +{ + "hosts": { + "tabProxmox": "Proxmox", + "authTypeStepca": "Шаг CA", + "proxmoxIntegration": "Интеграция Proxmox", + "enableProxmox": "Включить Proxmox", + "enableProxmoxDesc": "Пометить этот хост как узел Proxmox. Включает обнаружение и импорт гостевых систем непосредственно с этого хоста.", + "proxmoxDefaultAuthType": "Тип аутентификации по умолчанию", + "proxmoxDefaultAuthTypeDesc": "Метод аутентификации, применяемый к импортированным гостевым хостам. Выберите тип аутентификации, соответствующий способу подключения к гостевым хостам.", + "authTypePassword": "Пароль", + "authTypeKey": "SSH-ключ", + "authTypeCredential": "Учётные данные", + "authTypeOpkssh": "OPKSSH", + "authTypeNone": "Нет", + "proxmoxDefaultCredential": "Учётные данные по умолчанию", + "proxmoxDefaultCredentialDesc": "Учётные данные, используемые для импортированных гостевых хостов, когда в качестве типа аутентификации выбраны «Учётные данные».", + "proxmoxWindowsDetection": "Обнаружение Windows / RDP", + "proxmoxWindowsDetectionDesc": "Шаблоны имён через запятую, при совпадении с которыми используется RDP вместо SSH (без учёта регистра).", + "proxmoxDockerDetection": "Обнаружение Docker", + "proxmoxDockerDetectionDesc": "Шаблоны имён через запятую, при совпадении с которыми для гостя включается Docker.", + "proxmoxPreferredRanges": "Предпочтительные IP-диапазоны", + "proxmoxPreferredRangesDesc": "Список префиксов через запятую в порядке приоритета для выбора IP-адреса, если у гостя несколько интерфейсов.", + "proxmoxAutoSync": "Автосинхронизация гостей", + "proxmoxAutoSyncDesc": "Периодически обнаруживать этот узел Proxmox и создавать или обновлять импортированные гостевые хосты, пока ваш сеанс разблокирован.", + "proxmoxSyncInterval": "Интервал синхронизации (мин.)", + "proxmoxSyncIntervalDesc": "Минимум 5 минут. Планировщик пропускает заблокированные сеансы.", + "proxmoxMarkMissing": "Помечать отсутствующих гостей", + "proxmoxMarkMissingDesc": "Добавлять тег proxmox-missing, когда ранее импортированный гость исчезает, вместо его удаления.", + "proxmoxLastSync": "Последняя синхронизация", + "proxmoxLastSyncNever": "Не выполнялась", + "proxmoxLastSyncNoResult": "Нет сведений о результате", + "proxmoxLastSyncSummary": "{{created}} создано, {{updated}} обновлено, {{markedMissing}} отсутствует, {{skipped}} пропущено", + "proxmoxLastSyncStatus": { + "error": "Ошибка", + "pending": "Ожидание" + }, + "proxmoxDiscoverAction": "Обнаружить и импортировать гостей Proxmox", + "proxmoxImportTitle": "Импорт из Proxmox", + "proxmoxSelectHost": "Выберите хост Proxmox…", + "proxmoxDiscover": "Обнаружить", + "proxmoxDiscovering": "Обнаружение…", + "proxmoxDiscoverGuests": "Обнаружить гостей", + "proxmoxSelectAll": "Выбрать всё", + "proxmoxDeselectAll": "Снять выделение", + "proxmoxNoGuests": "На этом узле Proxmox гости не найдены.", + "proxmoxResultImported": "{{count}} импортировано", + "proxmoxResultUpdated": "{{count}} обновлено", + "proxmoxResultFailed": "{{count}} не удалось", + "proxmoxImportComplete": "Импорт Proxmox завершен: {{summary}}", + "proxmoxDiscoveryFailed": "Обнаружение не удалось", + "proxmoxImportFailed": "Импорт не удался" + } +} diff --git a/plugins/proxmox/locales/translated/sr_SP.json b/plugins/proxmox/locales/translated/sr_SP.json new file mode 100644 index 000000000..f1cad1637 --- /dev/null +++ b/plugins/proxmox/locales/translated/sr_SP.json @@ -0,0 +1,53 @@ +{ + "hosts": { + "tabProxmox": "Проксмокс", + "authTypeStepca": "Корак CA", + "proxmoxIntegration": "Интеграција са Proxmox-ом", + "enableProxmox": "Омогући Proxmox", + "enableProxmoxDesc": "Означи овај хост као Proxmox чвор. Омогућава откривање госта и увоз директно са овог хоста.", + "proxmoxDefaultAuthType": "Подразумевани тип овлашћења", + "proxmoxDefaultAuthTypeDesc": "Метод аутентификације примењен на увезене гостујуће хостове. Изаберите тип аутентификације који одговара начину на који се повезујете са гостима.", + "authTypePassword": "Лозинка", + "authTypeKey": "SSH кључ", + "authTypeCredential": "Акредитив", + "authTypeOpkssh": "ОПКШ", + "authTypeNone": "Ниједан", + "proxmoxDefaultCredential": "Подразумевани акредитив", + "proxmoxDefaultCredentialDesc": "Акредитив који се користи за увезене гостујуће хостове када је тип овлашћења подешен на Акредитив.", + "proxmoxWindowsDetection": "Детекција Windows-а / RDP-а", + "proxmoxWindowsDetectionDesc": "Обрасци имена раздвојени зарезима који покрећу RDP уместо SSH (не разликују велика и мала слова)", + "proxmoxDockerDetection": "Детекција Докера", + "proxmoxDockerDetectionDesc": "Обрасци имена одвојени зарезима који омогућавају Докеру да упари госте", + "proxmoxPreferredRanges": "Жељени IP опсези", + "proxmoxPreferredRangesDesc": "Префикси одвојени зарезима по редоследу приоритета за избор IP адресе када гост има више интерфејса", + "proxmoxAutoSync": "Аутоматска синхронизација гостију", + "proxmoxAutoSyncDesc": "Периодично откривајте овај Proxmox чвор и креирајте или ажурирајте увезене гостујуће хостове док је ваша сесија откључана.", + "proxmoxSyncInterval": "Интервал синхронизације (минути)", + "proxmoxSyncIntervalDesc": "Минимум 5 минута. Планер прескаче закључане корисничке сесије.", + "proxmoxMarkMissing": "Означи госте који недостају", + "proxmoxMarkMissingDesc": "Додајте ознаку proxmox-missing када претходно увезени гост нестане уместо да га избришете.", + "proxmoxLastSync": "Последња синхронизација", + "proxmoxLastSyncNever": "Још није синхронизовано", + "proxmoxLastSyncNoResult": "Нема детаља о резултатима", + "proxmoxLastSyncSummary": "{{created}} креирано, {{updated}} ажурирано, {{markedMissing}} недостаје, {{skipped}} прескочено", + "proxmoxLastSyncStatus": { + "error": "Неуспешно", + "pending": "На чекању" + }, + "proxmoxDiscoverAction": "Откријте и увезите госте Proxmox-а", + "proxmoxImportTitle": "Увоз из Proxmox-а", + "proxmoxSelectHost": "Изаберите Proxmox хост…", + "proxmoxDiscover": "Откријте", + "proxmoxDiscovering": "Откривање…", + "proxmoxDiscoverGuests": "Откријте госте", + "proxmoxSelectAll": "Изабери све", + "proxmoxDeselectAll": "Поништи избор свих", + "proxmoxNoGuests": "Није пронађен ниједан гост на овом Proxmox чвору.", + "proxmoxResultImported": "{{count}} увезено", + "proxmoxResultUpdated": "{{count}} ажурирано", + "proxmoxResultFailed": "{{count}} није успело", + "proxmoxImportComplete": "Увоз Proxmox-а завршен: {{summary}}", + "proxmoxDiscoveryFailed": "Откривање није успело", + "proxmoxImportFailed": "Увоз није успео" + } +} diff --git a/plugins/proxmox/locales/translated/sv_SE.json b/plugins/proxmox/locales/translated/sv_SE.json new file mode 100644 index 000000000..9fce0b3bd --- /dev/null +++ b/plugins/proxmox/locales/translated/sv_SE.json @@ -0,0 +1,53 @@ +{ + "hosts": { + "tabProxmox": "Proxmox", + "authTypeStepca": "Steg CA", + "proxmoxIntegration": "Proxmox-integration", + "enableProxmox": "Aktivera Proxmox", + "enableProxmoxDesc": "Markera denna värd som en Proxmox-nod. Aktiverar gästidentifiering och import direkt från denna värd.", + "proxmoxDefaultAuthType": "Standardautentiseringstyp", + "proxmoxDefaultAuthTypeDesc": "Autentiseringsmetod tillämpad på importerade gästvärdar. Välj den autentiseringstyp som matchar hur du ansluter till dina gäster.", + "authTypePassword": "Lösenord", + "authTypeKey": "SSH-nyckel", + "authTypeCredential": "Referenser", + "authTypeOpkssh": "OPKSSH", + "authTypeNone": "Ingen", + "proxmoxDefaultCredential": "Standardautentiseringsuppgifter", + "proxmoxDefaultCredentialDesc": "Autentiseringsuppgifter som används för importerade gästvärdar när autentiseringstypen är inställd på Autentiseringsuppgifter.", + "proxmoxWindowsDetection": "Windows/RDP-detektering", + "proxmoxWindowsDetectionDesc": "Kommaavgränsade namnmönster som utlöser RDP istället för SSH (skiftlägesobegränsande)", + "proxmoxDockerDetection": "Docker-detektering", + "proxmoxDockerDetectionDesc": "Kommaavgränsade namnmönster som gör det möjligt för Docker att matcha gäster", + "proxmoxPreferredRanges": "Föredragna IP-intervall", + "proxmoxPreferredRangesDesc": "Kommaavgränsade prefix i prioritetsordning för IP-val när en gäst har flera gränssnitt", + "proxmoxAutoSync": "Synkronisera gäster automatiskt", + "proxmoxAutoSyncDesc": "Upptäck regelbundet denna Proxmox-nod och skapa eller uppdatera importerade gästvärdar medan din session är upplåst.", + "proxmoxSyncInterval": "Synkroniseringsintervall (minuter)", + "proxmoxSyncIntervalDesc": "Minst 5 minuter. Schemaläggaren hoppar över låsta användarsessioner.", + "proxmoxMarkMissing": "Markera saknade gäster", + "proxmoxMarkMissingDesc": "Lägg till en proxmox-missing-tagg när en tidigare importerad gäst försvinner istället för att ta bort den.", + "proxmoxLastSync": "Senaste synkronisering", + "proxmoxLastSyncNever": "Inte synkroniserad än", + "proxmoxLastSyncNoResult": "Inga resultatdetaljer", + "proxmoxLastSyncSummary": "{{created}} skapad, {{updated}} uppdaterad, {{markedMissing}} saknas, {{skipped}} hoppad över", + "proxmoxLastSyncStatus": { + "error": "Misslyckades", + "pending": "I avvaktan på" + }, + "proxmoxDiscoverAction": "Upptäck och importera Proxmox-gäster", + "proxmoxImportTitle": "Importera från Proxmox", + "proxmoxSelectHost": "Välj en Proxmox-värd…", + "proxmoxDiscover": "Upptäcka", + "proxmoxDiscovering": "Upptäcker…", + "proxmoxDiscoverGuests": "Upptäck gäster", + "proxmoxSelectAll": "Markera alla", + "proxmoxDeselectAll": "Avmarkera alla", + "proxmoxNoGuests": "Inga gäster hittades på denna Proxmox-nod.", + "proxmoxResultImported": "{{count}} importerad", + "proxmoxResultUpdated": "{{count}} uppdaterad", + "proxmoxResultFailed": "{{count}} misslyckades", + "proxmoxImportComplete": "Proxmox-import klar: {{summary}}", + "proxmoxDiscoveryFailed": "Upptäckten misslyckades", + "proxmoxImportFailed": "Importen misslyckades" + } +} diff --git a/plugins/proxmox/locales/translated/th_TH.json b/plugins/proxmox/locales/translated/th_TH.json new file mode 100644 index 000000000..37705b929 --- /dev/null +++ b/plugins/proxmox/locales/translated/th_TH.json @@ -0,0 +1,53 @@ +{ + "hosts": { + "tabProxmox": "โปรกซ์ม็อกซ์", + "authTypeStepca": "ขั้นตอน CA", + "proxmoxIntegration": "การผสานรวม Proxmox", + "enableProxmox": "เปิดใช้งาน Proxmox", + "enableProxmoxDesc": "กำหนดให้โฮสต์นี้เป็นโหนด Proxmox เพื่อเปิดใช้งานการค้นหาและนำเข้าเครื่องเสมือนโดยตรงจากโฮสต์นี้", + "proxmoxDefaultAuthType": "ประเภทการตรวจสอบสิทธิ์เริ่มต้น", + "proxmoxDefaultAuthTypeDesc": "วิธีการตรวจสอบสิทธิ์ที่ใช้กับโฮสต์แขกที่นำเข้า เลือกประเภทการตรวจสอบสิทธิ์ที่ตรงกับวิธีการที่คุณเชื่อมต่อกับแขกของคุณ", + "authTypePassword": "รหัสผ่าน", + "authTypeKey": "คีย์ SSH", + "authTypeCredential": "ใบรับรอง", + "authTypeOpkssh": "โอพีเคเอสเอช", + "authTypeNone": "ไม่มี", + "proxmoxDefaultCredential": "ข้อมูลประจำตัวเริ่มต้น", + "proxmoxDefaultCredentialDesc": "ข้อมูลประจำตัวที่ใช้สำหรับโฮสต์แขกที่นำเข้าเมื่อตั้งค่าประเภทการตรวจสอบสิทธิ์เป็นข้อมูลประจำตัว (Credential)", + "proxmoxWindowsDetection": "การตรวจจับ Windows / RDP", + "proxmoxWindowsDetectionDesc": "รูปแบบชื่อที่คั่นด้วยเครื่องหมายจุลภาคซึ่งจะเรียกใช้งาน RDP แทน SSH (ไม่คำนึงถึงตัวพิมพ์ใหญ่เล็ก)", + "proxmoxDockerDetection": "การตรวจจับ Docker", + "proxmoxDockerDetectionDesc": "รูปแบบชื่อที่คั่นด้วยเครื่องหมายจุลภาค ซึ่งช่วยให้ Docker สามารถจับคู่กับเครื่องเสมือนได้", + "proxmoxPreferredRanges": "ช่วง IP ที่ต้องการ", + "proxmoxPreferredRangesDesc": "คำนำหน้า IP ที่คั่นด้วยเครื่องหมายจุลภาคเรียงตามลำดับความสำคัญสำหรับการเลือก IP เมื่อผู้ใช้งานมีอินเทอร์เฟซหลายตัว", + "proxmoxAutoSync": "ซิงค์ข้อมูลแขกโดยอัตโนมัติ", + "proxmoxAutoSyncDesc": "ตรวจสอบโหนด Proxmox นี้เป็นระยะ และสร้างหรืออัปเดตโฮสต์แขกที่นำเข้าในขณะที่เซสชันของคุณไม่ได้ล็อกอยู่", + "proxmoxSyncInterval": "ช่วงเวลาการซิงค์ (นาที)", + "proxmoxSyncIntervalDesc": "อย่างน้อย 5 นาที ระบบกำหนดเวลาจะข้ามเซสชันของผู้ใช้ที่ถูกล็อกไว้", + "proxmoxMarkMissing": "ทำเครื่องหมายแขกที่ขาดหายไป", + "proxmoxMarkMissingDesc": "เพิ่มแท็ก proxmox-missing เมื่อเครื่องเสมือนที่นำเข้าก่อนหน้านี้หายไป แทนที่จะลบออก", + "proxmoxLastSync": "การซิงค์ครั้งล่าสุด", + "proxmoxLastSyncNever": "ยังไม่ได้ซิงค์ข้อมูล", + "proxmoxLastSyncNoResult": "ไม่มีรายละเอียดผลลัพธ์", + "proxmoxLastSyncSummary": "{{created}} ถูกสร้างขึ้น, {{updated}} อัปเดตแล้ว, {{markedMissing}} หายไป, {{skipped}} ข้ามไป", + "proxmoxLastSyncStatus": { + "error": "ล้มเหลว", + "pending": "รอดำเนินการ" + }, + "proxmoxDiscoverAction": "ค้นหาและนำเข้าแขกของ Proxmox", + "proxmoxImportTitle": "นำเข้าจาก Proxmox", + "proxmoxSelectHost": "เลือกโฮสต์ Proxmox…", + "proxmoxDiscover": "ค้นพบ", + "proxmoxDiscovering": "การค้นพบ…", + "proxmoxDiscoverGuests": "ค้นพบแขก", + "proxmoxSelectAll": "เลือกทั้งหมด", + "proxmoxDeselectAll": "ยกเลิกการเลือกทั้งหมด", + "proxmoxNoGuests": "ไม่พบผู้ใช้งานในโหนด Proxmox นี้", + "proxmoxResultImported": "{{count}} นำเข้าแล้ว", + "proxmoxResultUpdated": "{{count}} อัปเดตแล้ว", + "proxmoxResultFailed": "{{count}} ล้มเหลว", + "proxmoxImportComplete": "การนำเข้า Proxmox เสร็จสมบูรณ์: {{summary}}", + "proxmoxDiscoveryFailed": "การค้นพบล้มเหลว", + "proxmoxImportFailed": "การนำเข้าล้มเหลว" + } +} diff --git a/plugins/proxmox/locales/translated/tr_TR.json b/plugins/proxmox/locales/translated/tr_TR.json new file mode 100644 index 000000000..864db4232 --- /dev/null +++ b/plugins/proxmox/locales/translated/tr_TR.json @@ -0,0 +1,53 @@ +{ + "hosts": { + "tabProxmox": "Proxmox", + "authTypeStepca": "Adım CA", + "proxmoxIntegration": "Proxmox Entegrasyonu", + "enableProxmox": "Proxmox'u Etkinleştir", + "enableProxmoxDesc": "Bu ana bilgisayarı bir Proxmox düğümü olarak işaretle. Bu ana bilgisayardan doğrudan konuk keşfi ve içe aktarmayı etkinleştirir.", + "proxmoxDefaultAuthType": "Varsayılan Kimlik Doğrulama Türü", + "proxmoxDefaultAuthTypeDesc": "İçe aktarılan konuk ana bilgisayarlara uygulanan kimlik doğrulama yöntemi. Konuklarınıza nasıl bağlandığınıza uygun kimlik doğrulama türünü seçin.", + "authTypePassword": "Parola", + "authTypeKey": "SSH Anahtarı", + "authTypeCredential": "Kimlik Bilgisi", + "authTypeOpkssh": "OPKSSH", + "authTypeNone": "Yok", + "proxmoxDefaultCredential": "Varsayılan Kimlik Bilgisi", + "proxmoxDefaultCredentialDesc": "Kimlik doğrulama türü Kimlik Bilgisi olarak ayarlandığında içe aktarılan misafir ana makineleri için kullanılan kimlik bilgisi.", + "proxmoxWindowsDetection": "Windows / RDP algılama", + "proxmoxWindowsDetectionDesc": "SSH yerine RDP'yi tetikleyen virgülle ayrılmış ad desenleri (büyük/küçük harf duyarsız)", + "proxmoxDockerDetection": "Docker algılama", + "proxmoxDockerDetectionDesc": "Eşleşen misafirler için Docker'ı etkinleştiren virgülle ayrılmış ad desenleri", + "proxmoxPreferredRanges": "Tercih edilen IP aralıkları", + "proxmoxPreferredRangesDesc": "Bir misafirde birden fazla arayüz olduğunda IP seçimi için öncelik sırasına göre virgülle ayrılmış önekler", + "proxmoxAutoSync": "Misafirleri otomatik eşitle", + "proxmoxAutoSyncDesc": "Oturumunuz açıkken bu Proxmox düğümünü periyodik olarak keşfet ve içe aktarılan misafir ana makinelerini oluştur veya güncelle.", + "proxmoxSyncInterval": "Eşitleme aralığı (dakika)", + "proxmoxSyncIntervalDesc": "En az 5 dakika. Zamanlayıcı kilitli kullanıcı oturumlarını atlar.", + "proxmoxMarkMissing": "Kayıp misafirleri işaretle", + "proxmoxMarkMissingDesc": "Daha önce içe aktarılan bir misafir kaybolduğunda onu silmek yerine bir proxmox-missing etiketi ekle.", + "proxmoxLastSync": "Son eşitleme", + "proxmoxLastSyncNever": "Henüz eşitlenmedi", + "proxmoxLastSyncNoResult": "Sonuç detayı yok", + "proxmoxLastSyncSummary": "{{created}} oluşturuldu, {{updated}} güncellendi, {{markedMissing}} kayıp işaretlendi, {{skipped}} atlandı", + "proxmoxLastSyncStatus": { + "error": "Başarısız", + "pending": "Beklemede" + }, + "proxmoxDiscoverAction": "Proxmox misafirlerini keşfet ve içe aktar", + "proxmoxImportTitle": "Proxmox'tan içe aktar", + "proxmoxSelectHost": "Bir Proxmox ana makinesi seç…", + "proxmoxDiscover": "Keşfet", + "proxmoxDiscovering": "Keşfediliyor…", + "proxmoxDiscoverGuests": "Misafirleri keşfet", + "proxmoxSelectAll": "Tümünü seç", + "proxmoxDeselectAll": "Tüm seçimi kaldır", + "proxmoxNoGuests": "Bu Proxmox düğümünde hiç misafir bulunamadı.", + "proxmoxResultImported": "{{count}} içe aktarıldı", + "proxmoxResultUpdated": "{{count}} güncellendi", + "proxmoxResultFailed": "{{count}} başarısız", + "proxmoxImportComplete": "Proxmox içe aktarma tamamlandı: {{summary}}", + "proxmoxDiscoveryFailed": "Keşif başarısız", + "proxmoxImportFailed": "İçe aktarma başarısız" + } +} diff --git a/plugins/proxmox/locales/translated/uk_UA.json b/plugins/proxmox/locales/translated/uk_UA.json new file mode 100644 index 000000000..0705fdbc9 --- /dev/null +++ b/plugins/proxmox/locales/translated/uk_UA.json @@ -0,0 +1,53 @@ +{ + "hosts": { + "tabProxmox": "Проксмокс", + "authTypeStepca": "Крок CA", + "proxmoxIntegration": "Інтеграція з Proxmox", + "enableProxmox": "Увімкнути Proxmox", + "enableProxmoxDesc": "Позначити цей хост як вузол Proxmox. Дозволяє виявлення гостьових систем та імпорт безпосередньо з цього хоста.", + "proxmoxDefaultAuthType": "Тип автентифікації за замовчуванням", + "proxmoxDefaultAuthTypeDesc": "Метод автентифікації, застосований до імпортованих гостьових хостів. Виберіть тип автентифікації, який відповідає способу підключення до ваших гостей.", + "authTypePassword": "Пароль", + "authTypeKey": "SSH-ключ", + "authTypeCredential": "Посвідчення", + "authTypeOpkssh": "ОПКШ", + "authTypeNone": "Жоден", + "proxmoxDefaultCredential": "Облікові дані за замовчуванням", + "proxmoxDefaultCredentialDesc": "Облікові дані, що використовуються для імпортованих гостьових хостів, коли для типу автентифікації встановлено значення \"Облікові дані\".", + "proxmoxWindowsDetection": "Виявлення Windows / RDP", + "proxmoxWindowsDetectionDesc": "Шаблони імен, розділені комами, які запускають RDP замість SSH (без урахування регістру)", + "proxmoxDockerDetection": "Виявлення Docker", + "proxmoxDockerDetectionDesc": "Шаблони імен, розділені комами, що дозволяють Docker знаходити гостьові файли", + "proxmoxPreferredRanges": "Бажані діапазони IP-адрес", + "proxmoxPreferredRangesDesc": "Префікси, розділені комами, у порядку пріоритетності для вибору IP-адреси, коли гость має кілька інтерфейсів", + "proxmoxAutoSync": "Автоматична синхронізація гостей", + "proxmoxAutoSyncDesc": "Періодично виявляйте цей вузол Proxmox та створюйте або оновлюйте імпортовані гостьові хости, поки ваш сеанс розблоковано.", + "proxmoxSyncInterval": "Інтервал синхронізації (хвилини)", + "proxmoxSyncIntervalDesc": "Мінімум 5 хвилин. Планувальник пропускає заблоковані сеанси користувачів.", + "proxmoxMarkMissing": "Позначте відсутніх гостей", + "proxmoxMarkMissingDesc": "Додати тег proxmox-missing, коли раніше імпортований гостьовий сервер зникає, замість його видалення.", + "proxmoxLastSync": "Остання синхронізація", + "proxmoxLastSyncNever": "Ще не синхронізовано", + "proxmoxLastSyncNoResult": "Немає деталей результату", + "proxmoxLastSyncSummary": "{{created}} створено, {{updated}} оновлено, {{markedMissing}} відсутнє, {{skipped}} пропущено", + "proxmoxLastSyncStatus": { + "error": "Не вдалося", + "pending": "Очікує на розгляд" + }, + "proxmoxDiscoverAction": "Пошук та імпорт гостьових систем Proxmox", + "proxmoxImportTitle": "Імпорт з Proxmox", + "proxmoxSelectHost": "Виберіть хост Proxmox…", + "proxmoxDiscover": "Відкрийте", + "proxmoxDiscovering": "Відкриття…", + "proxmoxDiscoverGuests": "Відкрийте для себе гостей", + "proxmoxSelectAll": "Вибрати все", + "proxmoxDeselectAll": "Зняти вибір усіх", + "proxmoxNoGuests": "На цьому вузлі Proxmox не знайдено гостей.", + "proxmoxResultImported": "{{count}} імпортовано", + "proxmoxResultUpdated": "{{count}} оновлено", + "proxmoxResultFailed": "{{count}} не вдалося", + "proxmoxImportComplete": "Імпорт Proxmox завершено: {{summary}}", + "proxmoxDiscoveryFailed": "Не вдалося знайти", + "proxmoxImportFailed": "Імпорт не вдалося" + } +} diff --git a/plugins/proxmox/locales/translated/vi_VN.json b/plugins/proxmox/locales/translated/vi_VN.json new file mode 100644 index 000000000..c2ce5fb3f --- /dev/null +++ b/plugins/proxmox/locales/translated/vi_VN.json @@ -0,0 +1,53 @@ +{ + "hosts": { + "tabProxmox": "Proxmox", + "authTypeStepca": "Bước CA", + "proxmoxIntegration": "Tích hợp Proxmox", + "enableProxmox": "Bật Proxmox", + "enableProxmoxDesc": "Đánh dấu máy chủ này là một node Proxmox. Cho phép khám phá và nhập khách trực tiếp từ máy chủ này.", + "proxmoxDefaultAuthType": "Loại xác thực mặc định", + "proxmoxDefaultAuthTypeDesc": "Phương thức xác thực áp dụng cho các máy khách được nhập. Chọn loại xác thực phù hợp với cách bạn kết nối đến máy khách của mình.", + "authTypePassword": "Mật khẩu", + "authTypeKey": "Khóa SSH", + "authTypeCredential": "Thông tin xác thực", + "authTypeOpkssh": "OPKSSH", + "authTypeNone": "Không", + "proxmoxDefaultCredential": "Thông tin đăng nhập mặc định", + "proxmoxDefaultCredentialDesc": "Thông tin xác thực dùng cho máy khách được nhập khi phương thức xác thực là Credential.", + "proxmoxWindowsDetection": "Phát hiện Windows / RDP", + "proxmoxWindowsDetectionDesc": "Các mẫu tên cách nhau bằng dấu phẩy để kích hoạt RDP thay vì SSH (không phân biệt hoa thường).", + "proxmoxDockerDetection": "Phát hiện Docker", + "proxmoxDockerDetectionDesc": "Các mẫu tên cách nhau bằng dấu phẩy để bật Docker cho các máy khách phù hợp.", + "proxmoxPreferredRanges": "Dải IP ưu tiên", + "proxmoxPreferredRangesDesc": "Các tiền tố cách nhau bằng dấu phẩy theo thứ tự ưu tiên để chọn IP khi máy khách có nhiều giao diện mạng.", + "proxmoxAutoSync": "Tự động đồng bộ máy khách", + "proxmoxAutoSyncDesc": "Định kỳ khám phá nút Proxmox này và tạo hoặc cập nhật máy khách đã nhập khi phiên của bạn được mở khóa.", + "proxmoxSyncInterval": "Khoảng đồng bộ (phút)", + "proxmoxSyncIntervalDesc": "Tối thiểu 5 phút. Bộ lập lịch bỏ qua các phiên người dùng bị khóa.", + "proxmoxMarkMissing": "Đánh dấu máy khách bị thiếu", + "proxmoxMarkMissingDesc": "Thêm thẻ proxmox-missing khi máy khách đã nhập trước đó biến mất thay vì xóa nó.", + "proxmoxLastSync": "Lần đồng bộ cuối", + "proxmoxLastSyncNever": "Chưa đồng bộ", + "proxmoxLastSyncNoResult": "Không có chi tiết kết quả", + "proxmoxLastSyncSummary": "Đã tạo {{created}}, cập nhật {{updated}}, thiếu {{markedMissing}}, bỏ qua {{skipped}}", + "proxmoxLastSyncStatus": { + "error": "Thất bại", + "pending": "Đang chờ" + }, + "proxmoxDiscoverAction": "Khám phá và nhập máy khách Proxmox", + "proxmoxImportTitle": "Nhập từ Proxmox", + "proxmoxSelectHost": "Chọn máy chủ Proxmox…", + "proxmoxDiscover": "Khám phá", + "proxmoxDiscovering": "Đang khám phá…", + "proxmoxDiscoverGuests": "Khám phá máy khách", + "proxmoxSelectAll": "Chọn tất cả", + "proxmoxDeselectAll": "Bỏ chọn tất cả", + "proxmoxNoGuests": "Không tìm thấy máy khách nào trên nút Proxmox này.", + "proxmoxResultImported": "Đã nhập {{count}}", + "proxmoxResultUpdated": "Đã cập nhật {{count}}", + "proxmoxResultFailed": "{{count}} thất bại", + "proxmoxImportComplete": "Hoàn tất nhập từ Proxmox: {{summary}}", + "proxmoxDiscoveryFailed": "Khám phá thất bại", + "proxmoxImportFailed": "Nhập thất bại" + } +} diff --git a/plugins/proxmox/locales/translated/zh_CN.json b/plugins/proxmox/locales/translated/zh_CN.json new file mode 100644 index 000000000..98a55cdbb --- /dev/null +++ b/plugins/proxmox/locales/translated/zh_CN.json @@ -0,0 +1,53 @@ +{ + "hosts": { + "tabProxmox": "Proxmox", + "authTypeStepca": "步骤 CA", + "proxmoxIntegration": "Proxmox 集成", + "enableProxmox": "启用 Proxmox", + "enableProxmoxDesc": "将此主机标记为 Proxmox 节点。启用从此主机直接进行客户机发现和导入。", + "proxmoxDefaultAuthType": "默认认证类型", + "proxmoxDefaultAuthTypeDesc": "应用于导入的客户机主机的认证方法。选择与您连接客户机的方式相匹配的认证类型。", + "authTypePassword": "密码", + "authTypeKey": "SSH 密钥", + "authTypeCredential": "凭据", + "authTypeOpkssh": "OPKSSH", + "authTypeNone": "无", + "proxmoxDefaultCredential": "默认凭据", + "proxmoxDefaultCredentialDesc": "当认证类型设置为凭据时,用于导入的客户主机的凭据。", + "proxmoxWindowsDetection": "Windows / RDP 检测", + "proxmoxWindowsDetectionDesc": "逗号分隔的名称模式,匹配时触发 RDP 而非 SSH(不区分大小写)", + "proxmoxDockerDetection": "Docker 检测", + "proxmoxDockerDetectionDesc": "逗号分隔的名称模式,为匹配的客户主机启用 Docker", + "proxmoxPreferredRanges": "首选 IP 范围", + "proxmoxPreferredRangesDesc": "逗号分隔的前缀,按优先级顺序用于当客户主机有多个网络接口时的 IP 选择", + "proxmoxAutoSync": "自动同步客户主机", + "proxmoxAutoSyncDesc": "在会话未锁定时定期发现此 Proxmox 节点,并创建或更新导入的客户主机。", + "proxmoxSyncInterval": "同步间隔(分钟)", + "proxmoxSyncIntervalDesc": "最小 5 分钟。调度器会跳过已锁定的用户会话。", + "proxmoxMarkMissing": "标记缺失的客户主机", + "proxmoxMarkMissingDesc": "当之前导入的客户主机消失时,添加 proxmox-missing 标签,而非删除它。", + "proxmoxLastSync": "上次同步", + "proxmoxLastSyncNever": "尚未同步", + "proxmoxLastSyncNoResult": "无结果详情", + "proxmoxLastSyncSummary": "已创建 {{created}},已更新 {{updated}},已标记缺失 {{markedMissing}},已跳过 {{skipped}}", + "proxmoxLastSyncStatus": { + "error": "失败", + "pending": "待处理" + }, + "proxmoxDiscoverAction": "发现并导入 Proxmox 客户主机", + "proxmoxImportTitle": "从 Proxmox 导入", + "proxmoxSelectHost": "选择 Proxmox 主机…", + "proxmoxDiscover": "发现", + "proxmoxDiscovering": "正在发现…", + "proxmoxDiscoverGuests": "发现客户主机", + "proxmoxSelectAll": "全选", + "proxmoxDeselectAll": "取消全选", + "proxmoxNoGuests": "此 Proxmox 节点上未找到客户主机。", + "proxmoxResultImported": "已导入 {{count}} 个", + "proxmoxResultUpdated": "已更新 {{count}} 个", + "proxmoxResultFailed": "已失败 {{count}} 个", + "proxmoxImportComplete": "Proxmox 导入完成:{{summary}}", + "proxmoxDiscoveryFailed": "发现失败", + "proxmoxImportFailed": "导入失败" + } +} diff --git a/plugins/proxmox/locales/translated/zh_TW.json b/plugins/proxmox/locales/translated/zh_TW.json new file mode 100644 index 000000000..bf7506394 --- /dev/null +++ b/plugins/proxmox/locales/translated/zh_TW.json @@ -0,0 +1,53 @@ +{ + "hosts": { + "tabProxmox": "Proxmox", + "authTypeStepca": "步驟 CA", + "proxmoxIntegration": "Proxmox 整合", + "enableProxmox": "啟用 Proxmox", + "enableProxmoxDesc": "將此主機標記為 Proxmox 節點。啟用直接從此主機探索及匯入客體的功能。", + "proxmoxDefaultAuthType": "預設驗證類型", + "proxmoxDefaultAuthTypeDesc": "套用至匯入客體主機的驗證方法。選擇與您連線至客體的方式相符的驗證類型。", + "authTypePassword": "密碼", + "authTypeKey": "SSH 金鑰", + "authTypeCredential": "憑證", + "authTypeOpkssh": "OPKSSH", + "authTypeNone": "無", + "proxmoxDefaultCredential": "預設憑證", + "proxmoxDefaultCredentialDesc": "當驗證類型設為憑證時,用於已匯入之訪客主機的憑證。", + "proxmoxWindowsDetection": "Windows / RDP 偵測", + "proxmoxWindowsDetectionDesc": "逗號分隔的名稱模式,符合時將觸發 RDP 而非 SSH(不分大小寫)", + "proxmoxDockerDetection": "Docker 偵測", + "proxmoxDockerDetectionDesc": "逗號分隔的名稱模式,符合時將為對應的訪客主機啟用 Docker", + "proxmoxPreferredRanges": "偏好的 IP 範圍", + "proxmoxPreferredRangesDesc": "當訪客主機有多個網路介面時,以此逗號分隔的前綴清單依優先順序選取 IP", + "proxmoxAutoSync": "自動同步訪客主機", + "proxmoxAutoSyncDesc": "在您的工作階段解鎖時,定期探索此 Proxmox 節點並建立或更新已匯入的訪客主機。", + "proxmoxSyncInterval": "同步間隔(分鐘)", + "proxmoxSyncIntervalDesc": "最少 5 分鐘。排程器會略過鎖定的使用者工作階段。", + "proxmoxMarkMissing": "標記遺失的訪客主機", + "proxmoxMarkMissingDesc": "當先前匯入的訪客主機消失時,新增 proxmox-missing 標籤而非將其刪除。", + "proxmoxLastSync": "上次同步", + "proxmoxLastSyncNever": "尚未同步", + "proxmoxLastSyncNoResult": "無結果詳細資料", + "proxmoxLastSyncSummary": "建立 {{created}},更新 {{updated}},遺失 {{markedMissing}},略過 {{skipped}}", + "proxmoxLastSyncStatus": { + "error": "失敗", + "pending": "待處理" + }, + "proxmoxDiscoverAction": "探索並匯入 Proxmox 訪客主機", + "proxmoxImportTitle": "從 Proxmox 匯入", + "proxmoxSelectHost": "選取 Proxmox 主機…", + "proxmoxDiscover": "探索", + "proxmoxDiscovering": "探索中…", + "proxmoxDiscoverGuests": "探索訪客主機", + "proxmoxSelectAll": "全選", + "proxmoxDeselectAll": "取消全選", + "proxmoxNoGuests": "此 Proxmox 節點上找不到任何訪客主機。", + "proxmoxResultImported": "已匯入 {{count}} 台", + "proxmoxResultUpdated": "已更新 {{count}} 台", + "proxmoxResultFailed": "失敗 {{count}} 台", + "proxmoxImportComplete": "Proxmox 匯入完成:{{summary}}", + "proxmoxDiscoveryFailed": "探索失敗", + "proxmoxImportFailed": "匯入失敗" + } +} diff --git a/src/ui/sidebar/HostEditorFeatureTabs.tsx b/plugins/proxmox/src/frontend/HostProxmoxTab.tsx similarity index 53% rename from src/ui/sidebar/HostEditorFeatureTabs.tsx rename to plugins/proxmox/src/frontend/HostProxmoxTab.tsx index 1e09253d4..9b9777095 100644 --- a/src/ui/sidebar/HostEditorFeatureTabs.tsx +++ b/plugins/proxmox/src/frontend/HostProxmoxTab.tsx @@ -1,78 +1,17 @@ import { useEffect, useState } from "react"; -import { useTranslation } from "react-i18next"; -import { Box, FolderSearch, Server } from "lucide-react"; - +import { useTranslation } from "@termix/plugin-sdk/frontend"; +import { Server } from "lucide-react"; import { Input } from "@/components/input"; import { SectionCard, SettingRow, FakeSwitch } from "@/components/section-card"; import { getCredentials } from "@/main-axios"; -import type { HostEditorForm, HostProtocols } from "./HostEditorData"; +import type { HostEditorForm } from "@/sidebar/HostEditorData"; import { Select2 } from "@/components/select2"; -import { resolveConnectionOrigin } from "@/lib/connection-origin"; -import { HostEditorWebUiSection } from "./HostEditorWebUiSection"; type SetHostField = ( key: K, value: HostEditorForm[K], ) => void; -export function HostDockerTab({ - form, - setField, -}: { - form: HostEditorForm; - setField: SetHostField; -}) { - const { t } = useTranslation(); - const dockerConfig = form.dockerConfig ?? { runtime: "docker" as const }; - const runtime = - dockerConfig.runtime === "podman" - ? ("podman" as const) - : ("docker" as const); - - return ( - } - > -
- - setField("enableDocker", v)} - /> - - {form.enableDocker && ( - - - setField("dockerConfig", { - ...dockerConfig, - runtime: e.target.value as "docker" | "podman", - }) - } - className="h-7 w-44 text-xs border border-border bg-background px-2 outline-none focus:ring-1 focus:ring-ring" - > - - - - - )} -
-
- ); -} - export function HostProxmoxTab({ form, setField, @@ -321,180 +260,3 @@ export function HostProxmoxTab({ ); } - -export function HostProxmoxStatsTab({ - form, - setField, -}: { - form: HostEditorForm; - setField: SetHostField; -}) { - const { t } = useTranslation(); - - return ( - } - > -
- - setField("enableProxmoxStats", v)} - /> - - {form.enableProxmoxStats && ( - <> - - - setField("proxmoxStatsConfig", { - ...form.proxmoxStatsConfig, - pollInterval: Math.max( - 15, - Number.parseInt(e.target.value || "60", 10), - ), - }) - } - /> - - - - setField("proxmoxStatsConfig", { - ...form.proxmoxStatsConfig, - nodeName: e.target.value || null, - }) - } - /> - - - )} -
-
- ); -} - -export function HostFilesTab({ - form, - setField, -}: { - form: HostEditorForm; - setField: SetHostField; -}) { - const { t } = useTranslation(); - - return ( - } - > -
- - setField("enableFileManager", v)} - /> - - - setField("scpLegacy", v)} - /> - -
- - setField("defaultPath", e.target.value)} - /> - - {t("hosts.fileManagerPathHint")} - -
-
-
- ); -} - -/** - * Owns the async connection-origin resolution for the Web UI tab's tunnel - * gate, then hands the resolved boolean to the presentational section. - * - * tunnelAvailable = enableSsh && originIsLocal. Deliberately NOT gated on - * isElectron(): the forward binds wherever the backend runs, exactly as the - * server tunnels feature does, and a web deployment reaches it at the host - * serving Termix provided the endpoint opted out of a loopback bind. Gating - * this on the desktop would be stricter than the tunnels feature it mirrors. - * - * connectionType is passed as "ssh" deliberately: a tunnel endpoint always - * rides an SSH connection, and "ssh" keeps resolveConnectionOrigin out of its - * RDP/VNC/Telnet guacamole special case, which always resolves to "remote". - * - * The origin state lives here rather than in HostEditor.tsx, which is already - * ~2600 lines; this follows HostEditorGeneralTab's precedent of taking - * `protocols` as a prop and gating its own connection-origin control. - * - * Note the deliberate asymmetry with the sidebar: the sidebar entry appears on - * enableWebUi alone, because a direct endpoint needs no SSH -- but Web UI is - * an SSH sub-tab, so a host with SSH disabled cannot configure endpoints at - * all. That is the accepted behaviour, not an oversight. - */ -export function HostWebUiTab({ - form, - setField, - protocols, -}: { - form: HostEditorForm; - setField: SetHostField; - protocols: HostProtocols; -}) { - const [originIsLocal, setOriginIsLocal] = useState(false); - - useEffect(() => { - let cancelled = false; - void resolveConnectionOrigin({ - connectionType: "ssh", - connectionOrigin: form.connectionOrigin, - }).then((origin) => { - if (!cancelled) setOriginIsLocal(origin === "local"); - }); - return () => { - cancelled = true; - }; - }, [form.connectionOrigin]); - - return ( - void} - /> - ); -} diff --git a/plugins/proxmox/src/frontend/ProxmoxDiscoverDialog.tsx b/plugins/proxmox/src/frontend/ProxmoxDiscoverDialog.tsx index ae1a90ba3..27630e506 100644 --- a/plugins/proxmox/src/frontend/ProxmoxDiscoverDialog.tsx +++ b/plugins/proxmox/src/frontend/ProxmoxDiscoverDialog.tsx @@ -1,6 +1,6 @@ import { useRef, useState } from "react"; import type { HostData } from "@/types/index"; -import { useTranslation } from "react-i18next"; +import { useTranslation } from "@termix/plugin-sdk/frontend"; import { Server, RefreshCw, CheckSquare, Square, Download } from "lucide-react"; import { toast } from "sonner"; import { Button } from "@/components/button"; diff --git a/plugins/proxmox/src/frontend/index.mjs b/plugins/proxmox/src/frontend/index.mjs deleted file mode 100644 index 96fb45be4..000000000 --- a/plugins/proxmox/src/frontend/index.mjs +++ /dev/null @@ -1,44 +0,0 @@ -/** - * Frontend half of the proxmox plugin. - * - * Unlike ssh-terminal/docker, proxmox has no rail tab or standalone view — - * only a discovery dialog (opened imperatively from HostsPanel.tsx, not - * through a tab seam) and a host-editor settings tab. Registers the - * host-editor tab through the same registerHostEditorTab seam docker uses. - * - * HostProxmoxTab itself stays in src/ui/sidebar/HostEditorFeatureTabs.tsx - * rather than moving into this plugin: it takes the same {form, setField} - * pair every other host editor tab does, and those types (HostEditorForm, - * the setField signature) are core types HostEditor.tsx owns, the same - * reason ssh-terminal leaves session-manager.ts in core rather than copying - * it here. - * - * register() is called when the plugin is enabled, unregister() when it is - * disabled. As of this change neither is actually invoked anywhere yet -- - * see plugins/ssh-terminal/frontend/index.mjs and - * src/ui/tests/sidebar/plugin-extension-seam.test.tsx, which says outright - * "there is no plugin loader yet" for the frontend half. This file follows - * the same shape so it is ready the moment that loader exists. The dialog - * is reached today through a direct import in HostsPanel.tsx, not through - * this seam. - */ - -export const id = "proxmox"; -export const hostEditorTabId = "proxmox"; - -export async function register({ registerHostEditorTab, icons }) { - if (registerHostEditorTab) { - const { HostProxmoxTab } = - await import("../../../../src/ui/sidebar/HostEditorFeatureTabs.tsx"); - registerHostEditorTab({ - id: hostEditorTabId, - labelKey: "hosts.tabProxmox", - icon: icons.Server, - component: HostProxmoxTab, - }); - } -} - -export async function unregister({ unregisterHostEditorTab }) { - unregisterHostEditorTab?.(hostEditorTabId); -} diff --git a/plugins/proxmox/src/frontend/index.tsx b/plugins/proxmox/src/frontend/index.tsx new file mode 100644 index 000000000..a3df8cf3a --- /dev/null +++ b/plugins/proxmox/src/frontend/index.tsx @@ -0,0 +1,128 @@ +import { useEffect, useState, type ComponentType } from "react"; +import { Boxes, Server } from "lucide-react"; +import { + useHosts, + useTranslation, + type HostEditorSectionProps, + type TermixApp, +} from "@termix/plugin-sdk/frontend"; +import { ComponentSlot, DropdownMenuItem } from "@termix/plugin-sdk/ui"; +import type { SSHHostWithStatus } from "@/main-axios"; +import { ProxmoxDiscoverDialog } from "./ProxmoxDiscoverDialog"; +import { HostProxmoxTab } from "./HostProxmoxTab"; + +interface DiscoverRequest { + hostId?: number; + defaultCredentialId?: number | null; + defaultAuthType?: string; +} + +type Opener = (request: DiscoverRequest) => void; + +function ProxmoxHostSection({ form, setField }: HostEditorSectionProps) { + return ( + <> + [0]["setField"]} + /> + {/* Other plugins add Proxmox-related settings here (stats). */} + + + ); +} + +export function activate(app: TermixApp): void { + // The dialog lives in the hosts panel; the menu item and host action open + // it through this, created per activation. + const openers = new Set(); + const openDiscover: Opener = (request) => { + for (const open of openers) open(request); + }; + + function DiscoverDialogHost({ + hosts, + onHostsChanged, + }: { + hosts: SSHHostWithStatus[]; + onHostsChanged: (hosts: SSHHostWithStatus[]) => void; + }) { + const [request, setRequest] = useState(null); + useEffect(() => { + openers.add(setRequest); + return () => { + openers.delete(setRequest); + }; + }, []); + if (!request) return null; + return ( + setRequest(null)} + hosts={hosts} + onHostsChanged={onHostsChanged} + preselectedHostId={request.hostId} + defaultCredentialId={request.defaultCredentialId ?? null} + defaultAuthType={request.defaultAuthType} + /> + ); + } + + function ImportMenuItem() { + const { t } = useTranslation(); + const { hosts } = useHosts(); + return ( + openDiscover({})} + disabled={!hosts.some((host) => host.enableProxmox)} + > + + {t("hosts.proxmoxImportTitle")} + + ); + } + + app.registerSlotContribution("hosts.panel", { + actionId: "proxmox.discoverDialog", + titleKey: "hosts.proxmoxImportTitle", + kind: "component", + component: DiscoverDialogHost as unknown as ComponentType< + Record + >, + }); + + app.registerSlotContribution("hosts.importMenu", { + actionId: "proxmox.import", + titleKey: "hosts.proxmoxImportTitle", + kind: "component", + component: ImportMenuItem as ComponentType>, + }); + + app.registerHostAction({ + id: "proxmox-discover", + titleKey: "hosts.proxmoxDiscoverAction", + icon: Boxes, + kind: "open", + order: 90, + when: (host) => !!host.enableProxmox, + run: (host) => { + const config = host.proxmoxConfig as + | { defaultCredentialId?: number | null; defaultAuthType?: string } + | undefined; + openDiscover({ + hostId: Number(host.id), + defaultCredentialId: config?.defaultCredentialId ?? null, + defaultAuthType: config?.defaultAuthType ?? undefined, + }); + }, + }); + + app.registerHostEditorSection({ + id: "proxmox", + group: "ssh", + titleKey: "hosts.tabProxmox", + icon: Server, + order: 50, + component: ProxmoxHostSection, + }); +} diff --git a/plugins/proxmox/tests/frontend/activate.test.tsx b/plugins/proxmox/tests/frontend/activate.test.tsx new file mode 100644 index 000000000..814097280 --- /dev/null +++ b/plugins/proxmox/tests/frontend/activate.test.tsx @@ -0,0 +1,53 @@ +import { afterEach, describe, expect, it } from "vitest"; +import { + renderWithApp, + type RenderedPluginApp, +} from "@termix/plugin-sdk/testing"; +import type { PluginManifest } from "@termix/plugin-sdk/manifest"; +import * as plugin from "../../src/frontend/index"; +import manifestJson from "../../manifest.json"; +import locales from "../../locales/en.json"; + +const manifest = manifestJson as unknown as PluginManifest; + +const declared = (views?: Array<{ id: string }>) => + (views ?? []).map((view) => view.id).sort(); + +let rendered: RenderedPluginApp | null = null; + +afterEach(async () => { + await rendered?.deactivate(); + rendered = null; +}); + +describe(`${manifest.id} activate`, () => { + it("activates and registers only views its manifest declares", async () => { + rendered = await renderWithApp(plugin, { manifest, locales }); + const contributes = manifest.contributes as unknown as Record< + string, + Array<{ id: string }> | undefined + >; + const tabs = declared(contributes.tabs); + // A rail panel may reuse one of the plugin's tab ids. + const panels = [...declared(contributes.panels), ...tabs]; + const cards = declared(contributes.dashboardCards); + for (const id of rendered.registered.tabs()) expect(tabs).toContain(id); + for (const id of rendered.registered.panels()) expect(panels).toContain(id); + for (const id of rendered.registered.dashboardCards()) { + expect(cards).toContain(id); + } + }); + + it("removes everything it registered on deactivate", async () => { + const app = await renderWithApp(plugin, { manifest, locales }); + await app.deactivate(); + expect(app.registered.tabs()).toEqual([]); + expect(app.registered.panels()).toEqual([]); + expect(app.registered.railItems()).toEqual([]); + expect(app.registered.hostActions()).toEqual([]); + expect(app.registered.hostEditorSections()).toEqual([]); + expect(app.registered.dashboardCards()).toEqual([]); + expect(app.registered.settingsComponents()).toEqual([]); + expect(app.registered.actions()).toEqual([]); + }); +}); diff --git a/plugins/remote-desktop/locales/en.json b/plugins/remote-desktop/locales/en.json index 0967ef424..7caeafab0 100644 --- a/plugins/remote-desktop/locales/en.json +++ b/plugins/remote-desktop/locales/en.json @@ -1 +1,214 @@ -{} +{ + "remoteDesktop": { + "connecting": "Connecting to {{type}} session...", + "checkingGuacd": "Checking remote desktop service...", + "requestingToken": "Requesting {{type}} connection token...", + "openingSession": "Opening {{type}} session...", + "negotiating": "Negotiating {{type}} handshake...", + "sessionReady": "{{type}} session ready", + "connectionError": "Connection error", + "connectionFailed": "Connection failed", + "failedToConnect": "Failed to get connection token", + "hostNotFound": "Host not found", + "noHostSelected": "No host selected", + "reconnect": "Reconnect", + "retry": "Retry", + "guacdUnavailable": "Remote desktop service (guacd) is not available. Please ensure guacd is running and accessible and configured properly in admin settings.", + "credentialPromptTitle": "Enter RDP Credentials", + "credentialPromptDescription": "This host is set to prompt for credentials on connect. They are used for this session only and are not saved.", + "connect": "Connect", + "ctrlAltDel": "Ctrl+Alt+Del", + "files": { + "title": "Drive Files", + "parent": "Parent directory", + "refresh": "Refresh", + "empty": "This folder is empty", + "listFailed": "Failed to read this folder", + "download": "Download", + "downloadFailed": "Failed to download {{name}}", + "upload": "Upload files", + "uploading": "Uploading {{name}}...", + "uploaded": "Uploaded {{name}}", + "uploadFailed": "Failed to upload {{name}}", + "uploadDisabled": "Uploads are disabled for this connection", + "driveUnavailable": "Enable RDP drive redirection before uploading files", + "driveNotWritable": "guacd cannot write to the drive folder. Check GUACD_DRIVE_PATH (or the host's Drive Path) and its permissions.", + "dropToUpload": "Drop files to upload" + }, + "toolbar": { + "ctrlAltDel": "Ctrl+Alt+Del", + "winL": "Win+L (Lock Screen)", + "winKey": "Windows Key", + "superL": "Super+L (Lock Screen)", + "superKey": "Super Key", + "super": "Super", + "cmdL": "Cmd+L (Lock Screen)", + "cmdKey": "Command Key", + "cmd": "Cmd", + "ctrl": "Ctrl", + "alt": "Alt", + "shift": "Shift", + "win": "Win", + "stickyActive": "{{key}} (latched - click to release)", + "stickyInactive": "{{key}} (click to latch)", + "esc": "Escape", + "tab": "Tab", + "home": "Home", + "end": "End", + "pageUp": "Page Up", + "pageDown": "Page Down", + "arrowUp": "Arrow Up", + "arrowDown": "Arrow Down", + "arrowLeft": "Arrow Left", + "arrowRight": "Arrow Right", + "fnToggle": "Function Keys", + "reconnect": "Reconnect Session", + "collapse": "Collapse toolbar", + "expand": "Expand toolbar", + "dragHandle": "Drag to reposition", + "hide": "Hide for this session. To disable it permanently, open Host Settings → General → Connection Toolbar.", + "zoomIn": "Zoom in", + "zoomOut": "Zoom out", + "resetZoom": "Reset zoom", + "fitToScreen": "Fit to screen", + "switchToTrackpad": "Switch to trackpad mode (drag to move cursor, tap to click)", + "switchToTouch": "Switch to touch mode (tap directly where you want to click)" + } + }, + "hosts": { + "nativeRdpOpened": "Opened in Windows Remote Desktop", + "nativeRdpFailed": "Failed to open Windows Remote Desktop", + "openNativeRdp": "Open in Windows Remote Desktop", + "guac": { + "connection": "Connection", + "authentication": "Authentication", + "storedCredential": "Stored Credential", + "authMethod": "Auth Method", + "authTypeNoneDesc": "No credentials are stored. You'll be prompted for a username and password each time you connect; they are not saved.", + "selectCredential": "Select a credential...", + "connectionSettings": "Connection Settings", + "displaySettings": "Display Settings", + "audioSettings": "Audio Settings", + "rdpPerformance": "RDP Performance", + "deviceRedirection": "Device Redirection", + "session": "Session", + "gateway": "Gateway", + "remoteApp": "RemoteApp", + "clipboard": "Clipboard", + "sessionRecording": "Session Recording", + "wakeOnLan": "Wake-on-LAN", + "vncSettings": "VNC Settings", + "terminalSettings": "Terminal Settings", + "rdpPort": "RDP Port", + "username": "Username", + "password": "Password", + "passwordSaved": "Password saved, type to change", + "domain": "Domain", + "securityMode": "Security Mode", + "width": "Width", + "height": "Height", + "dpi": "DPI", + "clientName": "Client Name", + "initialProgram": "Initial Program", + "serverLayout": "Server Layout", + "timezone": "Timezone", + "loadBalanceInfo": "Load Balance Info / Cookie", + "loadBalanceInfoDesc": "RD Connection Broker cookie for RDS farm load balancing (e.g. tsv://MS Terminal Services Plugin.1.CollectionName)", + "guacdProxy": "guacd Proxy", + "guacdHostname": "guacd Host", + "guacdHostnamePlaceholder": "Global default", + "guacdPort": "guacd Port", + "guacdProxyDesc": "Override the global guacd instance for this connection. Leave blank to use the globally configured guacd.", + "gatewayHostname": "Gateway Hostname", + "gatewayPort": "Gateway Port", + "gatewayUsername": "Gateway Username", + "gatewayPassword": "Gateway Password", + "gatewayDomain": "Gateway Domain", + "remoteAppProgram": "RemoteApp Program", + "workingDirectory": "Working Directory", + "arguments": "Arguments", + "normalizeLineEndings": "Normalize Line Endings", + "macAddress": "MAC Address", + "broadcastAddress": "Broadcast Address", + "udpPort": "UDP Port", + "waitTimeS": "Wait Time (s)", + "driveName": "Drive Name", + "drivePath": "Drive Path", + "ignoreCertificate": "Ignore Certificate", + "ignoreCertificateDesc": "Allow connections to hosts with self-signed certificates", + "forceLossless": "Force Lossless", + "forceLosslessDesc": "Force lossless image encoding (higher quality, more bandwidth)", + "disableAudio": "Disable Audio", + "disableAudioDesc": "Mute all audio from the remote session", + "enableAudioInput": "Enable Audio Input (Microphone)", + "enableAudioInputDesc": "Forward local microphone to the remote session", + "wallpaper": "Wallpaper", + "wallpaperDesc": "Show desktop wallpaper (disabling improves performance)", + "theming": "Theming", + "themingDesc": "Enable visual themes and styles", + "fontSmoothing": "Font Smoothing", + "fontSmoothingDesc": "Enable ClearType font rendering", + "fullWindowDrag": "Full Window Drag", + "fullWindowDragDesc": "Show window contents while dragging", + "desktopComposition": "Desktop Composition", + "desktopCompositionDesc": "Enable Aero glass effects", + "menuAnimations": "Menu Animations", + "menuAnimationsDesc": "Enable menu fade and slide animations", + "disableBitmapCaching": "Disable Bitmap Caching", + "disableBitmapCachingDesc": "Turn off bitmap cache (may help with glitches)", + "disableOffscreenCaching": "Disable Offscreen Caching", + "disableOffscreenCachingDesc": "Turn off offscreen cache", + "disableGlyphCaching": "Disable Glyph Caching", + "disableGlyphCachingDesc": "Turn off glyph cache", + "enableGfx": "Enable GFX", + "enableGfxDesc": "Use RemoteFX graphics pipeline", + "enablePrinting": "Enable Printing", + "enablePrintingDesc": "Redirect local printers to the remote session", + "enableDriveRedirection": "Enable Drive Redirection", + "enableDriveRedirectionDesc": "Map a local folder as a drive in the remote session", + "createDrivePath": "Create Drive Path", + "createDrivePathDesc": "Automatically create the folder if it does not exist", + "disableDownload": "Disable Download", + "disableDownloadDesc": "Prevent downloading files from the remote session", + "disableUpload": "Disable Upload", + "disableUploadDesc": "Prevent uploading files to the remote session", + "enableTouch": "Enable Touch", + "enableTouchDesc": "Enable touch input forwarding", + "consoleSession": "Console Session", + "consoleSessionDesc": "Connect to the console (session 0) instead of a new session", + "sendWolPacket": "Send WOL Packet", + "sendWolPacketDesc": "Send a magic packet to wake this host before connecting", + "disableCopy": "Disable Copy", + "disableCopyDesc": "Prevent copying text from the remote session", + "disablePaste": "Disable Paste", + "disablePasteDesc": "Prevent pasting text into the remote session", + "createPathIfMissing": "Create Path if Missing", + "createPathIfMissingDesc": "Automatically create the recording directory", + "excludeOutput": "Exclude Output", + "excludeOutputDesc": "Do not record screen output (metadata only)", + "excludeMouse": "Exclude Mouse", + "excludeMouseDesc": "Do not record mouse movements", + "includeKeystrokes": "Include Keystrokes", + "includeKeystrokesDesc": "Record raw keystrokes in addition to screen output", + "vncPort": "VNC Port", + "vncPassword": "VNC Password", + "vncUsernameOptional": "Username (optional)", + "vncLeaveBlank": "Leave blank if not required", + "cursorMode": "Cursor Mode", + "swapRedBlue": "Swap Red/Blue", + "swapRedBlueDesc": "Swap the red and blue color channels (fixes some colour issues)", + "readOnly": "Read-only", + "readOnlyDesc": "View the remote screen without sending any input", + "telnetPort": "Telnet Port", + "terminalType": "Terminal Type", + "fontName": "Font Name", + "fontSize": "Font Size", + "colorScheme": "Color Scheme", + "backspaceKey": "Backspace Key" + } + }, + "onboarding": { + "feature_desktop": "Remote desktop", + "feature_desktop_desc": "Open RDP, VNC and Telnet sessions in a tab, same as SSH." + } +} diff --git a/plugins/remote-desktop/locales/translated/af_ZA.json b/plugins/remote-desktop/locales/translated/af_ZA.json new file mode 100644 index 000000000..b3229544d --- /dev/null +++ b/plugins/remote-desktop/locales/translated/af_ZA.json @@ -0,0 +1,214 @@ +{ + "remoteDesktop": { + "connecting": "Verbind met {{type}} sessie...", + "checkingGuacd": "Kontroleer tans afstandwerkskermdiens...", + "requestingToken": "Versoek tans {{type}} verbindingstoken...", + "openingSession": "Maak {{type}} sessie oop...", + "negotiating": "Onderhandel {{type}} handdruk...", + "sessionReady": "{{type}} sessie gereed", + "connectionError": "Verbindingsfout", + "connectionFailed": "Verbinding het misluk", + "failedToConnect": "Kon nie verbindingstoken kry nie", + "hostNotFound": "Gasheer nie gevind nie", + "noHostSelected": "Geen gasheer gekies nie", + "reconnect": "Herkoppel", + "retry": "Probeer weer", + "guacdUnavailable": "Diens vir afstandwerkskerm (guacd) is nie beskikbaar nie. Maak asseblief seker dat guacd loop, toeganklik is en behoorlik in administrateurinstellings gekonfigureer is.", + "credentialPromptTitle": "Voer RDP-aanbewyse in", + "credentialPromptDescription": "Hierdie gasheer is ingestel om vir geloofsbriewe te vra tydens verbinding. Hulle word slegs vir hierdie sessie gebruik en word nie gestoor nie.", + "connect": "Verbind", + "ctrlAltDel": "Ctrl+Alt+Del", + "files": { + "title": "Drive-lêers", + "parent": "Ouergids", + "refresh": "Verfris", + "empty": "Hierdie vouer is leeg", + "listFailed": "Kon nie hierdie vouer lees nie", + "download": "Laai af", + "downloadFailed": "Kon nie {{name}} aflaai nie", + "upload": "Laai lêers op", + "uploading": "Laai tans {{name}} op ...", + "uploaded": "Opgelaai {{name}}", + "uploadFailed": "Kon nie {{name}} oplaai nie", + "uploadDisabled": "Oplaaie is gedeaktiveer vir hierdie verbinding", + "driveUnavailable": "Aktiveer RDP-skyfherleiding voordat lêers opgelaai word", + "driveNotWritable": "guacd kan nie na die skyf se lêergids skryf nie. Kontroleer GUACD_DRIVE_PATH (of die gasheer se skyfpad) en sy toestemmings.", + "dropToUpload": "Laat lêers los om op te laai" + }, + "toolbar": { + "ctrlAltDel": "Ctrl+Alt+Del", + "winL": "Win+L (Sluitskerm)", + "winKey": "Windows-sleutel", + "superL": "Super+L (Sluitskerm)", + "superKey": "Supersleutel", + "super": "Super", + "cmdL": "Cmd+L (Sluitskerm)", + "cmdKey": "Opdragsleutel", + "cmd": "Cmd", + "ctrl": "Ctrl", + "alt": "Alt", + "shift": "Skof", + "win": "Wen", + "stickyActive": "{{key}} (vasgeklem - klik om los te maak)", + "stickyInactive": "{{key}} (klik om te sluit)", + "esc": "Ontsnapping", + "tab": "Oortjie", + "home": "Tuis", + "end": "Einde", + "pageUp": "Bladsy op", + "pageDown": "Bladsy af", + "arrowUp": "Pyltjie Op", + "arrowDown": "Pyltjie Af", + "arrowLeft": "Pyltjie links", + "arrowRight": "Pyltjie Regs", + "fnToggle": "Funksiesleutels", + "reconnect": "Herkoppel Sessie", + "collapse": "Vou nutsbalk in", + "expand": "Vou die nutsbalk uit", + "dragHandle": "Sleep om te herposisioneer", + "hide": "Versteek vir hierdie sessie. Om dit permanent te deaktiveer, maak Gasheerinstellings → Algemeen → Verbindingsnutsbalk oop.", + "zoomIn": "Zoem in", + "zoomOut": "Zoem uit", + "resetZoom": "Stel zoom terug", + "fitToScreen": "Pas by skerm", + "switchToTrackpad": "Skakel oor na raakvlakmodus (sleep om wyser te beweeg, tik om te klik)", + "switchToTouch": "Skakel oor na raakmodus (tik direk waar jy wil klik)" + } + }, + "hosts": { + "nativeRdpOpened": "Geopen in Windows Afstandslessenaar", + "nativeRdpFailed": "Kon nie Windows Remote Desktop oopmaak nie", + "openNativeRdp": "Maak oop in Windows Afstandslessenaar", + "guac": { + "connection": "Verbinding", + "authentication": "Verifikasie", + "storedCredential": "Gestoorde geloofsbriewe", + "authMethod": "Magtigingsmetode", + "authTypeNoneDesc": "Geen aanmeldingsbesonderhede word gestoor nie. Jy sal elke keer as jy koppel vir 'n gebruikersnaam en wagwoord gevra word; hulle word nie gestoor nie.", + "selectCredential": "Kies 'n geloofsbrief...", + "connectionSettings": "Verbindingsinstellings", + "displaySettings": "Skerminstellings", + "audioSettings": "Oudio-instellings", + "rdpPerformance": "RDP-prestasie", + "deviceRedirection": "Toestelherleiding", + "session": "Sessie", + "gateway": "Poort", + "remoteApp": "Afstandsprogram", + "clipboard": "Klembord", + "sessionRecording": "Sessie-opname", + "wakeOnLan": "Wake-on-LAN", + "vncSettings": "VNC-instellings", + "terminalSettings": "Terminaalinstellings", + "rdpPort": "RDP-poort", + "username": "Gebruikersnaam", + "password": "Wagwoord", + "passwordSaved": "Wagwoord gestoor, tik om te verander", + "domain": "Domein", + "securityMode": "Sekuriteitsmodus", + "width": "Breedte", + "height": "Hoogte", + "dpi": "DPI", + "clientName": "Kliëntnaam", + "initialProgram": "Aanvanklike Program", + "serverLayout": "Bedieneruitleg", + "timezone": "Tydsone", + "loadBalanceInfo": "Laaibalansinligting / Koekie", + "loadBalanceInfoDesc": "RD Connection Broker-koekie vir RDS-plaaslasbalansering (bv. tsv://MS Terminal Services Plugin.1.CollectionName)", + "guacdProxy": "guacd Proxy", + "guacdHostname": "guacd-gasheer", + "guacdHostnamePlaceholder": "Globale verstekwaarde", + "guacdPort": "guacd-hawe", + "guacdProxyDesc": "Ignoreer die globale guacd-instansie vir hierdie verbinding. Los leeg om die globaal gekonfigureerde guacd te gebruik.", + "gatewayHostname": "Gateway-gasheernaam", + "gatewayPort": "Poortpoort", + "gatewayUsername": "Gateway-gebruikersnaam", + "gatewayPassword": "Gateway-wagwoord", + "gatewayDomain": "Gateway-domein", + "remoteAppProgram": "RemoteApp-program", + "workingDirectory": "Werkgids", + "arguments": "Argumente", + "normalizeLineEndings": "Normaliseer Lyn Eindigings", + "macAddress": "MAC-adres", + "broadcastAddress": "Uitsaaiadres", + "udpPort": "UDP-poort", + "waitTimeS": "Wagtyd (s)", + "driveName": "Skyfnaam", + "drivePath": "Rypad", + "ignoreCertificate": "Ignoreer Sertifikaat", + "ignoreCertificateDesc": "Laat verbindings na gashere met selfgetekende sertifikate toe", + "forceLossless": "Forseer verliesloos", + "forceLosslessDesc": "Forseer verlieslose beeldkodering (hoër gehalte, meer bandwydte)", + "disableAudio": "Deaktiveer oudio", + "disableAudioDesc": "Demp alle klank van die afstandsessie", + "enableAudioInput": "Aktiveer oudio-invoer (mikrofoon)", + "enableAudioInputDesc": "Stuur plaaslike mikrofoon na die afgeleë sessie aan", + "wallpaper": "Agtergrond", + "wallpaperDesc": "Wys lessenaar agtergrond (deaktivering verbeter werkverrigting)", + "theming": "Temavorming", + "themingDesc": "Aktiveer visuele temas en style", + "fontSmoothing": "Lettertipe-gladmaak", + "fontSmoothingDesc": "Aktiveer ClearType-lettertipe-weergawe", + "fullWindowDrag": "Volle Venster Sleep", + "fullWindowDragDesc": "Wys vensterinhoud terwyl jy sleep", + "desktopComposition": "Komposisie op die lessenaar", + "desktopCompositionDesc": "Aktiveer Aero-glaseffekte", + "menuAnimations": "Menu Animasies", + "menuAnimationsDesc": "Aktiveer menu-vervaag- en skuifanimasies", + "disableBitmapCaching": "Deaktiveer Bitmap-kasgeheue", + "disableBitmapCachingDesc": "Skakel bitmap-kasgeheue af (kan help met foute)", + "disableOffscreenCaching": "Deaktiveer buiteskerm-kasgeheue", + "disableOffscreenCachingDesc": "Skakel buiteskerm-kasgeheue af", + "disableGlyphCaching": "Deaktiveer glifkasgeheue", + "disableGlyphCachingDesc": "Skakel glifkasgeheue af", + "enableGfx": "Aktiveer GFX", + "enableGfxDesc": "Gebruik RemoteFX grafiese pyplyn", + "enablePrinting": "Aktiveer drukwerk", + "enablePrintingDesc": "Herlei plaaslike drukkers na die afgeleë sessie", + "enableDriveRedirection": "Aktiveer dryfherleiding", + "enableDriveRedirectionDesc": "Karaktereer 'n plaaslike vouer as 'n skyf in die afstandsessie", + "createDrivePath": "Skep 'n rylaanpad", + "createDrivePathDesc": "Skep die lêer outomaties as dit nie bestaan nie", + "disableDownload": "Deaktiveer aflaai", + "disableDownloadDesc": "Voorkom die aflaai van lêers vanaf die afgeleë sessie", + "disableUpload": "Deaktiveer oplaai", + "disableUploadDesc": "Voorkom die oplaai van lêers na die afgeleë sessie", + "enableTouch": "Aktiveer Aanraking", + "enableTouchDesc": "Aktiveer aanstuur van raakinvoer", + "consoleSession": "Konsolesessie", + "consoleSessionDesc": "Koppel aan die konsole (sessie 0) in plaas van 'n nuwe sessie", + "sendWolPacket": "Stuur WOL-pakket", + "sendWolPacketDesc": "Stuur 'n magiese pakket om hierdie gasheer wakker te maak voordat jy verbind", + "disableCopy": "Deaktiveer Kopieer", + "disableCopyDesc": "Voorkom die kopiëring van teks vanaf die afgeleë sessie", + "disablePaste": "Deaktiveer plak", + "disablePasteDesc": "Voorkom die plak van teks in die afgeleë sessie", + "createPathIfMissing": "Skep pad indien ontbreek", + "createPathIfMissingDesc": "Skep outomaties die opnamegids", + "excludeOutput": "Sluit Uitvoer Uit", + "excludeOutputDesc": "Moenie skermuitvoer opneem nie (slegs metadata)", + "excludeMouse": "Sluit Muis uit", + "excludeMouseDesc": "Moenie muisbewegings opneem nie", + "includeKeystrokes": "Sluit toetsaanslagen in", + "includeKeystrokesDesc": "Neem rou toetsaanslagen op benewens skermuitvoer", + "vncPort": "VNC-poort", + "vncPassword": "VNC-wagwoord", + "vncUsernameOptional": "Gebruikersnaam (opsioneel)", + "vncLeaveBlank": "Los leeg indien nie nodig nie", + "cursorMode": "Wysermodus", + "swapRedBlue": "Ruil Rooi/Blou", + "swapRedBlueDesc": "Ruil die rooi en blou kleurkanale om (maak sommige kleurprobleme reg)", + "readOnly": "Leesalleen", + "readOnlyDesc": "Bekyk die afstandskerm sonder om enige insette te stuur", + "telnetPort": "Telnet-poort", + "terminalType": "Terminaaltipe", + "fontName": "Lettertipe Naam", + "fontSize": "Lettergrootte", + "colorScheme": "Kleurskema", + "backspaceKey": "Terugspasie-sleutel" + } + }, + "onboarding": { + "feature_desktop": "Afstandlessenaar", + "feature_desktop_desc": "Maak RDP-, VNC- en Telnet-sessies in 'n oortjie oop, dieselfde as SSH." + } +} diff --git a/plugins/remote-desktop/locales/translated/ar_SA.json b/plugins/remote-desktop/locales/translated/ar_SA.json new file mode 100644 index 000000000..2365cd9c8 --- /dev/null +++ b/plugins/remote-desktop/locales/translated/ar_SA.json @@ -0,0 +1,214 @@ +{ + "remoteDesktop": { + "connecting": "جارٍ الاتصال بجلسة {{type}}...", + "checkingGuacd": "جارٍ التحقق من خدمة سطح المكتب البعيد...", + "requestingToken": "طلب رمز اتصال {{type}}...", + "openingSession": "جارٍ فتح الجلسة {{type}}...", + "negotiating": "التفاوض على مصافحة {{type}}...", + "sessionReady": "{{type}} الجلسة جاهزة", + "connectionError": "خطأ في الاتصال", + "connectionFailed": "فشل الاتصال", + "failedToConnect": "فشل الحصول على رمز الاتصال", + "hostNotFound": "المضيف غير موجود", + "noHostSelected": "لم يتم اختيار مضيف", + "reconnect": "إعادة الاتصال", + "retry": "إعادة المحاولة", + "guacdUnavailable": "خدمة سطح المكتب البعيد (guacd) غير متاحة. يرجى التأكد من تشغيل guacd وإمكانية الوصول إليه وتكوينه بشكل صحيح في إعدادات المسؤول.", + "credentialPromptTitle": "أدخل بيانات اعتماد RDP", + "credentialPromptDescription": "تم ضبط هذا المضيف ليطلب بيانات الاعتماد عند الاتصال. تُستخدم هذه البيانات لهذه الجلسة فقط ولا يتم حفظها.", + "connect": "يتصل", + "ctrlAltDel": "Ctrl+Alt+Del", + "files": { + "title": "ملفات محرك الأقراص", + "parent": "الدليل الرئيسي", + "refresh": "ينعش", + "empty": "هذا المجلد فارغ", + "listFailed": "فشل في قراءة هذا المجلد", + "download": "تحميل", + "downloadFailed": "فشل تنزيل {{name}}", + "upload": "تحميل الملفات", + "uploading": "جارٍ التحميل {{name}}...", + "uploaded": "تم التحميل {{name}}", + "uploadFailed": "فشل تحميل {{name}}", + "uploadDisabled": "تم تعطيل التحميلات لهذا الاتصال", + "driveUnavailable": "قم بتمكين إعادة توجيه محرك الأقراص RDP قبل تحميل الملفات", + "driveNotWritable": "لا يستطيع برنامج guacd الكتابة إلى مجلد القرص. تحقق من مسار محرك الأقراص GUACD_DRIVE_PATH (أو مسار محرك الأقراص الخاص بالجهاز المضيف) وصلاحياته.", + "dropToUpload": "قم بإسقاط الملفات لتحميلها" + }, + "toolbar": { + "ctrlAltDel": "Ctrl+Alt+Del", + "winL": "Win+L (قفل الشاشة)", + "winKey": "مفتاح Windows", + "superL": "Super+L (شاشة القفل)", + "superKey": "مفتاح سوبر", + "super": "ممتاز", + "cmdL": "Cmd+L (قفل الشاشة)", + "cmdKey": "مفتاح الاختصار", + "cmd": "الأمر", + "ctrl": "Ctrl", + "alt": "Alt", + "shift": "Shift", + "win": "Win", + "stickyActive": "{{key}} (مثبت - انقر لتحرير)", + "stickyInactive": "{{key}} (انقر للتثبيت)", + "esc": "Escape", + "tab": "Tab", + "home": "Home", + "end": "End", + "pageUp": "Page Up", + "pageDown": "Page Down", + "arrowUp": "Arrow Up", + "arrowDown": "Arrow Down", + "arrowLeft": "Arrow Left", + "arrowRight": "Arrow Right", + "fnToggle": "مفاتيح الوظائف", + "reconnect": "إعادة الاتصال بالجلسة", + "collapse": "طي شريط الأدوات", + "expand": "توسيع شريط الأدوات", + "dragHandle": "اسحب لتغيير الموضع", + "hide": "إخفاء هذه الميزة لهذه الجلسة. لتعطيلها نهائياً، افتح إعدادات المضيف ← عام ← شريط أدوات الاتصال.", + "zoomIn": "تكبير الصورة", + "zoomOut": "تصغير العرض", + "resetZoom": "إعادة ضبط التكبير", + "fitToScreen": "مناسب للشاشة", + "switchToTrackpad": "قم بالتبديل إلى وضع لوحة اللمس (اسحب لتحريك المؤشر، انقر للنقر)", + "switchToTouch": "قم بالتبديل إلى وضع اللمس (انقر مباشرة في المكان الذي تريد النقر فيه)" + } + }, + "hosts": { + "nativeRdpOpened": "تم فتحه في سطح المكتب البعيد لنظام التشغيل Windows", + "nativeRdpFailed": "فشل فتح سطح المكتب البعيد لنظام التشغيل Windows", + "openNativeRdp": "افتح في سطح المكتب البعيد لنظام التشغيل Windows", + "guac": { + "connection": "اتصال", + "authentication": "المصادقة", + "storedCredential": "بيانات الاعتماد المخزنة", + "authMethod": "طريقة المصادقة", + "authTypeNoneDesc": "لا يتم تخزين أي بيانات اعتماد. سيُطلب منك إدخال اسم المستخدم وكلمة المرور في كل مرة تتصل فيها؛ فهي غير محفوظة.", + "selectCredential": "اختر بيانات اعتماد...", + "connectionSettings": "إعدادات الاتصال", + "displaySettings": "إعدادات العرض", + "audioSettings": "إعدادات الصوت", + "rdpPerformance": "أداء RDP", + "deviceRedirection": "إعادة توجيه الأجهزة", + "session": "جلسة", + "gateway": "بوابة", + "remoteApp": "RemoteApp", + "clipboard": "الحافظة", + "sessionRecording": "تسجيل الجلسة", + "wakeOnLan": "الإيقاظ عبر الشبكة", + "vncSettings": "إعدادات VNC", + "terminalSettings": "إعدادات الطرفية", + "rdpPort": "منفذ RDP", + "username": "اسم المستخدم", + "password": "كلمة المرور", + "passwordSaved": "تم حفظ كلمة المرور، اكتب لتغييرها", + "domain": "مجال", + "securityMode": "وضع الأمان", + "width": "العرض", + "height": "الارتفاع", + "dpi": "DPI", + "clientName": "اسم العميل", + "initialProgram": "البرنامج الأولي", + "serverLayout": "تخطيط الخادم", + "timezone": "المنطقة الزمنية", + "loadBalanceInfo": "معلومات موازنة التحميل / ملف تعريف ارتباط", + "loadBalanceInfoDesc": "ملف تعريف ارتباط وسيط اتصال RD لموازنة تحميل مزرعة RDS (مثل: tsv://MS Terminal Services Plugin.1.CollectionName)", + "guacdProxy": "وكيل guacd", + "guacdHostname": "مضيف guacd", + "guacdHostnamePlaceholder": "الافتراضي العام", + "guacdPort": "منفذ guacd", + "guacdProxyDesc": "تجاوز مثيل guacd العام لهذا الاتصال. اتركه فارغًا لاستخدام إعدادات guacd العمومية.", + "gatewayHostname": "اسم مضيف البوابة", + "gatewayPort": "منفذ البوابة", + "gatewayUsername": "اسم مستخدم البوابة", + "gatewayPassword": "كلمة مرور البوابة", + "gatewayDomain": "مجال البوابة", + "remoteAppProgram": "برنامج RemoteApp", + "workingDirectory": "دليل العمل", + "arguments": "الوسائط", + "normalizeLineEndings": "تطبيع نهايات الأسطر", + "macAddress": "عنوان MAC", + "broadcastAddress": "عنوان البث", + "udpPort": "منفذ UDP", + "waitTimeS": "وقت الانتظار (ث)", + "driveName": "اسم القرص", + "drivePath": "مسار القرص", + "ignoreCertificate": "تجاهل الشهادة", + "ignoreCertificateDesc": "السماح بالاتصال بالمضيفين بشهادات موقعة ذاتيًا", + "forceLossless": "فرض بدون فقدان", + "forceLosslessDesc": "فرض ترميز الصور بدون فقدان (جودة أعلى، استهلاك أكبر للنطاق الترددي)", + "disableAudio": "تعطيل الصوت", + "disableAudioDesc": "كتم كل الصوت من الجلسة البعيدة", + "enableAudioInput": "تمكين إدخال الصوت (الميكروفون)", + "enableAudioInputDesc": "إعادة توجيه الميكروفون المحلي إلى الجلسة البعيدة", + "wallpaper": "خلفية سطح المكتب", + "wallpaperDesc": "إظهار خلفية سطح المكتب (التعطيل يحسن الأداء)", + "theming": "السمات", + "themingDesc": "تمكين السمات والأنماط المرئية", + "fontSmoothing": "تنعيم الخطوط", + "fontSmoothingDesc": "تمكين عرض خطوط ClearType", + "fullWindowDrag": "سحب النافذة بالكامل", + "fullWindowDragDesc": "إظهار محتويات النافذة أثناء السحب", + "desktopComposition": "تركيب سطح المكتب", + "desktopCompositionDesc": "تمكين تأثيرات Aero الزجاجية", + "menuAnimations": "حركات القوائم", + "menuAnimationsDesc": "تمكين حركات التلاشي والانزلاق للقوائم", + "disableBitmapCaching": "تعطيل التخزين المؤقت للصور النقطية", + "disableBitmapCachingDesc": "إيقاف التخزين المؤقت للصور النقطية (قد يساعد في حل المشكلات)", + "disableOffscreenCaching": "تعطيل التخزين المؤقت خارج الشاشة", + "disableOffscreenCachingDesc": "إيقاف التخزين المؤقت خارج الشاشة", + "disableGlyphCaching": "تعطيل التخزين المؤقت للأشكال", + "disableGlyphCachingDesc": "إيقاف التخزين المؤقت للأشكال", + "enableGfx": "تمكين GFX", + "enableGfxDesc": "استخدام خط أنابيب رسوميات RemoteFX", + "enablePrinting": "تمكين الطباعة", + "enablePrintingDesc": "إعادة توجيه الطابعات المحلية إلى الجلسة البعيدة", + "enableDriveRedirection": "تمكين إعادة توجيه القرص", + "enableDriveRedirectionDesc": "تعيين مجلد محلي كقرص في الجلسة البعيدة", + "createDrivePath": "إنشاء مسار محرك الأقراص", + "createDrivePathDesc": "إنشاء المجلد تلقائياً إذا لم يكن موجوداً", + "disableDownload": "تعطيل التحميل", + "disableDownloadDesc": "منع تنزيل الملفات من الجلسة البعيدة", + "disableUpload": "تعطيل الرفع", + "disableUploadDesc": "منع رفع الملفات إلى الجلسة البعيدة", + "enableTouch": "تمكين اللمس", + "enableTouchDesc": "تمكين تمرير إدخالات اللمس", + "consoleSession": "جلسة وحدة التحكم", + "consoleSessionDesc": "الاتصال بوحدة التحكم (الجلسة 0) بدلاً من جلسة جديدة", + "sendWolPacket": "إرسال حزمة WOL", + "sendWolPacketDesc": "إرسال حزمة سحرية لإيقاظ هذا المضيف قبل الاتصال", + "disableCopy": "تعطيل النسخ", + "disableCopyDesc": "منع نسخ النص من الجلسة البعيدة", + "disablePaste": "تعطيل اللصق", + "disablePasteDesc": "منع لصق النص في الجلسة البعيدة", + "createPathIfMissing": "إنشاء المسار إذا كان مفقوداً", + "createPathIfMissingDesc": "إنشاء دليل التسجيل تلقائياً", + "excludeOutput": "استبعاد المخرجات", + "excludeOutputDesc": "عدم تسجيل مخرجات الشاشة (البيانات الوصفية فقط)", + "excludeMouse": "استبعاد الفأرة", + "excludeMouseDesc": "عدم تسجيل حركات الفأرة", + "includeKeystrokes": "تضمين ضغطات المفاتيح", + "includeKeystrokesDesc": "تسجيل ضغطات المفاتيح الخام بالإضافة إلى مخرجات الشاشة", + "vncPort": "منفذ VNC", + "vncPassword": "كلمة مرور VNC", + "vncUsernameOptional": "اسم المستخدم (اختياري)", + "vncLeaveBlank": "اتركه فارغاً إذا لم يكن مطلوباً", + "cursorMode": "وضع المؤشر", + "swapRedBlue": "تبديل الأحمر/الأزرق", + "swapRedBlueDesc": "تبديل قنوات اللون الأحمر والأزرق (يصلح بعض مشكلات الألوان)", + "readOnly": "للقراءة فقط", + "readOnlyDesc": "عرض الشاشة البعيدة دون إرسال أي إدخال", + "telnetPort": "منفذ Telnet", + "terminalType": "نوع الطرفية", + "fontName": "اسم الخط", + "fontSize": "حجم الخط", + "colorScheme": "نظام الألوان", + "backspaceKey": "مفتاح Backspace" + } + }, + "onboarding": { + "feature_desktop": "سطح المكتب البعيد", + "feature_desktop_desc": "افتح جلسات RDP وVNC وTelnet في علامة تبويب، تمامًا مثل SSH." + } +} diff --git a/plugins/remote-desktop/locales/translated/bg_BG.json b/plugins/remote-desktop/locales/translated/bg_BG.json new file mode 100644 index 000000000..f8d35c6d4 --- /dev/null +++ b/plugins/remote-desktop/locales/translated/bg_BG.json @@ -0,0 +1,214 @@ +{ + "remoteDesktop": { + "connecting": "Свързване към сесия {{type}}...", + "checkingGuacd": "Проверка на услугата за отдалечен работен плот...", + "requestingToken": "Заявка за {{type}} токен за връзка...", + "openingSession": "Отваряне на {{type}} сесия...", + "negotiating": "Преговаряне {{type}} ръкостискане...", + "sessionReady": "{{type}} сесията е готова", + "connectionError": "Грешка при свързване", + "connectionFailed": "Връзката не бе успешна", + "failedToConnect": "Неуспешно получаване на токен за връзка", + "hostNotFound": "Хостът не е намерен", + "noHostSelected": "Няма избран хост", + "reconnect": "Свържете се отново", + "retry": "Опитай отново", + "guacdUnavailable": "Услугата за отдалечен работен плот (guacd) не е налична. Моля, уверете се, че guacd работи, е достъпна и е конфигурирана правилно в администраторските настройки.", + "credentialPromptTitle": "Въведете RDP идентификационни данни", + "credentialPromptDescription": "Този хост е настроен да изисква идентификационни данни при свързване. Те се използват само за тази сесия и не се запазват.", + "connect": "Свържете се", + "ctrlAltDel": "Ctrl+Alt+Del", + "files": { + "title": "Файлове на Диск", + "parent": "Родителска директория", + "refresh": "Обновяване", + "empty": "Тази папка е празна", + "listFailed": "Неуспешно четене на тази папка", + "download": "Изтегляне", + "downloadFailed": "Неуспешно изтегляне {{name}}", + "upload": "Качване на файлове", + "uploading": "Качване {{name}}...", + "uploaded": "Качено {{name}}", + "uploadFailed": "Качването не бе успешно {{name}}", + "uploadDisabled": "Качванията са деактивирани за тази връзка", + "driveUnavailable": "Активирайте пренасочването на RDP устройството, преди да качвате файлове", + "driveNotWritable": "guacd не може да записва в папката на устройството. Проверете GUACD_DRIVE_PATH (или пътя на устройството на хоста) и неговите разрешения.", + "dropToUpload": "Пуснете файловете, за да ги качите" + }, + "toolbar": { + "ctrlAltDel": "Ctrl+Alt+Del", + "winL": "Win+L (Заключен екран)", + "winKey": "Клавиш за Windows", + "superL": "Супер+L (Заключен екран)", + "superKey": "Супер ключ", + "super": "Супер", + "cmdL": "Cmd+L (Заключен екран)", + "cmdKey": "Команден ключ", + "cmd": "Команда", + "ctrl": "Ctrl", + "alt": "Алтернативно", + "shift": "Изместване", + "win": "Спечелете", + "stickyActive": "{{key}} (заключено - щракнете за освобождаване)", + "stickyInactive": "{{key}} (щракнете, за да заключите)", + "esc": "Бягство", + "tab": "Раздел", + "home": "Дом", + "end": "Край", + "pageUp": "Страница нагоре", + "pageDown": "Страница надолу", + "arrowUp": "Стрелка нагоре", + "arrowDown": "Стрелка надолу", + "arrowLeft": "Стрелка наляво", + "arrowRight": "Стрелка надясно", + "fnToggle": "Функционални клавиши", + "reconnect": "Сесия за повторно свързване", + "collapse": "Свиване на лентата с инструменти", + "expand": "Разгъване на лентата с инструменти", + "dragHandle": "Плъзнете, за да препозиционирате", + "hide": "Скриване за тази сесия. За да го деактивирате за постоянно, отворете Настройки на хоста → Общи → Лента с инструменти за връзка.", + "zoomIn": "Увеличаване", + "zoomOut": "Намаляване на мащаба", + "resetZoom": "Нулиране на мащаба", + "fitToScreen": "Побиране на екрана", + "switchToTrackpad": "Превключване в режим на тракпад (плъзнете, за да преместите курсора, докоснете, за да щракнете)", + "switchToTouch": "Превключване към режим на докосване (докоснете директно там, където искате да щракнете)" + } + }, + "hosts": { + "nativeRdpOpened": "Отворено в отдалечен работен плот на Windows", + "nativeRdpFailed": "Неуспешно отваряне на отдалечения работен плот на Windows", + "openNativeRdp": "Отваряне в отдалечен работен плот на Windows", + "guac": { + "connection": "Връзка", + "authentication": "Удостоверяване", + "storedCredential": "Съхранени идентификационни данни", + "authMethod": "Метод за удостоверяване", + "authTypeNoneDesc": "Не се съхраняват идентификационни данни. Ще бъдете подканени да въведете потребителско име и парола всеки път, когато се свържете; те не се запазват.", + "selectCredential": "Изберете идентификационен номер...", + "connectionSettings": "Настройки за връзка", + "displaySettings": "Настройки на дисплея", + "audioSettings": "Аудио настройки", + "rdpPerformance": "Производителност на RDP", + "deviceRedirection": "Пренасочване на устройството", + "session": "Сесия", + "gateway": "Портал", + "remoteApp": "Отдалечено приложение", + "clipboard": "Клипборд", + "sessionRecording": "Запис на сесия", + "wakeOnLan": "Събуждане по локална мрежа", + "vncSettings": "VNC настройки", + "terminalSettings": "Настройки на терминала", + "rdpPort": "RDP порт", + "username": "Потребителско име", + "password": "Парола", + "passwordSaved": "Паролата е запазена, въведете, за да я промените", + "domain": "Домейн", + "securityMode": "Режим на сигурност", + "width": "Ширина", + "height": "Височина", + "dpi": "DPI", + "clientName": "Име на клиента", + "initialProgram": "Първоначална програма", + "serverLayout": "Разположение на сървъра", + "timezone": "Часова зона", + "loadBalanceInfo": "Информация за балансиране на натоварването / бисквитка", + "loadBalanceInfoDesc": "„бисквитка“ на RD Connection Broker за балансиране на натоварването на RDS фермата (напр. tsv://MS Terminal Services Plugin.1.CollectionName)", + "guacdProxy": "guacd прокси", + "guacdHostname": "guacd хост", + "guacdHostnamePlaceholder": "Глобално по подразбиране", + "guacdPort": "порт guacd", + "guacdProxyDesc": "Заменете глобалния екземпляр на guacd за тази връзка. Оставете празно, за да използвате глобално конфигурирания guacd.", + "gatewayHostname": "Име на хост на шлюз", + "gatewayPort": "Порт на шлюза", + "gatewayUsername": "Потребителско име на шлюз", + "gatewayPassword": "Парола за шлюз", + "gatewayDomain": "Домейн на шлюз", + "remoteAppProgram": "Програма за отдалечено приложение", + "workingDirectory": "Работна директория", + "arguments": "Аргументи", + "normalizeLineEndings": "Нормализиране на края на редовете", + "macAddress": "MAC адрес", + "broadcastAddress": "Адрес за излъчване", + "udpPort": "UDP порт", + "waitTimeS": "Време за изчакване (и)", + "driveName": "Име на устройството", + "drivePath": "Път на устройството", + "ignoreCertificate": "Игнориране на сертификата", + "ignoreCertificateDesc": "Разрешаване на връзки към хостове със самоподписани сертификати", + "forceLossless": "Принудително беззагубно", + "forceLosslessDesc": "Принудително кодиране на изображения без загуби (по-високо качество, по-голяма честотна лента)", + "disableAudio": "Деактивиране на звука", + "disableAudioDesc": "Изключване на звука от отдалечената сесия", + "enableAudioInput": "Активиране на аудио вход (микрофон)", + "enableAudioInputDesc": "Пренасочване на локалния микрофон към отдалечената сесия", + "wallpaper": "Тапет", + "wallpaperDesc": "Показване на тапет на работния плот (деактивирането му подобрява производителността)", + "theming": "Темиране", + "themingDesc": "Активиране на визуални теми и стилове", + "fontSmoothing": "Изглаждане на шрифта", + "fontSmoothingDesc": "Активиране на рендирането на шрифтове ClearType", + "fullWindowDrag": "Плъзгане на целия прозорец", + "fullWindowDragDesc": "Показване на съдържанието на прозореца при плъзгане", + "desktopComposition": "Композиция на работния плот", + "desktopCompositionDesc": "Активиране на ефектите на Aero Glass", + "menuAnimations": "Анимации на менюто", + "menuAnimationsDesc": "Активиране на анимации за избледняване на менюта и слайдове", + "disableBitmapCaching": "Деактивиране на кеширането на растерни изображения", + "disableBitmapCachingDesc": "Изключете кеша на растерните изображения (може да помогне с проблеми)", + "disableOffscreenCaching": "Деактивиране на кеширането извън екрана", + "disableOffscreenCachingDesc": "Изключване на кеша извън екрана", + "disableGlyphCaching": "Деактивиране на кеширането на глифи", + "disableGlyphCachingDesc": "Изключване на кеша на глифове", + "enableGfx": "Активиране на графични ефекти", + "enableGfxDesc": "Използвайте графичен конвейер RemoteFX", + "enablePrinting": "Активиране на печат", + "enablePrintingDesc": "Пренасочване на локални принтери към отдалечена сесия", + "enableDriveRedirection": "Активиране на пренасочване на устройството", + "enableDriveRedirectionDesc": "Карта на локална папка като устройство в отдалечена сесия", + "createDrivePath": "Създаване на път за устройство", + "createDrivePathDesc": "Автоматично създаване на папката, ако тя не съществува", + "disableDownload": "Деактивиране на изтеглянето", + "disableDownloadDesc": "Предотвратяване на изтеглянето на файлове от отдалечената сесия", + "disableUpload": "Деактивиране на качването", + "disableUploadDesc": "Предотвратяване на качването на файлове към отдалечената сесия", + "enableTouch": "Активиране на докосване", + "enableTouchDesc": "Активиране на пренасочване на сензорен вход", + "consoleSession": "Конзолна сесия", + "consoleSessionDesc": "Свържете се с конзолата (сесия 0) вместо с нова сесия", + "sendWolPacket": "Изпращане на WOL пакет", + "sendWolPacketDesc": "Изпратете магически пакет, за да събудите този хост преди свързване", + "disableCopy": "Деактивиране на копирането", + "disableCopyDesc": "Предотвратяване на копирането на текст от отдалечената сесия", + "disablePaste": "Деактивиране на поставянето", + "disablePasteDesc": "Предотвратяване на поставянето на текст в отдалечената сесия", + "createPathIfMissing": "Създаване на път, ако липсва", + "createPathIfMissingDesc": "Автоматично създаване на директорията за записи", + "excludeOutput": "Изключване на изхода", + "excludeOutputDesc": "Не записвайте изхода на екрана (само метаданни)", + "excludeMouse": "Изключване на мишката", + "excludeMouseDesc": "Не записвайте движенията на мишката", + "includeKeystrokes": "Включи клавишни комбинации", + "includeKeystrokesDesc": "Записване на сурови натискания на клавиши в допълнение към изхода на екрана", + "vncPort": "VNC порт", + "vncPassword": "VNC парола", + "vncUsernameOptional": "Потребителско име (по избор)", + "vncLeaveBlank": "Оставете празно, ако не е необходимо", + "cursorMode": "Режим на курсора", + "swapRedBlue": "Разменете червено/синьо", + "swapRedBlueDesc": "Разменете червените и сините цветови канали (коригира някои проблеми с цветовете)", + "readOnly": "Само за четене", + "readOnlyDesc": "Преглеждайте отдалечения екран, без да изпращате никакви входни данни", + "telnetPort": "Telnet порт", + "terminalType": "Тип терминал", + "fontName": "Име на шрифта", + "fontSize": "Размер на шрифта", + "colorScheme": "Цветова схема", + "backspaceKey": "Клавиш Backspace" + } + }, + "onboarding": { + "feature_desktop": "Отдалечен работен плот", + "feature_desktop_desc": "Отваряне на RDP, VNC и Telnet сесии в раздел, както при SSH." + } +} diff --git a/plugins/remote-desktop/locales/translated/bn_BD.json b/plugins/remote-desktop/locales/translated/bn_BD.json new file mode 100644 index 000000000..def002c2d --- /dev/null +++ b/plugins/remote-desktop/locales/translated/bn_BD.json @@ -0,0 +1,214 @@ +{ + "remoteDesktop": { + "connecting": "{{type}} সেশনে সংযোগ স্থাপন করা হচ্ছে...", + "checkingGuacd": "রিমোট ডেস্কটপ পরিষেবা পরীক্ষা করা হচ্ছে...", + "requestingToken": "{{type}} সংযোগ টোকেনের জন্য অনুরোধ করা হচ্ছে...", + "openingSession": "{{type}} সেশন শুরু হচ্ছে...", + "negotiating": "{{type}} করমর্দন নিয়ে আলোচনা চলছে...", + "sessionReady": "{{type}} সেশন প্রস্তুত", + "connectionError": "সংযোগ ত্রুটি", + "connectionFailed": "সংযোগ ব্যর্থ হয়েছে", + "failedToConnect": "সংযোগ টোকেন পেতে ব্যর্থ হয়েছে", + "hostNotFound": "হোস্ট খুঁজে পাওয়া যায়নি", + "noHostSelected": "কোন হোস্ট নির্বাচন করা হয়নি", + "reconnect": "পুনরায় সংযোগ করুন", + "retry": "পুনরায় চেষ্টা করুন", + "guacdUnavailable": "রিমোট ডেস্কটপ সার্ভিস (guacd) উপলব্ধ নেই। অনুগ্রহ করে নিশ্চিত করুন যে guacd চালু ও অ্যাক্সেসযোগ্য আছে এবং অ্যাডমিন সেটিংসে সঠিকভাবে কনফিগার করা আছে।", + "credentialPromptTitle": "RDP পরিচয়পত্র প্রবেশ করান", + "credentialPromptDescription": "এই হোস্টটি সংযোগের সময় ক্রেডেনশিয়াল চাওয়ার জন্য সেট করা আছে। এগুলি শুধুমাত্র এই সেশনের জন্য ব্যবহৃত হয় এবং সংরক্ষিত হয় না।", + "connect": "সংযোগ করুন", + "ctrlAltDel": "Ctrl+Alt+Del", + "files": { + "title": "ড্রাইভ ফাইল", + "parent": "অভিভাবক ডিরেক্টরি", + "refresh": "রিফ্রেশ", + "empty": "এই ফোল্ডারটি খালি", + "listFailed": "এই ফোল্ডারটি পড়তে ব্যর্থ হয়েছে", + "download": "ডাউনলোড করুন", + "downloadFailed": "{{name}} ডাউনলোড করতে ব্যর্থ হয়েছে", + "upload": "ফাইল আপলোড করুন", + "uploading": "{{name}} আপলোড হচ্ছে ...", + "uploaded": "আপলোড করা হয়েছে {{name}}", + "uploadFailed": "{{name}} আপলোড করতে ব্যর্থ হয়েছে", + "uploadDisabled": "এই সংযোগের জন্য আপলোড নিষ্ক্রিয় করা হয়েছে।", + "driveUnavailable": "ফাইল আপলোড করার আগে RDP ড্রাইভ রিডাইরেকশন সক্রিয় করুন।", + "driveNotWritable": "guacd ড্রাইভ ফোল্ডারে লিখতে পারছে না। GUACD_DRIVE_PATH (অথবা হোস্টের ড্রাইভ পাথ) এবং এর অনুমতিগুলো পরীক্ষা করুন।", + "dropToUpload": "আপলোড করতে ফাইলগুলো ড্রপ করুন" + }, + "toolbar": { + "ctrlAltDel": "Ctrl+Alt+Del", + "winL": "উইন+এল (লক স্ক্রিন)", + "winKey": "উইন্ডোজ কী", + "superL": "সুপার+এল (লক স্ক্রিন)", + "superKey": "সুপার কী", + "super": "সুপার", + "cmdL": "Cmd+L (লক স্ক্রিন)", + "cmdKey": "কমান্ড কী", + "cmd": "কমান্ডার", + "ctrl": "Ctrl", + "alt": "বিকল্প", + "shift": "শিফট", + "win": "জয়", + "stickyActive": "{{key}} (আটকানো - খুলতে ক্লিক করুন)", + "stickyInactive": "{{key}} (আটকাতে ক্লিক করুন)", + "esc": "পালানো", + "tab": "ট্যাব", + "home": "হোম", + "end": "শেষ", + "pageUp": "পৃষ্ঠা উপরে", + "pageDown": "পৃষ্ঠা নিচে", + "arrowUp": "তীর ঊর্ধ্বমুখী", + "arrowDown": "অ্যারো ডাউন", + "arrowLeft": "বাম তীর", + "arrowRight": "ডান তীরচিহ্ন", + "fnToggle": "ফাংশন কী", + "reconnect": "পুনরায় সংযোগ সেশন", + "collapse": "টুলবার সংকুচিত করুন", + "expand": "টুলবার প্রসারিত করুন", + "dragHandle": "অবস্থান পরিবর্তন করতে টেনে আনুন", + "hide": "এই সেশনের জন্য লুকান। এটিকে স্থায়ীভাবে নিষ্ক্রিয় করতে, হোস্ট সেটিংস → সাধারণ → সংযোগ টুলবার খুলুন।", + "zoomIn": "জুম ইন", + "zoomOut": "জুম আউট", + "resetZoom": "জুম রিসেট করুন", + "fitToScreen": "স্ক্রিনের সাথে মানানসই", + "switchToTrackpad": "ট্র্যাকপ্যাড মোডে যান (কার্সার সরাতে ড্র্যাগ করুন, ক্লিক করতে ট্যাপ করুন)", + "switchToTouch": "টাচ মোডে যান (যেখানে ক্লিক করতে চান সেখানে সরাসরি ট্যাপ করুন)" + } + }, + "hosts": { + "nativeRdpOpened": "উইন্ডোজ রিমোট ডেস্কটপে খোলা হয়েছে", + "nativeRdpFailed": "উইন্ডোজ রিমোট ডেস্কটপ খুলতে ব্যর্থ হয়েছে", + "openNativeRdp": "উইন্ডোজ রিমোট ডেস্কটপে খুলুন", + "guac": { + "connection": "সংযোগ", + "authentication": "প্রমাণীকরণ", + "storedCredential": "সংরক্ষিত পরিচয়পত্র", + "authMethod": "প্রমাণীকরণ পদ্ধতি", + "authTypeNoneDesc": "কোনো পরিচয়পত্র সংরক্ষিত থাকে না। প্রতিবার সংযোগ করার সময় আপনাকে একটি ইউজারনেম এবং পাসওয়ার্ড দিতে বলা হবে; সেগুলি সংরক্ষণ করা হয় না।", + "selectCredential": "একটি শংসাপত্র নির্বাচন করুন...", + "connectionSettings": "সংযোগ সেটিংস", + "displaySettings": "ডিসপ্লে সেটিংস", + "audioSettings": "অডিও সেটিংস", + "rdpPerformance": "আরডিপি পারফরম্যান্স", + "deviceRedirection": "ডিভাইস পুনঃনির্দেশনা", + "session": "অধিবেশন", + "gateway": "গেটওয়ে", + "remoteApp": "রিমোটঅ্যাপ", + "clipboard": "ক্লিপবোর্ড", + "sessionRecording": "সেশন রেকর্ডিং", + "wakeOnLan": "ওয়েক-অন-ল্যান", + "vncSettings": "VNC সেটিংস", + "terminalSettings": "টার্মিনাল সেটিংস", + "rdpPort": "আরডিপি পোর্ট", + "username": "ব্যবহারকারীর নাম", + "password": "পাসওয়ার্ড", + "passwordSaved": "পাসওয়ার্ড সংরক্ষিত আছে, পরিবর্তন করতে টাইপ করুন", + "domain": "ডোমেইন", + "securityMode": "নিরাপত্তা মোড", + "width": "প্রস্থ", + "height": "উচ্চতা", + "dpi": "ডিপিআই", + "clientName": "ক্লায়েন্টের নাম", + "initialProgram": "প্রাথমিক প্রোগ্রাম", + "serverLayout": "সার্ভার লেআউট", + "timezone": "সময় অঞ্চল", + "loadBalanceInfo": "লোড ব্যালেন্স তথ্য / কুকি", + "loadBalanceInfoDesc": "RDS ফার্ম লোড ব্যালান্সিংয়ের জন্য RD কানেকশন ব্রোকার কুকি (যেমন tsv://MS Terminal Services Plugin.1.CollectionName)", + "guacdProxy": "গুয়াকড প্রক্সি", + "guacdHostname": "গুয়াকড হোস্ট", + "guacdHostnamePlaceholder": "গ্লোবাল ডিফল্ট", + "guacdPort": "গুয়াকড পোর্ট", + "guacdProxyDesc": "এই সংযোগের জন্য গ্লোবাল guacd ইনস্ট্যান্সটি ওভাররাইড করুন। বিশ্বব্যাপী কনফিগার করা guacd ব্যবহার করতে এটি খালি রাখুন।", + "gatewayHostname": "গেটওয়ে হোস্টনাম", + "gatewayPort": "গেটওয়ে পোর্ট", + "gatewayUsername": "গেটওয়ে ব্যবহারকারীর নাম", + "gatewayPassword": "গেটওয়ে পাসওয়ার্ড", + "gatewayDomain": "গেটওয়ে ডোমেইন", + "remoteAppProgram": "রিমোটঅ্যাপ প্রোগ্রাম", + "workingDirectory": "কর্ম ডিরেক্টরি", + "arguments": "যুক্তি", + "normalizeLineEndings": "লাইনের শেষাংশ স্বাভাবিক করুন", + "macAddress": "MAC ঠিকানা", + "broadcastAddress": "সম্প্রচার ঠিকানা", + "udpPort": "ইউডিপি পোর্ট", + "waitTimeS": "অপেক্ষার সময় (সেকেন্ড)", + "driveName": "ড্রাইভের নাম", + "drivePath": "ড্রাইভ পাথ", + "ignoreCertificate": "সার্টিফিকেট উপেক্ষা করুন", + "ignoreCertificateDesc": "স্ব-স্বাক্ষরিত শংসাপত্র সহ হোস্টগুলিতে সংযোগের অনুমতি দিন", + "forceLossless": "বল ক্ষয়হীন", + "forceLosslessDesc": "লসলেস ইমেজ এনকোডিং বাধ্যতামূলক করুন (উচ্চতর গুণমান, বেশি ব্যান্ডউইথ)", + "disableAudio": "অডিও নিষ্ক্রিয় করুন", + "disableAudioDesc": "রিমোট সেশন থেকে সমস্ত অডিও মিউট করুন", + "enableAudioInput": "অডিও ইনপুট (মাইক্রোফোন) সক্রিয় করুন", + "enableAudioInputDesc": "স্থানীয় মাইক্রোফোনটি রিমোট সেশনে ফরোয়ার্ড করুন", + "wallpaper": "ওয়ালপেপার", + "wallpaperDesc": "ডেস্কটপ ওয়ালপেপার দেখান (এটি বন্ধ করলে পারফরম্যান্স উন্নত হয়)", + "theming": "থিমিং", + "themingDesc": "ভিজ্যুয়াল থিম এবং স্টাইল সক্রিয় করুন", + "fontSmoothing": "ফন্ট মসৃণকরণ", + "fontSmoothingDesc": "ক্লিয়ারটাইপ ফন্ট রেন্ডারিং সক্ষম করুন", + "fullWindowDrag": "সম্পূর্ণ উইন্ডো ড্র্যাগ", + "fullWindowDragDesc": "ড্র্যাগ করার সময় উইন্ডোর বিষয়বস্তু দেখান", + "desktopComposition": "ডেস্কটপ কম্পোজিশন", + "desktopCompositionDesc": "এরো গ্লাস এফেক্টস সক্রিয় করুন", + "menuAnimations": "মেনু অ্যানিমেশন", + "menuAnimationsDesc": "মেনু ফেড এবং স্লাইড অ্যানিমেশন সক্রিয় করুন", + "disableBitmapCaching": "বিটম্যাপ ক্যাশিং নিষ্ক্রিয় করুন", + "disableBitmapCachingDesc": "বিটম্যাপ ক্যাশে বন্ধ করুন (এটি গ্লিচ কমাতে সাহায্য করতে পারে)।", + "disableOffscreenCaching": "অফস্ক্রিন ক্যাশিং নিষ্ক্রিয় করুন", + "disableOffscreenCachingDesc": "অফস্ক্রিন ক্যাশে বন্ধ করুন", + "disableGlyphCaching": "গ্লিফ ক্যাশিং নিষ্ক্রিয় করুন", + "disableGlyphCachingDesc": "গ্লিফ ক্যাশে বন্ধ করুন", + "enableGfx": "GFX সক্ষম করুন", + "enableGfxDesc": "RemoteFX গ্রাফিক্স পাইপলাইন ব্যবহার করুন", + "enablePrinting": "প্রিন্টিং সক্ষম করুন", + "enablePrintingDesc": "স্থানীয় প্রিন্টারগুলিকে রিমোট সেশনে পুনঃনির্দেশিত করুন", + "enableDriveRedirection": "ড্রাইভ পুনঃনির্দেশনা সক্ষম করুন", + "enableDriveRedirectionDesc": "রিমোট সেশনে একটি স্থানীয় ফোল্ডারকে ড্রাইভ হিসেবে ম্যাপ করুন।", + "createDrivePath": "ড্রাইভ পাথ তৈরি করুন", + "createDrivePathDesc": "ফোল্ডারটি বিদ্যমান না থাকলে স্বয়ংক্রিয়ভাবে তৈরি করুন।", + "disableDownload": "ডাউনলোড নিষ্ক্রিয় করুন", + "disableDownloadDesc": "রিমোট সেশন থেকে ফাইল ডাউনলোড করা প্রতিরোধ করুন", + "disableUpload": "আপলোড নিষ্ক্রিয় করুন", + "disableUploadDesc": "রিমোট সেশনে ফাইল আপলোড করা প্রতিরোধ করুন", + "enableTouch": "টাচ সক্ষম করুন", + "enableTouchDesc": "টাচ ইনপুট ফরওয়ার্ডিং সক্ষম করুন", + "consoleSession": "কনসোল সেশন", + "consoleSessionDesc": "নতুন সেশন শুরু করার পরিবর্তে কনসোলে (সেশন ০) সংযোগ করুন।", + "sendWolPacket": "WOL প্যাকেট পাঠান", + "sendWolPacketDesc": "সংযোগ করার আগে এই হোস্টকে জাগিয়ে তুলতে একটি ম্যাজিক প্যাকেট পাঠান।", + "disableCopy": "কপি নিষ্ক্রিয় করুন", + "disableCopyDesc": "রিমোট সেশন থেকে টেক্সট কপি করা প্রতিরোধ করুন", + "disablePaste": "পেস্ট নিষ্ক্রিয় করুন", + "disablePasteDesc": "রিমোট সেশনে টেক্সট পেস্ট করা প্রতিরোধ করুন", + "createPathIfMissing": "অনুপস্থিত থাকলে পাথ তৈরি করুন", + "createPathIfMissingDesc": "স্বয়ংক্রিয়ভাবে রেকর্ডিং ডিরেক্টরি তৈরি করুন", + "excludeOutput": "আউটপুট বাদ দিন", + "excludeOutputDesc": "স্ক্রিন আউটপুট রেকর্ড করবেন না (শুধুমাত্র মেটাডেটা)", + "excludeMouse": "মাউস বাদ দিন", + "excludeMouseDesc": "মাউসের নড়াচড়া রেকর্ড করবেন না।", + "includeKeystrokes": "কীস্ট্রোক অন্তর্ভুক্ত করুন", + "includeKeystrokesDesc": "স্ক্রিন আউটপুটের পাশাপাশি সরাসরি কীস্ট্রোক রেকর্ড করুন।", + "vncPort": "ভিএনসি পোর্ট", + "vncPassword": "VNC পাসওয়ার্ড", + "vncUsernameOptional": "ব্যবহারকারীর নাম (ঐচ্ছিক)", + "vncLeaveBlank": "প্রয়োজন না হলে খালি রাখুন", + "cursorMode": "কার্সার মোড", + "swapRedBlue": "লাল/নীল অদলবদল করুন", + "swapRedBlueDesc": "লাল এবং নীল রঙের চ্যানেলগুলি অদলবদল করুন (কিছু রঙের সমস্যা সমাধান করে)", + "readOnly": "শুধুমাত্র পঠনযোগ্য", + "readOnlyDesc": "কোনো ইনপুট না পাঠিয়ে রিমোট স্ক্রিন দেখুন।", + "telnetPort": "টেলনেট পোর্ট", + "terminalType": "টার্মিনাল টাইপ", + "fontName": "ফন্টের নাম", + "fontSize": "ফন্ট সাইজ", + "colorScheme": "রঙের পরিকল্পনা", + "backspaceKey": "ব্যাকস্পেস কী" + } + }, + "onboarding": { + "feature_desktop": "রিমোট ডেস্কটপ", + "feature_desktop_desc": "SSH-এর মতোই একটি ট্যাবে RDP, VNC এবং Telnet সেশন খুলুন।" + } +} diff --git a/plugins/remote-desktop/locales/translated/ca_ES.json b/plugins/remote-desktop/locales/translated/ca_ES.json new file mode 100644 index 000000000..24e412192 --- /dev/null +++ b/plugins/remote-desktop/locales/translated/ca_ES.json @@ -0,0 +1,214 @@ +{ + "remoteDesktop": { + "connecting": "Connectant a la sessió {{type}}...", + "checkingGuacd": "S'està comprovant el servei d'escriptori remot...", + "requestingToken": "Sol·licitant el testimoni de connexió {{type}}...", + "openingSession": "Obrint sessió {{type}}...", + "negotiating": "Negociant una {{type}} encaixada de mans...", + "sessionReady": "{{type}} sessió a punt", + "connectionError": "Error de connexió", + "connectionFailed": "La connexió ha fallat", + "failedToConnect": "No s'ha pogut obtenir el testimoni de connexió", + "hostNotFound": "No s'ha trobat l'amfitrió", + "noHostSelected": "No s'ha seleccionat cap amfitrió", + "reconnect": "Reconnecta", + "retry": "Torna-ho a intentar", + "guacdUnavailable": "El servei d'escriptori remot (guacd) no està disponible. Assegureu-vos que guacd estigui en execució, sigui accessible i estigui configurat correctament a la configuració d'administrador.", + "credentialPromptTitle": "Introduïu les credencials RDP", + "credentialPromptDescription": "Aquest amfitrió està configurat per demanar credencials en connectar-se. Només s'utilitzen per a aquesta sessió i no es desen.", + "connect": "Connecta", + "ctrlAltDel": "Ctrl+Alt+Supr", + "files": { + "title": "Fitxers de Drive", + "parent": "Directori principal", + "refresh": "Actualitza", + "empty": "Aquesta carpeta està buida", + "listFailed": "No s'ha pogut llegir aquesta carpeta", + "download": "Descarrega", + "downloadFailed": "No s'ha pogut descarregar {{name}}", + "upload": "Puja fitxers", + "uploading": "S'està carregant {{name}}...", + "uploaded": "Pujat {{name}}", + "uploadFailed": "No s'ha pogut carregar {{name}}", + "uploadDisabled": "Les càrregues estan desactivades per a aquesta connexió", + "driveUnavailable": "Activa la redirecció de la unitat RDP abans de carregar fitxers", + "driveNotWritable": "guacd no pot escriure a la carpeta de la unitat. Comproveu GUACD_DRIVE_PATH (o la ruta de la unitat de l'amfitrió) i els seus permisos.", + "dropToUpload": "Deixa anar els fitxers per pujar-los" + }, + "toolbar": { + "ctrlAltDel": "Ctrl+Alt+Supr", + "winL": "Win+L (Pantalla de bloqueig)", + "winKey": "Clau de Windows", + "superL": "Super+L (Pantalla de bloqueig)", + "superKey": "Superclau", + "super": "Súper", + "cmdL": "Cmd+L (Pantalla de bloqueig)", + "cmdKey": "Tecla de comandament", + "cmd": "Cmd", + "ctrl": "Ctrl", + "alt": "Alt", + "shift": "Majúscules", + "win": "Guanyar", + "stickyActive": "{{key}} (bloquejat - feu clic per alliberar)", + "stickyInactive": "{{key}} (feu clic per bloquejar)", + "esc": "Escapada", + "tab": "Pestanya", + "home": "Inici", + "end": "Final", + "pageUp": "Pàgina amunt", + "pageDown": "Pàgina avall", + "arrowUp": "Fletxa amunt", + "arrowDown": "Fletxa avall", + "arrowLeft": "Fletxa esquerra", + "arrowRight": "Fletxa dreta", + "fnToggle": "Tecles de funció", + "reconnect": "Sessió de reconnexió", + "collapse": "Replega la barra d'eines", + "expand": "Expandeix la barra d'eines", + "dragHandle": "Arrossega per reposicionar", + "hide": "Amaga-ho per a aquesta sessió. Per desactivar-ho permanentment, obriu Configuració de l'amfitrió → General → Barra d'eines de connexió.", + "zoomIn": "Amplia la imatge", + "zoomOut": "Allunya", + "resetZoom": "Restableix el zoom", + "fitToScreen": "Ajusta a la pantalla", + "switchToTrackpad": "Canvia al mode trackpad (arrossega per moure el cursor, toca per fer clic)", + "switchToTouch": "Canvia al mode tàctil (toca directament on vols fer clic)" + } + }, + "hosts": { + "nativeRdpOpened": "Obert a l'escriptori remot de Windows", + "nativeRdpFailed": "No s'ha pogut obrir l'escriptori remot de Windows", + "openNativeRdp": "Obre a l'escriptori remot de Windows", + "guac": { + "connection": "Connexió", + "authentication": "Autenticació", + "storedCredential": "Credencial emmagatzemada", + "authMethod": "Mètode d'autenticació", + "authTypeNoneDesc": "No s'emmagatzemen les credencials. Se us demanarà un nom d'usuari i una contrasenya cada vegada que us connecteu; no es desen.", + "selectCredential": "Selecciona una credencial...", + "connectionSettings": "Configuració de connexió", + "displaySettings": "Configuració de la pantalla", + "audioSettings": "Configuració d'àudio", + "rdpPerformance": "Rendiment de l'RDP", + "deviceRedirection": "Redirecció de dispositius", + "session": "Sessió", + "gateway": "Porta d'entrada", + "remoteApp": "Aplicació remota", + "clipboard": "Porta-retalls", + "sessionRecording": "Gravació de sessions", + "wakeOnLan": "Wake-on-LAN", + "vncSettings": "Configuració de VNC", + "terminalSettings": "Configuració del terminal", + "rdpPort": "Port RDP", + "username": "Nom d'usuari", + "password": "Contrasenya", + "passwordSaved": "Contrasenya desada, escriu per canviar-la", + "domain": "Domini", + "securityMode": "Mode de seguretat", + "width": "Amplada", + "height": "Alçada", + "dpi": "DPI", + "clientName": "Nom del client", + "initialProgram": "Programa inicial", + "serverLayout": "Disseny del servidor", + "timezone": "Zona horària", + "loadBalanceInfo": "Informació de balanç de càrrega / Galeta", + "loadBalanceInfoDesc": "Galeta del broker de connexió RD per a l'equilibri de càrrega de granges RDS (per exemple, tsv://MS Terminal Services Plugin.1.CollectionName)", + "guacdProxy": "Proxy guacd", + "guacdHostname": "Host guacd", + "guacdHostnamePlaceholder": "Predeterminat global", + "guacdPort": "Port de Guacd", + "guacdProxyDesc": "Substitueix la instància global de guacd per a aquesta connexió. Deixa-ho en blanc per utilitzar el guacd configurat globalment.", + "gatewayHostname": "Nom de l'amfitrió de la passarel·la", + "gatewayPort": "Port de passarel·la", + "gatewayUsername": "Nom d'usuari de la passarel·la", + "gatewayPassword": "Contrasenya de la passarel·la", + "gatewayDomain": "Domini de passarel·la", + "remoteAppProgram": "Programa RemoteApp", + "workingDirectory": "Directori de treball", + "arguments": "Arguments", + "normalizeLineEndings": "Normalitzar els finals de línia", + "macAddress": "Adreça MAC", + "broadcastAddress": "Adreça de difusió", + "udpPort": "Port UDP", + "waitTimeS": "Temps d'espera (s)", + "driveName": "Nom de la unitat", + "drivePath": "Camí de conducció", + "ignoreCertificate": "Ignora el certificat", + "ignoreCertificateDesc": "Permet connexions a amfitrions amb certificats autosignats", + "forceLossless": "Força sense pèrdues", + "forceLosslessDesc": "Força la codificació d'imatges sense pèrdues (més qualitat, més amplada de banda)", + "disableAudio": "Desactiva l'àudio", + "disableAudioDesc": "Silencia tot l'àudio de la sessió remota", + "enableAudioInput": "Activa l'entrada d'àudio (micròfon)", + "enableAudioInputDesc": "Reenvia el micròfon local a la sessió remota", + "wallpaper": "Fons de pantalla", + "wallpaperDesc": "Mostra el fons de pantalla de l'escriptori (desactivar-lo millora el rendiment)", + "theming": "Tematització", + "themingDesc": "Habilita els temes i estils visuals", + "fontSmoothing": "Suavitzat de fonts", + "fontSmoothingDesc": "Activa la renderització de fonts ClearType", + "fullWindowDrag": "Arrossegar per tota la finestra", + "fullWindowDragDesc": "Mostra el contingut de la finestra mentre arrossegues", + "desktopComposition": "Composició d'escriptori", + "desktopCompositionDesc": "Activa els efectes Aero Glass", + "menuAnimations": "Animacions de menú", + "menuAnimationsDesc": "Activa les animacions de diapositives i esvaïment del menú", + "disableBitmapCaching": "Desactiva la memòria cau de mapes de bits", + "disableBitmapCachingDesc": "Desactiva la memòria cau de mapes de bits (pot ajudar amb errors)", + "disableOffscreenCaching": "Desactiva la memòria cau fora de pantalla", + "disableOffscreenCachingDesc": "Desactiva la memòria cau fora de pantalla", + "disableGlyphCaching": "Desactiva la memòria cau de glifs", + "disableGlyphCachingDesc": "Desactiva la memòria cau de glifos", + "enableGfx": "Activa els efectes especials", + "enableGfxDesc": "Utilitza el canal de gràfics RemoteFX", + "enablePrinting": "Habilita la impressió", + "enablePrintingDesc": "Redirigir les impressores locals a la sessió remota", + "enableDriveRedirection": "Activa la redirecció de la unitat", + "enableDriveRedirectionDesc": "Assignar una carpeta local com a unitat a la sessió remota", + "createDrivePath": "Crea una ruta de conducció", + "createDrivePathDesc": "Crea automàticament la carpeta si no existeix", + "disableDownload": "Desactiva la descàrrega", + "disableDownloadDesc": "Impedir la descàrrega de fitxers des de la sessió remota", + "disableUpload": "Desactiva la càrrega", + "disableUploadDesc": "Impedir la càrrega de fitxers a la sessió remota", + "enableTouch": "Activa el tacte", + "enableTouchDesc": "Activa el reenviament d'entrada tàctil", + "consoleSession": "Sessió de consola", + "consoleSessionDesc": "Connecta't a la consola (sessió 0) en comptes d'una nova sessió", + "sendWolPacket": "Enviar paquet WOL", + "sendWolPacketDesc": "Envia un paquet màgic per despertar aquest host abans de connectar-se", + "disableCopy": "Desactiva la còpia", + "disableCopyDesc": "Impedir la còpia de text des de la sessió remota", + "disablePaste": "Desactiva l'enganxament", + "disablePasteDesc": "Impedir enganxar text a la sessió remota", + "createPathIfMissing": "Crea un camí si falta", + "createPathIfMissingDesc": "Crea automàticament el directori d'enregistrament", + "excludeOutput": "Exclou la sortida", + "excludeOutputDesc": "No enregistrar la sortida de pantalla (només metadades)", + "excludeMouse": "Exclou el ratolí", + "excludeMouseDesc": "No enregistreu els moviments del ratolí", + "includeKeystrokes": "Inclou les pulsacions de tecles", + "includeKeystrokesDesc": "Enregistra les pulsacions de tecles en brut a més de la sortida de la pantalla", + "vncPort": "Port VNC", + "vncPassword": "Contrasenya de VNC", + "vncUsernameOptional": "Nom d'usuari (opcional)", + "vncLeaveBlank": "Deixeu-ho en blanc si no és necessari", + "cursorMode": "Mode del cursor", + "swapRedBlue": "Intercanvia vermell/blau", + "swapRedBlueDesc": "Intercanvia els canals de color vermell i blau (corregeix alguns problemes de color)", + "readOnly": "Només lectura", + "readOnlyDesc": "Visualitza la pantalla remota sense enviar cap entrada", + "telnetPort": "Port Telnet", + "terminalType": "Tipus de terminal", + "fontName": "Nom de la font", + "fontSize": "Mida de la lletra", + "colorScheme": "Esquema de colors", + "backspaceKey": "Tecla Retrocés" + } + }, + "onboarding": { + "feature_desktop": "Escriptori remot", + "feature_desktop_desc": "Obriu sessions RDP, VNC i Telnet en una pestanya, igual que SSH." + } +} diff --git a/plugins/remote-desktop/locales/translated/cs_CZ.json b/plugins/remote-desktop/locales/translated/cs_CZ.json new file mode 100644 index 000000000..d6038ddad --- /dev/null +++ b/plugins/remote-desktop/locales/translated/cs_CZ.json @@ -0,0 +1,214 @@ +{ + "remoteDesktop": { + "connecting": "Připojování k relaci {{type}}...", + "checkingGuacd": "Kontrola služby vzdálené plochy...", + "requestingToken": "Žádost o token připojení {{type}}...", + "openingSession": "Otevírání {{type}} relace...", + "negotiating": "Vyjednávání {{type}} podání ruky...", + "sessionReady": "{{type}} relace připravena", + "connectionError": "Chyba připojení", + "connectionFailed": "Připojení se nezdařilo", + "failedToConnect": "Nepodařilo se získat token připojení", + "hostNotFound": "Hostitel nenalezen", + "noHostSelected": "Nebyl vybrán žádný hostitel", + "reconnect": "Znovu se připojte", + "retry": "Zkusit znovu", + "guacdUnavailable": "Služba vzdálené plochy (guacd) není k dispozici. Ujistěte se prosím, že je guacd spuštěná, přístupná a správně nakonfigurovaná v nastavení administrátora.", + "credentialPromptTitle": "Zadejte přihlašovací údaje RDP", + "credentialPromptDescription": "Tento hostitel je nastaven tak, aby při připojení vyžadoval přihlašovací údaje. Tyto přihlašovací údaje se používají pouze pro tuto relaci a neukládají se.", + "connect": "Připojit", + "ctrlAltDel": "Ctrl+Alt+Del", + "files": { + "title": "Soubory na Disku", + "parent": "Nadřazený adresář", + "refresh": "Obnovit", + "empty": "Tato složka je prázdná", + "listFailed": "Tuto složku se nepodařilo přečíst.", + "download": "Stáhnout", + "downloadFailed": "Stažení se nezdařilo {{name}}", + "upload": "Nahrát soubory", + "uploading": "Nahrávání {{name}}...", + "uploaded": "Nahráno {{name}}", + "uploadFailed": "Nahrávání se nezdařilo {{name}}", + "uploadDisabled": "Nahrávání je pro toto připojení zakázáno.", + "driveUnavailable": "Před nahráváním souborů povolte přesměrování disku RDP", + "driveNotWritable": "Příkaz guacd nemůže zapisovat do složky na disku. Zkontrolujte cestu k disku GUACD_DRIVE_PATH (nebo cestu k disku hostitele) a její oprávnění.", + "dropToUpload": "Přetáhněte soubory k nahrání" + }, + "toolbar": { + "ctrlAltDel": "Ctrl+Alt+Del", + "winL": "Win+L (Zamknout obrazovku)", + "winKey": "Klávesa Windows", + "superL": "Super+L (Zamykací obrazovka)", + "superKey": "Super klíč", + "super": "Super", + "cmdL": "Cmd+L (Zamykací obrazovka)", + "cmdKey": "Příkazový klíč", + "cmd": "Příkaz", + "ctrl": "Ctrl", + "alt": "Alternativní", + "shift": "Posun", + "win": "Vyhrát", + "stickyActive": "{{key}} (zajištěno - kliknutím uvolníte)", + "stickyInactive": "{{key}} (kliknutím zajistíte)", + "esc": "Uniknout", + "tab": "Záložka", + "home": "Domov", + "end": "Konec", + "pageUp": "Stránka nahoru", + "pageDown": "Stránka dolů", + "arrowUp": "Šipka nahoru", + "arrowDown": "Šipka dolů", + "arrowLeft": "Šipka vlevo", + "arrowRight": "Šipka vpravo", + "fnToggle": "Funkční klávesy", + "reconnect": "Znovu připojit relaci", + "collapse": "Sbalit panel nástrojů", + "expand": "Rozbalit panel nástrojů", + "dragHandle": "Přetažením změníte pozici", + "hide": "Skrýt pro tuto relaci. Chcete-li jej trvale zakázat, otevřete Nastavení hostitele → Obecné → Panel nástrojů pro připojení.", + "zoomIn": "Přiblížit", + "zoomOut": "Oddálit", + "resetZoom": "Obnovit zoom", + "fitToScreen": "Přizpůsobit obrazovce", + "switchToTrackpad": "Přepnout do režimu trackpadu (tažením přesunete kurzor, klepnutím kliknete)", + "switchToTouch": "Přepnout do dotykového režimu (klepněte přímo na místo, kam chcete kliknout)" + } + }, + "hosts": { + "nativeRdpOpened": "Otevřeno ve Vzdálené ploše systému Windows", + "nativeRdpFailed": "Nepodařilo se otevřít Vzdálenou plochu systému Windows", + "openNativeRdp": "Otevřít ve Vzdálené ploše systému Windows", + "guac": { + "connection": "Spojení", + "authentication": "Ověřování", + "storedCredential": "Uložené přihlašovací údaje", + "authMethod": "Metoda ověřování", + "authTypeNoneDesc": "Nejsou uloženy žádné přihlašovací údaje. Při každém připojení budete vyzváni k zadání uživatelského jména a hesla; tyto údaje se neukládají.", + "selectCredential": "Vyberte pověření...", + "connectionSettings": "Nastavení připojení", + "displaySettings": "Nastavení displeje", + "audioSettings": "Nastavení zvuku", + "rdpPerformance": "Výkon RDP", + "deviceRedirection": "Přesměrování zařízení", + "session": "Zasedání", + "gateway": "Brána", + "remoteApp": "Vzdálená aplikace", + "clipboard": "Schránka", + "sessionRecording": "Nahrávání relace", + "wakeOnLan": "Probuzení přes LAN", + "vncSettings": "Nastavení VNC", + "terminalSettings": "Nastavení terminálu", + "rdpPort": "RDP port", + "username": "Uživatelské jméno", + "password": "Heslo", + "passwordSaved": "Heslo uloženo, zadejte heslo pro změnu", + "domain": "Doména", + "securityMode": "Bezpečnostní režim", + "width": "Šířka", + "height": "Výška", + "dpi": "DPI", + "clientName": "Jméno klienta", + "initialProgram": "Počáteční program", + "serverLayout": "Rozložení serveru", + "timezone": "Časové pásmo", + "loadBalanceInfo": "Informace o vyrovnávání zátěže / soubor cookie", + "loadBalanceInfoDesc": "Soubor cookie RD Connection Broker pro vyvažování zátěže farmy RDS (např. tsv://MS Terminal Services Plugin.1.CollectionName)", + "guacdProxy": "Proxy GUACD", + "guacdHostname": "Hostitel guacd", + "guacdHostnamePlaceholder": "Globální výchozí nastavení", + "guacdPort": "Port GUACD", + "guacdProxyDesc": "Pro toto připojení přepište globální instanci guacd. Pokud chcete použít globálně nakonfigurovaný guacd, ponechte pole prázdné.", + "gatewayHostname": "Název hostitele brány", + "gatewayPort": "Port brány", + "gatewayUsername": "Uživatelské jméno brány", + "gatewayPassword": "Heslo brány", + "gatewayDomain": "Doména brány", + "remoteAppProgram": "Program RemoteApp", + "workingDirectory": "Pracovní adresář", + "arguments": "Argumenty", + "normalizeLineEndings": "Normalizovat konce řádků", + "macAddress": "MAC adresa", + "broadcastAddress": "Vysílací adresa", + "udpPort": "UDP port", + "waitTimeS": "Čekací doba (s)", + "driveName": "Název disku", + "drivePath": "Cesta k jednotce", + "ignoreCertificate": "Ignorovat certifikát", + "ignoreCertificateDesc": "Povolit připojení k hostitelům s certifikáty podepsanými držitelem", + "forceLossless": "Vynutit bezztrátové", + "forceLosslessDesc": "Vynucení bezztrátového kódování obrazu (vyšší kvalita, větší šířka pásma)", + "disableAudio": "Zakázat zvuk", + "disableAudioDesc": "Ztlumit veškerý zvuk ze vzdálené relace", + "enableAudioInput": "Povolit zvukový vstup (mikrofon)", + "enableAudioInputDesc": "Přesměrování lokálního mikrofonu do vzdálené relace", + "wallpaper": "Tapeta", + "wallpaperDesc": "Zobrazit tapetu plochy (zakázání zlepšuje výkon)", + "theming": "Témata", + "themingDesc": "Povolit vizuální motivy a styly", + "fontSmoothing": "Vyhlazování písma", + "fontSmoothingDesc": "Povolit vykreslování písma ClearType", + "fullWindowDrag": "Přetažení celého okna", + "fullWindowDragDesc": "Zobrazit obsah okna při přetahování", + "desktopComposition": "Složení plochy", + "desktopCompositionDesc": "Povolit efekty Aero Glass", + "menuAnimations": "Animace v menu", + "menuAnimationsDesc": "Povolit animace prolínání a snímání nabídek", + "disableBitmapCaching": "Zakázat ukládání bitmap do mezipaměti", + "disableBitmapCachingDesc": "Vypnout mezipaměť bitmap (může pomoci s chybami)", + "disableOffscreenCaching": "Zakázat ukládání do mezipaměti mimo obrazovku", + "disableOffscreenCachingDesc": "Vypnout mezipaměť mimo obrazovku", + "disableGlyphCaching": "Zakázat ukládání glyfů do mezipaměti", + "disableGlyphCachingDesc": "Vypnout mezipaměť glyfů", + "enableGfx": "Povolit grafické efekty", + "enableGfxDesc": "Použití grafického kanálu RemoteFX", + "enablePrinting": "Povolit tisk", + "enablePrintingDesc": "Přesměrování lokálních tiskáren na vzdálenou relaci", + "enableDriveRedirection": "Povolit přesměrování disku", + "enableDriveRedirectionDesc": "Namapování lokální složky jako jednotky ve vzdálené relaci", + "createDrivePath": "Vytvořit cestu k disku", + "createDrivePathDesc": "Automaticky vytvořit složku, pokud neexistuje", + "disableDownload": "Zakázat stahování", + "disableDownloadDesc": "Zabránit stahování souborů ze vzdálené relace", + "disableUpload": "Zakázat nahrávání", + "disableUploadDesc": "Zabránit nahrávání souborů do vzdálené relace", + "enableTouch": "Povolit dotyk", + "enableTouchDesc": "Povolit přesměrování dotykového vstupu", + "consoleSession": "Relace konzole", + "consoleSessionDesc": "Připojení ke konzoli (relace 0) namísto nové relace", + "sendWolPacket": "Odeslat paket WOL", + "sendWolPacketDesc": "Odeslat magický paket pro probuzení tohoto hostitele před připojením", + "disableCopy": "Zakázat kopírování", + "disableCopyDesc": "Zabránit kopírování textu ze vzdálené relace", + "disablePaste": "Zakázat vkládání", + "disablePasteDesc": "Zabránit vkládání textu do vzdálené relace", + "createPathIfMissing": "Vytvořit cestu, pokud chybí", + "createPathIfMissingDesc": "Automaticky vytvořit adresář pro nahrávání", + "excludeOutput": "Vyloučit výstup", + "excludeOutputDesc": "Nezaznamenávat výstup obrazovky (pouze metadata)", + "excludeMouse": "Vyloučit myš", + "excludeMouseDesc": "Nezaznamenávat pohyby myši", + "includeKeystrokes": "Zahrnout klávesové zkratky", + "includeKeystrokesDesc": "Zaznamenávat nezpracované stisky kláves kromě výstupu na obrazovku", + "vncPort": "VNC port", + "vncPassword": "Heslo VNC", + "vncUsernameOptional": "Uživatelské jméno (volitelné)", + "vncLeaveBlank": "Pokud není vyžadováno, nechte prázdné.", + "cursorMode": "Režim kurzoru", + "swapRedBlue": "Prohodit červenou/modrou", + "swapRedBlueDesc": "Prohoďte červený a modrý barevný kanál (opravuje některé problémy s barvami)", + "readOnly": "Pouze pro čtení", + "readOnlyDesc": "Zobrazení vzdálené obrazovky bez odesílání jakýchkoli vstupních dat", + "telnetPort": "Telnetový port", + "terminalType": "Typ terminálu", + "fontName": "Název písma", + "fontSize": "Velikost písma", + "colorScheme": "Barevné schéma", + "backspaceKey": "Klávesa Backspace" + } + }, + "onboarding": { + "feature_desktop": "Vzdálená plocha", + "feature_desktop_desc": "Otevírejte relace RDP, VNC a Telnet na kartě, stejně jako SSH." + } +} diff --git a/plugins/remote-desktop/locales/translated/da_DK.json b/plugins/remote-desktop/locales/translated/da_DK.json new file mode 100644 index 000000000..571123d1b --- /dev/null +++ b/plugins/remote-desktop/locales/translated/da_DK.json @@ -0,0 +1,214 @@ +{ + "remoteDesktop": { + "connecting": "Forbinder til {{type}} session...", + "checkingGuacd": "Tjekker fjernskrivebordstjeneste...", + "requestingToken": "Anmoder om {{type}} forbindelsestoken...", + "openingSession": "Åbner {{type}} session...", + "negotiating": "Forhandler {{type}} håndtryk...", + "sessionReady": "{{type}} session klar", + "connectionError": "Forbindelsesfejl", + "connectionFailed": "Forbindelsen mislykkedes", + "failedToConnect": "Kunne ikke hente forbindelsestoken", + "hostNotFound": "Værten blev ikke fundet", + "noHostSelected": "Ingen vært valgt", + "reconnect": "Genopret forbindelse", + "retry": "Prøv igen", + "guacdUnavailable": "Fjernskrivebordstjenesten (guacd) er ikke tilgængelig. Sørg for, at guacd kører, er tilgængelig og konfigureret korrekt i administratorindstillingerne.", + "credentialPromptTitle": "Indtast RDP-legitimationsoplysninger", + "credentialPromptDescription": "Denne vært er indstillet til at bede om legitimationsoplysninger ved forbindelse. De bruges kun til denne session og gemmes ikke.", + "connect": "Forbinde", + "ctrlAltDel": "Ctrl+Alt+Del", + "files": { + "title": "Drev-filer", + "parent": "Forældreregister", + "refresh": "Opfriske", + "empty": "Denne mappe er tom", + "listFailed": "Kunne ikke læse denne mappe", + "download": "Download", + "downloadFailed": "Kunne ikke downloade {{name}}", + "upload": "Upload filer", + "uploading": "Uploader {{name}}...", + "uploaded": "Uploadet {{name}}", + "uploadFailed": "Kunne ikke uploade {{name}}", + "uploadDisabled": "Uploads er deaktiveret for denne forbindelse", + "driveUnavailable": "Aktivér omdirigering af RDP-drev før upload af filer", + "driveNotWritable": "guacd kan ikke skrive til drevmappen. Kontroller GUACD_DRIVE_PATH (eller værtens drevsti) og dens tilladelser.", + "dropToUpload": "Slip filer for at uploade" + }, + "toolbar": { + "ctrlAltDel": "Ctrl+Alt+Del", + "winL": "Win+L (Låseskærm)", + "winKey": "Windows-nøgle", + "superL": "Super+L (Låseskærm)", + "superKey": "Supernøgle", + "super": "Super", + "cmdL": "Cmd+L (Låseskærm)", + "cmdKey": "Kommandotast", + "cmd": "Kommando", + "ctrl": "Ctrl", + "alt": "Alt", + "shift": "Flytte", + "win": "Vinde", + "stickyActive": "{{key}} (låst - klik for at slippe)", + "stickyInactive": "{{key}} (klik for at låse)", + "esc": "Flugt", + "tab": "Faneblad", + "home": "Hjem", + "end": "Ende", + "pageUp": "Side op", + "pageDown": "Side ned", + "arrowUp": "Pil op", + "arrowDown": "Pil ned", + "arrowLeft": "Pil til venstre", + "arrowRight": "Pil til højre", + "fnToggle": "Funktionstaster", + "reconnect": "Genopret forbindelse til sessionen", + "collapse": "Skjul værktøjslinjen", + "expand": "Udvid værktøjslinjen", + "dragHandle": "Træk for at flytte", + "hide": "Skjul for denne session. For at deaktivere det permanent skal du åbne Værtsindstillinger → Generelt → Forbindelsesværktøjslinje.", + "zoomIn": "Zoom ind", + "zoomOut": "Zoom ud", + "resetZoom": "Nulstil zoom", + "fitToScreen": "Tilpas til skærm", + "switchToTrackpad": "Skift til trackpad-tilstand (træk for at flytte markøren, tryk for at klikke)", + "switchToTouch": "Skift til berøringstilstand (tryk direkte der, hvor du vil klikke)" + } + }, + "hosts": { + "nativeRdpOpened": "Åbnet i Windows Fjernskrivebord", + "nativeRdpFailed": "Kunne ikke åbne Windows Fjernskrivebord", + "openNativeRdp": "Åbn i Windows Fjernskrivebord", + "guac": { + "connection": "Forbindelse", + "authentication": "Godkendelse", + "storedCredential": "Gemte legitimationsoplysninger", + "authMethod": "Godkendelsesmetode", + "authTypeNoneDesc": "Ingen loginoplysninger gemmes. Du vil blive bedt om et brugernavn og en adgangskode, hver gang du opretter forbindelse; de gemmes ikke.", + "selectCredential": "Vælg en legitimationsoplysninger...", + "connectionSettings": "Forbindelsesindstillinger", + "displaySettings": "Skærmindstillinger", + "audioSettings": "Lydindstillinger", + "rdpPerformance": "RDP-ydeevne", + "deviceRedirection": "Omdirigering af enhed", + "session": "Session", + "gateway": "Gateway", + "remoteApp": "Fjernbetjening", + "clipboard": "Udklipsholder", + "sessionRecording": "Sessionsoptagelse", + "wakeOnLan": "Wake-on-LAN", + "vncSettings": "VNC-indstillinger", + "terminalSettings": "Terminalindstillinger", + "rdpPort": "RDP-port", + "username": "Brugernavn", + "password": "Adgangskode", + "passwordSaved": "Adgangskode gemt, skriv for at ændre", + "domain": "Domæne", + "securityMode": "Sikkerhedstilstand", + "width": "Bredde", + "height": "Højde", + "dpi": "DPI", + "clientName": "Klientnavn", + "initialProgram": "Indledende program", + "serverLayout": "Serverlayout", + "timezone": "Tidszone", + "loadBalanceInfo": "Oplysninger om belastningsbalance / Cookie", + "loadBalanceInfoDesc": "RD Connection Broker-cookie til belastningsbalancering af RDS-farm (f.eks. tsv://MS Terminal Services Plugin.1.CollectionName)", + "guacdProxy": "guacd Proxy", + "guacdHostname": "guacd-vært", + "guacdHostnamePlaceholder": "Global standard", + "guacdPort": "guacd Port", + "guacdProxyDesc": "Tilsidesæt den globale guacd-instans for denne forbindelse. Lad være tom for at bruge den globalt konfigurerede guacd.", + "gatewayHostname": "Gateway-værtsnavn", + "gatewayPort": "Gateway-porten", + "gatewayUsername": "Gateway-brugernavn", + "gatewayPassword": "Gateway-adgangskode", + "gatewayDomain": "Gateway-domæne", + "remoteAppProgram": "RemoteApp-programmet", + "workingDirectory": "Arbejdskatalog", + "arguments": "Argumenter", + "normalizeLineEndings": "Normaliser linjeafslutninger", + "macAddress": "MAC-adresse", + "broadcastAddress": "Udsendelsesadresse", + "udpPort": "UDP-port", + "waitTimeS": "Ventetid (s)", + "driveName": "Drevnavn", + "drivePath": "Kørselssti", + "ignoreCertificate": "Ignorer certifikat", + "ignoreCertificateDesc": "Tillad forbindelser til værter med selvsignerede certifikater", + "forceLossless": "Tving tabsfri", + "forceLosslessDesc": "Tving tabsfri billedkodning (højere kvalitet, mere båndbredde)", + "disableAudio": "Deaktiver lyd", + "disableAudioDesc": "Slå al lyd fra fra fjernsessionen", + "enableAudioInput": "Aktivér lydindgang (mikrofon)", + "enableAudioInputDesc": "Videresend den lokale mikrofon til den eksterne session", + "wallpaper": "Tapet", + "wallpaperDesc": "Vis skrivebordsbaggrund (deaktivering forbedrer ydeevnen)", + "theming": "Temaer", + "themingDesc": "Aktivér visuelle temaer og stilarter", + "fontSmoothing": "Skrifttypeudjævning", + "fontSmoothingDesc": "Aktivér gengivelse af ClearType-skrifttyper", + "fullWindowDrag": "Træk i hele vinduet", + "fullWindowDragDesc": "Vis vinduesindhold under træk", + "desktopComposition": "Skrivebordskomposition", + "desktopCompositionDesc": "Aktivér Aero Glass-effekter", + "menuAnimations": "Menuanimationer", + "menuAnimationsDesc": "Aktivér menuudtoning og slideanimationer", + "disableBitmapCaching": "Deaktiver bitmap-caching", + "disableBitmapCachingDesc": "Slå bitmap-cache fra (kan muligvis hjælpe med fejl)", + "disableOffscreenCaching": "Deaktiver cachelagring uden for skærmen", + "disableOffscreenCachingDesc": "Slå cache uden for skærmen fra", + "disableGlyphCaching": "Deaktiver glyf-cachelagring", + "disableGlyphCachingDesc": "Slå glyfcache fra", + "enableGfx": "Aktivér GFX", + "enableGfxDesc": "Brug RemoteFX-grafikpipeline", + "enablePrinting": "Aktivér udskrivning", + "enablePrintingDesc": "Omdiriger lokale printere til fjernsessionen", + "enableDriveRedirection": "Aktivér drevomdirigering", + "enableDriveRedirectionDesc": "Tilknyt en lokal mappe som et drev i den eksterne session", + "createDrivePath": "Opret drevsti", + "createDrivePathDesc": "Opret mappen automatisk, hvis den ikke findes", + "disableDownload": "Deaktiver download", + "disableDownloadDesc": "Forhindr download af filer fra fjernsessionen", + "disableUpload": "Deaktiver upload", + "disableUploadDesc": "Forhindr upload af filer til fjernsessionen", + "enableTouch": "Aktivér berøring", + "enableTouchDesc": "Aktivér videresendelse af berøringsinput", + "consoleSession": "Konsolsession", + "consoleSessionDesc": "Opret forbindelse til konsollen (session 0) i stedet for en ny session", + "sendWolPacket": "Send WOL-pakke", + "sendWolPacketDesc": "Send en magisk pakke for at vække denne vært før forbindelse", + "disableCopy": "Deaktiver kopiering", + "disableCopyDesc": "Forhindr kopiering af tekst fra fjernsessionen", + "disablePaste": "Deaktiver indsætning", + "disablePasteDesc": "Forhindr indsættelse af tekst i fjernsessionen", + "createPathIfMissing": "Opret sti, hvis den mangler", + "createPathIfMissingDesc": "Opret automatisk optagelsesmappen", + "excludeOutput": "Udeluk output", + "excludeOutputDesc": "Optag ikke skærmoutput (kun metadata)", + "excludeMouse": "Udeluk mus", + "excludeMouseDesc": "Optag ikke musebevægelser", + "includeKeystrokes": "Inkluder tastetryk", + "includeKeystrokesDesc": "Optag rå tastetryk ud over skærmoutput", + "vncPort": "VNC-port", + "vncPassword": "VNC-adgangskode", + "vncUsernameOptional": "Brugernavn (valgfrit)", + "vncLeaveBlank": "Lad stå tomt, hvis det ikke er nødvendigt", + "cursorMode": "Markørtilstand", + "swapRedBlue": "Skift rød/blå", + "swapRedBlueDesc": "Byt de røde og blå farvekanaler (løser nogle farveproblemer)", + "readOnly": "Skrivebeskyttet", + "readOnlyDesc": "Se fjernskærmen uden at sende input", + "telnetPort": "Telnet-port", + "terminalType": "Terminaltype", + "fontName": "Skrifttypenavn", + "fontSize": "Skriftstørrelse", + "colorScheme": "Farveskema", + "backspaceKey": "Tilbagetast" + } + }, + "onboarding": { + "feature_desktop": "Fjernskrivebord", + "feature_desktop_desc": "Åbn RDP-, VNC- og Telnet-sessioner i en fane, ligesom med SSH." + } +} diff --git a/plugins/remote-desktop/locales/translated/de_DE.json b/plugins/remote-desktop/locales/translated/de_DE.json new file mode 100644 index 000000000..f9cd43e46 --- /dev/null +++ b/plugins/remote-desktop/locales/translated/de_DE.json @@ -0,0 +1,214 @@ +{ + "remoteDesktop": { + "connecting": "Verbinde mit {{type}}-Sitzung...", + "checkingGuacd": "Überprüfung des Remotedesktopdienstes...", + "requestingToken": "Verbindungstoken {{type}} wird angefordert...", + "openingSession": "Öffne {{type}} Sitzung...", + "negotiating": "Verhandlung {{type}} Handschlag...", + "sessionReady": "{{type}} Sitzung bereit", + "connectionError": "Verbindungsfehler", + "connectionFailed": "Verbindung fehlgeschlagen", + "failedToConnect": "Fehler beim Abrufen des Verbindungstokens", + "hostNotFound": "Host nicht gefunden", + "noHostSelected": "Kein Host ausgewählt", + "reconnect": "Erneut verbinden", + "retry": "Wiederholen", + "guacdUnavailable": "Der Remote-Desktop-Dienst (guacd) ist nicht verfügbar. Bitte stellen Sie sicher, dass guacd ausgeführt wird, erreichbar ist und in den Admin-Einstellungen richtig konfiguriert ist.", + "credentialPromptTitle": "Geben Sie die RDP-Anmeldeinformationen ein.", + "credentialPromptDescription": "Dieser Host ist so konfiguriert, dass er beim Verbindungsaufbau zur Eingabe von Anmeldeinformationen auffordert. Diese werden nur für diese Sitzung verwendet und nicht gespeichert.", + "connect": "Verbinden", + "ctrlAltDel": "Strg+Alt+Entf", + "files": { + "title": "Laufwerksdateien", + "parent": "Übergeordnetes Verzeichnis", + "refresh": "Aktualisieren", + "empty": "Dieser Ordner ist leer", + "listFailed": "Dieser Ordner konnte nicht gelesen werden", + "download": "Herunterladen", + "downloadFailed": "Download fehlgeschlagen {{name}}", + "upload": "Dateien hochladen", + "uploading": "Hochladen {{name}}...", + "uploaded": "Hochgeladen {{name}}", + "uploadFailed": "Hochladen fehlgeschlagen {{name}}", + "uploadDisabled": "Uploads sind für diese Verbindung deaktiviert.", + "driveUnavailable": "Aktivieren Sie die RDP-Laufwerksumleitung, bevor Sie Dateien hochladen.", + "driveNotWritable": "guacd kann nicht in den Laufwerksordner schreiben. Überprüfen Sie GUACD_DRIVE_PATH (oder den Laufwerkspfad des Hosts) und dessen Berechtigungen.", + "dropToUpload": "Dateien zum Hochladen per Drag & Drop ablegen" + }, + "toolbar": { + "ctrlAltDel": "Strg+Alt+Entf", + "winL": "Win+L (Bildschirm sperren)", + "winKey": "Windows-Taste", + "superL": "Super+L (Sperrbildschirm)", + "superKey": "Super Key", + "super": "Super", + "cmdL": "Cmd+L (Sperrbildschirm)", + "cmdKey": "Befehlstaste", + "cmd": "Cmd", + "ctrl": "Strg", + "alt": "Alt", + "shift": "Umschalt", + "win": "Win", + "stickyActive": "{{key}} (eingerastet – zum Lösen klicken)", + "stickyInactive": "{{key}} (zum Einrasten klicken)", + "esc": "Escape", + "tab": "Tab", + "home": "Pos1", + "end": "Ende", + "pageUp": "Bild auf", + "pageDown": "Bild ab", + "arrowUp": "Pfeil nach oben", + "arrowDown": "Pfeil nach unten", + "arrowLeft": "Pfeil nach links", + "arrowRight": "Pfeil nach rechts", + "fnToggle": "Funktionstasten", + "reconnect": "Sitzung erneut verbinden", + "collapse": "Symbolleiste einklappen", + "expand": "Symbolleiste ausklappen", + "dragHandle": "Zum Neupositionieren ziehen", + "hide": "Für diese Sitzung ausblenden. Um es dauerhaft zu deaktivieren, öffnen Sie Host-Einstellungen → Allgemein → Verbindungssymbolleiste.", + "zoomIn": "Vergrößern", + "zoomOut": "Herauszoomen", + "resetZoom": "Zoom zurücksetzen", + "fitToScreen": "An Bildschirm anpassen", + "switchToTrackpad": "In den Trackpad-Modus wechseln (Zum Bewegen des Cursors ziehen, zum Klicken tippen)", + "switchToTouch": "Wechseln Sie in den Touch-Modus (tippen Sie direkt auf die Stelle, an der Sie klicken möchten)." + } + }, + "hosts": { + "nativeRdpOpened": "In Windows-Remotedesktop geöffnet", + "nativeRdpFailed": "Windows-Remotedesktop konnte nicht geöffnet werden", + "openNativeRdp": "In Windows-Remotedesktop öffnen", + "guac": { + "connection": "Verbindung", + "authentication": "Authentifizierung", + "storedCredential": "Gespeicherte Anmeldeinformation", + "authMethod": "Authentifizierungsmethode", + "authTypeNoneDesc": "Es werden keine Zugangsdaten gespeichert. Sie werden bei jeder Verbindung zur Eingabe eines Benutzernamens und eines Passworts aufgefordert; diese werden nicht gespeichert.", + "selectCredential": "Anmeldeinformation auswählen...", + "connectionSettings": "Verbindungseinstellungen", + "displaySettings": "Anzeigeeinstellungen", + "audioSettings": "Audioeinstellungen", + "rdpPerformance": "RDP-Leistung", + "deviceRedirection": "Geräteumleitung", + "session": "Sitzung", + "gateway": "Gateway", + "remoteApp": "RemoteApp", + "clipboard": "Zwischenablage", + "sessionRecording": "Sitzungsaufzeichnung", + "wakeOnLan": "Wake-on-LAN", + "vncSettings": "VNC-Einstellungen", + "terminalSettings": "Terminaleinstellungen", + "rdpPort": "RDP-Port", + "username": "Benutzername", + "password": "Passwort", + "passwordSaved": "Passwort gespeichert, zum Ändern eingeben", + "domain": "Domäne", + "securityMode": "Sicherheitsmodus", + "width": "Breite", + "height": "Höhe", + "dpi": "DPI", + "clientName": "Client-Name", + "initialProgram": "Startprogramm", + "serverLayout": "Tastaturlayout", + "timezone": "Zeitzone", + "loadBalanceInfo": "Lastverteilungsinfo / Cookie", + "loadBalanceInfoDesc": "RD-Verbindungsbroker-Cookie für den Lastausgleich einer RDS-Farm (z.B. tsv://MS Terminal Services Plugin.1.CollectionName)", + "guacdProxy": "guacd-Proxy", + "guacdHostname": "guacd-Host", + "guacdHostnamePlaceholder": "Globaler Standard", + "guacdPort": "guacd-Port", + "guacdProxyDesc": "Überschreibt die globale guacd-Instanz für diese Verbindung. Leer lassen, um die global konfigurierte guacd zu verwenden.", + "gatewayHostname": "Gateway-Hostname", + "gatewayPort": "Gateway-Port", + "gatewayUsername": "Gateway-Benutzername", + "gatewayPassword": "Gateway-Passwort", + "gatewayDomain": "Gateway-Domäne", + "remoteAppProgram": "RemoteApp-Programm", + "workingDirectory": "Arbeitsverzeichnis", + "arguments": "Argumente", + "normalizeLineEndings": "Zeilenenden normalisieren", + "macAddress": "MAC-Adresse", + "broadcastAddress": "Broadcast-Adresse", + "udpPort": "UDP-Port", + "waitTimeS": "Wartezeit (s)", + "driveName": "Laufwerksname", + "drivePath": "Laufwerkspfad", + "ignoreCertificate": "Zertifikat ignorieren", + "ignoreCertificateDesc": "Verbindungen zu Hosts mit selbstsignierten Zertifikaten erlauben", + "forceLossless": "Verlustfreie Übertragung erzwingen", + "forceLosslessDesc": "Verlustfreie Bildcodierung erzwingen (höhere Qualität, mehr Bandbreite)", + "disableAudio": "Audio deaktivieren", + "disableAudioDesc": "Gesamten Ton der Remote-Sitzung stummschalten", + "enableAudioInput": "Audioeingabe aktivieren (Mikrofon)", + "enableAudioInputDesc": "Lokales Mikrofon an die Remote-Sitzung weiterleiten", + "wallpaper": "Hintergrundbild", + "wallpaperDesc": "Desktop-Hintergrundbild anzeigen (Deaktivierung verbessert die Leistung)", + "theming": "Designs", + "themingDesc": "Visuelle Designs und Stile aktivieren", + "fontSmoothing": "Schriftglättung", + "fontSmoothingDesc": "ClearType-Schriftdarstellung aktivieren", + "fullWindowDrag": "Vollständiges Fensterziehen", + "fullWindowDragDesc": "Fensterinhalt beim Ziehen anzeigen", + "desktopComposition": "Desktopkomposition", + "desktopCompositionDesc": "Aero-Glaseffekte aktivieren", + "menuAnimations": "Menüanimationen", + "menuAnimationsDesc": "Ein- und Ausblendeanimationen für Menüs aktivieren", + "disableBitmapCaching": "Bitmap-Caching deaktivieren", + "disableBitmapCachingDesc": "Bitmap-Cache deaktivieren (kann bei Grafikfehlern helfen)", + "disableOffscreenCaching": "Offscreen-Caching deaktivieren", + "disableOffscreenCachingDesc": "Offscreen-Cache deaktivieren", + "disableGlyphCaching": "Glyphen-Caching deaktivieren", + "disableGlyphCachingDesc": "Glyphen-Cache deaktivieren", + "enableGfx": "GFX aktivieren", + "enableGfxDesc": "RemoteFX-Grafikpipeline verwenden", + "enablePrinting": "Drucken aktivieren", + "enablePrintingDesc": "Lokale Drucker an die Remote-Sitzung umleiten", + "enableDriveRedirection": "Laufwerksumleitung aktivieren", + "enableDriveRedirectionDesc": "Lokalen Ordner als Laufwerk in der Remote-Sitzung einbinden", + "createDrivePath": "Laufwerkspfad erstellen", + "createDrivePathDesc": "Ordner automatisch erstellen, falls nicht vorhanden", + "disableDownload": "Download deaktivieren", + "disableDownloadDesc": "Herunterladen von Dateien aus der entfernten Sitzung verhindern", + "disableUpload": "Upload deaktivieren", + "disableUploadDesc": "Hochladen von Dateien in die entfernte Sitzung verhindern", + "enableTouch": "Touch aktivieren", + "enableTouchDesc": "Touch-Eingabeweiterleitung aktivieren", + "consoleSession": "Konsolensitzung", + "consoleSessionDesc": "Mit der Konsole (Sitzung 0) statt mit einer neuen Sitzung verbinden", + "sendWolPacket": "WOL-Paket senden", + "sendWolPacketDesc": "Magic Packet senden, um diesen Host vor dem Verbinden aufzuwecken", + "disableCopy": "Kopieren deaktivieren", + "disableCopyDesc": "Kopieren von Text aus der entfernten Sitzung verhindern", + "disablePaste": "Einfügen deaktivieren", + "disablePasteDesc": "Einfügen von Text in die entfernte Sitzung verhindern", + "createPathIfMissing": "Pfad erstellen, falls nicht vorhanden", + "createPathIfMissingDesc": "Aufzeichnungsverzeichnis automatisch erstellen", + "excludeOutput": "Ausgabe ausschließen", + "excludeOutputDesc": "Bildschirmausgabe nicht aufzeichnen (nur Metadaten)", + "excludeMouse": "Maus ausschließen", + "excludeMouseDesc": "Mausbewegungen nicht aufzeichnen", + "includeKeystrokes": "Tastatureingaben einschließen", + "includeKeystrokesDesc": "Rohe Tastatureingaben zusätzlich zur Bildschirmausgabe aufzeichnen", + "vncPort": "VNC-Port", + "vncPassword": "VNC-Passwort", + "vncUsernameOptional": "Benutzername (optional)", + "vncLeaveBlank": "Leer lassen, falls nicht erforderlich", + "cursorMode": "Cursor-Modus", + "swapRedBlue": "Rot/Blau tauschen", + "swapRedBlueDesc": "Die roten und blauen Farbkanäle tauschen (behebt einige Farbprobleme)", + "readOnly": "Schreibgeschützt", + "readOnlyDesc": "Bildschirm anzeigen, ohne Eingaben zu senden", + "telnetPort": "Telnet-Port", + "terminalType": "Terminaltyp", + "fontName": "Schriftname", + "fontSize": "Schriftgröße", + "colorScheme": "Farbschema", + "backspaceKey": "Backspace-Taste" + } + }, + "onboarding": { + "feature_desktop": "Remote-Desktop", + "feature_desktop_desc": "Öffnen Sie RDP-, VNC- und Telnet-Sitzungen in einem Tab, genau wie bei SSH." + } +} diff --git a/plugins/remote-desktop/locales/translated/el_GR.json b/plugins/remote-desktop/locales/translated/el_GR.json new file mode 100644 index 000000000..7d07e4a81 --- /dev/null +++ b/plugins/remote-desktop/locales/translated/el_GR.json @@ -0,0 +1,214 @@ +{ + "remoteDesktop": { + "connecting": "Σύνδεση σε συνεδρία {{type}}...", + "checkingGuacd": "Έλεγχος υπηρεσίας απομακρυσμένης επιφάνειας εργασίας...", + "requestingToken": "Αίτημα διακριτικού σύνδεσης {{type}}...", + "openingSession": "Άνοιγμα συνεδρίας {{type}}...", + "negotiating": "Διαπραγμάτευση χειραψίας {{type}}...", + "sessionReady": "{{type}} συνεδρία έτοιμη", + "connectionError": "Σφάλμα σύνδεσης", + "connectionFailed": "Η σύνδεση απέτυχε", + "failedToConnect": "Αποτυχία λήψης διακριτικού σύνδεσης", + "hostNotFound": "Δεν βρέθηκε κεντρικός υπολογιστής", + "noHostSelected": "Δεν έχει επιλεγεί κεντρικός υπολογιστής", + "reconnect": "Επανασύνδεση", + "retry": "Δοκιμάζω πάλι", + "guacdUnavailable": "Η υπηρεσία απομακρυσμένης επιφάνειας εργασίας (guacd) δεν είναι διαθέσιμη. Βεβαιωθείτε ότι το guacd εκτελείται και είναι προσβάσιμο, καθώς και ότι έχει ρυθμιστεί σωστά στις ρυθμίσεις διαχειριστή.", + "credentialPromptTitle": "Εισαγάγετε τα διαπιστευτήρια RDP", + "credentialPromptDescription": "Αυτός ο κεντρικός υπολογιστής έχει ρυθμιστεί να ζητά διαπιστευτήρια κατά τη σύνδεση. Χρησιμοποιούνται μόνο για αυτήν την περίοδο σύνδεσης και δεν αποθηκεύονται.", + "connect": "Συνδέω", + "ctrlAltDel": "Ctrl+Alt+Del", + "files": { + "title": "Αρχεία μονάδας δίσκου", + "parent": "Γονικός κατάλογος", + "refresh": "Φρεσκάρω", + "empty": "Αυτός ο φάκελος είναι κενός", + "listFailed": "Αποτυχία ανάγνωσης αυτού του φακέλου", + "download": "Λήψη", + "downloadFailed": "Αποτυχία λήψης {{name}}", + "upload": "Μεταφόρτωση αρχείων", + "uploading": "Μεταφόρτωση {{name}}...", + "uploaded": "Μεταφορτώθηκε {{name}}", + "uploadFailed": "Αποτυχία μεταφόρτωσης {{name}}", + "uploadDisabled": "Οι μεταφορτώσεις είναι απενεργοποιημένες για αυτήν τη σύνδεση", + "driveUnavailable": "Ενεργοποίηση ανακατεύθυνσης μονάδας δίσκου RDP πριν από την αποστολή αρχείων", + "driveNotWritable": "Το guacd δεν μπορεί να γράψει στον φάκελο της μονάδας δίσκου. Ελέγξτε το GUACD_DRIVE_PATH (ή τη διαδρομή μονάδας δίσκου του κεντρικού υπολογιστή) και τα δικαιώματά του.", + "dropToUpload": "Αποθέστε αρχεία για μεταφόρτωση" + }, + "toolbar": { + "ctrlAltDel": "Ctrl+Alt+Del", + "winL": "Win+L (Κλείδωμα οθόνης)", + "winKey": "Κλειδί των Windows", + "superL": "Super+L (Κλείδωμα οθόνης)", + "superKey": "Σούπερ Κλειδί", + "super": "Σούπερ", + "cmdL": "Cmd+L (Κλείδωμα οθόνης)", + "cmdKey": "Πλήκτρο εντολών", + "cmd": "Εκτελεστής", + "ctrl": "Ctrl", + "alt": "Εναλλακτική", + "shift": "Αλλαγή", + "win": "Νίκη", + "stickyActive": "{{key}} (κλειδωμένο - κάντε κλικ για απελευθέρωση)", + "stickyInactive": "{{key}} (κάντε κλικ για να κλειδώσετε)", + "esc": "Διαφυγή", + "tab": "Αυτί", + "home": "Σπίτι", + "end": "Τέλος", + "pageUp": "Σελίδα προς τα πάνω", + "pageDown": "Σελίδα προς τα κάτω", + "arrowUp": "Βέλος προς τα πάνω", + "arrowDown": "Βέλος προς τα κάτω", + "arrowLeft": "Βέλος αριστερά", + "arrowRight": "Βέλος δεξιά", + "fnToggle": "Πλήκτρα λειτουργιών", + "reconnect": "Επανασύνδεση περιόδου σύνδεσης", + "collapse": "Σύμπτυξη γραμμής εργαλείων", + "expand": "Ανάπτυξη γραμμής εργαλείων", + "dragHandle": "Σύρετε για αλλαγή θέσης", + "hide": "Απόκρυψη για αυτήν την περίοδο λειτουργίας. Για να την απενεργοποιήσετε μόνιμα, ανοίξτε τις Ρυθμίσεις κεντρικού υπολογιστή → Γενικά → Γραμμή εργαλείων σύνδεσης.", + "zoomIn": "Μεγέθυνση", + "zoomOut": "Σμίκρυνση", + "resetZoom": "Επαναφορά ζουμ", + "fitToScreen": "Προσαρμογή στην οθόνη", + "switchToTrackpad": "Μετάβαση σε λειτουργία trackpad (σύρσιμο για μετακίνηση του κέρσορα, άγγιγμα για κλικ)", + "switchToTouch": "Μετάβαση σε λειτουργία αφής (πατήστε απευθείας εκεί που θέλετε να κάνετε κλικ)" + } + }, + "hosts": { + "nativeRdpOpened": "Άνοιξε στην Απομακρυσμένη επιφάνεια εργασίας των Windows", + "nativeRdpFailed": "Αποτυχία ανοίγματος της Απομακρυσμένης επιφάνειας εργασίας των Windows", + "openNativeRdp": "Άνοιγμα στην Απομακρυσμένη επιφάνεια εργασίας των Windows", + "guac": { + "connection": "Σύνδεση", + "authentication": "Πιστοποίηση", + "storedCredential": "Αποθηκευμένα διαπιστευτήρια", + "authMethod": "Μέθοδος Εξουσιοδότησης", + "authTypeNoneDesc": "Δεν αποθηκεύονται διαπιστευτήρια. Θα σας ζητείται όνομα χρήστη και κωδικός πρόσβασης κάθε φορά που συνδέεστε. Δεν αποθηκεύονται.", + "selectCredential": "Επιλέξτε ένα πιστοποιητικό...", + "connectionSettings": "Ρυθμίσεις σύνδεσης", + "displaySettings": "Ρυθμίσεις οθόνης", + "audioSettings": "Ρυθμίσεις ήχου", + "rdpPerformance": "Απόδοση RDP", + "deviceRedirection": "Ανακατεύθυνση συσκευής", + "session": "Συνεδρίαση", + "gateway": "Είσοδος πυλών", + "remoteApp": "Απομακρυσμένη εφαρμογή", + "clipboard": "Πρόχειρο", + "sessionRecording": "Ηχογράφηση συνεδρίας", + "wakeOnLan": "Αφύπνιση μέσω LAN", + "vncSettings": "Ρυθμίσεις VNC", + "terminalSettings": "Ρυθμίσεις τερματικού", + "rdpPort": "Θύρα RDP", + "username": "Όνομα χρήστη", + "password": "Σύνθημα", + "passwordSaved": "Ο κωδικός πρόσβασης αποθηκεύτηκε, πληκτρολογήστε για να τον αλλάξετε", + "domain": "Πεδίο ορισμού", + "securityMode": "Λειτουργία ασφαλείας", + "width": "Πλάτος", + "height": "Υψος", + "dpi": "DPI", + "clientName": "Όνομα πελάτη", + "initialProgram": "Αρχικό Πρόγραμμα", + "serverLayout": "Διάταξη διακομιστή", + "timezone": "Ζώνη ώρας", + "loadBalanceInfo": "Πληροφορίες ισορροπίας φορτίου / Cookie", + "loadBalanceInfoDesc": "Cookie RD Connection Broker για εξισορρόπηση φόρτου συστοιχίας RDS (π.χ. tsv://MS Terminal Services Plugin.1.CollectionName)", + "guacdProxy": "guacd Proxy", + "guacdHostname": "οικοδεσπότης guacd", + "guacdHostnamePlaceholder": "Παγκόσμια προεπιλογή", + "guacdPort": "Λιμάνι Guacd", + "guacdProxyDesc": "Παρακάμψτε την καθολική παρουσία guacd για αυτήν τη σύνδεση. Αφήστε το κενό για να χρησιμοποιήσετε την καθολικά διαμορφωμένη παρουσία guacd.", + "gatewayHostname": "Όνομα κεντρικού υπολογιστή πύλης", + "gatewayPort": "Λιμάνι Πύλης", + "gatewayUsername": "Όνομα χρήστη πύλης", + "gatewayPassword": "Κωδικός πρόσβασης πύλης", + "gatewayDomain": "Τομέας πύλης", + "remoteAppProgram": "Πρόγραμμα RemoteApp", + "workingDirectory": "Κατάλογος εργασίας", + "arguments": "Επιχειρήματα", + "normalizeLineEndings": "Κανονικοποίηση τελών γραμμών", + "macAddress": "Διεύθυνση MAC", + "broadcastAddress": "Διεύθυνση μετάδοσης", + "udpPort": "Θύρα UDP", + "waitTimeS": "Χρόνος αναμονής (s)", + "driveName": "Όνομα μονάδας δίσκου", + "drivePath": "Μονοπάτι οδήγησης", + "ignoreCertificate": "Αγνόηση πιστοποιητικού", + "ignoreCertificateDesc": "Επιτρέψτε συνδέσεις σε κεντρικούς υπολογιστές με αυτο-υπογεγραμμένα πιστοποιητικά", + "forceLossless": "Δύναμη χωρίς απώλειες", + "forceLosslessDesc": "Επιβολή κωδικοποίησης εικόνας χωρίς απώλειες (υψηλότερη ποιότητα, μεγαλύτερο εύρος ζώνης)", + "disableAudio": "Απενεργοποίηση ήχου", + "disableAudioDesc": "Σίγαση όλου του ήχου από την απομακρυσμένη συνεδρία", + "enableAudioInput": "Ενεργοποίηση εισόδου ήχου (Μικρόφωνο)", + "enableAudioInputDesc": "Προώθηση τοπικού μικροφώνου στην απομακρυσμένη συνεδρία", + "wallpaper": "Ταπετσαρία", + "wallpaperDesc": "Εμφάνιση ταπετσαρίας επιφάνειας εργασίας (η απενεργοποίηση βελτιώνει την απόδοση)", + "theming": "Θέμα", + "themingDesc": "Ενεργοποίηση οπτικών θεμάτων και στυλ", + "fontSmoothing": "Εξομάλυνση γραμματοσειράς", + "fontSmoothingDesc": "Ενεργοποίηση απόδοσης γραμματοσειράς ClearType", + "fullWindowDrag": "Πλήρες σύρσιμο παραθύρου", + "fullWindowDragDesc": "Εμφάνιση περιεχομένων παραθύρου κατά τη μεταφορά", + "desktopComposition": "Σύνθεση επιφάνειας εργασίας", + "desktopCompositionDesc": "Ενεργοποίηση εφέ Aero glass", + "menuAnimations": "Κινήσεις μενού", + "menuAnimationsDesc": "Ενεργοποίηση κινούμενων εικόνων fade και slide μενού", + "disableBitmapCaching": "Απενεργοποίηση προσωρινής αποθήκευσης bitmap", + "disableBitmapCachingDesc": "Απενεργοποίηση της προσωρινής μνήμης bitmap (μπορεί να βοηθήσει με προβλήματα)", + "disableOffscreenCaching": "Απενεργοποίηση προσωρινής αποθήκευσης εκτός οθόνης", + "disableOffscreenCachingDesc": "Απενεργοποίηση προσωρινής μνήμης εκτός οθόνης", + "disableGlyphCaching": "Απενεργοποίηση προσωρινής αποθήκευσης γλύφων", + "disableGlyphCachingDesc": "Απενεργοποίηση προσωρινής μνήμης glyph", + "enableGfx": "Ενεργοποίηση GFX", + "enableGfxDesc": "Χρήση αγωγού γραφικών RemoteFX", + "enablePrinting": "Ενεργοποίηση εκτύπωσης", + "enablePrintingDesc": "Ανακατεύθυνση τοπικών εκτυπωτών στην απομακρυσμένη συνεδρία", + "enableDriveRedirection": "Ενεργοποίηση ανακατεύθυνσης μονάδας δίσκου", + "enableDriveRedirectionDesc": "Αντιστοίχιση τοπικού φακέλου ως μονάδας δίσκου στην απομακρυσμένη συνεδρία", + "createDrivePath": "Δημιουργία διαδρομής μονάδας δίσκου", + "createDrivePathDesc": "Αυτόματη δημιουργία του φακέλου εάν δεν υπάρχει", + "disableDownload": "Απενεργοποίηση λήψης", + "disableDownloadDesc": "Αποτροπή λήψης αρχείων από την απομακρυσμένη συνεδρία", + "disableUpload": "Απενεργοποίηση μεταφόρτωσης", + "disableUploadDesc": "Αποτροπή μεταφόρτωσης αρχείων στην απομακρυσμένη συνεδρία", + "enableTouch": "Ενεργοποίηση αφής", + "enableTouchDesc": "Ενεργοποίηση προώθησης εισόδου αφής", + "consoleSession": "Συνεδρία κονσόλας", + "consoleSessionDesc": "Σύνδεση στην κονσόλα (περίοδος λειτουργίας 0) αντί για νέα περίοδο λειτουργίας", + "sendWolPacket": "Αποστολή πακέτου WOL", + "sendWolPacketDesc": "Στείλτε ένα μαγικό πακέτο για να αφυπνίσετε αυτόν τον κεντρικό υπολογιστή πριν από τη σύνδεση", + "disableCopy": "Απενεργοποίηση αντιγραφής", + "disableCopyDesc": "Αποτροπή αντιγραφής κειμένου από την απομακρυσμένη συνεδρία", + "disablePaste": "Απενεργοποίηση επικόλλησης", + "disablePasteDesc": "Αποτροπή επικόλλησης κειμένου στην απομακρυσμένη συνεδρία", + "createPathIfMissing": "Δημιουργία διαδρομής εάν λείπει", + "createPathIfMissingDesc": "Αυτόματη δημιουργία του καταλόγου ηχογράφησης", + "excludeOutput": "Εξαίρεση εξόδου", + "excludeOutputDesc": "Μην καταγράφετε την έξοδο οθόνης (μόνο μεταδεδομένα)", + "excludeMouse": "Εξαίρεση ποντικιού", + "excludeMouseDesc": "Μην καταγράφετε τις κινήσεις του ποντικιού", + "includeKeystrokes": "Συμπερίληψη πληκτρολογήσεων", + "includeKeystrokesDesc": "Εγγραφή ακατέργαστων πληκτρολογήσεων εκτός από την έξοδο οθόνης", + "vncPort": "Θύρα VNC", + "vncPassword": "Κωδικός πρόσβασης VNC", + "vncUsernameOptional": "Όνομα χρήστη (προαιρετικό)", + "vncLeaveBlank": "Αφήστε κενό εάν δεν απαιτείται", + "cursorMode": "Λειτουργία δρομέα", + "swapRedBlue": "Εναλλαγή Κόκκινου/Μπλε", + "swapRedBlueDesc": "Εναλλαγή των καναλιών κόκκινου και μπλε χρώματος (διορθώνει ορισμένα προβλήματα χρώματος)", + "readOnly": "Μόνο για ανάγνωση", + "readOnlyDesc": "Δείτε την οθόνη του τηλεχειριστηρίου χωρίς να στείλετε καμία πληροφορία", + "telnetPort": "Θύρα Telnet", + "terminalType": "Τύπος τερματικού", + "fontName": "Όνομα γραμματοσειράς", + "fontSize": "Μέγεθος γραμματοσειράς", + "colorScheme": "Χρωματικό σχήμα", + "backspaceKey": "Πλήκτρο Backspace" + } + }, + "onboarding": { + "feature_desktop": "Απομακρυσμένη επιφάνεια εργασίας", + "feature_desktop_desc": "Ανοίξτε τις συνεδρίες RDP, VNC και Telnet σε μια καρτέλα, όπως και το SSH." + } +} diff --git a/plugins/remote-desktop/locales/translated/es_ES.json b/plugins/remote-desktop/locales/translated/es_ES.json new file mode 100644 index 000000000..8295dfd97 --- /dev/null +++ b/plugins/remote-desktop/locales/translated/es_ES.json @@ -0,0 +1,214 @@ +{ + "remoteDesktop": { + "connecting": "Conectando a la sesión {{type}}...", + "checkingGuacd": "Comprobando el servicio de escritorio remoto...", + "requestingToken": "Solicitando el token de conexión {{type}}...", + "openingSession": "Abriendo {{type}} sesión...", + "negotiating": "Negociando el apretón de manos {{type}}...", + "sessionReady": "{{type}} sesión lista", + "connectionError": "Error de conexión", + "connectionFailed": "Conexión fallida", + "failedToConnect": "Error al obtener el token de conexión", + "hostNotFound": "Host no encontrado", + "noHostSelected": "Ningún host seleccionado", + "reconnect": "Reconectar", + "retry": "Reintentar", + "guacdUnavailable": "El servicio de escritorio remoto (guacd) no está disponible. Por favor, asegúrate de que guacd se está ejecutando, es accesible y está correctamente configurado en los ajustes de administración.", + "credentialPromptTitle": "Introduzca las credenciales de RDP", + "credentialPromptDescription": "Este host está configurado para solicitar credenciales al conectarse. Estas se utilizan únicamente para esta sesión y no se guardan.", + "connect": "Conectar", + "ctrlAltDel": "Ctrl+Alt+Del", + "files": { + "title": "Archivos de Drive", + "parent": "Directorio principal", + "refresh": "Refrescar", + "empty": "Esta carpeta está vacía", + "listFailed": "No se pudo leer esta carpeta.", + "download": "Descargar", + "downloadFailed": "Error al descargar {{name}}", + "upload": "Subir archivos", + "uploading": "Subiendo {{name}}...", + "uploaded": "Subido {{name}}", + "uploadFailed": "Error al cargar {{name}}", + "uploadDisabled": "Las cargas están deshabilitadas para esta conexión.", + "driveUnavailable": "Habilite la redirección de unidades RDP antes de cargar archivos.", + "driveNotWritable": "guacd no puede escribir en la carpeta de la unidad. Compruebe GUACD_DRIVE_PATH (o la ruta de la unidad del host) y sus permisos.", + "dropToUpload": "Arrastra y suelta los archivos para subirlos" + }, + "toolbar": { + "ctrlAltDel": "Ctrl+Alt+Del", + "winL": "Win+L (Bloquear pantalla)", + "winKey": "Tecla Windows", + "superL": "Super+L (Pantalla de bloqueo)", + "superKey": "Súper llave", + "super": "Súper", + "cmdL": "Cmd+L (Pantalla de bloqueo)", + "cmdKey": "Tecla de comando", + "cmd": "Comando", + "ctrl": "Ctrl", + "alt": "Alt", + "shift": "Shift", + "win": "Win", + "stickyActive": "{{key}} (activado - clic para soltar)", + "stickyInactive": "{{key}} (clic para activar)", + "esc": "Escape", + "tab": "Tab", + "home": "Inicio", + "end": "Fin", + "pageUp": "Re Pág", + "pageDown": "Av Pág", + "arrowUp": "Flecha arriba", + "arrowDown": "Flecha abajo", + "arrowLeft": "Flecha izquierda", + "arrowRight": "Flecha derecha", + "fnToggle": "Teclas de función", + "reconnect": "Reconectar sesión", + "collapse": "Contraer barra de herramientas", + "expand": "Expandir barra de herramientas", + "dragHandle": "Arrastrar para reposicionar", + "hide": "Ocultar para esta sesión. Para desactivarlo permanentemente, abra Configuración del host → General → Barra de herramientas de conexión.", + "zoomIn": "Dar un golpe de zoom", + "zoomOut": "Aleja la vista", + "resetZoom": "Restablecer zoom", + "fitToScreen": "Ajustar a la pantalla", + "switchToTrackpad": "Cambia al modo panel táctil (arrastra para mover el cursor, toca para hacer clic).", + "switchToTouch": "Cambia al modo táctil (pulsa directamente donde quieras hacer clic)." + } + }, + "hosts": { + "nativeRdpOpened": "Abierto en Escritorio remoto de Windows", + "nativeRdpFailed": "No se pudo abrir el Escritorio remoto de Windows.", + "openNativeRdp": "Abrir en Escritorio remoto de Windows", + "guac": { + "connection": "Conexión", + "authentication": "Autenticación", + "storedCredential": "Credencial almacenada", + "authMethod": "Método de autenticación", + "authTypeNoneDesc": "No se almacenan credenciales. Se le solicitará un nombre de usuario y una contraseña cada vez que se conecte; estos no se guardan.", + "selectCredential": "Seleccionar una credencial...", + "connectionSettings": "Configuración de conexión", + "displaySettings": "Configuración de pantalla", + "audioSettings": "Configuración de audio", + "rdpPerformance": "Rendimiento RDP", + "deviceRedirection": "Redirección de dispositivos", + "session": "Sesión", + "gateway": "Gateway", + "remoteApp": "RemoteApp", + "clipboard": "Portapapeles", + "sessionRecording": "Grabación de sesión", + "wakeOnLan": "Wake-on-LAN", + "vncSettings": "Configuración de VNC", + "terminalSettings": "Configuración de terminal", + "rdpPort": "Puerto RDP", + "username": "Nombre de usuario", + "password": "Contraseña", + "passwordSaved": "Contraseña guardada, escriba para cambiarla", + "domain": "Dominio", + "securityMode": "Modo de seguridad", + "width": "Ancho", + "height": "Alto", + "dpi": "DPI", + "clientName": "Nombre del cliente", + "initialProgram": "Programa inicial", + "serverLayout": "Disposición del teclado", + "timezone": "Zona horaria", + "loadBalanceInfo": "Información de balanceo de carga / Cookie", + "loadBalanceInfoDesc": "Cookie del agente de conexiones a Escritorio Remoto para el balanceo de carga de la granja RDS (p. ej. tsv://MS Terminal Services Plugin.1.CollectionName)", + "guacdProxy": "Proxy de guacd", + "guacdHostname": "Host de guacd", + "guacdHostnamePlaceholder": "Predeterminado global", + "guacdPort": "Puerto de guacd", + "guacdProxyDesc": "Sobrescribir la instancia global de guacd para esta conexión. Dejar en blanco para usar la configuración global de guacd.", + "gatewayHostname": "Nombre de host de la puerta de enlace", + "gatewayPort": "Puerto de la puerta de enlace", + "gatewayUsername": "Nombre de usuario de la puerta de enlace", + "gatewayPassword": "Contraseña de la puerta de enlace", + "gatewayDomain": "Dominio de la puerta de enlace", + "remoteAppProgram": "Programa RemoteApp", + "workingDirectory": "Directorio de trabajo", + "arguments": "Argumentos", + "normalizeLineEndings": "Normalizar finales de línea", + "macAddress": "Dirección MAC", + "broadcastAddress": "Dirección de difusión", + "udpPort": "Puerto UDP", + "waitTimeS": "Tiempo de espera (s)", + "driveName": "Nombre de la unidad", + "drivePath": "Ruta de la unidad", + "ignoreCertificate": "Ignorar certificado", + "ignoreCertificateDesc": "Permitir conexiones a hosts con certificados autofirmados", + "forceLossless": "Forzar sin pérdida", + "forceLosslessDesc": "Forzar codificación de imagen sin pérdida (más calidad, más ancho de banda)", + "disableAudio": "Desactivar audio", + "disableAudioDesc": "Silenciar todo el audio de la sesión remota", + "enableAudioInput": "Activar entrada de audio (micrófono)", + "enableAudioInputDesc": "Reenviar el micrófono local a la sesión remota", + "wallpaper": "Fondo de pantalla", + "wallpaperDesc": "Mostrar fondo de escritorio (desactivarlo mejora el rendimiento)", + "theming": "Temas", + "themingDesc": "Activar temas y estilos visuales", + "fontSmoothing": "Suavizado de fuentes", + "fontSmoothingDesc": "Activar renderizado de fuentes ClearType", + "fullWindowDrag": "Arrastre de ventana completa", + "fullWindowDragDesc": "Mostrar el contenido de la ventana al arrastrar", + "desktopComposition": "Composición de escritorio", + "desktopCompositionDesc": "Activar efectos Aero Glass", + "menuAnimations": "Animaciones de menú", + "menuAnimationsDesc": "Activar animaciones de fundido y deslizamiento de menú", + "disableBitmapCaching": "Desactivar caché de mapa de bits", + "disableBitmapCachingDesc": "Desactivar la caché de mapa de bits (puede ayudar con fallos)", + "disableOffscreenCaching": "Desactivar caché fuera de pantalla", + "disableOffscreenCachingDesc": "Desactivar la caché fuera de pantalla", + "disableGlyphCaching": "Desactivar caché de glifos", + "disableGlyphCachingDesc": "Desactivar la caché de glifos", + "enableGfx": "Activar GFX", + "enableGfxDesc": "Usar la canalización de gráficos RemoteFX", + "enablePrinting": "Activar impresión", + "enablePrintingDesc": "Redirigir las impresoras locales a la sesión remota", + "enableDriveRedirection": "Activar redirección de unidades", + "enableDriveRedirectionDesc": "Asignar una carpeta local como una unidad en la sesión remota", + "createDrivePath": "Crear ruta de unidad", + "createDrivePathDesc": "Crear automáticamente la carpeta si no existe", + "disableDownload": "Deshabilitar descarga", + "disableDownloadDesc": "Impedir la descarga de archivos de la sesión remota", + "disableUpload": "Deshabilitar subida", + "disableUploadDesc": "Impedir la subida de archivos a la sesión remota", + "enableTouch": "Habilitar táctil", + "enableTouchDesc": "Habilitar el reenvío de entrada táctil", + "consoleSession": "Sesión de consola", + "consoleSessionDesc": "Conectar a la consola (sesión 0) en lugar de una nueva sesión", + "sendWolPacket": "Enviar paquete WOL", + "sendWolPacketDesc": "Enviar un paquete mágico para encender este equipo antes de conectar", + "disableCopy": "Deshabilitar copia", + "disableCopyDesc": "Impedir la copia de texto de la sesión remota", + "disablePaste": "Deshabilitar pegado", + "disablePasteDesc": "Impedir el pegado de texto en la sesión remota", + "createPathIfMissing": "Crear ruta si no existe", + "createPathIfMissingDesc": "Crear automáticamente el directorio de grabación", + "excludeOutput": "Excluir salida", + "excludeOutputDesc": "No grabar la salida de pantalla (solo metadatos)", + "excludeMouse": "Excluir ratón", + "excludeMouseDesc": "No grabar los movimientos del ratón", + "includeKeystrokes": "Incluir pulsaciones de teclas", + "includeKeystrokesDesc": "Grabar las pulsaciones de teclas en bruto además de la salida de pantalla", + "vncPort": "Puerto VNC", + "vncPassword": "Contraseña VNC", + "vncUsernameOptional": "Nombre de usuario (opcional)", + "vncLeaveBlank": "Dejar en blanco si no es necesario", + "cursorMode": "Modo de cursor", + "swapRedBlue": "Intercambiar rojo/azul", + "swapRedBlueDesc": "Intercambiar los canales de color rojo y azul (corrige algunos problemas de color)", + "readOnly": "Solo lectura", + "readOnlyDesc": "Ver la pantalla remota sin enviar ninguna entrada", + "telnetPort": "Puerto Telnet", + "terminalType": "Tipo de terminal", + "fontName": "Nombre de fuente", + "fontSize": "Tamaño de fuente", + "colorScheme": "Esquema de color", + "backspaceKey": "Tecla de retroceso" + } + }, + "onboarding": { + "feature_desktop": "Escritorio remoto", + "feature_desktop_desc": "Abre sesiones RDP, VNC y Telnet en una pestaña, igual que con SSH." + } +} diff --git a/plugins/remote-desktop/locales/translated/fi_FI.json b/plugins/remote-desktop/locales/translated/fi_FI.json new file mode 100644 index 000000000..f00bdc40f --- /dev/null +++ b/plugins/remote-desktop/locales/translated/fi_FI.json @@ -0,0 +1,214 @@ +{ + "remoteDesktop": { + "connecting": "Yhdistetään {{type}} -istuntoon...", + "checkingGuacd": "Tarkistetaan etätyöpöytäpalvelua...", + "requestingToken": "Pyydetään {{type}} yhteystunnusta...", + "openingSession": "Avataan {{type}} -istuntoa...", + "negotiating": "Neuvottelen {{type}} kädenpuristuksesta...", + "sessionReady": "{{type}} istunto valmis", + "connectionError": "Yhteysvirhe", + "connectionFailed": "Yhteys epäonnistui", + "failedToConnect": "Yhteystunnuksen hakeminen epäonnistui", + "hostNotFound": "Isäntää ei löydy", + "noHostSelected": "Ei valittua isäntää", + "reconnect": "Yhdistä uudelleen", + "retry": "Yritä uudelleen", + "guacdUnavailable": "Etätyöpöytäpalvelu (guacd) ei ole käytettävissä. Varmista, että guacd on käynnissä, käytettävissä ja määritetty oikein järjestelmänvalvojan asetuksissa.", + "credentialPromptTitle": "Syötä RDP-tunnistetiedot", + "credentialPromptDescription": "Tämä isäntä on asetettu kysymään tunnistetietoja yhteyden muodostamisen yhteydessä. Niitä käytetään vain tässä istunnossa, eikä niitä tallenneta.", + "connect": "Yhdistä", + "ctrlAltDel": "Ctrl+Alt+Del", + "files": { + "title": "Drive-tiedostot", + "parent": "Ylähakemisto", + "refresh": "Päivitä", + "empty": "Tämä kansio on tyhjä", + "listFailed": "Tämän kansion lukeminen epäonnistui", + "download": "Lataa", + "downloadFailed": "Lataus epäonnistui {{name}}", + "upload": "Lataa tiedostoja", + "uploading": "Ladataan {{name}}...", + "uploaded": "Ladattu {{name}}", + "uploadFailed": "Lataus epäonnistui {{name}}", + "uploadDisabled": "Lähetykset on poistettu käytöstä tällä yhteydellä", + "driveUnavailable": "Ota RDP-aseman uudelleenohjaus käyttöön ennen tiedostojen lataamista", + "driveNotWritable": "guacd ei voi kirjoittaa asemakansioon. Tarkista GUACD_DRIVE_PATH (tai isännän asemapolku) ja sen käyttöoikeudet.", + "dropToUpload": "Pudota tiedostot ladattavaksi" + }, + "toolbar": { + "ctrlAltDel": "Ctrl+Alt+Del", + "winL": "Win+L (Lukitusnäyttö)", + "winKey": "Windows-näppäin", + "superL": "Super+L (Lukitusnäyttö)", + "superKey": "Superavain", + "super": "Super", + "cmdL": "Cmd+L (Lukitusnäyttö)", + "cmdKey": "Komento-näppäin", + "cmd": "Komento", + "ctrl": "Ctrl", + "alt": "Vaihtoehto", + "shift": "Siirtää", + "win": "Voittaa", + "stickyActive": "{{key}} (lukittu - napsauta vapauttaaksesi)", + "stickyInactive": "{{key}} (napsauta lukitaksesi)", + "esc": "Paeta", + "tab": "Välilehti", + "home": "Kotiin", + "end": "Loppu", + "pageUp": "Sivu ylös", + "pageDown": "Sivu alas", + "arrowUp": "Nuoli ylös", + "arrowDown": "Nuoli alas", + "arrowLeft": "Nuoli vasemmalle", + "arrowRight": "Nuoli oikealle", + "fnToggle": "Toimintonäppäimet", + "reconnect": "Yhdistä istunto uudelleen", + "collapse": "Pienennä työkalupalkki", + "expand": "Laajenna työkalupalkkia", + "dragHandle": "Vedä siirtääksesi", + "hide": "Piilota tältä istunnolta. Voit poistaa sen käytöstä pysyvästi avaamalla Isäntäasetukset → Yleiset → Yhteystyökalurivi.", + "zoomIn": "Lähennä", + "zoomOut": "Loitonna", + "resetZoom": "Palauta zoomaus", + "fitToScreen": "Sovita näyttöön", + "switchToTrackpad": "Vaihda ohjauslevytilaan (vedä siirtääksesi kohdistinta, napauta napsauttamalla)", + "switchToTouch": "Vaihda kosketustilaan (napauta suoraan haluamaasi kohtaan)" + } + }, + "hosts": { + "nativeRdpOpened": "Avattu Windowsin etätyöpöydällä", + "nativeRdpFailed": "Windowsin etätyöpöydän avaaminen epäonnistui", + "openNativeRdp": "Avaa Windowsin etätyöpöydällä", + "guac": { + "connection": "Yhteys", + "authentication": "Todennus", + "storedCredential": "Tallennetut tunnistetiedot", + "authMethod": "Todennustapa", + "authTypeNoneDesc": "Tunnuksia ei tallenneta. Sinulta kysytään käyttäjätunnusta ja salasanaa aina, kun muodostat yhteyden; niitä ei tallenneta.", + "selectCredential": "Valitse tunnistetiedot...", + "connectionSettings": "Yhteysasetukset", + "displaySettings": "Näyttöasetukset", + "audioSettings": "Ääniasetukset", + "rdpPerformance": "RDP-suorituskyky", + "deviceRedirection": "Laitteen uudelleenohjaus", + "session": "Istunto", + "gateway": "Yhdyskäytävä", + "remoteApp": "Etäsovellus", + "clipboard": "Leikepöytä", + "sessionRecording": "Istunnon tallennus", + "wakeOnLan": "Wake-on-LAN", + "vncSettings": "VNC-asetukset", + "terminalSettings": "Pääteasetukset", + "rdpPort": "RDP-portti", + "username": "Käyttäjätunnus", + "password": "Salasana", + "passwordSaved": "Salasana tallennettu, kirjoita muuttaaksesi", + "domain": "Verkkotunnus", + "securityMode": "Suojaustila", + "width": "Leveys", + "height": "Korkeus", + "dpi": "DPI", + "clientName": "Asiakkaan nimi", + "initialProgram": "Alkuperäinen ohjelma", + "serverLayout": "Palvelimen asettelu", + "timezone": "Aikavyöhyke", + "loadBalanceInfo": "Kuormituksen tasapainotustiedot / eväste", + "loadBalanceInfoDesc": "RD Connection Broker -eväste RDS-farmin kuormituksen tasapainottamista varten (esim. tsv://MS Terminal Services Plugin.1.CollectionName)", + "guacdProxy": "guacd-välityspalvelin", + "guacdHostname": "guacd-isäntä", + "guacdHostnamePlaceholder": "Globaali oletusarvo", + "guacdPort": "guacdin satama", + "guacdProxyDesc": "Ohita tämän yhteyden globaali guacd-instanssi. Jätä tyhjäksi käyttääksesi globaalisti määritettyä guacd-instanssia.", + "gatewayHostname": "Yhdyskäytävän isäntänimi", + "gatewayPort": "Yhdyskäytäväportti", + "gatewayUsername": "Yhdyskäytävän käyttäjätunnus", + "gatewayPassword": "Yhdyskäytävän salasana", + "gatewayDomain": "Yhdyskäytävän verkkotunnus", + "remoteAppProgram": "RemoteApp-ohjelma", + "workingDirectory": "Työhakemisto", + "arguments": "Argumentit", + "normalizeLineEndings": "Normalisoi rivinpäätteet", + "macAddress": "MAC-osoite", + "broadcastAddress": "Lähetysosoite", + "udpPort": "UDP-portti", + "waitTimeS": "Odotusaika (s)", + "driveName": "Aseman nimi", + "drivePath": "Ajopolku", + "ignoreCertificate": "Ohita varmenne", + "ignoreCertificateDesc": "Salli yhteydet itse allekirjoitettuja varmenteita käyttäviin isäntiin", + "forceLossless": "Pakota häviötön", + "forceLosslessDesc": "Pakota häviötön kuvan koodaus (korkeampi laatu, enemmän kaistanleveyttä)", + "disableAudio": "Poista ääni käytöstä", + "disableAudioDesc": "Mykistä kaikki etäistunnon äänet", + "enableAudioInput": "Ota äänitulo käyttöön (mikrofoni)", + "enableAudioInputDesc": "Lähetä paikallinen mikrofoni etäistuntoon", + "wallpaper": "Taustakuva", + "wallpaperDesc": "Näytä työpöydän taustakuva (poistaminen käytöstä parantaa suorituskykyä)", + "theming": "Teemat", + "themingDesc": "Ota käyttöön visuaaliset teemat ja tyylit", + "fontSmoothing": "Fontin pehmennys", + "fontSmoothingDesc": "Ota ClearType-fonttien renderöinti käyttöön", + "fullWindowDrag": "Koko ikkunan vetäminen", + "fullWindowDragDesc": "Näytä ikkunan sisältö vetämisen aikana", + "desktopComposition": "Työpöydän sommittelu", + "desktopCompositionDesc": "Ota Aero Glass -tehosteet käyttöön", + "menuAnimations": "Valikkoanimaatiot", + "menuAnimationsDesc": "Ota käyttöön valikoiden häivytys ja dia-animaatiot", + "disableBitmapCaching": "Poista bittikarttavälimuisti käytöstä", + "disableBitmapCachingDesc": "Poista bittikarttavälimuisti käytöstä (saattaa auttaa häiriöiden kanssa)", + "disableOffscreenCaching": "Poista käytöstä näytön ulkopuolinen välimuisti", + "disableOffscreenCachingDesc": "Poista käytöstä näytön ulkopuolinen välimuisti", + "disableGlyphCaching": "Poista käytöstä glyfien välimuisti", + "disableGlyphCachingDesc": "Poista merkkijonojen välimuisti käytöstä", + "enableGfx": "Ota käyttöön näytönsäästäjä", + "enableGfxDesc": "Käytä RemoteFX-grafiikkaputkea", + "enablePrinting": "Ota tulostus käyttöön", + "enablePrintingDesc": "Ohjaa paikalliset tulostimet etäistuntoon", + "enableDriveRedirection": "Ota aseman uudelleenohjaus käyttöön", + "enableDriveRedirectionDesc": "Yhdistä paikallinen kansio asemaksi etäistunnossa", + "createDrivePath": "Luo ajopolku", + "createDrivePathDesc": "Luo kansio automaattisesti, jos sitä ei ole olemassa", + "disableDownload": "Poista lataus käytöstä", + "disableDownloadDesc": "Estä tiedostojen lataaminen etäistunnosta", + "disableUpload": "Poista lähetys käytöstä", + "disableUploadDesc": "Estä tiedostojen lataaminen etäistuntoon", + "enableTouch": "Ota kosketus käyttöön", + "enableTouchDesc": "Ota kosketussyötteen edelleenlähetys käyttöön", + "consoleSession": "Konsoli-istunto", + "consoleSessionDesc": "Yhdistä konsoliin (istunto 0) uuden istunnon sijaan", + "sendWolPacket": "Lähetä WOL-paketti", + "sendWolPacketDesc": "Lähetä taikapaketti herättääksesi tämän isännän ennen yhteyden muodostamista", + "disableCopy": "Poista kopiointi käytöstä", + "disableCopyDesc": "Estä tekstin kopioiminen etäistunnosta", + "disablePaste": "Poista liittäminen käytöstä", + "disablePasteDesc": "Estä tekstin liittäminen etäistuntoon", + "createPathIfMissing": "Luo polku, jos se puuttuu", + "createPathIfMissingDesc": "Luo tallennushakemisto automaattisesti", + "excludeOutput": "Sulje pois tuloste", + "excludeOutputDesc": "Älä tallenna näytön tulostetta (vain metatiedot)", + "excludeMouse": "Sulje hiiri pois", + "excludeMouseDesc": "Älä tallenna hiiren liikkeitä", + "includeKeystrokes": "Sisällytä näppäinpainallukset", + "includeKeystrokesDesc": "Tallenna raakat näppäinpainallukset näytön tulosteen lisäksi", + "vncPort": "VNC-portti", + "vncPassword": "VNC-salasana", + "vncUsernameOptional": "Käyttäjätunnus (valinnainen)", + "vncLeaveBlank": "Jätä tyhjäksi, jos ei pakollinen", + "cursorMode": "Kohdistimen tila", + "swapRedBlue": "Vaihda punainen/sininen", + "swapRedBlueDesc": "Vaihda punaisen ja sinisen värikanavan paikkaa (korjaa joitakin väriongelmia)", + "readOnly": "Vain lukuoikeus", + "readOnlyDesc": "Katso etänäyttöä lähettämättä mitään syötettä", + "telnetPort": "Telnet-portti", + "terminalType": "Liittimen tyyppi", + "fontName": "Fontin nimi", + "fontSize": "Fonttikoko", + "colorScheme": "Värimaailma", + "backspaceKey": "Askelpalautin-näppäin" + } + }, + "onboarding": { + "feature_desktop": "Etätyöpöytä", + "feature_desktop_desc": "Avaa RDP-, VNC- ja Telnet-istunnot välilehdellä, samalla tavalla kuin SSH:ssa." + } +} diff --git a/plugins/remote-desktop/locales/translated/fr_FR.json b/plugins/remote-desktop/locales/translated/fr_FR.json new file mode 100644 index 000000000..25a456a34 --- /dev/null +++ b/plugins/remote-desktop/locales/translated/fr_FR.json @@ -0,0 +1,214 @@ +{ + "remoteDesktop": { + "connecting": "Connexion à la session {{type}}...", + "checkingGuacd": "Vérification du service de bureau à distance...", + "requestingToken": "Demande de jeton de connexion {{type}}...", + "openingSession": "Ouverture de la session {{type}}...", + "negotiating": "Negotiating {{type}} handshake...", + "sessionReady": "{{type}} session prête", + "connectionError": "Erreur de connexion", + "connectionFailed": "Échec de la connexion", + "failedToConnect": "Échec de l'obtention du jeton de connexion", + "hostNotFound": "Hôte introuvable", + "noHostSelected": "Aucun hôte sélectionné", + "reconnect": "Reconnecter", + "retry": "Réessayer", + "guacdUnavailable": "Le service de bureau à distance (guacd) n'est pas disponible. Veuillez vous assurer que guacd est en cours d'exécution, accessible et correctement configuré dans les paramètres administrateur.", + "credentialPromptTitle": "Saisir les informations d'identification RDP", + "credentialPromptDescription": "Cet hôte est configuré pour demander des identifiants lors de la connexion. Ces identifiants sont utilisés uniquement pour cette session et ne sont pas enregistrés.", + "connect": "Connecter", + "ctrlAltDel": "Ctrl+Alt+Del", + "files": { + "title": "Fichiers Drive", + "parent": "Répertoire parent", + "refresh": "Rafraîchir", + "empty": "Ce dossier est vide.", + "listFailed": "Impossible de lire ce dossier", + "download": "Télécharger", + "downloadFailed": "Échec du téléchargement {{name}}", + "upload": "Téléverser des fichiers", + "uploading": "Téléchargement en cours {{name}}...", + "uploaded": "Téléchargé {{name}}", + "uploadFailed": "Échec du chargement {{name}}", + "uploadDisabled": "Les chargements sont désactivés pour cette connexion.", + "driveUnavailable": "Activez la redirection du lecteur RDP avant de télécharger les fichiers", + "driveNotWritable": "guacd ne peut pas écrire dans le dossier du lecteur. Vérifiez la variable d'environnement GUACD_DRIVE_PATH (ou le chemin d'accès au lecteur de l'hôte) et ses autorisations.", + "dropToUpload": "Déposez les fichiers à télécharger" + }, + "toolbar": { + "ctrlAltDel": "Ctrl+Alt+Del", + "winL": "Win+L (Verrouiller l'écran)", + "winKey": "Touche Windows", + "superL": "Super+L (Écran de verrouillage)", + "superKey": "Super Clé", + "super": "Super", + "cmdL": "Cmd+L (Écran de verrouillage)", + "cmdKey": "Touche de commande", + "cmd": "Commande", + "ctrl": "Ctrl", + "alt": "Alt", + "shift": "Maj", + "win": "Win", + "stickyActive": "{{key}} (verrouillé - cliquer pour libérer)", + "stickyInactive": "{{key}} (cliquer pour verrouiller)", + "esc": "Échap", + "tab": "Tab", + "home": "Début", + "end": "Fin", + "pageUp": "Page préc.", + "pageDown": "Page suiv.", + "arrowUp": "Flèche haut", + "arrowDown": "Flèche bas", + "arrowLeft": "Flèche gauche", + "arrowRight": "Flèche droite", + "fnToggle": "Touches de fonction", + "reconnect": "Reconnecter la session", + "collapse": "Réduire la barre d'outils", + "expand": "Développer la barre d'outils", + "dragHandle": "Glisser pour repositionner", + "hide": "Masquer cette option pour cette session. Pour la désactiver définitivement, ouvrez Paramètres de l'hôte → Général → Barre d'outils de connexion.", + "zoomIn": "Zoomer", + "zoomOut": "Dézoomer", + "resetZoom": "Réinitialiser le zoom", + "fitToScreen": "Ajuster à l'écran", + "switchToTrackpad": "Passez en mode pavé tactile (glissez pour déplacer le curseur, appuyez pour cliquer)", + "switchToTouch": "Passez en mode tactile (appuyez directement à l'endroit où vous souhaitez cliquer)." + } + }, + "hosts": { + "nativeRdpOpened": "Ouvert dans Bureau à distance Windows", + "nativeRdpFailed": "Impossible d'ouvrir le Bureau à distance Windows", + "openNativeRdp": "Ouvrir dans le Bureau à distance Windows", + "guac": { + "connection": "Connexion", + "authentication": "Authentification", + "storedCredential": "Identifiant enregistré", + "authMethod": "Méthode d'authentification", + "authTypeNoneDesc": "Aucune information d'identification n'est stockée. Un nom d'utilisateur et un mot de passe vous seront demandés à chaque connexion ; ils ne sont pas enregistrés.", + "selectCredential": "Sélectionner un identifiant...", + "connectionSettings": "Paramètres de connexion", + "displaySettings": "Paramètres d'affichage", + "audioSettings": "Paramètres audio", + "rdpPerformance": "Performances RDP", + "deviceRedirection": "Redirection de périphériques", + "session": "Session", + "gateway": "Passerelle", + "remoteApp": "RemoteApp", + "clipboard": "Presse-papiers", + "sessionRecording": "Enregistrement de session", + "wakeOnLan": "Wake-on-LAN", + "vncSettings": "Paramètres VNC", + "terminalSettings": "Paramètres du terminal", + "rdpPort": "Port RDP", + "username": "Nom d'utilisateur", + "password": "Mot de passe", + "passwordSaved": "Mot de passe enregistré, saisissez-le pour le modifier", + "domain": "Domaine", + "securityMode": "Mode de sécurité", + "width": "Largeur", + "height": "Hauteur", + "dpi": "DPI", + "clientName": "Nom du client", + "initialProgram": "Programme initial", + "serverLayout": "Disposition du clavier", + "timezone": "Fuseau horaire", + "loadBalanceInfo": "Infos d'équilibrage de charge / Cookie", + "loadBalanceInfoDesc": "Cookie du RD Connection Broker pour l'équilibrage de charge d'une ferme RDS (ex. tsv://MS Terminal Services Plugin.1.CollectionName)", + "guacdProxy": "Proxy guacd", + "guacdHostname": "Hôte guacd", + "guacdHostnamePlaceholder": "Valeur globale par défaut", + "guacdPort": "Port guacd", + "guacdProxyDesc": "Remplacer l'instance guacd globale pour cette connexion. Laisser vide pour utiliser le guacd configuré globalement.", + "gatewayHostname": "Nom d'hôte de la passerelle", + "gatewayPort": "Port de la passerelle", + "gatewayUsername": "Nom d'utilisateur de la passerelle", + "gatewayPassword": "Mot de passe de la passerelle", + "gatewayDomain": "Domaine de la passerelle", + "remoteAppProgram": "Programme RemoteApp", + "workingDirectory": "Répertoire de travail", + "arguments": "Arguments", + "normalizeLineEndings": "Normaliser les fins de ligne", + "macAddress": "Adresse MAC", + "broadcastAddress": "Adresse de diffusion", + "udpPort": "Port UDP", + "waitTimeS": "Délai d'attente (s)", + "driveName": "Nom du lecteur", + "drivePath": "Chemin du lecteur", + "ignoreCertificate": "Ignorer le certificat", + "ignoreCertificateDesc": "Autoriser les connexions aux hôtes avec des certificats auto-signés", + "forceLossless": "Forcer sans perte", + "forceLosslessDesc": "Forcer l'encodage d'image sans perte (meilleure qualité, plus de bande passante)", + "disableAudio": "Désactiver l'audio", + "disableAudioDesc": "Couper tout le son de la session distante", + "enableAudioInput": "Activer l'entrée audio (microphone)", + "enableAudioInputDesc": "Transférer le microphone local vers la session distante", + "wallpaper": "Fond d'écran", + "wallpaperDesc": "Afficher le fond d'écran du bureau (désactiver cette option améliore les performances)", + "theming": "Thèmes", + "themingDesc": "Activer les thèmes et styles visuels", + "fontSmoothing": "Lissage des polices", + "fontSmoothingDesc": "Activer le rendu des polices ClearType", + "fullWindowDrag": "Afficher le contenu de la fenêtre lors du déplacement", + "fullWindowDragDesc": "Afficher le contenu de la fenêtre lors du déplacement", + "desktopComposition": "Composition du bureau", + "desktopCompositionDesc": "Activer les effets Aero Glass", + "menuAnimations": "Animations des menus", + "menuAnimationsDesc": "Activer les animations de fondu et de glissement des menus", + "disableBitmapCaching": "Désactiver le cache bitmap", + "disableBitmapCachingDesc": "Désactiver le cache bitmap (peut aider en cas de problèmes graphiques)", + "disableOffscreenCaching": "Désactiver le cache hors écran", + "disableOffscreenCachingDesc": "Désactiver le cache hors écran", + "disableGlyphCaching": "Désactiver le cache des glyphes", + "disableGlyphCachingDesc": "Désactiver le cache des glyphes", + "enableGfx": "Activer GFX", + "enableGfxDesc": "Utiliser le pipeline graphique RemoteFX", + "enablePrinting": "Activer l'impression", + "enablePrintingDesc": "Rediriger les imprimantes locales vers la session distante", + "enableDriveRedirection": "Activer la redirection de lecteur", + "enableDriveRedirectionDesc": "Monter un dossier local en tant que lecteur dans la session distante", + "createDrivePath": "Créer le chemin du lecteur", + "createDrivePathDesc": "Créer automatiquement le dossier s'il n'existe pas", + "disableDownload": "Désactiver le téléchargement", + "disableDownloadDesc": "Empêcher le téléchargement des fichiers depuis la session distante", + "disableUpload": "Désactiver le téléversement", + "disableUploadDesc": "Empêcher le téléversement de fichiers vers la session distante", + "enableTouch": "Activer le tactile", + "enableTouchDesc": "Activer la transmission des entrées tactiles", + "consoleSession": "Session console", + "consoleSessionDesc": "Se connecter à la console (session 0) au lieu d'une nouvelle session", + "sendWolPacket": "Envoyer un paquet WOL", + "sendWolPacketDesc": "Envoyer un paquet magique pour réveiller cet hôte avant la connexion", + "disableCopy": "Désactiver la copie", + "disableCopyDesc": "Empêcher la copie de texte depuis la session distante", + "disablePaste": "Désactiver le collage", + "disablePasteDesc": "Empêcher le collage de texte dans la session distante", + "createPathIfMissing": "Créer le chemin si absent", + "createPathIfMissingDesc": "Créer automatiquement le répertoire d'enregistrement", + "excludeOutput": "Exclure la sortie", + "excludeOutputDesc": "Ne pas enregistrer l'affichage écran (métadonnées uniquement)", + "excludeMouse": "Exclure la souris", + "excludeMouseDesc": "Ne pas enregistrer les mouvements de la souris", + "includeKeystrokes": "Inclure les frappes", + "includeKeystrokesDesc": "Enregistrer les frappes brutes en plus de l'affichage écran", + "vncPort": "Port VNC", + "vncPassword": "Mot de passe VNC", + "vncUsernameOptional": "Nom d'utilisateur (facultatif)", + "vncLeaveBlank": "Laisser vide si non requis", + "cursorMode": "Mode curseur", + "swapRedBlue": "Échanger rouge/bleu", + "swapRedBlueDesc": "Échanger les canaux de couleur rouge et bleu (corrige certains problèmes de couleur)", + "readOnly": "Lecture seule", + "readOnlyDesc": "Afficher l'écran distant sans envoyer d'entrée", + "telnetPort": "Port Telnet", + "terminalType": "Type de terminal", + "fontName": "Nom de la police", + "fontSize": "Taille de la police", + "colorScheme": "Schéma de couleurs", + "backspaceKey": "Touche Backspace" + } + }, + "onboarding": { + "feature_desktop": "Bureau à distance", + "feature_desktop_desc": "Ouvrez les sessions RDP, VNC et Telnet dans un onglet, de la même manière que SSH." + } +} diff --git a/plugins/remote-desktop/locales/translated/he_IL.json b/plugins/remote-desktop/locales/translated/he_IL.json new file mode 100644 index 000000000..154527568 --- /dev/null +++ b/plugins/remote-desktop/locales/translated/he_IL.json @@ -0,0 +1,214 @@ +{ + "remoteDesktop": { + "connecting": "מתחבר לסשן {{type}}...", + "checkingGuacd": "בודק שירות שולחן עבודה מרוחק...", + "requestingToken": "מבקש אסימון חיבור {{type}}...", + "openingSession": "פותח סשן {{type}}...", + "negotiating": "מנהל משא ומתן על לחיצת יד {{type}}...", + "sessionReady": "{{type}} מוכנה לסשן", + "connectionError": "שגיאת חיבור", + "connectionFailed": "החיבור נכשל", + "failedToConnect": "נכשל בקבלת אסימון החיבור", + "hostNotFound": "המארח לא נמצא", + "noHostSelected": "לא נבחר מארח", + "reconnect": "התחבר מחדש", + "retry": "נסה שוב", + "guacdUnavailable": "שירות שולחן עבודה מרוחק (guacd) אינו זמין. אנא ודא ש-guacd פועל, נגיש ומוגדר כראוי בהגדרות המנהל.", + "credentialPromptTitle": "הזן אישורי RDP", + "credentialPromptDescription": "מארח זה מוגדר לבקש אישורים בעת התחברות. הם משמשים עבור הפעלה זו בלבד ואינם נשמרים.", + "connect": "לְחַבֵּר", + "ctrlAltDel": "Ctrl+Alt+Del", + "files": { + "title": "קבצי דרייב", + "parent": "ספריית הורים", + "refresh": "לְרַעֲנֵן", + "empty": "תיקייה זו ריקה", + "listFailed": "נכשלה קריאת התיקייה הזו", + "download": "הורדה", + "downloadFailed": "נכשל בהורדת {{name}}", + "upload": "העלאת קבצים", + "uploading": "מעלה {{name}}...", + "uploaded": "הועלה {{name}}", + "uploadFailed": "נכשלה העלאת {{name}}", + "uploadDisabled": "העלאות מושבתות עבור חיבור זה", + "driveUnavailable": "הפעל ניתוב מחדש של כונן RDP לפני העלאת קבצים", + "driveNotWritable": "ל-guacd אין אפשרות לכתוב לתיקיית הכונן. בדוק את GUACD_DRIVE_PATH (או את נתיב הכונן של המארח) ואת ההרשאות שלו.", + "dropToUpload": "שחררו קבצים להעלאה" + }, + "toolbar": { + "ctrlAltDel": "Ctrl+Alt+Del", + "winL": "Win+L (מסך נעילה)", + "winKey": "מפתח חלונות", + "superL": "סופר+L (מסך נעילה)", + "superKey": "סופר קי", + "super": "סוּפֶּר", + "cmdL": "Cmd+L (מסך נעילה)", + "cmdKey": "מקש פקודה", + "cmd": "פקודה", + "ctrl": "קונטרול", + "alt": "אלט", + "shift": "מִשׁמֶרֶת", + "win": "לְנַצֵחַ", + "stickyActive": "{{key}} (נעול - לחץ לשחרור)", + "stickyInactive": "{{key}} (לחץ כדי לנעול)", + "esc": "לִברוֹחַ", + "tab": "טאב", + "home": "בַּיִת", + "end": "סוֹף", + "pageUp": "עמוד למעלה", + "pageDown": "עמוד למטה", + "arrowUp": "חץ למעלה", + "arrowDown": "חץ למטה", + "arrowLeft": "חץ שמאלה", + "arrowRight": "חץ ימינה", + "fnToggle": "מקשי פונקציה", + "reconnect": "חיבור מחדש של הפעלת המושב", + "collapse": "כיווץ סרגל הכלים", + "expand": "הרחב את סרגל הכלים", + "dragHandle": "גרור כדי למקם מחדש", + "hide": "הסתר עבור הפעלה זו. כדי להשבית זאת לצמיתות, פתח את הגדרות המארח ← כללי ← סרגל הכלים לחיבור.", + "zoomIn": "לְהִתְמַקֵד", + "zoomOut": "התרחקות", + "resetZoom": "איפוס זום", + "fitToScreen": "התאמה למסך", + "switchToTrackpad": "מעבר למצב משטח עקיבה (גרור כדי להזיז את הסמן, הקש כדי ללחוץ)", + "switchToTouch": "מעבר למצב מגע (הקש ישירות במקום שברצונך ללחוץ)" + } + }, + "hosts": { + "nativeRdpOpened": "נפתח בשולחן עבודה מרוחק של Windows", + "nativeRdpFailed": "נכשלה פתיחת שולחן עבודה מרוחק של Windows", + "openNativeRdp": "פתח בשולחן עבודה מרוחק של Windows", + "guac": { + "connection": "קֶשֶׁר", + "authentication": "אימות", + "storedCredential": "אישורים מאוחסנים", + "authMethod": "שיטת אימות", + "authTypeNoneDesc": "לא נשמרים פרטי גישה. תתבקש להזין שם משתמש וסיסמה בכל פעם שתתחבר; הם לא נשמרים.", + "selectCredential": "בחר אישור...", + "connectionSettings": "הגדרות חיבור", + "displaySettings": "הגדרות תצוגה", + "audioSettings": "הגדרות שמע", + "rdpPerformance": "ביצועי RDP", + "deviceRedirection": "ניתוב מחדש של מכשירים", + "session": "מוֹשָׁב", + "gateway": "כְּנִיסָה", + "remoteApp": "אפליקציה מרחוק", + "clipboard": "לוח כתיבה", + "sessionRecording": "הקלטת סשן", + "wakeOnLan": "התעוררות ברשת LAN", + "vncSettings": "הגדרות VNC", + "terminalSettings": "הגדרות מסוף", + "rdpPort": "יציאת RDP", + "username": "שם משתמש", + "password": "סִיסמָה", + "passwordSaved": "הסיסמה נשמרה, הקלד כדי לשנות", + "domain": "תְחוּם", + "securityMode": "מצב אבטחה", + "width": "רוֹחַב", + "height": "גוֹבַה", + "dpi": "DPI", + "clientName": "שם הלקוח", + "initialProgram": "תוכנית ראשונית", + "serverLayout": "פריסת שרת", + "timezone": "אזור זמן", + "loadBalanceInfo": "מידע על מאזן עומס / קובץ Cookie", + "loadBalanceInfoDesc": "קובץ cookie של RD Connection Broker עבור איזון עומסים של חוות RDS (לדוגמה tsv://MS Terminal Services Plugin.1.CollectionName)", + "guacdProxy": "פרוקסי של guacd", + "guacdHostname": "מארח guacd", + "guacdHostnamePlaceholder": "ברירת מחדל גלובלית", + "guacdPort": "נמל גואקד", + "guacdProxyDesc": "עקוף את מופע ה-guacd הגלובלי עבור חיבור זה. השאר ריק כדי להשתמש ב-guacd שתצורתו הגלובלית.", + "gatewayHostname": "שם מארח השער", + "gatewayPort": "שער היציאה", + "gatewayUsername": "שם משתמש של השער", + "gatewayPassword": "סיסמת השער", + "gatewayDomain": "דומיין שער", + "remoteAppProgram": "תוכנית RemoteApp", + "workingDirectory": "ספריית עבודה", + "arguments": "טיעונים", + "normalizeLineEndings": "נרמול סיומות שורות", + "macAddress": "כתובת MAC", + "broadcastAddress": "כתובת שידור", + "udpPort": "יציאת UDP", + "waitTimeS": "זמן המתנה (שניות)", + "driveName": "שם הכונן", + "drivePath": "נתיב הנסיעה", + "ignoreCertificate": "התעלם מהתעודה", + "ignoreCertificateDesc": "אפשר חיבורים למארחים עם אישורים חתומים עצמית", + "forceLossless": "כפיית אובדן נתונים", + "forceLosslessDesc": "כפיית קידוד תמונה ללא אובדן נתונים (איכות גבוהה יותר, רוחב פס גדול יותר)", + "disableAudio": "השבתת שמע", + "disableAudioDesc": "השתקת כל האודיו מההפעלה המרוחקת", + "enableAudioInput": "הפעלת קלט שמע (מיקרופון)", + "enableAudioInputDesc": "העברת המיקרופון המקומי לסשן המרוחק", + "wallpaper": "טָפֵּט", + "wallpaperDesc": "הצגת טפט שולחן עבודה (השבתה משפרת את הביצועים)", + "theming": "ת'מינג", + "themingDesc": "הפעלת ערכות נושא וסגנונות חזותיים", + "fontSmoothing": "החלקת גופנים", + "fontSmoothingDesc": "הפעלת עיבוד גופני ClearType", + "fullWindowDrag": "גרירת חלון מלאה", + "fullWindowDragDesc": "הצגת תוכן החלון בעת גרירה", + "desktopComposition": "קומפוזיציה לשולחן העבודה", + "desktopCompositionDesc": "הפעלת אפקטים של Aero Glass", + "menuAnimations": "אנימציות תפריטים", + "menuAnimationsDesc": "הפעלת אנימציות של דהייה והחלקה בתפריט", + "disableBitmapCaching": "השבתת אחסון במטמון של מפת סיביות", + "disableBitmapCachingDesc": "כבה את מטמון הסיביות (עשוי לעזור עם תקלות)", + "disableOffscreenCaching": "השבתת אחסון במטמון מחוץ למסך", + "disableOffscreenCachingDesc": "כבה את המטמון מחוץ למסך", + "disableGlyphCaching": "השבתת אחסון גליפים במטמון", + "disableGlyphCachingDesc": "כבה את מטמון הגליפים", + "enableGfx": "הפעלת GFX", + "enableGfxDesc": "השתמש בצינור הגרפיקה של RemoteFX", + "enablePrinting": "הפעל הדפסה", + "enablePrintingDesc": "ניתוב מחדש של מדפסות מקומיות להפעלה מרוחקת", + "enableDriveRedirection": "הפעל ניתוב מחדש של כונן", + "enableDriveRedirectionDesc": "מיפוי תיקייה מקומית ככונן בהפעלה מרוחקת", + "createDrivePath": "צור נתיב כונן", + "createDrivePathDesc": "צור את התיקייה באופן אוטומטי אם היא אינה קיימת", + "disableDownload": "השבתת הורדה", + "disableDownloadDesc": "מניעת הורדת קבצים מההפעלה המרוחקת", + "disableUpload": "השבתת העלאה", + "disableUploadDesc": "מניעת העלאת קבצים לסשן מרחוק", + "enableTouch": "הפעל מגע", + "enableTouchDesc": "הפעל העברת קלט מגע", + "consoleSession": "סשן קונסולה", + "consoleSessionDesc": "התחברות לקונסולה (סשן 0) במקום סשן חדש", + "sendWolPacket": "שלח חבילת WOL", + "sendWolPacketDesc": "שלח חבילת קסם כדי להעיר את המארח הזה לפני התחברות", + "disableCopy": "השבתת העתקה", + "disableCopyDesc": "מניעת העתקת טקסט מההפעלה המרוחקת", + "disablePaste": "השבתת הדבקה", + "disablePasteDesc": "מניעת הדבקת טקסט לתוך ההפעלה המרוחקת", + "createPathIfMissing": "צור נתיב אם חסר", + "createPathIfMissingDesc": "צור אוטומטית את ספריית ההקלטה", + "excludeOutput": "אי הכללת פלט", + "excludeOutputDesc": "אל תקליטו פלט מסך (מטא-נתונים בלבד)", + "excludeMouse": "אי הכללת עכבר", + "excludeMouseDesc": "אל תתעדו תנועות עכבר", + "includeKeystrokes": "כלול הקשות מקשים", + "includeKeystrokesDesc": "הקלטת הקשות גולמיות בנוסף לפלט המסך", + "vncPort": "יציאת VNC", + "vncPassword": "סיסמת VNC", + "vncUsernameOptional": "שם משתמש (אופציונלי)", + "vncLeaveBlank": "השאר ריק אם לא נדרש", + "cursorMode": "מצב סמן", + "swapRedBlue": "החלפת אדום/כחול", + "swapRedBlueDesc": "החלפת ערוצי הצבע האדום והכחול (תיקון של כמה בעיות צבע)", + "readOnly": "לקריאה בלבד", + "readOnlyDesc": "צפה במסך השלט הרחוק מבלי לשלוח קלט כלשהו", + "telnetPort": "יציאת טלנט", + "terminalType": "סוג הטרמינל", + "fontName": "שם הגופן", + "fontSize": "גודל גופן", + "colorScheme": "ערכת צבעים", + "backspaceKey": "מקש Backspace" + } + }, + "onboarding": { + "feature_desktop": "שולחן עבודה מרוחק", + "feature_desktop_desc": "פתחו הפעלות RDP, VNC ו-Telnet בכרטיסייה, בדומה ל-SSH." + } +} diff --git a/plugins/remote-desktop/locales/translated/hi_IN.json b/plugins/remote-desktop/locales/translated/hi_IN.json new file mode 100644 index 000000000..a02f49154 --- /dev/null +++ b/plugins/remote-desktop/locales/translated/hi_IN.json @@ -0,0 +1,214 @@ +{ + "remoteDesktop": { + "connecting": "{{type}} सत्र से कनेक्ट हो रहा है...", + "checkingGuacd": "रिमोट डेस्कटॉप सेवा की जाँच की जा रही है...", + "requestingToken": "{{type}} कनेक्शन टोकन का अनुरोध किया जा रहा है...", + "openingSession": "Opening {{type}} session...", + "negotiating": "बातचीत चल रही है {{type}} हाथ मिलाना...", + "sessionReady": "{{type}} सत्र तैयार है", + "connectionError": "कनेक्शन त्रुटि", + "connectionFailed": "कनेक्शन विफल", + "failedToConnect": "कनेक्शन टोकन प्राप्त करने में विफल", + "hostNotFound": "होस्ट नहीं मिला", + "noHostSelected": "कोई होस्ट चयनित नहीं", + "reconnect": "रीकनेक्ट", + "retry": "पुनः प्रयास करें", + "guacdUnavailable": "रिमोट डेस्कटॉप सेवा (guacd) उपलब्ध नहीं है। कृपया सुनिश्चित करें कि guacd चल रहा है और पहुंच योग्य है और एडमिन सेटिंग्स में ठीक से कॉन्फ़िगर किया गया है।", + "credentialPromptTitle": "आरडीपी क्रेडेंशियल दर्ज करें", + "credentialPromptDescription": "इस होस्ट पर कनेक्ट होने पर क्रेडेंशियल मांगे जाएंगे। ये क्रेडेंशियल केवल इसी सेशन के लिए उपयोग किए जाएंगे और सेव नहीं किए जाएंगे।", + "connect": "जोड़ना", + "ctrlAltDel": "Ctrl+Alt+Del", + "files": { + "title": "ड्राइव फ़ाइलें", + "parent": "मूल निर्देशिका", + "refresh": "ताज़ा करना", + "empty": "यह फ़ोल्डर खाली है", + "listFailed": "इस फ़ोल्डर को पढ़ने में विफल रहा", + "download": "डाउनलोड करना", + "downloadFailed": "डाउनलोड करने में विफल {{name}}", + "upload": "फाइलें अपलोड करें", + "uploading": "अपलोड हो रहा है {{name}}...", + "uploaded": "अपलोड किया गया {{name}}", + "uploadFailed": "अपलोड करने में विफल {{name}}", + "uploadDisabled": "इस कनेक्शन के लिए अपलोड अक्षम हैं।", + "driveUnavailable": "फ़ाइलें अपलोड करने से पहले RDP ड्राइव रीडायरेक्शन को सक्षम करें", + "driveNotWritable": "GUACD ड्राइव फ़ोल्डर में लिख नहीं सकता। कृपया GUACD_DRIVE_PATH (या होस्ट का ड्राइव पाथ) और उसकी अनुमतियाँ जाँचें।", + "dropToUpload": "अपलोड करने के लिए फ़ाइलें ड्रॉप करें" + }, + "toolbar": { + "ctrlAltDel": "Ctrl+Alt+Del", + "winL": "Win+L (लॉक स्क्रीन)", + "winKey": "विंडोज की", + "superL": "सुपर+एल (लॉक स्क्रीन)", + "superKey": "सुपर कुंजी", + "super": "बहुत अच्छा", + "cmdL": "Cmd+L (लॉक स्क्रीन)", + "cmdKey": "कमांड कुंजी", + "cmd": "अध्यक्ष एवं प्रबंध निदेशक", + "ctrl": "Ctrl", + "alt": "Alt", + "shift": "Shift", + "win": "Win", + "stickyActive": "{{key}} (लैच्ड - रिलीज़ करने के लिए क्लिक करें)", + "stickyInactive": "{{key}} (लैच करने के लिए क्लिक करें)", + "esc": "Escape", + "tab": "Tab", + "home": "Home", + "end": "End", + "pageUp": "Page Up", + "pageDown": "Page Down", + "arrowUp": "Arrow Up", + "arrowDown": "Arrow Down", + "arrowLeft": "Arrow Left", + "arrowRight": "Arrow Right", + "fnToggle": "फ़ंक्शन कुंजियाँ", + "reconnect": "सत्र पुनः कनेक्ट करें", + "collapse": "टूलबार समेटें", + "expand": "टूलबार विस्तारित करें", + "dragHandle": "स्थान बदलने के लिए खींचें", + "hide": "इस सत्र के लिए इसे छुपाएं। इसे स्थायी रूप से अक्षम करने के लिए, होस्ट सेटिंग्स → सामान्य → कनेक्शन टूलबार खोलें।", + "zoomIn": "ज़ूम इन", + "zoomOut": "ज़ूम आउट", + "resetZoom": "ज़ूम रीसेट करें", + "fitToScreen": "स्क्रीनिंग के लिए उपयुक्त", + "switchToTrackpad": "ट्रैकपैड मोड पर स्विच करें (कर्सर को स्थानांतरित करने के लिए ड्रैग करें, क्लिक करने के लिए टैप करें)", + "switchToTouch": "टच मोड पर स्विच करें (जहां क्लिक करना चाहते हैं वहां सीधे टैप करें)" + } + }, + "hosts": { + "nativeRdpOpened": "विंडोज़ रिमोट डेस्कटॉप में खोला गया", + "nativeRdpFailed": "विंडोज़ रिमोट डेस्कटॉप खोलने में विफल", + "openNativeRdp": "विंडोज़ रिमोट डेस्कटॉप में खोलें", + "guac": { + "connection": "कनेक्शन", + "authentication": "प्रमाणीकरण", + "storedCredential": "संग्रहीत क्रेडेंशियल", + "authMethod": "प्रमाणीकरण विधि", + "authTypeNoneDesc": "कोई भी क्रेडेंशियल स्टोर नहीं किए जाते हैं। हर बार कनेक्ट करते समय आपसे उपयोगकर्ता नाम और पासवर्ड मांगा जाएगा; वे सहेजे नहीं जाते हैं।", + "selectCredential": "एक क्रेडेंशियल चुनें...", + "connectionSettings": "कनेक्शन सेटिंग्स", + "displaySettings": "प्रदर्शन सेटिंग्स", + "audioSettings": "ऑडियो सेटिंग्स", + "rdpPerformance": "RDP प्रदर्शन", + "deviceRedirection": "डिवाइस पुनर्निर्देशन", + "session": "सत्र", + "gateway": "गेटवे", + "remoteApp": "RemoteApp", + "clipboard": "क्लिपबोर्ड", + "sessionRecording": "सत्र रिकॉर्डिंग", + "wakeOnLan": "Wake-on-LAN", + "vncSettings": "VNC सेटिंग्स", + "terminalSettings": "टर्मिनल सेटिंग्स", + "rdpPort": "RDP पोर्ट", + "username": "उपयोगकर्ता नाम", + "password": "पासवर्ड", + "passwordSaved": "पासवर्ड सहेज लिया गया है, बदलने के लिए टाइप करें", + "domain": "डोमेन", + "securityMode": "सुरक्षा मोड", + "width": "चौड़ाई", + "height": "ऊंचाई", + "dpi": "DPI", + "clientName": "क्लाइंट नाम", + "initialProgram": "आरंभिक प्रोग्राम", + "serverLayout": "सर्वर लेआउट", + "timezone": "समय क्षेत्र", + "loadBalanceInfo": "लोड बैलेंस जानकारी / कुकी", + "loadBalanceInfoDesc": "RDS फ़ार्म लोड संतुलन के लिए RD कनेक्शन ब्रोकर कुकी (उदा. tsv://MS Terminal Services Plugin.1.CollectionName)", + "guacdProxy": "guacd प्रॉक्सी", + "guacdHostname": "guacd होस्ट", + "guacdHostnamePlaceholder": "वैश्विक डिफ़ॉल्ट", + "guacdPort": "guacd पोर्ट", + "guacdProxyDesc": "इस कनेक्शन के लिए वैश्विक guacd इंस्टेंस को अधिलेखित करें। वैश्विक रूप से कॉन्फ़िगर किए गए guacd का उपयोग करने के लिए खाली छोड़ें।", + "gatewayHostname": "गेटवे होस्टनाम", + "gatewayPort": "गेटवे पोर्ट", + "gatewayUsername": "गेटवे उपयोगकर्ता नाम", + "gatewayPassword": "गेटवे पासवर्ड", + "gatewayDomain": "गेटवे डोमेन", + "remoteAppProgram": "RemoteApp प्रोग्राम", + "workingDirectory": "कार्यशील निर्देशिका", + "arguments": "तर्क", + "normalizeLineEndings": "लाइन अंत सामान्यीकृत करें", + "macAddress": "MAC पता", + "broadcastAddress": "प्रसारण पता", + "udpPort": "UDP पोर्ट", + "waitTimeS": "प्रतीक्षा समय (s)", + "driveName": "ड्राइव का नाम", + "drivePath": "ड्राइव पथ", + "ignoreCertificate": "प्रमाणपत्र अनदेखा करें", + "ignoreCertificateDesc": "स्व-हस्ताक्षरित प्रमाणपत्र वाले होस्ट से कनेक्शन की अनुमति दें", + "forceLossless": "दोषरहित बाध्य करें", + "forceLosslessDesc": "दोषरहित छवि एन्कोडिंग बाध्य करें (उच्च गुणवत्ता, अधिक बैंडविड्थ)", + "disableAudio": "ऑडियो अक्षम करें", + "disableAudioDesc": "दूरस्थ सत्र से सभी ऑडियो म्यूट करें", + "enableAudioInput": "ऑडियो इनपुट सक्षम करें (माइक्रोफ़ोन)", + "enableAudioInputDesc": "स्थानीय माइक्रोफ़ोन को दूरस्थ सत्र में अग्रेषित करें", + "wallpaper": "वॉलपेपर", + "wallpaperDesc": "डेस्कटॉप वॉलपेपर दिखाएं (अक्षम करने से प्रदर्शन बेहतर होता है)", + "theming": "थीमिंग", + "themingDesc": "दृश्य थीम और शैलियाँ सक्षम करें", + "fontSmoothing": "फ़ॉन्ट स्मूथिंग", + "fontSmoothingDesc": "ClearType फ़ॉन्ट रेंडरिंग सक्षम करें", + "fullWindowDrag": "पूर्ण विंडो ड्रैग", + "fullWindowDragDesc": "ड्रैग करते समय विंडो सामग्री दिखाएं", + "desktopComposition": "डेस्कटॉप कंपोज़िशन", + "desktopCompositionDesc": "Aero ग्लास प्रभाव सक्षम करें", + "menuAnimations": "मेन्यू एनिमेशन", + "menuAnimationsDesc": "मेन्यू फेड और स्लाइड एनिमेशन सक्षम करें", + "disableBitmapCaching": "बिटमैप कैशिंग अक्षम करें", + "disableBitmapCachingDesc": "बिटमैप कैश बंद करें (गड़बड़ियों में मदद कर सकता है)", + "disableOffscreenCaching": "ऑफस्क्रीन कैशिंग अक्षम करें", + "disableOffscreenCachingDesc": "ऑफस्क्रीन कैश बंद करें", + "disableGlyphCaching": "ग्लिफ़ कैशिंग अक्षम करें", + "disableGlyphCachingDesc": "ग्लिफ़ कैश बंद करें", + "enableGfx": "GFX सक्षम करें", + "enableGfxDesc": "RemoteFX ग्राफ़िक्स पाइपलाइन का उपयोग करें", + "enablePrinting": "प्रिंटिंग सक्षम करें", + "enablePrintingDesc": "स्थानीय प्रिंटर को दूरस्थ सत्र में पुनर्निर्देशित करें", + "enableDriveRedirection": "ड्राइव पुनर्निर्देशन सक्षम करें", + "enableDriveRedirectionDesc": "स्थानीय फ़ोल्डर को दूरस्थ सत्र में ड्राइव के रूप में मैप करें", + "createDrivePath": "ड्राइव पथ बनाएँ", + "createDrivePathDesc": "यदि फ़ोल्डर मौजूद न हो तो स्वचालित रूप से बनाएँ", + "disableDownload": "डाउनलोड अक्षम करें", + "disableDownloadDesc": "रिमोट सत्र से फ़ाइलें डाउनलोड करना रोकें", + "disableUpload": "अपलोड अक्षम करें", + "disableUploadDesc": "रिमोट सत्र पर फ़ाइलें अपलोड करना रोकें", + "enableTouch": "टच सक्षम करें", + "enableTouchDesc": "टच इनपुट अग्रेषण सक्षम करें", + "consoleSession": "कंसोल सत्र", + "consoleSessionDesc": "नए सत्र के बजाय कंसोल (सत्र 0) से कनेक्ट करें", + "sendWolPacket": "WOL पैकेट भेजें", + "sendWolPacketDesc": "कनेक्ट करने से पहले इस होस्ट को जगाने के लिए मैजिक पैकेट भेजें", + "disableCopy": "कॉपी अक्षम करें", + "disableCopyDesc": "रिमोट सत्र से टेक्स्ट कॉपी करना रोकें", + "disablePaste": "पेस्ट अक्षम करें", + "disablePasteDesc": "रिमोट सत्र में टेक्स्ट पेस्ट करना रोकें", + "createPathIfMissing": "यदि पथ मौजूद न हो तो बनाएँ", + "createPathIfMissingDesc": "रिकॉर्डिंग निर्देशिका स्वचालित रूप से बनाएँ", + "excludeOutput": "आउटपुट बहिष्कृत करें", + "excludeOutputDesc": "स्क्रीन आउटपुट रिकॉर्ड न करें (केवल मेटाडेटा)", + "excludeMouse": "माउस बहिष्कृत करें", + "excludeMouseDesc": "माउस गतिविधियाँ रिकॉर्ड न करें", + "includeKeystrokes": "कीस्ट्रोक्स शामिल करें", + "includeKeystrokesDesc": "स्क्रीन आउटपुट के अतिरिक्त कच्चे कीस्ट्रोक्स रिकॉर्ड करें", + "vncPort": "VNC पोर्ट", + "vncPassword": "VNC पासवर्ड", + "vncUsernameOptional": "उपयोगकर्ता नाम (वैकल्पिक)", + "vncLeaveBlank": "यदि आवश्यक न हो तो खाली छोड़ें", + "cursorMode": "कर्सर मोड", + "swapRedBlue": "लाल/नीला अदल-बदल करें", + "swapRedBlueDesc": "लाल और नीले रंग चैनलों को अदल-बदल करें (कुछ रंग समस्याओं को ठीक करता है)", + "readOnly": "केवल-पठनीय", + "readOnlyDesc": "बिना कोई इनपुट भेजे रिमोट स्क्रीन देखें", + "telnetPort": "टेलनेट पोर्ट", + "terminalType": "टर्मिनल प्रकार", + "fontName": "फ़ॉन्ट नाम", + "fontSize": "फ़ॉन्ट आकार", + "colorScheme": "रंग योजना", + "backspaceKey": "बैकस्पेस कुंजी" + } + }, + "onboarding": { + "feature_desktop": "दूरवर्ती डेस्कटॉप", + "feature_desktop_desc": "RDP, VNC और Telnet सेशन को SSH की तरह ही एक टैब में खोलें।" + } +} diff --git a/plugins/remote-desktop/locales/translated/hu_HU.json b/plugins/remote-desktop/locales/translated/hu_HU.json new file mode 100644 index 000000000..336aa82ef --- /dev/null +++ b/plugins/remote-desktop/locales/translated/hu_HU.json @@ -0,0 +1,214 @@ +{ + "remoteDesktop": { + "connecting": "Kapcsolódás ehhez: {{type}} munkamenet...", + "checkingGuacd": "Távoli asztal szolgáltatás ellenőrzése...", + "requestingToken": "{{type}} kapcsolati token kérése...", + "openingSession": "{{type}} munkamenet megnyitása...", + "negotiating": "Kézfogásról tárgyalunk... {{type}}", + "sessionReady": "{{type}} munkamenet kész", + "connectionError": "Csatlakozási hiba", + "connectionFailed": "Kapcsolódás sikertelen", + "failedToConnect": "Nem sikerült lekérni a kapcsolati tokent", + "hostNotFound": "Nem található gazdagép", + "noHostSelected": "Nincs kiválasztva gazdagép", + "reconnect": "Újracsatlakozás", + "retry": "Újrapróbálkozás", + "guacdUnavailable": "A távoli asztali szolgáltatás (guacd) nem érhető el. Kérjük, győződjön meg róla, hogy a guacd fut, elérhető és megfelelően van konfigurálva az adminisztrátori beállításokban.", + "credentialPromptTitle": "RDP hitelesítő adatok megadása", + "credentialPromptDescription": "Ez a gazdagép úgy van beállítva, hogy csatlakozáskor hitelesítő adatokat kérjen. Ezeket csak ehhez a munkamenethez használjuk, és nem kerülnek mentésre.", + "connect": "Csatlakozás", + "ctrlAltDel": "Ctrl+Alt+Del", + "files": { + "title": "Drive-fájlok", + "parent": "Szülőkönyvtár", + "refresh": "Frissítés", + "empty": "Ez a mappa üres", + "listFailed": "Nem sikerült beolvasni ezt a mappát", + "download": "Letöltés", + "downloadFailed": "Nem sikerült letölteni {{name}}", + "upload": "Fájlok feltöltése", + "uploading": "Feltöltés {{name}}...", + "uploaded": "Feltöltve {{name}}", + "uploadFailed": "Nem sikerült feltölteni {{name}}", + "uploadDisabled": "A feltöltések le vannak tiltva ennél a kapcsolatnál.", + "driveUnavailable": "RDP meghajtó átirányításának engedélyezése fájlok feltöltése előtt", + "driveNotWritable": "A guacd nem tud írni a meghajtó mappájába. Ellenőrizd a GUACD_DRIVE_PATH-ot (vagy a gazdagép meghajtó elérési útját) és a hozzá tartozó jogosultságokat.", + "dropToUpload": "Fájlok húzása a feltöltéshez" + }, + "toolbar": { + "ctrlAltDel": "Ctrl+Alt+Del", + "winL": "Win+L (Képernyőzár)", + "winKey": "Windows billentyű", + "superL": "Super+L (Képernyőzár)", + "superKey": "Szuperkulcs", + "super": "Szuper", + "cmdL": "Cmd+L (Képernyő lezárása)", + "cmdKey": "Parancsbillentyű", + "cmd": "Parancs", + "ctrl": "Ctrl", + "alt": "Alt", + "shift": "Váltás", + "win": "Győzelem", + "stickyActive": "{{key}} (reteszelve - kattintson a kioldáshoz)", + "stickyInactive": "{{key}} (kattintson a rögzítéshez)", + "esc": "Menekülés", + "tab": "Fül", + "home": "Otthon", + "end": "Vége", + "pageUp": "Oldal fel", + "pageDown": "Oldal le", + "arrowUp": "Felfelé nyíl", + "arrowDown": "Lefelé mutató nyíl", + "arrowLeft": "Balra nyíl", + "arrowRight": "Jobbra nyíl", + "fnToggle": "Funkcióbillentyűk", + "reconnect": "Munkamenet újracsatlakoztatása", + "collapse": "Eszköztár összecsukása", + "expand": "Eszköztár kibontása", + "dragHandle": "Húzással áthelyezhető", + "hide": "Elrejtés ehhez a munkamenethez. A végleges letiltáshoz nyissa meg a Gazdagép beállításai → Általános → Kapcsolat eszköztár menüpontot.", + "zoomIn": "Nagyítás", + "zoomOut": "Kicsinyítés", + "resetZoom": "Nagyítás visszaállítása", + "fitToScreen": "Képernyőhöz igazítás", + "switchToTrackpad": "Váltás trackpad módra (húzással mozgathatja a kurzort, koppintással kattinthat)", + "switchToTouch": "Váltás érintőképernyős módra (koppintson közvetlenül oda, ahová kattintani szeretne)" + } + }, + "hosts": { + "nativeRdpOpened": "Megnyitva a Windows Távoli asztal alkalmazásban", + "nativeRdpFailed": "Nem sikerült megnyitni a Windows távoli asztalt", + "openNativeRdp": "Megnyitás a Windows távoli asztalon", + "guac": { + "connection": "Kapcsolat", + "authentication": "Hitelesítés", + "storedCredential": "Tárolt hitelesítő adatok", + "authMethod": "Aut. módszer", + "authTypeNoneDesc": "Nincsenek tárolt hitelesítő adatok. Minden csatlakozáskor meg kell adnia a felhasználónevet és a jelszót; ezek nem kerülnek mentésre.", + "selectCredential": "Válasszon hitelesítő adatot...", + "connectionSettings": "Kapcsolati beállítások", + "displaySettings": "Kijelzőbeállítások", + "audioSettings": "Hangbeállítások", + "rdpPerformance": "RDP-teljesítmény", + "deviceRedirection": "Eszközátirányítás", + "session": "Ülés", + "gateway": "Átjáró", + "remoteApp": "RemoteApp", + "clipboard": "Vágólap", + "sessionRecording": "Munkamenet-felvétel", + "wakeOnLan": "Wake-on-LAN", + "vncSettings": "VNC-beállítások", + "terminalSettings": "Terminálbeállítások", + "rdpPort": "RDP-port", + "username": "Felhasználónév", + "password": "Jelszó", + "passwordSaved": "Jelszó mentve, gépelje be a módosításhoz", + "domain": "Domain", + "securityMode": "Biztonsági mód", + "width": "Szélesség", + "height": "Magasság", + "dpi": "DPI", + "clientName": "Ügyfél neve", + "initialProgram": "Kezdeti program", + "serverLayout": "Szerver elrendezése", + "timezone": "Időzóna", + "loadBalanceInfo": "Terheléselosztási információk / Süti", + "loadBalanceInfoDesc": "RD Connection Broker süti az RDS farm terheléselosztásához (pl. tsv://MS Terminal Services Plugin.1.CollectionName)", + "guacdProxy": "guacd proxy", + "guacdHostname": "guacd Host", + "guacdHostnamePlaceholder": "Globális alapértelmezett", + "guacdPort": "guacd kikötő", + "guacdProxyDesc": "Írja felül a globális guacd példányt ehhez a kapcsolathoz. Hagyja üresen a globálisan konfigurált guacd használatához.", + "gatewayHostname": "Átjáró állomásneve", + "gatewayPort": "Átjáró kikötő", + "gatewayUsername": "Átjáró felhasználóneve", + "gatewayPassword": "Átjáró jelszava", + "gatewayDomain": "Átjáró domain", + "remoteAppProgram": "RemoteApp program", + "workingDirectory": "Munkakönyvtár", + "arguments": "érvek", + "normalizeLineEndings": "Sorvégek normalizálása", + "macAddress": "MAC-cím", + "broadcastAddress": "Sugárzási cím", + "udpPort": "UDP port", + "waitTimeS": "Várakozási idő (s)", + "driveName": "Meghajtó neve", + "drivePath": "Útvonal", + "ignoreCertificate": "Tanúsítvány figyelmen kívül hagyása", + "ignoreCertificateDesc": "Kapcsolódás engedélyezése önaláírt tanúsítványokkal rendelkező gazdagépekhez", + "forceLossless": "Veszteségmentes erő", + "forceLosslessDesc": "Veszteségmentes képkódolás kényszerítése (jobb minőség, nagyobb sávszélesség)", + "disableAudio": "Hang letiltása", + "disableAudioDesc": "Némítsa el az összes hangot a távoli munkamenetből", + "enableAudioInput": "Hangbemenet engedélyezése (mikrofon)", + "enableAudioInputDesc": "Helyi mikrofon továbbítása a távoli munkamenetbe", + "wallpaper": "Tapéta", + "wallpaperDesc": "Asztali háttérkép megjelenítése (a letiltás javítja a teljesítményt)", + "theming": "Témázás", + "themingDesc": "Vizuális témák és stílusok engedélyezése", + "fontSmoothing": "Betűsimítás", + "fontSmoothingDesc": "ClearType betűtípus-megjelenítés engedélyezése", + "fullWindowDrag": "Teljes ablak húzása", + "fullWindowDragDesc": "Ablak tartalmának megjelenítése húzás közben", + "desktopComposition": "Asztali kompozíció", + "desktopCompositionDesc": "Aero Glass effektek engedélyezése", + "menuAnimations": "Menüanimációk", + "menuAnimationsDesc": "Menü elhalványulásának és diaanimációk engedélyezése", + "disableBitmapCaching": "Bitképes gyorsítótár letiltása", + "disableBitmapCachingDesc": "Kapcsold ki a bitképes gyorsítótárat (segíthet a hibákon)", + "disableOffscreenCaching": "Képernyőn kívüli gyorsítótár letiltása", + "disableOffscreenCachingDesc": "Kapcsolja ki a képernyőn kívüli gyorsítótárat", + "disableGlyphCaching": "Karakterjel-gyorsítótár letiltása", + "disableGlyphCachingDesc": "Kapcsolja ki a karakterjel-gyorsítótárat", + "enableGfx": "GFX engedélyezése", + "enableGfxDesc": "RemoteFX grafikus folyamatsor használata", + "enablePrinting": "Nyomtatás engedélyezése", + "enablePrintingDesc": "Helyi nyomtatók átirányítása a távoli munkamenetre", + "enableDriveRedirection": "Meghajtó átirányításának engedélyezése", + "enableDriveRedirectionDesc": "Helyi mappa meghajtóként való leképezése a távoli munkamenetben", + "createDrivePath": "Útvonal létrehozása", + "createDrivePathDesc": "Automatikusan létrehozza a mappát, ha az nem létezik", + "disableDownload": "Letöltés letiltása", + "disableDownloadDesc": "Fájlok letöltésének megakadályozása a távoli munkamenetből", + "disableUpload": "Feltöltés letiltása", + "disableUploadDesc": "Fájlok távoli munkamenetbe való feltöltésének megakadályozása", + "enableTouch": "Érintés engedélyezése", + "enableTouchDesc": "Érintéses bevitel továbbításának engedélyezése", + "consoleSession": "Konzol munkamenet", + "consoleSessionDesc": "Csatlakozás a konzolhoz (0. munkamenet) egy új munkamenet helyett", + "sendWolPacket": "WOL csomag küldése", + "sendWolPacketDesc": "Küldjön egy varázslatos csomagot a gazdagép felébresztéséhez a csatlakozás előtt", + "disableCopy": "Másolás letiltása", + "disableCopyDesc": "Szöveg másolásának megakadályozása a távoli munkamenetből", + "disablePaste": "Beillesztés letiltása", + "disablePasteDesc": "Szöveg beillesztésének megakadályozása a távoli munkamenetbe", + "createPathIfMissing": "Útvonal létrehozása, ha hiányzik", + "createPathIfMissingDesc": "Felvételi könyvtár automatikus létrehozása", + "excludeOutput": "Kimenet kizárása", + "excludeOutputDesc": "Ne rögzítse a képernyőkimenetet (csak metaadatok)", + "excludeMouse": "Egér kizárása", + "excludeMouseDesc": "Ne rögzítse az egér mozgását", + "includeKeystrokes": "Billentyűleütések belefoglalása", + "includeKeystrokesDesc": "Nyers billentyűleütések rögzítése a képernyőn megjelenő kimenet mellett", + "vncPort": "VNC port", + "vncPassword": "VNC jelszó", + "vncUsernameOptional": "Felhasználónév (opcionális)", + "vncLeaveBlank": "Hagyja üresen, ha nem szükséges", + "cursorMode": "Kurzor mód", + "swapRedBlue": "Piros/Kék csere", + "swapRedBlueDesc": "Cserélje fel a piros és kék színcsatornákat (javít néhány színproblémát)", + "readOnly": "Csak olvasható", + "readOnlyDesc": "Távoli képernyő megtekintése bemenet küldése nélkül", + "telnetPort": "Telnet port", + "terminalType": "Terminál típusa", + "fontName": "Betűtípus neve", + "fontSize": "Betűméret", + "colorScheme": "Színséma", + "backspaceKey": "Visszatörlés billentyű" + } + }, + "onboarding": { + "feature_desktop": "Távoli asztal", + "feature_desktop_desc": "Nyisson meg RDP, VNC és Telnet munkameneteket egy lapon, ugyanúgy, mint az SSH-n." + } +} diff --git a/plugins/remote-desktop/locales/translated/id_ID.json b/plugins/remote-desktop/locales/translated/id_ID.json new file mode 100644 index 000000000..7b01e8448 --- /dev/null +++ b/plugins/remote-desktop/locales/translated/id_ID.json @@ -0,0 +1,214 @@ +{ + "remoteDesktop": { + "connecting": "Menghubungkan ke sesi {{type}}...", + "checkingGuacd": "Memeriksa layanan desktop jarak jauh...", + "requestingToken": "Meminta token koneksi {{type}}...", + "openingSession": "Membuka sesi {{type}}...", + "negotiating": "Bernegosiasi {{type}} jabat tangan...", + "sessionReady": "{{type}} sesi siap", + "connectionError": "Kesalahan koneksi", + "connectionFailed": "Koneksi gagal", + "failedToConnect": "Gagal mendapatkan token koneksi.", + "hostNotFound": "Host tidak ditemukan", + "noHostSelected": "Tidak ada pembawa acara yang dipilih.", + "reconnect": "Terhubung kembali", + "retry": "Mencoba kembali", + "guacdUnavailable": "Layanan desktop jarak jauh (guacd) tidak tersedia. Pastikan guacd berjalan, dapat diakses, dan dikonfigurasi dengan benar di pengaturan admin.", + "credentialPromptTitle": "Masukkan Kredensial RDP", + "credentialPromptDescription": "Host ini diatur untuk meminta kredensial saat terhubung. Kredensial tersebut hanya digunakan untuk sesi ini dan tidak disimpan.", + "connect": "Menghubungkan", + "ctrlAltDel": "Ctrl+Alt+Del", + "files": { + "title": "File Drive", + "parent": "Direktori induk", + "refresh": "Menyegarkan", + "empty": "Folder ini kosong", + "listFailed": "Gagal membaca folder ini", + "download": "Unduh", + "downloadFailed": "Gagal mengunduh {{name}}", + "upload": "Unggah file", + "uploading": "Mengunggah {{name}}...", + "uploaded": "Diunggah {{name}}", + "uploadFailed": "Gagal mengunggah {{name}}", + "uploadDisabled": "Unggahan dinonaktifkan untuk koneksi ini.", + "driveUnavailable": "Aktifkan pengalihan drive RDP sebelum mengunggah file.", + "driveNotWritable": "guacd tidak dapat menulis ke folder drive. Periksa GUACD_DRIVE_PATH (atau Drive Path host) dan izinnya.", + "dropToUpload": "Seret file untuk diunggah" + }, + "toolbar": { + "ctrlAltDel": "Ctrl+Alt+Del", + "winL": "Win+L (Kunci Layar)", + "winKey": "Kunci Windows", + "superL": "Super+L (Layar Kunci)", + "superKey": "Kunci Super", + "super": "Super", + "cmdL": "Cmd+L (Kunci Layar)", + "cmdKey": "Tombol Perintah", + "cmd": "Perintah", + "ctrl": "Ctrl", + "alt": "Alternatif", + "shift": "Menggeser", + "win": "Menang", + "stickyActive": "{{key}} (terkunci - klik untuk membuka)", + "stickyInactive": "{{key}} (klik untuk mengunci)", + "esc": "Melarikan diri", + "tab": "Tab", + "home": "Rumah", + "end": "Akhir", + "pageUp": "Halaman Atas", + "pageDown": "Halaman ke Bawah", + "arrowUp": "Panah Atas", + "arrowDown": "Panah ke Bawah", + "arrowLeft": "Panah Kiri", + "arrowRight": "Panah Kanan", + "fnToggle": "Tombol Fungsi", + "reconnect": "Sesi Terhubung Kembali", + "collapse": "Ciutkan bilah alat", + "expand": "Perluas bilah alat", + "dragHandle": "Seret untuk mengubah posisi", + "hide": "Sembunyikan untuk sesi ini. Untuk menonaktifkannya secara permanen, buka Pengaturan Host → Umum → Bilah Alat Koneksi.", + "zoomIn": "Perbesar", + "zoomOut": "Perbesar tampilan", + "resetZoom": "Atur ulang zoom", + "fitToScreen": "Sesuaikan dengan layar", + "switchToTrackpad": "Beralih ke mode trackpad (seret untuk memindahkan kursor, ketuk untuk mengklik)", + "switchToTouch": "Beralih ke mode sentuh (ketuk langsung di tempat yang ingin Anda klik)" + } + }, + "hosts": { + "nativeRdpOpened": "Dibuka di Windows Remote Desktop", + "nativeRdpFailed": "Gagal membuka Windows Remote Desktop", + "openNativeRdp": "Buka di Windows Remote Desktop", + "guac": { + "connection": "Koneksi", + "authentication": "Autentikasi", + "storedCredential": "Kredensial Tersimpan", + "authMethod": "Metode Otentikasi", + "authTypeNoneDesc": "Tidak ada kredensial yang disimpan. Anda akan diminta memasukkan nama pengguna dan kata sandi setiap kali Anda terhubung; informasi tersebut tidak disimpan.", + "selectCredential": "Pilih kredensial...", + "connectionSettings": "Pengaturan Koneksi", + "displaySettings": "Pengaturan Tampilan", + "audioSettings": "Pengaturan Audio", + "rdpPerformance": "Kinerja RDP", + "deviceRedirection": "Pengalihan Perangkat", + "session": "Sidang", + "gateway": "Gerbang", + "remoteApp": "RemoteApp", + "clipboard": "Papan klip", + "sessionRecording": "Rekaman Sesi", + "wakeOnLan": "Wake-on-LAN", + "vncSettings": "Pengaturan VNC", + "terminalSettings": "Pengaturan Terminal", + "rdpPort": "Port RDP", + "username": "Nama belakang", + "password": "Kata sandi", + "passwordSaved": "Kata sandi tersimpan, ketik untuk mengubahnya", + "domain": "Domain", + "securityMode": "Mode Keamanan", + "width": "Lebar", + "height": "Tinggi", + "dpi": "DPI", + "clientName": "Nama Klien", + "initialProgram": "Program Awal", + "serverLayout": "Tata Letak Server", + "timezone": "Zona waktu", + "loadBalanceInfo": "Informasi Saldo Beban / Cookie", + "loadBalanceInfoDesc": "Cookie RD Connection Broker untuk penyeimbangan beban farm RDS (misalnya tsv://MS Terminal Services Plugin.1.CollectionName)", + "guacdProxy": "Proksi guacd", + "guacdHostname": "guacd Host", + "guacdHostnamePlaceholder": "Pengaturan default global", + "guacdPort": "guacd Port", + "guacdProxyDesc": "Ganti instance guacd global untuk koneksi ini. Biarkan kosong untuk menggunakan guacd yang dikonfigurasi secara global.", + "gatewayHostname": "Nama Host Gateway", + "gatewayPort": "Port Gerbang", + "gatewayUsername": "Nama Pengguna Gateway", + "gatewayPassword": "Kata Sandi Gerbang", + "gatewayDomain": "Domain Gerbang", + "remoteAppProgram": "Program RemoteApp", + "workingDirectory": "Direktori Kerja", + "arguments": "Argumen", + "normalizeLineEndings": "Normalisasi Akhiran Baris", + "macAddress": "Alamat MAC", + "broadcastAddress": "Pidato Siaran", + "udpPort": "Port UDP", + "waitTimeS": "Waktu Tunggu (detik)", + "driveName": "Nama Drive", + "drivePath": "Jalur Berkendara", + "ignoreCertificate": "Abaikan Sertifikat", + "ignoreCertificateDesc": "Izinkan koneksi ke host dengan sertifikat yang ditandatangani sendiri.", + "forceLossless": "Paksa Tanpa Kehilangan", + "forceLosslessDesc": "Paksa pengkodean gambar tanpa kehilangan data (kualitas lebih tinggi, bandwidth lebih besar)", + "disableAudio": "Nonaktifkan Audio", + "disableAudioDesc": "Nonaktifkan semua audio dari sesi jarak jauh.", + "enableAudioInput": "Aktifkan Input Audio (Mikrofon)", + "enableAudioInputDesc": "Teruskan mikrofon lokal ke sesi jarak jauh.", + "wallpaper": "Wallpaper", + "wallpaperDesc": "Tampilkan wallpaper desktop (menonaktifkannya akan meningkatkan kinerja)", + "theming": "Tema", + "themingDesc": "Aktifkan tema dan gaya visual.", + "fontSmoothing": "Penghalusan Font", + "fontSmoothingDesc": "Aktifkan rendering font ClearType", + "fullWindowDrag": "Geser Jendela Penuh", + "fullWindowDragDesc": "Tampilkan isi jendela saat menyeret", + "desktopComposition": "Komposisi Desktop", + "desktopCompositionDesc": "Aktifkan efek kaca Aero", + "menuAnimations": "Animasi Menu", + "menuAnimationsDesc": "Aktifkan animasi pudar dan geser menu", + "disableBitmapCaching": "Nonaktifkan Cache Bitmap", + "disableBitmapCachingDesc": "Matikan cache bitmap (dapat membantu mengatasi gangguan)", + "disableOffscreenCaching": "Nonaktifkan Cache di Luar Layar", + "disableOffscreenCachingDesc": "Matikan cache di luar layar.", + "disableGlyphCaching": "Nonaktifkan Cache Glif", + "disableGlyphCachingDesc": "Matikan cache glif", + "enableGfx": "Aktifkan GFX", + "enableGfxDesc": "Gunakan pipeline grafis RemoteFX.", + "enablePrinting": "Aktifkan Pencetakan", + "enablePrintingDesc": "Alihkan printer lokal ke sesi jarak jauh.", + "enableDriveRedirection": "Aktifkan Pengalihan Drive", + "enableDriveRedirectionDesc": "Petakan folder lokal sebagai drive di sesi jarak jauh.", + "createDrivePath": "Buat Jalur Mengemudi", + "createDrivePathDesc": "Buat folder secara otomatis jika belum ada.", + "disableDownload": "Nonaktifkan Unduhan", + "disableDownloadDesc": "Mencegah pengunduhan file dari sesi jarak jauh", + "disableUpload": "Nonaktifkan Unggahan", + "disableUploadDesc": "Mencegah pengunggahan file ke sesi jarak jauh", + "enableTouch": "Aktifkan Sentuhan", + "enableTouchDesc": "Aktifkan penerusan input sentuh", + "consoleSession": "Sesi Konsol", + "consoleSessionDesc": "Hubungkan ke konsol (sesi 0) alih-alih sesi baru.", + "sendWolPacket": "Kirim Paket WOL", + "sendWolPacketDesc": "Kirim paket ajaib untuk membangunkan host ini sebelum terhubung.", + "disableCopy": "Nonaktifkan Salin", + "disableCopyDesc": "Mencegah penyalinan teks dari sesi jarak jauh", + "disablePaste": "Nonaktifkan Tempel", + "disablePasteDesc": "Mencegah penyisipan teks ke dalam sesi jarak jauh", + "createPathIfMissing": "Buat Jalur jika Belum Ada", + "createPathIfMissingDesc": "Membuat direktori rekaman secara otomatis.", + "excludeOutput": "Kecualikan Output", + "excludeOutputDesc": "Jangan merekam output layar (hanya metadata)", + "excludeMouse": "Kecualikan Tikus", + "excludeMouseDesc": "Jangan merekam pergerakan mouse.", + "includeKeystrokes": "Sertakan Penekanan Tombol", + "includeKeystrokesDesc": "Rekam setiap ketukan keyboard mentah selain output layar.", + "vncPort": "Port VNC", + "vncPassword": "Kata Sandi VNC", + "vncUsernameOptional": "Nama pengguna (opsional)", + "vncLeaveBlank": "Kosongkan jika tidak diperlukan", + "cursorMode": "Mode Kursor", + "swapRedBlue": "Tukar Merah/Biru", + "swapRedBlueDesc": "Tukar saluran warna merah dan biru (memperbaiki beberapa masalah warna)", + "readOnly": "Hanya baca", + "readOnlyDesc": "Lihat layar jarak jauh tanpa mengirimkan input apa pun.", + "telnetPort": "Port Telnet", + "terminalType": "Jenis Terminal", + "fontName": "Nama Font", + "fontSize": "Ukuran Huruf", + "colorScheme": "Skema Warna", + "backspaceKey": "Tombol Backspace" + } + }, + "onboarding": { + "feature_desktop": "Desktop jarak jauh", + "feature_desktop_desc": "Buka sesi RDP, VNC, dan Telnet dalam satu tab, sama seperti SSH." + } +} diff --git a/plugins/remote-desktop/locales/translated/it_IT.json b/plugins/remote-desktop/locales/translated/it_IT.json new file mode 100644 index 000000000..bfc53ce6d --- /dev/null +++ b/plugins/remote-desktop/locales/translated/it_IT.json @@ -0,0 +1,214 @@ +{ + "remoteDesktop": { + "connecting": "Connessione alla sessione {{type}} in corso...", + "checkingGuacd": "Verifica del servizio desktop remoto...", + "requestingToken": "Richiesta del token di connessione {{type}}...", + "openingSession": "Apertura della sessione {{type}}...", + "negotiating": "Negoziazione della stretta di mano {{type}}...", + "sessionReady": "{{type}} sessione pronta", + "connectionError": "Errore di connessione", + "connectionFailed": "Connessione fallita", + "failedToConnect": "Impossibile ottenere il token di connessione", + "hostNotFound": "Host non trovato", + "noHostSelected": "Nessun host selezionato", + "reconnect": "Riconnetti", + "retry": "Riprova", + "guacdUnavailable": "Il servizio desktop remoto (guacd) non è disponibile. Assicurati che guacd sia in esecuzione, accessibile e configurato correttamente nelle impostazioni di amministrazione.", + "credentialPromptTitle": "Inserisci le credenziali RDP", + "credentialPromptDescription": "Questo host è configurato per richiedere le credenziali al momento della connessione. Tali credenziali vengono utilizzate solo per questa sessione e non vengono salvate.", + "connect": "Collegare", + "ctrlAltDel": "Ctrl+Alt+Del", + "files": { + "title": "File di Drive", + "parent": "Cartella principale", + "refresh": "Rinfrescato", + "empty": "Questa cartella è vuota", + "listFailed": "Impossibile leggere questa cartella", + "download": "Scaricamento", + "downloadFailed": "Impossibile scaricare {{name}}", + "upload": "Carica i file", + "uploading": "Caricamento in corso {{name}}...", + "uploaded": "Caricato {{name}}", + "uploadFailed": "Impossibile caricare {{name}}", + "uploadDisabled": "Il caricamento è disabilitato per questa connessione.", + "driveUnavailable": "Abilita il reindirizzamento delle unità RDP prima di caricare i file", + "driveNotWritable": "guacd non può scrivere nella cartella dell'unità. Verificare GUACD_DRIVE_PATH (o il percorso dell'unità host) e le relative autorizzazioni.", + "dropToUpload": "Trascina i file da caricare" + }, + "toolbar": { + "ctrlAltDel": "Ctrl+Alt+Del", + "winL": "Win+L (Blocca schermo)", + "winKey": "Tasto Windows", + "superL": "Super+L (Schermata di blocco)", + "superKey": "Super Chiave", + "super": "Super", + "cmdL": "Cmd+L (Blocca schermo)", + "cmdKey": "Tasto di comando", + "cmd": "Comando", + "ctrl": "Ctrl", + "alt": "Alt", + "shift": "Shift", + "win": "Win", + "stickyActive": "{{key}} (bloccato - clicca per rilasciare)", + "stickyInactive": "{{key}} (clicca per bloccare)", + "esc": "Esc", + "tab": "Tab", + "home": "Home", + "end": "Fine", + "pageUp": "Pag Su", + "pageDown": "Pag Giù", + "arrowUp": "Freccia su", + "arrowDown": "Freccia giù", + "arrowLeft": "Freccia sinistra", + "arrowRight": "Freccia destra", + "fnToggle": "Tasti funzione", + "reconnect": "Riconnetti sessione", + "collapse": "Comprimi barra degli strumenti", + "expand": "Espandi barra degli strumenti", + "dragHandle": "Trascina per riposizionare", + "hide": "Nascondi per questa sessione. Per disabilitarlo in modo permanente, apri Impostazioni host → Generale → Barra degli strumenti di connessione.", + "zoomIn": "Ingrandisci", + "zoomOut": "Riduci lo zoom", + "resetZoom": "Ripristina lo zoom", + "fitToScreen": "Adatto allo schermo", + "switchToTrackpad": "Passa alla modalità trackpad (trascina per spostare il cursore, tocca per fare clic)", + "switchToTouch": "Passa alla modalità touch (tocca direttamente il punto in cui desideri fare clic)" + } + }, + "hosts": { + "nativeRdpOpened": "Aperto in Desktop remoto di Windows", + "nativeRdpFailed": "Impossibile aprire Desktop remoto di Windows", + "openNativeRdp": "Apri in Desktop remoto di Windows", + "guac": { + "connection": "Connessione", + "authentication": "Autenticazione", + "storedCredential": "Credenziale memorizzata", + "authMethod": "Metodo di autenticazione", + "authTypeNoneDesc": "Non vengono memorizzate credenziali. Ti verrà richiesto di inserire nome utente e password ogni volta che effettuerai la connessione; questi dati non verranno salvati.", + "selectCredential": "Seleziona una credenziale...", + "connectionSettings": "Impostazioni di connessione", + "displaySettings": "Impostazioni schermo", + "audioSettings": "Impostazioni audio", + "rdpPerformance": "Prestazioni RDP", + "deviceRedirection": "Reindirizzamento dispositivi", + "session": "Sessione", + "gateway": "Gateway", + "remoteApp": "RemoteApp", + "clipboard": "Appunti", + "sessionRecording": "Registrazione sessione", + "wakeOnLan": "Wake-on-LAN", + "vncSettings": "Impostazioni VNC", + "terminalSettings": "Impostazioni terminale", + "rdpPort": "Porta RDP", + "username": "Nome utente", + "password": "Password", + "passwordSaved": "Password salvata, digita per modificarla", + "domain": "Dominio", + "securityMode": "Modalità di sicurezza", + "width": "Larghezza", + "height": "Altezza", + "dpi": "DPI", + "clientName": "Nome client", + "initialProgram": "Programma iniziale", + "serverLayout": "Layout del server", + "timezone": "Fuso orario", + "loadBalanceInfo": "Info bilanciamento carico / Cookie", + "loadBalanceInfoDesc": "Cookie del RD Connection Broker per il bilanciamento del carico della farm RDS (es. tsv://MS Terminal Services Plugin.1.CollectionName)", + "guacdProxy": "Proxy guacd", + "guacdHostname": "Host guacd", + "guacdHostnamePlaceholder": "Default globale", + "guacdPort": "Porta guacd", + "guacdProxyDesc": "Sostituisci l'istanza guacd globale per questa connessione. Lascia vuoto per utilizzare il guacd configurato globalmente.", + "gatewayHostname": "Hostname del gateway", + "gatewayPort": "Porta del gateway", + "gatewayUsername": "Nome utente gateway", + "gatewayPassword": "Password gateway", + "gatewayDomain": "Dominio gateway", + "remoteAppProgram": "Programma RemoteApp", + "workingDirectory": "Directory di lavoro", + "arguments": "Argomenti", + "normalizeLineEndings": "Normalizza terminazioni di riga", + "macAddress": "Indirizzo MAC", + "broadcastAddress": "Indirizzo di broadcast", + "udpPort": "Porta UDP", + "waitTimeS": "Tempo di attesa (s)", + "driveName": "Nome unità", + "drivePath": "Percorso unità", + "ignoreCertificate": "Ignora certificato", + "ignoreCertificateDesc": "Consente connessioni a host con certificati autofirmati", + "forceLossless": "Forza lossless", + "forceLosslessDesc": "Forza la codifica lossless delle immagini (qualità più alta, maggiore utilizzo di banda)", + "disableAudio": "Disabilita audio", + "disableAudioDesc": "Disattiva tutto l'audio dalla sessione remota", + "enableAudioInput": "Abilita ingresso audio (microfono)", + "enableAudioInputDesc": "Inoltra il microfono locale alla sessione remota", + "wallpaper": "Sfondo", + "wallpaperDesc": "Mostra lo sfondo del desktop (disabilitarlo migliora le prestazioni)", + "theming": "Temi", + "themingDesc": "Abilita temi e stili visivi", + "fontSmoothing": "Smussamento caratteri", + "fontSmoothingDesc": "Abilita il rendering dei caratteri ClearType", + "fullWindowDrag": "Trascinamento finestra intera", + "fullWindowDragDesc": "Mostra il contenuto della finestra durante il trascinamento", + "desktopComposition": "Composizione desktop", + "desktopCompositionDesc": "Abilita gli effetti Aero Glass", + "menuAnimations": "Animazioni menu", + "menuAnimationsDesc": "Abilita animazioni di dissolvenza e scorrimento dei menu", + "disableBitmapCaching": "Disabilita cache bitmap", + "disableBitmapCachingDesc": "Disattiva la cache bitmap (può essere utile per risolvere anomalie)", + "disableOffscreenCaching": "Disabilita cache fuori schermo", + "disableOffscreenCachingDesc": "Disattiva la cache fuori schermo", + "disableGlyphCaching": "Disabilita cache glifi", + "disableGlyphCachingDesc": "Disattiva la cache dei glifi", + "enableGfx": "Abilita GFX", + "enableGfxDesc": "Usa la pipeline grafica RemoteFX", + "enablePrinting": "Abilita stampa", + "enablePrintingDesc": "Reindirizza le stampanti locali alla sessione remota", + "enableDriveRedirection": "Abilita reindirizzamento unità", + "enableDriveRedirectionDesc": "Mappa una cartella locale come unità nella sessione remota", + "createDrivePath": "Crea percorso drive", + "createDrivePathDesc": "Crea automaticamente la cartella se non esiste", + "disableDownload": "Disabilita download", + "disableDownloadDesc": "Impedisce il download di file dalla sessione remota", + "disableUpload": "Disabilita upload", + "disableUploadDesc": "Impedisce il caricamento di file sulla sessione remota", + "enableTouch": "Abilita input tattile", + "enableTouchDesc": "Abilita l'inoltro dell'input tattile", + "consoleSession": "Sessione console", + "consoleSessionDesc": "Connetti alla console (sessione 0) invece di una nuova sessione", + "sendWolPacket": "Invia pacchetto WOL", + "sendWolPacketDesc": "Invia un pacchetto magico per riattivare questo host prima della connessione", + "disableCopy": "Disabilita copia", + "disableCopyDesc": "Impedisce la copia di testo dalla sessione remota", + "disablePaste": "Disabilita incolla", + "disablePasteDesc": "Impedisce di incollare testo nella sessione remota", + "createPathIfMissing": "Crea percorso se mancante", + "createPathIfMissingDesc": "Crea automaticamente la directory di registrazione", + "excludeOutput": "Escludi output", + "excludeOutputDesc": "Non registrare l'output dello schermo (solo metadati)", + "excludeMouse": "Escludi mouse", + "excludeMouseDesc": "Non registrare i movimenti del mouse", + "includeKeystrokes": "Includi tasti premuti", + "includeKeystrokesDesc": "Registra i tasti premuti non elaborati in aggiunta all'output dello schermo", + "vncPort": "Porta VNC", + "vncPassword": "Password VNC", + "vncUsernameOptional": "Nome utente (opzionale)", + "vncLeaveBlank": "Lascia vuoto se non richiesto", + "cursorMode": "Modalità cursore", + "swapRedBlue": "Scambia Rosso/Blu", + "swapRedBlueDesc": "Scambia i canali di colore rosso e blu (corregge alcuni problemi di colore)", + "readOnly": "Sola lettura", + "readOnlyDesc": "Visualizza lo schermo remoto senza inviare alcun input", + "telnetPort": "Porta Telnet", + "terminalType": "Tipo terminale", + "fontName": "Nome font", + "fontSize": "Dimensione font", + "colorScheme": "Schema colori", + "backspaceKey": "Tasto Backspace" + } + }, + "onboarding": { + "feature_desktop": "Desktop remoto", + "feature_desktop_desc": "Apri le sessioni RDP, VNC e Telnet in una scheda, proprio come per SSH." + } +} diff --git a/plugins/remote-desktop/locales/translated/ja_JP.json b/plugins/remote-desktop/locales/translated/ja_JP.json new file mode 100644 index 000000000..763e54814 --- /dev/null +++ b/plugins/remote-desktop/locales/translated/ja_JP.json @@ -0,0 +1,214 @@ +{ + "remoteDesktop": { + "connecting": "{{type}} セッションに接続中...", + "checkingGuacd": "リモートデスクトップサービスを確認しています...", + "requestingToken": "{{type}} 接続トークンを要求しています...", + "openingSession": "{{type}} セッションを開始しています...", + "negotiating": "交渉中 {{type}} 握手...", + "sessionReady": "{{type}} セッション準備完了", + "connectionError": "接続エラー", + "connectionFailed": "接続失敗", + "failedToConnect": "接続トークンの取得に失敗しました", + "hostNotFound": "ホストが見つかりません", + "noHostSelected": "ホストが選択されていません", + "reconnect": "再接続", + "retry": "再試行", + "guacdUnavailable": "リモートデスクトップサービス (guacd) が利用できません。guacd が実行中でアクセス可能であり、管理者設定で正しく構成されていることを確認してください。", + "credentialPromptTitle": "RDP認証情報を入力してください", + "credentialPromptDescription": "このホストは、接続時に認証情報の入力を求めるように設定されています。認証情報は今回のセッションのみで使用され、保存されません。", + "connect": "接続する", + "ctrlAltDel": "Ctrl+Alt+Del", + "files": { + "title": "ドライブファイル", + "parent": "親ディレクトリ", + "refresh": "更新", + "empty": "このフォルダは空です", + "listFailed": "このフォルダの読み取りに失敗しました", + "download": "ダウンロード", + "downloadFailed": "ダウンロードに失敗しました {{name}}", + "upload": "ファイルをアップロードする", + "uploading": "{{name}} をアップロード中...", + "uploaded": "アップロード済み {{name}}", + "uploadFailed": "アップロードに失敗しました {{name}}", + "uploadDisabled": "この接続ではアップロードが無効になっています。", + "driveUnavailable": "ファイルをアップロードする前に、RDPドライブリダイレクトを有効にしてください。", + "driveNotWritable": "guacd はドライブフォルダに書き込むことができません。GUACD_DRIVE_PATH(またはホストのドライブパス)とそのアクセス許可を確認してください。", + "dropToUpload": "アップロードするファイルをドロップしてください" + }, + "toolbar": { + "ctrlAltDel": "Ctrl+Alt+Del", + "winL": "Win+L (画面ロック)", + "winKey": "Windows キー", + "superL": "Super+L(ロック画面)", + "superKey": "スーパーキー", + "super": "素晴らしい", + "cmdL": "Cmd+L(画面ロック)", + "cmdKey": "コマンドキー", + "cmd": "コマンド", + "ctrl": "Ctrl", + "alt": "Alt", + "shift": "Shift", + "win": "Win", + "stickyActive": "{{key}}(ラッチ中 - クリックで解除)", + "stickyInactive": "{{key}}(クリックでラッチ)", + "esc": "Escape", + "tab": "Tab", + "home": "Home", + "end": "End", + "pageUp": "Page Up", + "pageDown": "Page Down", + "arrowUp": "Arrow Up", + "arrowDown": "Arrow Down", + "arrowLeft": "Arrow Left", + "arrowRight": "Arrow Right", + "fnToggle": "ファンクションキー", + "reconnect": "セッション再接続", + "collapse": "ツールバーを折りたたむ", + "expand": "ツールバーを展開", + "dragHandle": "ドラッグで位置変更", + "hide": "このセッション中は非表示にします。完全に無効にするには、ホスト設定 → 一般 → 接続ツールバーを開いてください。", + "zoomIn": "ズームイン", + "zoomOut": "ズームアウト", + "resetZoom": "ズームをリセット", + "fitToScreen": "画面に合わせる", + "switchToTrackpad": "トラックパッドモードに切り替える(ドラッグでカーソルを移動、タップでクリック)", + "switchToTouch": "タッチモードに切り替える(クリックしたい場所を直接タップする)" + } + }, + "hosts": { + "nativeRdpOpened": "Windowsリモートデスクトップで開きました", + "nativeRdpFailed": "Windowsリモートデスクトップを開くことができませんでした", + "openNativeRdp": "Windowsリモートデスクトップで開く", + "guac": { + "connection": "接続", + "authentication": "認証", + "storedCredential": "保存された認証情報", + "authMethod": "認証方法", + "authTypeNoneDesc": "認証情報は保存されません。接続するたびにユーザー名とパスワードの入力を求められますが、それらは保存されません。", + "selectCredential": "認証情報を選択...", + "connectionSettings": "接続設定", + "displaySettings": "表示設定", + "audioSettings": "オーディオ設定", + "rdpPerformance": "RDP パフォーマンス", + "deviceRedirection": "デバイスリダイレクト", + "session": "セッション", + "gateway": "ゲートウェイ", + "remoteApp": "RemoteApp", + "clipboard": "クリップボード", + "sessionRecording": "セッション記録", + "wakeOnLan": "Wake-on-LAN", + "vncSettings": "VNC設定", + "terminalSettings": "ターミナル設定", + "rdpPort": "RDPポート", + "username": "ユーザー名", + "password": "パスワード", + "passwordSaved": "パスワードが保存されました。変更するには入力してください。", + "domain": "ドメイン", + "securityMode": "セキュリティモード", + "width": "幅", + "height": "高さ", + "dpi": "DPI", + "clientName": "クライアント名", + "initialProgram": "初期プログラム", + "serverLayout": "サーバーレイアウト", + "timezone": "タイムゾーン", + "loadBalanceInfo": "負荷分散情報 / Cookie", + "loadBalanceInfoDesc": "RDSファームの負荷分散用RD接続ブローカーCookie (例: tsv://MS Terminal Services Plugin.1.CollectionName)", + "guacdProxy": "guacdプロキシ", + "guacdHostname": "guacdホスト", + "guacdHostnamePlaceholder": "全体のデフォルト", + "guacdPort": "guacdポート", + "guacdProxyDesc": "この接続に対してグローバル guacd インスタンスを上書きします。空白にするとグローバルに設定された guacd を使用します。", + "gatewayHostname": "ゲートウェイホスト名", + "gatewayPort": "ゲートウェイポート", + "gatewayUsername": "ゲートウェイユーザー名", + "gatewayPassword": "ゲートウェイパスワード", + "gatewayDomain": "ゲートウェイドメイン", + "remoteAppProgram": "RemoteAppプログラム", + "workingDirectory": "作業ディレクトリ", + "arguments": "引数", + "normalizeLineEndings": "改行コードの正規化", + "macAddress": "MACアドレス", + "broadcastAddress": "ブロードキャストアドレス", + "udpPort": "UDPポート", + "waitTimeS": "待機時間(秒)", + "driveName": "ドライブ名", + "drivePath": "ドライブパス", + "ignoreCertificate": "証明書を無視", + "ignoreCertificateDesc": "自己署名証明書を持つホストへの接続を許可する", + "forceLossless": "ロスレスを強制", + "forceLosslessDesc": "ロスレス画像エンコーディングを強制する(高品質だが帯域幅を多く消費)", + "disableAudio": "オーディオを無効化", + "disableAudioDesc": "リモートセッションの音声をすべてミュートする", + "enableAudioInput": "音声入力(マイク)を有効化", + "enableAudioInputDesc": "ローカルマイクをリモートセッションに転送する", + "wallpaper": "壁紙", + "wallpaperDesc": "デスクトップ壁紙を表示する(無効にするとパフォーマンスが向上)", + "theming": "テーマ", + "themingDesc": "ビジュアルテーマとスタイルを有効にする", + "fontSmoothing": "フォントスムージング", + "fontSmoothingDesc": "ClearTypeフォントレンダリングを有効にする", + "fullWindowDrag": "フルウィンドウドラッグ", + "fullWindowDragDesc": "ウィンドウドラッグ中に内容を表示する", + "desktopComposition": "デスクトップコンポジション", + "desktopCompositionDesc": "Aero Glass効果を有効にする", + "menuAnimations": "メニューアニメーション", + "menuAnimationsDesc": "メニューのフェードおよびスライドアニメーションを有効にする", + "disableBitmapCaching": "ビットマップキャッシュを無効化", + "disableBitmapCachingDesc": "ビットマップキャッシュをオフにする(不具合の解決に役立つ場合がある)", + "disableOffscreenCaching": "オフスクリーンキャッシュを無効化", + "disableOffscreenCachingDesc": "オフスクリーンキャッシュをオフにする", + "disableGlyphCaching": "グリフキャッシュを無効化", + "disableGlyphCachingDesc": "グリフキャッシュをオフにする", + "enableGfx": "GFXを有効化", + "enableGfxDesc": "RemoteFXグラフィックスパイプラインを使用する", + "enablePrinting": "印刷を有効化", + "enablePrintingDesc": "ローカルプリンターをリモートセッションにリダイレクトする", + "enableDriveRedirection": "ドライブリダイレクションを有効化", + "enableDriveRedirectionDesc": "リモートセッションでローカルフォルダーをドライブとしてマッピングする", + "createDrivePath": "ドライブパスを作成", + "createDrivePathDesc": "フォルダが存在しない場合に自動的に作成します", + "disableDownload": "ダウンロードを無効にする", + "disableDownloadDesc": "リモートセッションからファイルをダウンロードできないようにします", + "disableUpload": "アップロードを無効にする", + "disableUploadDesc": "リモートセッションにファイルをアップロードできないようにします", + "enableTouch": "タッチを有効にする", + "enableTouchDesc": "タッチ入力転送を有効にします", + "consoleSession": "コンソールセッション", + "consoleSessionDesc": "新しいセッションではなくコンソール(セッション0)に接続します", + "sendWolPacket": "WOLパケットを送信", + "sendWolPacketDesc": "接続前にこのホストを起動するためのマジックパケットを送信します", + "disableCopy": "コピーを無効にする", + "disableCopyDesc": "リモートセッションからのテキストコピーを禁止します", + "disablePaste": "貼り付けを無効にする", + "disablePasteDesc": "リモートセッションへのテキスト貼り付けを禁止します", + "createPathIfMissing": "パスが存在しない場合に作成", + "createPathIfMissingDesc": "レコーディングディレクトリが存在しない場合に自動的に作成します", + "excludeOutput": "出力を除外", + "excludeOutputDesc": "画面出力を記録しません(メタデータのみ)", + "excludeMouse": "マウスを除外", + "excludeMouseDesc": "マウスの動きを記録しません", + "includeKeystrokes": "キーストロークを含める", + "includeKeystrokesDesc": "画面出力に加えて生のキーストロークを記録します", + "vncPort": "VNCポート", + "vncPassword": "VNCパスワード", + "vncUsernameOptional": "ユーザー名(オプション)", + "vncLeaveBlank": "必要ない場合は空白のままにしてください", + "cursorMode": "カーソルモード", + "swapRedBlue": "赤/青を入れ替え", + "swapRedBlueDesc": "赤と青の色チャネルを入れ替えます(色の問題を修正)", + "readOnly": "読み取り専用", + "readOnlyDesc": "入力を送信せずにリモート画面を表示します", + "telnetPort": "Telnetポート", + "terminalType": "端末タイプ", + "fontName": "フォント名", + "fontSize": "フォントサイズ", + "colorScheme": "カラースキーム", + "backspaceKey": "バックスペースキー" + } + }, + "onboarding": { + "feature_desktop": "リモートデスクトップ", + "feature_desktop_desc": "RDP、VNC、Telnetのセッションは、SSHと同様にタブで開きます。" + } +} diff --git a/plugins/remote-desktop/locales/translated/ko_KR.json b/plugins/remote-desktop/locales/translated/ko_KR.json new file mode 100644 index 000000000..71762195a --- /dev/null +++ b/plugins/remote-desktop/locales/translated/ko_KR.json @@ -0,0 +1,214 @@ +{ + "remoteDesktop": { + "connecting": "{{type}} 세션에 연결 중...", + "checkingGuacd": "원격 데스크톱 서비스를 확인하는 중...", + "requestingToken": "{{type}} 연결 토큰을 요청하는 중...", + "openingSession": "{{type}} 세션을 여는 중...", + "negotiating": "협상 중 {{type}} 악수...", + "sessionReady": "{{type}} 세션 준비 완료", + "connectionError": "연결 오류", + "connectionFailed": "연결 실패", + "failedToConnect": "연결 토큰을 가져오지 못했습니다.", + "hostNotFound": "호스트를 찾을 수 없음", + "noHostSelected": "선택된 호스트 없음", + "reconnect": "재연결", + "retry": "재시도", + "guacdUnavailable": "원격 데스크톱 서비스(guacd)를 사용할 수 없습니다. guacd가 실행 중이고 접근 가능하며 관리자 설정에서 올바르게 구성되었는지 확인하세요.", + "credentialPromptTitle": "RDP 자격 증명을 입력하십시오.", + "credentialPromptDescription": "이 호스트는 연결 시 자격 증명을 입력하라는 메시지를 표시하도록 설정되어 있습니다. 입력된 자격 증명은 해당 세션 동안에만 사용되며 저장되지 않습니다.", + "connect": "연결하다", + "ctrlAltDel": "Ctrl+Alt+Del", + "files": { + "title": "드라이브 파일", + "parent": "상위 디렉토리", + "refresh": "새로 고치다", + "empty": "이 폴더는 비어 있습니다", + "listFailed": "이 폴더를 읽는 데 실패했습니다.", + "download": "다운로드", + "downloadFailed": "{{name}} 다운로드에 실패했습니다.", + "upload": "파일 업로드", + "uploading": "{{name}} 업로드 중...", + "uploaded": "업로드됨 {{name}}", + "uploadFailed": "{{name}} 업로드에 실패했습니다.", + "uploadDisabled": "이 연결에서는 업로드가 비활성화되어 있습니다.", + "driveUnavailable": "파일을 업로드하기 전에 RDP 드라이브 리디렉션을 활성화하십시오.", + "driveNotWritable": "guacd가 드라이브 폴더에 쓰기 권한이 없습니다. GUACD_DRIVE_PATH(또는 호스트의 드라이브 경로)와 해당 권한을 확인하십시오.", + "dropToUpload": "업로드할 파일을 드롭하세요" + }, + "toolbar": { + "ctrlAltDel": "Ctrl+Alt+Del", + "winL": "Win+L (화면 잠금)", + "winKey": "Windows 키", + "superL": "Super+L (잠금 화면)", + "superKey": "슈퍼 키", + "super": "감독자", + "cmdL": "Cmd+L (화면 잠금)", + "cmdKey": "명령 키", + "cmd": "명령", + "ctrl": "Ctrl", + "alt": "Alt", + "shift": "Shift", + "win": "Win", + "stickyActive": "{{key}} (고정됨 - 클릭하여 해제)", + "stickyInactive": "{{key}} (클릭하여 고정)", + "esc": "Esc", + "tab": "Tab", + "home": "Home", + "end": "End", + "pageUp": "Page Up", + "pageDown": "Page Down", + "arrowUp": "위쪽 화살표", + "arrowDown": "아래쪽 화살표", + "arrowLeft": "왼쪽 화살표", + "arrowRight": "오른쪽 화살표", + "fnToggle": "기능 키", + "reconnect": "세션 재연결", + "collapse": "도구 모음 접기", + "expand": "도구 모음 펼치기", + "dragHandle": "드래그하여 위치 이동", + "hide": "이번 세션 동안에는 숨깁니다. 영구적으로 비활성화하려면 호스트 설정 → 일반 → 연결 도구 모음을 여세요.", + "zoomIn": "확대", + "zoomOut": "축소하기", + "resetZoom": "확대/축소 초기화", + "fitToScreen": "화면에 맞추기", + "switchToTrackpad": "트랙패드 모드로 전환하세요 (드래그하여 커서 이동, 탭하여 클릭).", + "switchToTouch": "터치 모드로 전환하세요 (클릭하려는 위치를 직접 탭하세요)." + } + }, + "hosts": { + "nativeRdpOpened": "Windows 원격 데스크톱에서 열림", + "nativeRdpFailed": "Windows 원격 데스크톱을 열지 못했습니다.", + "openNativeRdp": "Windows 원격 데스크톱에서 열기", + "guac": { + "connection": "연결", + "authentication": "인증", + "storedCredential": "저장된 자격 증명", + "authMethod": "인증 방법", + "authTypeNoneDesc": "사용자 이름은 저장되지 않습니다. 접속할 때마다 사용자 이름과 비밀번호를 입력하라는 메시지가 표시되며, 해당 정보는 저장되지 않습니다.", + "selectCredential": "자격 증명 선택...", + "connectionSettings": "연결 설정", + "displaySettings": "화면 설정", + "audioSettings": "오디오 설정", + "rdpPerformance": "RDP 성능", + "deviceRedirection": "장치 리디렉션", + "session": "세션", + "gateway": "게이트웨이", + "remoteApp": "RemoteApp", + "clipboard": "클립보드", + "sessionRecording": "세션 녹화", + "wakeOnLan": "Wake-on-LAN", + "vncSettings": "VNC 설정", + "terminalSettings": "터미널 설정", + "rdpPort": "RDP 포트", + "username": "사용자 이름", + "password": "비밀번호", + "passwordSaved": "비밀번호가 저장되었습니다. 변경하려면 입력하세요.", + "domain": "도메인", + "securityMode": "보안 모드", + "width": "너비", + "height": "높이", + "dpi": "DPI", + "clientName": "클라이언트 이름", + "initialProgram": "초기 프로그램", + "serverLayout": "서버 레이아웃", + "timezone": "시간대", + "loadBalanceInfo": "로드 밸런스 정보 / 쿠키", + "loadBalanceInfoDesc": "RDS 팜 로드 밸런싱을 위한 RD 연결 브로커 쿠키 (예: tsv://MS Terminal Services Plugin.1.CollectionName)", + "guacdProxy": "guacd 프록시", + "guacdHostname": "guacd 호스트", + "guacdHostnamePlaceholder": "전역 기본값", + "guacdPort": "guacd 포트", + "guacdProxyDesc": "이 연결에 대해 전역 guacd 인스턴스를 재정의합니다. 공란으로 두면 전역으로 구성된 guacd를 사용합니다.", + "gatewayHostname": "게이트웨이 호스트 이름", + "gatewayPort": "게이트웨이 포트", + "gatewayUsername": "게이트웨이 사용자 이름", + "gatewayPassword": "게이트웨이 비밀번호", + "gatewayDomain": "게이트웨이 도메인", + "remoteAppProgram": "RemoteApp 프로그램", + "workingDirectory": "작업 디렉터리", + "arguments": "인수", + "normalizeLineEndings": "줄 끝 정규화", + "macAddress": "MAC 주소", + "broadcastAddress": "브로드캐스트 주소", + "udpPort": "UDP 포트", + "waitTimeS": "대기 시간(초)", + "driveName": "드라이브 이름", + "drivePath": "드라이브 경로", + "ignoreCertificate": "인증서 무시", + "ignoreCertificateDesc": "자체 서명 인증서가 있는 호스트에 연결 허용", + "forceLossless": "무손실 강제", + "forceLosslessDesc": "무손실 이미지 인코딩 강제 (더 높은 품질, 더 많은 대역폭)", + "disableAudio": "오디오 비활성화", + "disableAudioDesc": "원격 세션의 모든 오디오 음소거", + "enableAudioInput": "오디오 입력 활성화 (마이크)", + "enableAudioInputDesc": "로컬 마이크를 원격 세션으로 전달", + "wallpaper": "배경 화면", + "wallpaperDesc": "바탕 화면 배경 표시 (비활성화 시 성능 향상)", + "theming": "테마", + "themingDesc": "비주얼 테마 및 스타일 활성화", + "fontSmoothing": "글꼴 다듬기", + "fontSmoothingDesc": "ClearType 글꼴 렌더링 사용", + "fullWindowDrag": "전체 창 끌기", + "fullWindowDragDesc": "드래그하는 동안 창 내용 표시", + "desktopComposition": "데스크톱 구성", + "desktopCompositionDesc": "Aero 글래스 효과 활성화", + "menuAnimations": "메뉴 애니메이션", + "menuAnimationsDesc": "메뉴 페이드 및 슬라이드 애니메이션 활성화", + "disableBitmapCaching": "비트맵 캐싱 비활성화", + "disableBitmapCachingDesc": "비트맵 캐시 끄기 (오류 해결에 도움이 될 수 있음)", + "disableOffscreenCaching": "오프스크린 캐싱 비활성화", + "disableOffscreenCachingDesc": "오프스크린 캐시 끄기", + "disableGlyphCaching": "글리프 캐싱 비활성화", + "disableGlyphCachingDesc": "글리프 캐시 끄기", + "enableGfx": "GFX 활성화", + "enableGfxDesc": "RemoteFX 그래픽 파이프라인 사용", + "enablePrinting": "인쇄 활성화", + "enablePrintingDesc": "로컬 프린터를 원격 세션으로 리디렉션", + "enableDriveRedirection": "드라이브 리디렉션 활성화", + "enableDriveRedirectionDesc": "로컬 폴더를 원격 세션에서 드라이브로 매핑", + "createDrivePath": "드라이브 경로 생성", + "createDrivePathDesc": "폴더가 없으면 자동 생성", + "disableDownload": "다운로드 비활성화", + "disableDownloadDesc": "원격 세션에서 파일 다운로드 방지", + "disableUpload": "업로드 비활성화", + "disableUploadDesc": "원격 세션으로 파일 업로드 방지", + "enableTouch": "터치 활성화", + "enableTouchDesc": "터치 입력 전달 활성화", + "consoleSession": "콘솔 세션", + "consoleSessionDesc": "새 세션 대신 콘솔(세션 0)에 연결", + "sendWolPacket": "WOL 패킷 전송", + "sendWolPacketDesc": "연결 전에 호스트를 깨우기 위해 매직 패킷 전송", + "disableCopy": "복사 비활성화", + "disableCopyDesc": "원격 세션에서 텍스트 복사 방지", + "disablePaste": "붙여넣기 비활성화", + "disablePasteDesc": "원격 세션으로 텍스트 붙여넣기 방지", + "createPathIfMissing": "경로가 없으면 생성", + "createPathIfMissingDesc": "녹화 디렉터리 자동 생성", + "excludeOutput": "출력 제외", + "excludeOutputDesc": "화면 출력 기록 안 함(메타데이터만)", + "excludeMouse": "마우스 제외", + "excludeMouseDesc": "마우스 움직임 기록 안 함", + "includeKeystrokes": "키 입력 포함", + "includeKeystrokesDesc": "화면 출력 외에 원시 키 입력 기록", + "vncPort": "VNC 포트", + "vncPassword": "VNC 비밀번호", + "vncUsernameOptional": "사용자 이름(선택 사항)", + "vncLeaveBlank": "필요하지 않으면 비워 두세요", + "cursorMode": "커서 모드", + "swapRedBlue": "적색/청색 교환", + "swapRedBlueDesc": "적색과 청색 채널을 교환(일부 색상 문제 해결)", + "readOnly": "읽기 전용", + "readOnlyDesc": "입력을 보내지 않고 원격 화면 보기", + "telnetPort": "Telnet 포트", + "terminalType": "터미널 유형", + "fontName": "글꼴 이름", + "fontSize": "글꼴 크기", + "colorScheme": "색 구성표", + "backspaceKey": "백스페이스 키" + } + }, + "onboarding": { + "feature_desktop": "원격 데스크톱", + "feature_desktop_desc": "SSH와 마찬가지로 RDP, VNC 및 Telnet 세션을 탭에서 열 수 있습니다." + } +} diff --git a/plugins/remote-desktop/locales/translated/nl_NL.json b/plugins/remote-desktop/locales/translated/nl_NL.json new file mode 100644 index 000000000..275f445bb --- /dev/null +++ b/plugins/remote-desktop/locales/translated/nl_NL.json @@ -0,0 +1,214 @@ +{ + "remoteDesktop": { + "connecting": "Verbinding maken met de {{type}} sessie...", + "checkingGuacd": "De externe bureaubladservice controleren...", + "requestingToken": "Verzoek om {{type}} verbindingstoken...", + "openingSession": "Sessie {{type}} openen...", + "negotiating": "Onderhandelen over een {{type}} handdruk...", + "sessionReady": "{{type}} sessie gereed", + "connectionError": "Verbindingsfout", + "connectionFailed": "Verbinding mislukt", + "failedToConnect": "Verbindingstoken kon niet worden verkregen.", + "hostNotFound": "Host niet gevonden", + "noHostSelected": "Geen host geselecteerd", + "reconnect": "Opnieuw verbinding maken", + "retry": "Opnieuw proberen", + "guacdUnavailable": "De service voor extern bureaublad (guacd) is niet beschikbaar. Zorg ervoor dat guacd actief en toegankelijk is en correct is geconfigureerd in de beheerdersinstellingen.", + "credentialPromptTitle": "Voer de RDP-inloggegevens in.", + "credentialPromptDescription": "Deze host is zo ingesteld dat er bij het verbinden om inloggegevens wordt gevraagd. Deze worden alleen voor deze sessie gebruikt en niet opgeslagen.", + "connect": "Verbinden", + "ctrlAltDel": "Ctrl+Alt+Del", + "files": { + "title": "Drive-bestanden", + "parent": "Hoofdmap", + "refresh": "Vernieuwen", + "empty": "Deze map is leeg.", + "listFailed": "Het lezen van deze map is mislukt.", + "download": "Download", + "downloadFailed": "Downloaden mislukt {{name}}", + "upload": "Bestanden uploaden", + "uploading": "Bezig met uploaden {{name}}...", + "uploaded": "Geüpload {{name}}", + "uploadFailed": "Uploaden mislukt {{name}}", + "uploadDisabled": "Uploaden is uitgeschakeld voor deze verbinding.", + "driveUnavailable": "Schakel RDP-schijfomleiding in voordat u bestanden uploadt.", + "driveNotWritable": "guacd kan niet naar de schijfmap schrijven. Controleer GUACD_DRIVE_PATH (of het schijfpad van de host) en de bijbehorende machtigingen.", + "dropToUpload": "Sleep de bestanden hierheen om ze te uploaden." + }, + "toolbar": { + "ctrlAltDel": "Ctrl+Alt+Del", + "winL": "Win+L (Vergrendelscherm)", + "winKey": "Windows-toets", + "superL": "Super+L (Vergrendelscherm)", + "superKey": "Supersleutel", + "super": "Super", + "cmdL": "Cmd+L (Scherm vergrendelen)", + "cmdKey": "Commando-toets", + "cmd": "Commando", + "ctrl": "Ctrl", + "alt": "Alt", + "shift": "Verschuiving", + "win": "Winnen", + "stickyActive": "{{key}} (vergrendeld - klik om te ontgrendelen)", + "stickyInactive": "{{key}} (klik om te vergrendelen)", + "esc": "Ontsnappen", + "tab": "Tab", + "home": "Thuis", + "end": "Einde", + "pageUp": "Pagina omhoog", + "pageDown": "Pagina omlaag", + "arrowUp": "Pijl omhoog", + "arrowDown": "Pijl omlaag", + "arrowLeft": "Pijl naar links", + "arrowRight": "Pijl naar rechts", + "fnToggle": "Functietoetsen", + "reconnect": "Herverbindingssessie", + "collapse": "Werkbalk inklappen", + "expand": "Werkbalk uitklappen", + "dragHandle": "Sleep om te verplaatsen", + "hide": "Voor deze sessie verbergen. Om het permanent uit te schakelen, opent u Hostinstellingen → Algemeen → Verbindingswerkbalk.", + "zoomIn": "Zoom in", + "zoomOut": "Uitzoomen", + "resetZoom": "Zoom opnieuw instellen", + "fitToScreen": "Aan het scherm aanpassen", + "switchToTrackpad": "Schakel over naar de trackpadmodus (sleep om de cursor te verplaatsen, tik om te klikken).", + "switchToTouch": "Schakel over naar de aanraakmodus (tik direct op de plek waar u wilt klikken)." + } + }, + "hosts": { + "nativeRdpOpened": "Geopend in Windows Remote Desktop", + "nativeRdpFailed": "Het openen van Windows Remote Desktop is mislukt.", + "openNativeRdp": "Openen in Windows Extern bureaublad", + "guac": { + "connection": "Verbinding", + "authentication": "Authenticatie", + "storedCredential": "Opgeslagen inloggegevens", + "authMethod": "Authenticatiemethode", + "authTypeNoneDesc": "Er worden geen inloggegevens opgeslagen. U wordt bij elke verbinding gevraagd om een gebruikersnaam en wachtwoord; deze worden niet bewaard.", + "selectCredential": "Selecteer een certificaat...", + "connectionSettings": "Verbindingsinstellingen", + "displaySettings": "Weergave-instellingen", + "audioSettings": "Audio-instellingen", + "rdpPerformance": "RDP-prestaties", + "deviceRedirection": "Apparaatomleiding", + "session": "Sessie", + "gateway": "Gateway", + "remoteApp": "RemoteApp", + "clipboard": "Klembord", + "sessionRecording": "Sessieopname", + "wakeOnLan": "Wake-on-LAN", + "vncSettings": "VNC-instellingen", + "terminalSettings": "Terminalinstellingen", + "rdpPort": "RDP-poort", + "username": "Gebruikersnaam", + "password": "Wachtwoord", + "passwordSaved": "Wachtwoord opgeslagen, typ om te wijzigen", + "domain": "Domein", + "securityMode": "Beveiligingsmodus", + "width": "Breedte", + "height": "Hoogte", + "dpi": "DPI", + "clientName": "Klantnaam", + "initialProgram": "Initiële programma", + "serverLayout": "Serverindeling", + "timezone": "Tijdzone", + "loadBalanceInfo": "Informatie over load balancing / Cookie", + "loadBalanceInfoDesc": "RD Connection Broker-cookie voor load balancing van RDS-farms (bijv. tsv://MS Terminal Services Plugin.1.CollectionName)", + "guacdProxy": "guacd-proxy", + "guacdHostname": "guacd Host", + "guacdHostnamePlaceholder": "Globale standaard", + "guacdPort": "bewakingshaven", + "guacdProxyDesc": "Overschrijf de globale guacd-instantie voor deze verbinding. Laat dit veld leeg om de globaal geconfigureerde guacd te gebruiken.", + "gatewayHostname": "Gateway-hostnaam", + "gatewayPort": "Gateway-poort", + "gatewayUsername": "Gateway-gebruikersnaam", + "gatewayPassword": "Gateway-wachtwoord", + "gatewayDomain": "Gateway-domein", + "remoteAppProgram": "RemoteApp-programma", + "workingDirectory": "Werkmap", + "arguments": "Argumenten", + "normalizeLineEndings": "Normaliseer regeleinden", + "macAddress": "MAC-adres", + "broadcastAddress": "Uitzendadres", + "udpPort": "UDP-poort", + "waitTimeS": "Wachttijd (s)", + "driveName": "Schijfnaam", + "drivePath": "Rijpad", + "ignoreCertificate": "Certificaat negeren", + "ignoreCertificateDesc": "Sta verbindingen toe met hosts die zelfondertekende certificaten hebben.", + "forceLossless": "Krachtverliesloos", + "forceLosslessDesc": "Forceer verliesvrije beeldcodering (hogere kwaliteit, meer bandbreedte)", + "disableAudio": "Geluid uitschakelen", + "disableAudioDesc": "Demp alle audio van de externe sessie.", + "enableAudioInput": "Audio-ingang (microfoon) inschakelen", + "enableAudioInputDesc": "Stuur de lokale microfoon door naar de externe sessie.", + "wallpaper": "Behang", + "wallpaperDesc": "Toon bureaubladachtergrond (uitschakelen verbetert de prestaties)", + "theming": "Thema", + "themingDesc": "Schakel visuele thema's en stijlen in.", + "fontSmoothing": "Lettertype-vloeiendheid", + "fontSmoothingDesc": "Schakel ClearType-lettertypeweergave in", + "fullWindowDrag": "Volledig venster slepen", + "fullWindowDragDesc": "Toon de inhoud van het venster tijdens het slepen.", + "desktopComposition": "Bureaubladcompositie", + "desktopCompositionDesc": "Schakel Aero-glaseffecten in", + "menuAnimations": "Menu-animaties", + "menuAnimationsDesc": "Schakel menu-vervagings- en schuifanimaties in.", + "disableBitmapCaching": "Bitmapcaching uitschakelen", + "disableBitmapCachingDesc": "Schakel de bitmapcache uit (dit kan helpen bij storingen).", + "disableOffscreenCaching": "Offscreen-caching uitschakelen", + "disableOffscreenCachingDesc": "Schakel de offscreen cache uit.", + "disableGlyphCaching": "Glyph-caching uitschakelen", + "disableGlyphCachingDesc": "Schakel de glyph-cache uit.", + "enableGfx": "Schakel GFX in", + "enableGfxDesc": "Gebruik de RemoteFX-grafische pipeline", + "enablePrinting": "Afdrukken inschakelen", + "enablePrintingDesc": "Lokale printers doorverwijzen naar de externe sessie", + "enableDriveRedirection": "Schakel schijfomleiding in", + "enableDriveRedirectionDesc": "Een lokale map toewijzen als schijfstation in de externe sessie.", + "createDrivePath": "Maak een rijpad aan", + "createDrivePathDesc": "Maak de map automatisch aan als deze nog niet bestaat.", + "disableDownload": "Download uitschakelen", + "disableDownloadDesc": "Voorkom het downloaden van bestanden vanuit de externe sessie.", + "disableUpload": "Uploaden uitschakelen", + "disableUploadDesc": "Voorkom het uploaden van bestanden naar de externe sessie.", + "enableTouch": "Aanraakbediening inschakelen", + "enableTouchDesc": "Schakel het doorsturen van aanraakinvoer in.", + "consoleSession": "Consolesessie", + "consoleSessionDesc": "Maak verbinding met de console (sessie 0) in plaats van een nieuwe sessie te starten.", + "sendWolPacket": "Verzend WOL-pakket", + "sendWolPacketDesc": "Verzend een magic packet om deze host te activeren voordat u verbinding maakt.", + "disableCopy": "Kopiëren uitschakelen", + "disableCopyDesc": "Voorkom het kopiëren van tekst vanuit de externe sessie.", + "disablePaste": "Plakken uitschakelen", + "disablePasteDesc": "Voorkom dat tekst in de externe sessie wordt geplakt.", + "createPathIfMissing": "Maak een pad aan als dit ontbreekt.", + "createPathIfMissingDesc": "Maak automatisch de opnamemap aan.", + "excludeOutput": "Uitvoer uitsluiten", + "excludeOutputDesc": "Schermuitvoer niet opnemen (alleen metadata).", + "excludeMouse": "Muis uitsluiten", + "excludeMouseDesc": "Neem geen muisbewegingen op.", + "includeKeystrokes": "Inclusief toetsaanslagen", + "includeKeystrokesDesc": "Registreer naast de schermuitvoer ook onbewerkte toetsaanslagen.", + "vncPort": "VNC-poort", + "vncPassword": "VNC-wachtwoord", + "vncUsernameOptional": "Gebruikersnaam (optioneel)", + "vncLeaveBlank": "Laat dit veld leeg als het niet verplicht is.", + "cursorMode": "Cursormodus", + "swapRedBlue": "Wissel rood/blauw om.", + "swapRedBlueDesc": "Wissel de rode en blauwe kleurkanalen om (dit lost enkele kleurproblemen op).", + "readOnly": "Alleen-lezen", + "readOnlyDesc": "Bekijk het externe scherm zonder invoer te verzenden.", + "telnetPort": "Telnet-poort", + "terminalType": "Terminaltype", + "fontName": "Lettertypenaam", + "fontSize": "Lettergrootte", + "colorScheme": "Kleurenschema", + "backspaceKey": "Backspace-toets" + } + }, + "onboarding": { + "feature_desktop": "Extern bureaublad", + "feature_desktop_desc": "Open RDP-, VNC- en Telnet-sessies in een tabblad, net als bij SSH." + } +} diff --git a/plugins/remote-desktop/locales/translated/no_NO.json b/plugins/remote-desktop/locales/translated/no_NO.json new file mode 100644 index 000000000..ba4130e8c --- /dev/null +++ b/plugins/remote-desktop/locales/translated/no_NO.json @@ -0,0 +1,214 @@ +{ + "remoteDesktop": { + "connecting": "Kobler til {{type}} økt...", + "checkingGuacd": "Sjekker tjenesten for eksternt skrivebord...", + "requestingToken": "Ber om {{type}} tilkoblingstoken...", + "openingSession": "Åpner {{type}} økt...", + "negotiating": "Forhandler {{type}} håndtrykk...", + "sessionReady": "{{type}} økt klar", + "connectionError": "Tilkoblingsfeil", + "connectionFailed": "Tilkoblingen mislyktes", + "failedToConnect": "Kunne ikke hente tilkoblingstoken", + "hostNotFound": "Verten ble ikke funnet", + "noHostSelected": "Ingen vert valgt", + "reconnect": "Koble til igjen", + "retry": "Prøv på nytt", + "guacdUnavailable": "Ekstern skrivebordstjeneste (guacd) er ikke tilgjengelig. Sørg for at guacd kjører, er tilgjengelig og riktig konfigurert i administratorinnstillingene.", + "credentialPromptTitle": "Skriv inn RDP-legitimasjon", + "credentialPromptDescription": "Denne verten er satt til å be om påloggingsinformasjon ved tilkobling. Disse brukes kun for denne økten og lagres ikke.", + "connect": "Koble til", + "ctrlAltDel": "Ctrl+Alt+Del", + "files": { + "title": "Disk-filer", + "parent": "Foreldrekatalog", + "refresh": "Forfriske", + "empty": "Denne mappen er tom", + "listFailed": "Kunne ikke lese denne mappen", + "download": "Last ned", + "downloadFailed": "Kunne ikke laste ned {{name}}", + "upload": "Last opp filer", + "uploading": "Laster opp {{name}}...", + "uploaded": "Lastet opp {{name}}", + "uploadFailed": "Kunne ikke laste opp {{name}}", + "uploadDisabled": "Opplastinger er deaktivert for denne tilkoblingen", + "driveUnavailable": "Aktiver omdirigering av RDP-stasjoner før du laster opp filer", + "driveNotWritable": "guacd kan ikke skrive til stasjonsmappen. Sjekk GUACD_DRIVE_PATH (eller vertens stasjonsbane) og dens tillatelser.", + "dropToUpload": "Slipp filer for å laste opp" + }, + "toolbar": { + "ctrlAltDel": "Ctrl+Alt+Del", + "winL": "Win+L (Låseskjerm)", + "winKey": "Windows-nøkkel", + "superL": "Super+L (Låseskjerm)", + "superKey": "Supernøkkel", + "super": "Super", + "cmdL": "Cmd+L (Låseskjerm)", + "cmdKey": "Kommandotast", + "cmd": "Kommando", + "ctrl": "Ctrl", + "alt": "Alt", + "shift": "Skifte", + "win": "Vinne", + "stickyActive": "{{key}} (låst – klikk for å slippe)", + "stickyInactive": "{{key}} (klikk for å låse)", + "esc": "Flykte", + "tab": "Fane", + "home": "Hjem", + "end": "Slutt", + "pageUp": "Side opp", + "pageDown": "Side ned", + "arrowUp": "Pil opp", + "arrowDown": "Pil ned", + "arrowLeft": "Pil venstre", + "arrowRight": "Pil høyre", + "fnToggle": "Funksjonstaster", + "reconnect": "Koble til økten på nytt", + "collapse": "Skjul verktøylinjen", + "expand": "Utvid verktøylinjen", + "dragHandle": "Dra for å flytte", + "hide": "Skjul for denne økten. For å deaktivere den permanent, åpne Vertsinnstillinger → Generelt → Tilkoblingsverktøylinje.", + "zoomIn": "Zoom inn", + "zoomOut": "Zoom ut", + "resetZoom": "Tilbakestill zoom", + "fitToScreen": "Tilpass til skjerm", + "switchToTrackpad": "Bytt til styreflatemodus (dra for å flytte markøren, trykk for å klikke)", + "switchToTouch": "Bytt til berøringsmodus (trykk direkte der du vil klikke)" + } + }, + "hosts": { + "nativeRdpOpened": "Åpnet i Windows Eksternt skrivebord", + "nativeRdpFailed": "Kunne ikke åpne Windows Eksternt skrivebord", + "openNativeRdp": "Åpne i Windows Eksternt skrivebord", + "guac": { + "connection": "Forbindelse", + "authentication": "Autentisering", + "storedCredential": "Lagret legitimasjon", + "authMethod": "Autentiseringsmetode", + "authTypeNoneDesc": "Ingen påloggingsinformasjon lagres. Du blir bedt om å oppgi brukernavn og passord hver gang du kobler til; de lagres ikke.", + "selectCredential": "Velg en legitimasjon...", + "connectionSettings": "Tilkoblingsinnstillinger", + "displaySettings": "Skjerminnstillinger", + "audioSettings": "Lydinnstillinger", + "rdpPerformance": "RDP-ytelse", + "deviceRedirection": "Omdirigering av enheter", + "session": "Økt", + "gateway": "Inngangsport", + "remoteApp": "Fjernapp", + "clipboard": "Utklippstavlen", + "sessionRecording": "Øktopptak", + "wakeOnLan": "Wake-on-LAN", + "vncSettings": "VNC-innstillinger", + "terminalSettings": "Terminalinnstillinger", + "rdpPort": "RDP-port", + "username": "Brukernavn", + "password": "Passord", + "passwordSaved": "Passord lagret, skriv inn for å endre", + "domain": "Domene", + "securityMode": "Sikkerhetsmodus", + "width": "Bredde", + "height": "Høyde", + "dpi": "DPI", + "clientName": "Klientnavn", + "initialProgram": "Innledende program", + "serverLayout": "Serveroppsett", + "timezone": "Tidssone", + "loadBalanceInfo": "Informasjon om lastbalanse / informasjonskapsler", + "loadBalanceInfoDesc": "RD Connection Broker-informasjonskapsel for lastbalansering på RDS-farm (f.eks. tsv://MS Terminal Services Plugin.1.CollectionName)", + "guacdProxy": "guacd-proxy", + "guacdHostname": "guacd-vert", + "guacdHostnamePlaceholder": "Global standard", + "guacdPort": "guacd-porten", + "guacdProxyDesc": "Overstyr den globale guacd-forekomsten for denne tilkoblingen. La stå tomt for å bruke den globalt konfigurerte guacd-en.", + "gatewayHostname": "Gateway-vertsnavn", + "gatewayPort": "Gateway-porten", + "gatewayUsername": "Gateway-brukernavn", + "gatewayPassword": "Gateway-passord", + "gatewayDomain": "Gateway-domene", + "remoteAppProgram": "RemoteApp-programmet", + "workingDirectory": "Arbeidskatalog", + "arguments": "Argumenter", + "normalizeLineEndings": "Normaliser linjeavslutninger", + "macAddress": "MAC-adresse", + "broadcastAddress": "Kringkastingsadresse", + "udpPort": "UDP-port", + "waitTimeS": "Ventetid (s)", + "driveName": "Stasjonsnavn", + "drivePath": "Kjøresti", + "ignoreCertificate": "Ignorer sertifikat", + "ignoreCertificateDesc": "Tillat tilkoblinger til verter med selvsignerte sertifikater", + "forceLossless": "Tving tapsfri", + "forceLosslessDesc": "Tving frem tapsfri bildekoding (høyere kvalitet, mer båndbredde)", + "disableAudio": "Deaktiver lyd", + "disableAudioDesc": "Demp all lyd fra den eksterne økten", + "enableAudioInput": "Aktiver lydinngang (mikrofon)", + "enableAudioInputDesc": "Videresend den lokale mikrofonen til den eksterne økten", + "wallpaper": "Bakgrunn", + "wallpaperDesc": "Vis skrivebordsbakgrunn (deaktivering forbedrer ytelsen)", + "theming": "Temaer", + "themingDesc": "Aktiver visuelle temaer og stiler", + "fontSmoothing": "Skriftutjevning", + "fontSmoothingDesc": "Aktiver gjengivelse av ClearType-skrifttyper", + "fullWindowDrag": "Dra i hele vinduet", + "fullWindowDragDesc": "Vis vindusinnhold mens du drar", + "desktopComposition": "Skrivebordskomposisjon", + "desktopCompositionDesc": "Aktiver Aero Glass-effekter", + "menuAnimations": "Menyanimasjoner", + "menuAnimationsDesc": "Aktiver menyuttoning og lysbildeanimasjoner", + "disableBitmapCaching": "Deaktiver punktmap-hurtigbufring", + "disableBitmapCachingDesc": "Slå av bitmap-hurtigbufferen (kan hjelpe med feil)", + "disableOffscreenCaching": "Deaktiver mellomlagring utenfor skjermen", + "disableOffscreenCachingDesc": "Slå av hurtigbuffer utenfor skjermen", + "disableGlyphCaching": "Deaktiver glyff-caching", + "disableGlyphCachingDesc": "Slå av glyph-cache", + "enableGfx": "Aktiver GFX", + "enableGfxDesc": "Bruk RemoteFX-grafikkpipeline", + "enablePrinting": "Aktiver utskrift", + "enablePrintingDesc": "Omdiriger lokale skrivere til den eksterne økten", + "enableDriveRedirection": "Aktiver omdirigering av stasjoner", + "enableDriveRedirectionDesc": "Tilordne en lokal mappe som en stasjon i den eksterne økten", + "createDrivePath": "Opprett stasjonssti", + "createDrivePathDesc": "Opprett mappen automatisk hvis den ikke finnes", + "disableDownload": "Deaktiver nedlasting", + "disableDownloadDesc": "Forhindre nedlasting av filer fra den eksterne økten", + "disableUpload": "Deaktiver opplasting", + "disableUploadDesc": "Forhindre opplasting av filer til den eksterne økten", + "enableTouch": "Aktiver berøring", + "enableTouchDesc": "Aktiver videresending av berøringsinndata", + "consoleSession": "Konsolløkt", + "consoleSessionDesc": "Koble til konsollen (økt 0) i stedet for en ny økt", + "sendWolPacket": "Send WOL-pakke", + "sendWolPacketDesc": "Send en magisk pakke for å vekke denne verten før du kobler til", + "disableCopy": "Deaktiver kopiering", + "disableCopyDesc": "Forhindre kopiering av tekst fra den eksterne økten", + "disablePaste": "Deaktiver liming", + "disablePasteDesc": "Forhindre innliming av tekst i den eksterne økten", + "createPathIfMissing": "Opprett sti hvis den mangler", + "createPathIfMissingDesc": "Opprett opptaksmappen automatisk", + "excludeOutput": "Ekskluder utdata", + "excludeOutputDesc": "Ikke ta opp skjermutdata (kun metadata)", + "excludeMouse": "Utelukk mus", + "excludeMouseDesc": "Ikke opptak musebevegelser", + "includeKeystrokes": "Inkluder tastetrykk", + "includeKeystrokesDesc": "Ta opp rå tastetrykk i tillegg til skjermutdata", + "vncPort": "VNC-port", + "vncPassword": "VNC-passord", + "vncUsernameOptional": "Brukernavn (valgfritt)", + "vncLeaveBlank": "La stå tomt hvis det ikke er nødvendig", + "cursorMode": "Markørmodus", + "swapRedBlue": "Bytt rød/blå", + "swapRedBlueDesc": "Bytt om de røde og blå fargekanalene (rettar opp nokre fargeproblem)", + "readOnly": "Skrivebeskyttet", + "readOnlyDesc": "Vis fjernskjermen uten å sende noen input", + "telnetPort": "Telnet-port", + "terminalType": "Terminaltype", + "fontName": "Skriftnavn", + "fontSize": "Skriftstørrelse", + "colorScheme": "Fargeskjema", + "backspaceKey": "Tilbaketast" + } + }, + "onboarding": { + "feature_desktop": "Eksternt skrivebord", + "feature_desktop_desc": "Åpne RDP-, VNC- og Telnet-økter i en fane, på samme måte som SSH." + } +} diff --git a/plugins/remote-desktop/locales/translated/pl_PL.json b/plugins/remote-desktop/locales/translated/pl_PL.json new file mode 100644 index 000000000..33177ca19 --- /dev/null +++ b/plugins/remote-desktop/locales/translated/pl_PL.json @@ -0,0 +1,214 @@ +{ + "remoteDesktop": { + "connecting": "Łączenie z sesją {{type}}...", + "checkingGuacd": "Sprawdzanie usługi pulpitu zdalnego...", + "requestingToken": "Żądanie tokena połączenia {{type}}...", + "openingSession": "Otwieranie sesji {{type}}...", + "negotiating": "Negocjowanie {{type}} uścisku dłoni...", + "sessionReady": "{{type}} sesja gotowa", + "connectionError": "Błąd połączenia", + "connectionFailed": "Połączenie nieudane", + "failedToConnect": "Nie udało się uzyskać tokena połączenia", + "hostNotFound": "Nie znaleziono hosta", + "noHostSelected": "Nie wybrano hosta", + "reconnect": "Połącz ponownie", + "retry": "Ponów", + "guacdUnavailable": "Usługa pulpitu zdalnego (guacd) jest niedostępna. Upewnij się, że usługa guacd jest uruchomiona, dostępna i poprawnie skonfigurowana w ustawieniach administratora.", + "credentialPromptTitle": "Wprowadź poświadczenia RDP", + "credentialPromptDescription": "Ten host jest ustawiony tak, aby pytać o poświadczenia przy łączeniu. Są używane tylko w tej sesji i nie są zapisywane.", + "connect": "Połącz", + "ctrlAltDel": "Ctrl+Alt+Del", + "files": { + "title": "Pliki dysku", + "parent": "Katalog nadrzędny", + "refresh": "Odśwież", + "empty": "Ten folder jest pusty", + "listFailed": "Nie udało się odczytać tego folderu", + "download": "Pobierz", + "downloadFailed": "Nie udało się pobrać {{name}}", + "upload": "Prześlij pliki", + "uploading": "Przesyłanie {{name}}...", + "uploaded": "Przesłano {{name}}", + "uploadFailed": "Nie udało się przesłać {{name}}", + "uploadDisabled": "Przesyłanie plików jest wyłączone dla tego połączenia", + "driveUnavailable": "Włącz przekierowanie dysku RDP przed przesłaniem plików", + "driveNotWritable": "guacd nie może zapisać do folderu dysku. Sprawdź zmienną GUACD_DRIVE_PATH (lub ścieżkę do dysku hosta) i jej uprawnienia.", + "dropToUpload": "Upuść pliki, aby je przesłać" + }, + "toolbar": { + "ctrlAltDel": "Ctrl+Alt+Del", + "winL": "Win+L (zablokuj ekran)", + "winKey": "Klawisz Windows", + "superL": "Super+L (ekran blokady)", + "superKey": "Super klucz", + "super": "Super", + "cmdL": "Cmd+L (ekran blokady)", + "cmdKey": "Klawisz polecenia", + "cmd": "Polecenie", + "ctrl": "Ctrl", + "alt": "Alt", + "shift": "Shift", + "win": "Win", + "stickyActive": "{{key}} (zatrzaśnięty - kliknij, aby zwolnić)", + "stickyInactive": "{{key}} (kliknij, aby zatrzasnąć)", + "esc": "Esc", + "tab": "Tab", + "home": "Home", + "end": "End", + "pageUp": "Page Up", + "pageDown": "Page Down", + "arrowUp": "Strzałka w górę", + "arrowDown": "Strzałka w dół", + "arrowLeft": "Strzałka w lewo", + "arrowRight": "Strzałka w prawo", + "fnToggle": "Klawisze funkcyjne", + "reconnect": "Połącz sesję ponownie", + "collapse": "Zwiń pasek narzędzi", + "expand": "Rozwiń pasek narzędzi", + "dragHandle": "Przeciągnij, aby zmienić położenie", + "hide": "Ukryj na czas tej sesji. Aby trwale wyłączyć tę opcję, otwórz Ustawienia hosta → Ogólne → Pasek narzędzi połączenia.", + "zoomIn": "Powiększ", + "zoomOut": "Oddal", + "resetZoom": "Zresetuj powiększenie", + "fitToScreen": "Dopasuj do ekranu", + "switchToTrackpad": "Przełącz na tryb gładzika (przeciągnij, aby przesunąć kursor, dotknij, aby kliknąć)", + "switchToTouch": "Przełącz na tryb dotykowy (dotknij bezpośrednio miejsca, w którym chcesz kliknąć)" + } + }, + "hosts": { + "nativeRdpOpened": "Otwarto w Pulpicie zdalnym systemu Windows", + "nativeRdpFailed": "Nie udało się otworzyć pulpitu zdalnego systemu Windows", + "openNativeRdp": "Otwórz w Pulpicie zdalnym systemu Windows", + "guac": { + "connection": "Połączenie", + "authentication": "Uwierzytelnianie", + "storedCredential": "Zapisane poświadczenie", + "authMethod": "Metoda uwierzytelniania", + "authTypeNoneDesc": "Żadne poświadczenia nie są przechowywane. Przy każdym połączeniu pojawi się prośba o nazwę użytkownika i hasło; nie są zapisywane.", + "selectCredential": "Wybierz poświadczenie...", + "connectionSettings": "Ustawienia połączenia", + "displaySettings": "Ustawienia wyświetlania", + "audioSettings": "Ustawienia audio", + "rdpPerformance": "Wydajność RDP", + "deviceRedirection": "Przekierowanie urządzenia", + "session": "Sesja", + "gateway": "Brama", + "remoteApp": "RemoteApp", + "clipboard": "Schowek", + "sessionRecording": "Nagrywanie sesji", + "wakeOnLan": "Wake-on-LAN", + "vncSettings": "Ustawienia VNC", + "terminalSettings": "Ustawienia terminala", + "rdpPort": "Port RDP", + "username": "Nazwa użytkownika", + "password": "Hasło", + "passwordSaved": "Hasło zapisane, wpisz, aby zmienić", + "domain": "Domena", + "securityMode": "Tryb bezpieczeństwa", + "width": "Szerokość", + "height": "Wysokość", + "dpi": "DPI", + "clientName": "Nazwa klienta", + "initialProgram": "Program początkowy", + "serverLayout": "Układ serwera", + "timezone": "Strefa czasowa", + "loadBalanceInfo": "Informacje o równoważeniu obciążenia / cookie", + "loadBalanceInfoDesc": "Plik cookie brokera połączeń usług pulpitu zdalnego do równoważenia obciążenia farmy usług pulpitu zdalnego (np. tsv://MS Terminal Services Plugin.1.CollectionName)", + "guacdProxy": "Serwer proxy guacd", + "guacdHostname": "Host guacd", + "guacdHostnamePlaceholder": "Globalne ustawienie domyślne", + "guacdPort": "Port guacd", + "guacdProxyDesc": "Zastąp globalną instancję guacd dla tego połączenia. Pozostaw puste, aby użyć globalnie skonfigurowanego guacd.", + "gatewayHostname": "Nazwa hosta bramy", + "gatewayPort": "Port bramy", + "gatewayUsername": "Nazwa użytkownika bramy", + "gatewayPassword": "Hasło bramy", + "gatewayDomain": "Domena bramy", + "remoteAppProgram": "Program RemoteApp", + "workingDirectory": "Katalog roboczy", + "arguments": "Argumenty", + "normalizeLineEndings": "Normalizuj zakończenia linii", + "macAddress": "Adres MAC", + "broadcastAddress": "Adres rozgłoszeniowy", + "udpPort": "Port UDP", + "waitTimeS": "Czas oczekiwania (s)", + "driveName": "Nazwa dysku", + "drivePath": "Ścieżka dysku", + "ignoreCertificate": "Ignoruj certyfikat", + "ignoreCertificateDesc": "Zezwalaj na połączenia z hostami z certyfikatami samopodpisanymi", + "forceLossless": "Wymuś bezstratność", + "forceLosslessDesc": "Wymuś bezstratne kodowanie obrazu (wyższa jakość, większa przepustowość)", + "disableAudio": "Wyłącz dźwięk", + "disableAudioDesc": "Wycisz cały dźwięk z sesji zdalnej", + "enableAudioInput": "Włącz wejście audio (mikrofon)", + "enableAudioInputDesc": "Przekaż lokalny mikrofon do sesji zdalnej", + "wallpaper": "Tapeta", + "wallpaperDesc": "Pokaż tapetę pulpitu (wyłączenie poprawia wydajność)", + "theming": "Motywy", + "themingDesc": "Włącz motywy i style wizualne", + "fontSmoothing": "Wygładzanie czcionek", + "fontSmoothingDesc": "Włącz renderowanie czcionek ClearType", + "fullWindowDrag": "Przeciąganie pełnego okna", + "fullWindowDragDesc": "Pokaż zawartość okna podczas przeciągania", + "desktopComposition": "Kompozycja pulpitu", + "desktopCompositionDesc": "Włącz efekty Aero Glass", + "menuAnimations": "Animacje menu", + "menuAnimationsDesc": "Włącz animacje zanikania i wysuwania menu", + "disableBitmapCaching": "Wyłącz buforowanie bitmap", + "disableBitmapCachingDesc": "Wyłącz pamięć podręczną bitmap (może pomóc przy artefaktach)", + "disableOffscreenCaching": "Wyłącz buforowanie poza ekranem", + "disableOffscreenCachingDesc": "Wyłącz pamięć podręczną poza ekranem", + "disableGlyphCaching": "Wyłącz buforowanie glifów", + "disableGlyphCachingDesc": "Wyłącz pamięć podręczną glifów", + "enableGfx": "Włącz GFX", + "enableGfxDesc": "Użyj potoku graficznego RemoteFX", + "enablePrinting": "Włącz drukowanie", + "enablePrintingDesc": "Przekieruj drukarki lokalne do sesji zdalnej", + "enableDriveRedirection": "Włącz przekierowanie dysku", + "enableDriveRedirectionDesc": "Mapuj folder lokalny jako dysk w sesji zdalnej", + "createDrivePath": "Utwórz ścieżkę dysku", + "createDrivePathDesc": "Automatycznie utwórz folder, jeśli nie istnieje", + "disableDownload": "Wyłącz pobieranie", + "disableDownloadDesc": "Zapobiegaj pobieraniu plików z sesji zdalnej", + "disableUpload": "Wyłącz przesyłanie", + "disableUploadDesc": "Zapobiegaj przesyłaniu plików do sesji zdalnej", + "enableTouch": "Włącz dotyk", + "enableTouchDesc": "Włącz przekazywanie wejścia dotykowego", + "consoleSession": "Sesja konsoli", + "consoleSessionDesc": "Połącz się z konsolą (sesja 0) zamiast z nową sesją", + "sendWolPacket": "Wyślij pakiet WOL", + "sendWolPacketDesc": "Wyślij magic packet, aby obudzić tego hosta przed połączeniem", + "disableCopy": "Wyłącz kopiowanie", + "disableCopyDesc": "Zapobiegaj kopiowaniu tekstu z sesji zdalnej", + "disablePaste": "Wyłącz wklejanie", + "disablePasteDesc": "Zapobiegaj wklejaniu tekstu do sesji zdalnej", + "createPathIfMissing": "Utwórz ścieżkę, jeśli nie istnieje", + "createPathIfMissingDesc": "Automatycznie utwórz katalog nagrań", + "excludeOutput": "Wyklucz obraz", + "excludeOutputDesc": "Nie nagrywaj obrazu ekranu (tylko metadane)", + "excludeMouse": "Wyklucz mysz", + "excludeMouseDesc": "Nie nagrywaj ruchów myszy", + "includeKeystrokes": "Uwzględnij naciśnięcia klawiszy", + "includeKeystrokesDesc": "Rejestruj surowe naciśnięcia klawiszy oprócz obrazu ekranu", + "vncPort": "Port VNC", + "vncPassword": "Hasło VNC", + "vncUsernameOptional": "Nazwa użytkownika (opcjonalnie)", + "vncLeaveBlank": "Pozostaw puste, jeśli nie jest wymagane", + "cursorMode": "Tryb kursora", + "swapRedBlue": "Zamień czerwony/niebieski", + "swapRedBlueDesc": "Zamień kanały kolorów czerwonego i niebieskiego (rozwiązuje niektóre problemy z kolorami)", + "readOnly": "Tylko do odczytu", + "readOnlyDesc": "Oglądaj zdalny ekran bez wysyłania jakiegokolwiek wejścia", + "telnetPort": "Port Telnet", + "terminalType": "Typ terminala", + "fontName": "Nazwa czcionki", + "fontSize": "Rozmiar czcionki", + "colorScheme": "Schemat kolorów", + "backspaceKey": "Klawisz Backspace" + } + }, + "onboarding": { + "feature_desktop": "Zdalny pulpit", + "feature_desktop_desc": "Otwieraj sesje RDP, VNC i Telnet w karcie, tak samo jak SSH." + } +} diff --git a/plugins/remote-desktop/locales/translated/pt_BR.json b/plugins/remote-desktop/locales/translated/pt_BR.json new file mode 100644 index 000000000..3b01f1470 --- /dev/null +++ b/plugins/remote-desktop/locales/translated/pt_BR.json @@ -0,0 +1,214 @@ +{ + "remoteDesktop": { + "connecting": "Conectando à sessão {{type}}...", + "checkingGuacd": "Verificando o serviço de área de trabalho remota...", + "requestingToken": "Solicitando token de conexão {{type}}...", + "openingSession": "Abrindo {{type}} sessão...", + "negotiating": "Negotiating {{type}} handshake...", + "sessionReady": "{{type}} sessão pronta", + "connectionError": "Erro de conexão", + "connectionFailed": "Falha na conexão", + "failedToConnect": "Falha ao obter o token de conexão", + "hostNotFound": "Host não encontrado", + "noHostSelected": "Nenhum host selecionado", + "reconnect": "Reconectar", + "retry": "Tentar novamente", + "guacdUnavailable": "O serviço de área de trabalho remota (guacd) não está disponível. Certifique-se de que o guacd esteja em execução, acessível e configurado corretamente nas configurações de administrador.", + "credentialPromptTitle": "Insira as credenciais RDP", + "credentialPromptDescription": "Este host está configurado para solicitar credenciais ao conectar. Elas são usadas apenas para esta sessão e não são salvas.", + "connect": "Conectar", + "ctrlAltDel": "Ctrl+Alt+Del", + "files": { + "title": "Arquivos do Drive", + "parent": "Diretório pai", + "refresh": "Atualizar", + "empty": "Esta pasta está vazia", + "listFailed": "Não foi possível ler esta pasta.", + "download": "Download", + "downloadFailed": "Falha ao baixar {{name}}", + "upload": "Carregar arquivos", + "uploading": "Carregando {{name}}...", + "uploaded": "Enviado {{name}}", + "uploadFailed": "Falha ao carregar {{name}}", + "uploadDisabled": "Os uploads estão desativados para esta conexão.", + "driveUnavailable": "Ative o redirecionamento de unidade RDP antes de enviar arquivos.", + "driveNotWritable": "O guacd não consegue gravar na pasta da unidade. Verifique a variável de ambiente GUACD_DRIVE_PATH (ou o caminho da unidade do host) e suas permissões.", + "dropToUpload": "Arraste e solte os arquivos para fazer o upload." + }, + "toolbar": { + "ctrlAltDel": "Ctrl+Alt+Del", + "winL": "Win+L (Bloquear tela)", + "winKey": "Tecla Windows", + "superL": "Super+L (Tela de bloqueio)", + "superKey": "Super Chave", + "super": "Super", + "cmdL": "Cmd+L (Bloquear tela)", + "cmdKey": "Tecla de comando", + "cmd": "Comando", + "ctrl": "Ctrl", + "alt": "Alternativa", + "shift": "Mudança", + "win": "Ganhar", + "stickyActive": "{{key}} (travado - clique para liberar)", + "stickyInactive": "{{key}} (clique para travar)", + "esc": "Escapar", + "tab": "Aba", + "home": "Lar", + "end": "Fim", + "pageUp": "Página acima", + "pageDown": "Página abaixo", + "arrowUp": "Seta para cima", + "arrowDown": "Seta para baixo", + "arrowLeft": "Seta para a esquerda", + "arrowRight": "Seta para a direita", + "fnToggle": "Teclas de função", + "reconnect": "Sessão de reconexão", + "collapse": "Recolher barra de ferramentas", + "expand": "Expandir barra de ferramentas", + "dragHandle": "Arraste para reposicionar", + "hide": "Ocultar para esta sessão. Para desativá-lo permanentemente, abra Configurações do Host → Geral → Barra de Ferramentas de Conexão.", + "zoomIn": "Ampliar", + "zoomOut": "Diminuir o zoom", + "resetZoom": "Redefinir zoom", + "fitToScreen": "Ajustar à tela", + "switchToTrackpad": "Alternar para o modo trackpad (arraste para mover o cursor, toque para clicar)", + "switchToTouch": "Mude para o modo de toque (toque diretamente onde deseja clicar)." + } + }, + "hosts": { + "nativeRdpOpened": "Aberto na Área de Trabalho Remota do Windows", + "nativeRdpFailed": "Falha ao abrir a Área de Trabalho Remota do Windows", + "openNativeRdp": "Abrir no Windows Remote Desktop", + "guac": { + "connection": "Conexão", + "authentication": "Autenticação", + "storedCredential": "Credencial armazenada", + "authMethod": "Método de autenticação", + "authTypeNoneDesc": "Nenhuma credencial é armazenada. Você será solicitado a inserir um nome de usuário e uma senha sempre que se conectar; eles não são salvos.", + "selectCredential": "Selecione uma credencial...", + "connectionSettings": "Configurações de conexão", + "displaySettings": "Configurações de exibição", + "audioSettings": "Configurações de áudio", + "rdpPerformance": "Desempenho do RDP", + "deviceRedirection": "Redirecionamento de Dispositivos", + "session": "Sessão", + "gateway": "Portal", + "remoteApp": "Aplicativo remoto", + "clipboard": "Área de transferência", + "sessionRecording": "Gravação da sessão", + "wakeOnLan": "Wake-on-LAN", + "vncSettings": "Configurações VNC", + "terminalSettings": "Configurações do terminal", + "rdpPort": "Porta RDP", + "username": "Nome de usuário", + "password": "Senha", + "passwordSaved": "Senha salva, digite para alterar", + "domain": "Domínio", + "securityMode": "Modo de segurança", + "width": "Largura", + "height": "Altura", + "dpi": "DPI", + "clientName": "Nome do cliente", + "initialProgram": "Programa Inicial", + "serverLayout": "Layout do servidor", + "timezone": "Fuso horário", + "loadBalanceInfo": "Informações de balanceamento de carga / Cookies", + "loadBalanceInfoDesc": "Cookie do agente de conexão RD para balanceamento de carga do farm RDS (ex: tsv://MS Terminal Services Plugin.1.CollectionName)", + "guacdProxy": "Proxy guacd", + "guacdHostname": "guacd Host", + "guacdHostnamePlaceholder": "Padrão global", + "guacdPort": "Porto guacd", + "guacdProxyDesc": "Substitua a instância global do guacd para esta conexão. Deixe em branco para usar o guacd configurado globalmente.", + "gatewayHostname": "Nome do host do gateway", + "gatewayPort": "Porta de entrada", + "gatewayUsername": "Nome de usuário do gateway", + "gatewayPassword": "Senha do Gateway", + "gatewayDomain": "Domínio de entrada", + "remoteAppProgram": "Programa RemoteApp", + "workingDirectory": "Diretório de Trabalho", + "arguments": "Argumentos", + "normalizeLineEndings": "Normalizar as quebras de linha", + "macAddress": "Endereço MAC", + "broadcastAddress": "Discurso de transmissão", + "udpPort": "Porta UDP", + "waitTimeS": "Tempo de espera (s)", + "driveName": "Nome da unidade", + "drivePath": "Percurso de condução", + "ignoreCertificate": "Ignorar certificado", + "ignoreCertificateDesc": "Permitir conexões a hosts com certificados autoassinados", + "forceLossless": "Força sem perdas", + "forceLosslessDesc": "Forçar codificação de imagem sem perdas (maior qualidade, mais largura de banda)", + "disableAudio": "Desativar áudio", + "disableAudioDesc": "Silenciar todo o áudio da sessão remota.", + "enableAudioInput": "Ativar entrada de áudio (microfone)", + "enableAudioInputDesc": "Encaminhar o microfone local para a sessão remota.", + "wallpaper": "Papel de parede", + "wallpaperDesc": "Exibir papel de parede da área de trabalho (desativar melhora o desempenho)", + "theming": "Tematização", + "themingDesc": "Ativar temas e estilos visuais", + "fontSmoothing": "Suavização de fontes", + "fontSmoothingDesc": "Ativar renderização de fontes ClearType", + "fullWindowDrag": "Arrastar janela inteira", + "fullWindowDragDesc": "Exibir o conteúdo da janela enquanto arrasta", + "desktopComposition": "Composição de mesa", + "desktopCompositionDesc": "Ative os efeitos de vidro Aero", + "menuAnimations": "Animações de menu", + "menuAnimationsDesc": "Ativar animações de transição e deslizamento do menu", + "disableBitmapCaching": "Desativar o cache de bitmaps", + "disableBitmapCachingDesc": "Desative o cache de bitmaps (pode ajudar a resolver problemas técnicos).", + "disableOffscreenCaching": "Desativar o cache fora da tela", + "disableOffscreenCachingDesc": "Desative o cache fora da tela", + "disableGlyphCaching": "Desativar o cache de glifos", + "disableGlyphCachingDesc": "Desative o cache de glifos", + "enableGfx": "Ativar GFX", + "enableGfxDesc": "Utilize o pipeline gráfico RemoteFX", + "enablePrinting": "Habilitar impressão", + "enablePrintingDesc": "Redirecionar impressoras locais para a sessão remota.", + "enableDriveRedirection": "Ativar o redirecionamento de unidades", + "enableDriveRedirectionDesc": "Mapear uma pasta local como uma unidade na sessão remota.", + "createDrivePath": "Criar caminho de unidade", + "createDrivePathDesc": "Criar automaticamente a pasta caso ela não exista.", + "disableDownload": "Desativar download", + "disableDownloadDesc": "Impedir o download de arquivos da sessão remota.", + "disableUpload": "Desativar o upload", + "disableUploadDesc": "Impedir o envio de arquivos para a sessão remota.", + "enableTouch": "Ativar toque", + "enableTouchDesc": "Ativar o encaminhamento de entrada por toque", + "consoleSession": "Sessão do console", + "consoleSessionDesc": "Conecte-se ao console (sessão 0) em vez de uma nova sessão.", + "sendWolPacket": "Enviar pacote WOL", + "sendWolPacketDesc": "Envie um pacote mágico para ativar este host antes de se conectar.", + "disableCopy": "Desativar cópia", + "disableCopyDesc": "Impedir a cópia de texto da sessão remota", + "disablePaste": "Desativar colagem", + "disablePasteDesc": "Impedir a colagem de texto na sessão remota.", + "createPathIfMissing": "Criar caminho se estiver faltando", + "createPathIfMissingDesc": "Criar automaticamente o diretório de gravação", + "excludeOutput": "Excluir saída", + "excludeOutputDesc": "Não gravar a saída da tela (apenas metadados).", + "excludeMouse": "Excluir o rato", + "excludeMouseDesc": "Não grave os movimentos do mouse.", + "includeKeystrokes": "Incluir teclas pressionadas", + "includeKeystrokesDesc": "Registre as teclas digitadas em sua forma original, além da saída na tela.", + "vncPort": "Porta VNC", + "vncPassword": "Senha VNC", + "vncUsernameOptional": "Nome de usuário (opcional)", + "vncLeaveBlank": "Deixe em branco se não for necessário.", + "cursorMode": "Modo Cursor", + "swapRedBlue": "Trocar Vermelho/Azul", + "swapRedBlueDesc": "Trocar os canais de cor vermelho e azul resolve alguns problemas de cor.", + "readOnly": "Somente leitura", + "readOnlyDesc": "Visualize a tela remota sem enviar nenhum comando.", + "telnetPort": "Porta Telnet", + "terminalType": "Tipo de terminal", + "fontName": "Nome da fonte", + "fontSize": "Tamanho da fonte", + "colorScheme": "Esquema de cores", + "backspaceKey": "Tecla Backspace" + } + }, + "onboarding": { + "feature_desktop": "Área de trabalho remota", + "feature_desktop_desc": "Abra sessões RDP, VNC e Telnet em uma aba, da mesma forma que o SSH." + } +} diff --git a/plugins/remote-desktop/locales/translated/pt_PT.json b/plugins/remote-desktop/locales/translated/pt_PT.json new file mode 100644 index 000000000..1493f46a3 --- /dev/null +++ b/plugins/remote-desktop/locales/translated/pt_PT.json @@ -0,0 +1,214 @@ +{ + "remoteDesktop": { + "connecting": "A ligar à sessão {{type}}...", + "checkingGuacd": "Verificação do serviço de ambiente de trabalho remoto...", + "requestingToken": "A solicitar token de ligação {{type}}...", + "openingSession": "Abertura {{type}} sessão...", + "negotiating": "Negotiating {{type}} handshake...", + "sessionReady": "{{type}} sessão pronta", + "connectionError": "Erro de ligação", + "connectionFailed": "Falha na ligação", + "failedToConnect": "Falha ao obter o token de ligação", + "hostNotFound": "Servidor não encontrado", + "noHostSelected": "Nenhum servidor selecionado", + "reconnect": "Religar", + "retry": "Repetir", + "guacdUnavailable": "O serviço de ambiente de trabalho remoto (guacd) não está disponível. Certifique-se de que o guacd está em execução, acessível e devidamente configurado nas definições de administração.", + "credentialPromptTitle": "Introduza as credenciais RDP", + "credentialPromptDescription": "Este host está configurado para solicitar credenciais ao ligar. São utilizadas apenas para esta sessão e não são guardadas.", + "connect": "Ligar", + "ctrlAltDel": "Ctrl+Alt+Del", + "files": { + "title": "Arquivos do Drive", + "parent": "Diretório pai", + "refresh": "Atualizar", + "empty": "Esta pasta está vazia", + "listFailed": "Não foi possível ler esta pasta.", + "download": "Transferir", + "downloadFailed": "Falha ao descarregar {{name}}", + "upload": "Carregar ficheiros", + "uploading": "Carregando {{name}}...", + "uploaded": "Enviado {{name}}", + "uploadFailed": "Falha ao carregar {{name}}", + "uploadDisabled": "Os uploads estão desativados para esta ligação.", + "driveUnavailable": "Ative o redireccionamento da unidade RDP antes de enviar ficheiros.", + "driveNotWritable": "O guacd não consegue escrever na pasta da unidade. Verifique a variável de ambiente GUACD_DRIVE_PATH (ou o caminho da unidade do host) e as suas permissões.", + "dropToUpload": "Arraste e largue os ficheiros para fazer o upload." + }, + "toolbar": { + "ctrlAltDel": "Ctrl+Alt+Del", + "winL": "Win+L (Bloquear ecrã)", + "winKey": "Tecla Windows", + "superL": "Super+L (Ecrã de bloqueio)", + "superKey": "Super Chave", + "super": "Super", + "cmdL": "Cmd+L (Bloquear ecrã)", + "cmdKey": "Tecla de comando", + "cmd": "Comando", + "ctrl": "Ctrl", + "alt": "Alt", + "shift": "Shift", + "win": "Win", + "stickyActive": "{{key}} (bloqueado - clique para libertar)", + "stickyInactive": "{{key}} (clique para bloquear)", + "esc": "Escape", + "tab": "Tab", + "home": "Home", + "end": "End", + "pageUp": "Page Up", + "pageDown": "Page Down", + "arrowUp": "Arrow Up", + "arrowDown": "Arrow Down", + "arrowLeft": "Arrow Left", + "arrowRight": "Arrow Right", + "fnToggle": "Teclas de Função", + "reconnect": "Reconectar Sessão", + "collapse": "Recolher barra", + "expand": "Expandir barra", + "dragHandle": "Arraste para reposicionar", + "hide": "Ocultar para esta sessão. Para o desativar permanentemente, abra as Definições do Host → Geral → Barra de Ferramentas de Ligação.", + "zoomIn": "Ampliar", + "zoomOut": "Diminuir o zoom", + "resetZoom": "Redefinir zoom", + "fitToScreen": "Ajustar ao ecrã", + "switchToTrackpad": "Mudar para o modo trackpad (arraste para mover o cursor, toque para clicar)", + "switchToTouch": "Mude para o modo de toque (toque diretamente onde pretende clicar)." + } + }, + "hosts": { + "nativeRdpOpened": "Aberto na Área de Trabalho Remota do Windows", + "nativeRdpFailed": "Falha ao abrir a Área de Trabalho Remota do Windows", + "openNativeRdp": "Abrir no Windows Remote Desktop", + "guac": { + "connection": "Ligação", + "authentication": "Autenticação", + "storedCredential": "Credencial Armazenada", + "authMethod": "Método de Autenticação", + "authTypeNoneDesc": "Nenhuma credencial é armazenada. Ser-lhe-á pedido que insira um nome de utilizador e uma senha sempre que se conectar; não são salvos.", + "selectCredential": "Selecionar uma credencial...", + "connectionSettings": "Definições de Ligação", + "displaySettings": "Definições de Ecrã", + "audioSettings": "Definições de Áudio", + "rdpPerformance": "Desempenho do RDP", + "deviceRedirection": "Redirecionamento de Dispositivos", + "session": "Sessão", + "gateway": "Gateway", + "remoteApp": "RemoteApp", + "clipboard": "Área de Transferência", + "sessionRecording": "Gravação de Sessão", + "wakeOnLan": "Wake-on-LAN", + "vncSettings": "Definições VNC", + "terminalSettings": "Definições do Terminal", + "rdpPort": "Porta RDP", + "username": "Nome de utilizador", + "password": "Palavra-passe", + "passwordSaved": "Palavra-passe guardada, digite para alterar", + "domain": "Domínio", + "securityMode": "Modo de segurança", + "width": "Largura", + "height": "Altura", + "dpi": "DPI", + "clientName": "Nome do cliente", + "initialProgram": "Programa inicial", + "serverLayout": "Layout do servidor", + "timezone": "Fuso horário", + "loadBalanceInfo": "Informação de balanceamento de carga / Cookie", + "loadBalanceInfoDesc": "Cookie do RD Connection Broker para balanceamento de carga em farms RDS (ex: tsv://MS Terminal Services Plugin.1.CollectionName)", + "guacdProxy": "Proxy guacd", + "guacdHostname": "Host guacd", + "guacdHostnamePlaceholder": "Padrão global", + "guacdPort": "Porta guacd", + "guacdProxyDesc": "Substituir a instância guacd global para esta ligação. Deixe em branco para usar o guacd configurado globalmente.", + "gatewayHostname": "Nome de host do gateway", + "gatewayPort": "Porta do gateway", + "gatewayUsername": "Nome de utilizador do gateway", + "gatewayPassword": "Palavra-passe do gateway", + "gatewayDomain": "Domínio do gateway", + "remoteAppProgram": "Programa RemoteApp", + "workingDirectory": "Diretório de trabalho", + "arguments": "Argumentos", + "normalizeLineEndings": "Normalizar fins de linha", + "macAddress": "Endereço MAC", + "broadcastAddress": "Endereço de broadcast", + "udpPort": "Porta UDP", + "waitTimeS": "Tempo de Espera (s)", + "driveName": "Nome da Unidade", + "drivePath": "Caminho da Unidade", + "ignoreCertificate": "Ignorar Certificado", + "ignoreCertificateDesc": "Permitir ligações a hosts com certificados auto-assinados", + "forceLossless": "Forçar sem perdas", + "forceLosslessDesc": "Forçar codificação de imagem sem perdas (maior qualidade, mais largura de banda)", + "disableAudio": "Desativar Áudio", + "disableAudioDesc": "Silenciar todo o áudio da sessão remota", + "enableAudioInput": "Ativar Entrada de Áudio (Microfone)", + "enableAudioInputDesc": "Encaminhar microfone local para a sessão remota", + "wallpaper": "Fundo de ecrã", + "wallpaperDesc": "Mostrar fundo de ecrã (desativar melhora o desempenho)", + "theming": "Temas", + "themingDesc": "Ativar temas e estilos visuais", + "fontSmoothing": "Suavização de Fontes", + "fontSmoothingDesc": "Ativar renderização de fontes ClearType", + "fullWindowDrag": "Arrasto de Janela Completo", + "fullWindowDragDesc": "Mostrar conteúdo da janela ao arrastar", + "desktopComposition": "Composição do ambiente de trabalho", + "desktopCompositionDesc": "Ativar efeitos de transparência Aero", + "menuAnimations": "Animações de Menu", + "menuAnimationsDesc": "Ativar animações de desvanecimento e deslizamento de menus", + "disableBitmapCaching": "Desativar cache de bitmaps", + "disableBitmapCachingDesc": "Desativar a cache de bitmaps (pode ajudar com falhas)", + "disableOffscreenCaching": "Desativar cache fora do ecrã", + "disableOffscreenCachingDesc": "Desativar a cache fora do ecrã", + "disableGlyphCaching": "Desativar cache de glifos", + "disableGlyphCachingDesc": "Desativar a cache de glifos", + "enableGfx": "Ativar GFX", + "enableGfxDesc": "Usar pipeline gráfico RemoteFX", + "enablePrinting": "Ativar Impressão", + "enablePrintingDesc": "Redirecionar impressoras locais para a sessão remota", + "enableDriveRedirection": "Ativar Redirecionamento de Unidades", + "enableDriveRedirectionDesc": "Mapear uma pasta local como unidade na sessão remota", + "createDrivePath": "Criar Caminho de Unidade", + "createDrivePathDesc": "Criar automaticamente a pasta se não existir", + "disableDownload": "Desativar Download", + "disableDownloadDesc": "Impedir o download de ficheiros da sessão remota", + "disableUpload": "Desativar Upload", + "disableUploadDesc": "Impedir o envio de ficheiros para a sessão remota", + "enableTouch": "Ativar Toque", + "enableTouchDesc": "Ativar o reencaminhamento de entrada tátil", + "consoleSession": "Sessão de Consola", + "consoleSessionDesc": "Ligar à consola (sessão 0) em vez de uma nova sessão", + "sendWolPacket": "Enviar Pacote WOL", + "sendWolPacketDesc": "Enviar um pacote mágico para despertar este host antes de ligar", + "disableCopy": "Desativar Cópia", + "disableCopyDesc": "Impedir a cópia de texto da sessão remota", + "disablePaste": "Desativar Colagem", + "disablePasteDesc": "Impedir a colagem de texto na sessão remota", + "createPathIfMissing": "Criar caminho se não existir", + "createPathIfMissingDesc": "Criar automaticamente o diretório de gravação", + "excludeOutput": "Excluir Saída", + "excludeOutputDesc": "Não gravar a saída do ecrã (apenas metadados)", + "excludeMouse": "Excluir Rato", + "excludeMouseDesc": "Não gravar os movimentos do rato", + "includeKeystrokes": "Incluir Teclas", + "includeKeystrokesDesc": "Gravar as teclas premidas em bruto, além da saída do ecrã", + "vncPort": "Porta VNC", + "vncPassword": "Palavra-passe VNC", + "vncUsernameOptional": "Nome de utilizador (opcional)", + "vncLeaveBlank": "Deixar em branco se não for necessário", + "cursorMode": "Modo do Cursor", + "swapRedBlue": "Trocar Vermelho/Azul", + "swapRedBlueDesc": "Trocar os canais de cor vermelha e azul (corrige alguns problemas de cor)", + "readOnly": "Apenas leitura", + "readOnlyDesc": "Visualizar o ecrã remoto sem enviar qualquer entrada", + "telnetPort": "Porta Telnet", + "terminalType": "Tipo de Terminal", + "fontName": "Nome da Fonte", + "fontSize": "Tamanho da Fonte", + "colorScheme": "Esquema de Cores", + "backspaceKey": "Tecla Backspace" + } + }, + "onboarding": { + "feature_desktop": "Área de trabalho remota", + "feature_desktop_desc": "Abra as sessões RDP, VNC e Telnet num separador, da mesma forma que o SSH." + } +} diff --git a/plugins/remote-desktop/locales/translated/ro_RO.json b/plugins/remote-desktop/locales/translated/ro_RO.json new file mode 100644 index 000000000..1838ecdb3 --- /dev/null +++ b/plugins/remote-desktop/locales/translated/ro_RO.json @@ -0,0 +1,214 @@ +{ + "remoteDesktop": { + "connecting": "Se conectează la sesiunea {{type}}...", + "checkingGuacd": "Se verifică serviciul desktop la distanță...", + "requestingToken": "Se solicită tokenul de conexiune {{type}}...", + "openingSession": "Se deschide sesiunea {{type}}...", + "negotiating": "Se negociază o strângere de mână {{type}}...", + "sessionReady": "{{type}} sesiune gata", + "connectionError": "Eroare de conexiune", + "connectionFailed": "Conexiunea a eșuat", + "failedToConnect": "Nu s-a putut obține token-ul de conexiune", + "hostNotFound": "Gazdă negăsită", + "noHostSelected": "Nicio gazdă selectată", + "reconnect": "Reconectați-vă", + "retry": "Reîncercați", + "guacdUnavailable": "Serviciul desktop la distanță (guacd) nu este disponibil. Asigurați-vă că guacd rulează, este accesibil și configurat corect în setările de administrare.", + "credentialPromptTitle": "Introduceți acreditările RDP", + "credentialPromptDescription": "Această gazdă este configurată să solicite acreditări la conectare. Acestea sunt utilizate doar pentru această sesiune și nu sunt salvate.", + "connect": "Conectează-te", + "ctrlAltDel": "Ctrl+Alt+Del", + "files": { + "title": "Fișiere Drive", + "parent": "Directorul părinte", + "refresh": "Reîmprospăta", + "empty": "Acest folder este gol", + "listFailed": "Nu s-a putut citi acest folder", + "download": "Descărcare", + "downloadFailed": "Descărcarea {{name}} a eșuat", + "upload": "Încărcați fișiere", + "uploading": "Se încarcă {{name}}...", + "uploaded": "Încărcat {{name}}", + "uploadFailed": "Nu s-a putut încărca {{name}}", + "uploadDisabled": "Încărcările sunt dezactivate pentru această conexiune", + "driveUnavailable": "Activați redirecționarea unității RDP înainte de încărcarea fișierelor", + "driveNotWritable": "guacd nu poate scrie în folderul unității. Verificați GUACD_DRIVE_PATH (sau calea unității gazdă) și permisiunile acesteia.", + "dropToUpload": "Plasați fișierele pentru încărcare" + }, + "toolbar": { + "ctrlAltDel": "Ctrl+Alt+Del", + "winL": "Win+L (Ecran de blocare)", + "winKey": "Cheie Windows", + "superL": "Super+L (Ecran de blocare)", + "superKey": "Super Cheie", + "super": "Super", + "cmdL": "Cmd+L (Ecran de blocare)", + "cmdKey": "Tastă de comandă", + "cmd": "Comandă", + "ctrl": "Ctrl", + "alt": "Alt", + "shift": "Schimbare", + "win": "Câştiga", + "stickyActive": "{{key}} (blocat - clic pentru eliberare)", + "stickyInactive": "{{key}} (clic pentru blocare)", + "esc": "Evadare", + "tab": "Tab", + "home": "Acasă", + "end": "Sfârşit", + "pageUp": "Pagină sus", + "pageDown": "Pagină în jos", + "arrowUp": "Săgeată în sus", + "arrowDown": "Săgeată în jos", + "arrowLeft": "Săgeată stânga", + "arrowRight": "Săgeată dreapta", + "fnToggle": "Taste funcționale", + "reconnect": "Sesiune de reconectare", + "collapse": "Restrângeți bara de instrumente", + "expand": "Extindeți bara de instrumente", + "dragHandle": "Trageți pentru a repoziționa", + "hide": "Ascundeți pentru această sesiune. Pentru a o dezactiva definitiv, deschideți Setări gazdă → General → Bara de instrumente conexiune.", + "zoomIn": "Măriți", + "zoomOut": "Micșorare", + "resetZoom": "Resetare zoom", + "fitToScreen": "Potrivire la ecran", + "switchToTrackpad": "Comutare la modul trackpad (tragere pentru mutarea cursorului, atingere pentru clic)", + "switchToTouch": "Comutare la modul tactil (atingere direct unde doriți să faceți clic)" + } + }, + "hosts": { + "nativeRdpOpened": "Deschis în Desktop la distanță Windows", + "nativeRdpFailed": "Nu s-a putut deschide Desktop la distanță Windows", + "openNativeRdp": "Deschideți în Desktop la distanță Windows", + "guac": { + "connection": "Conexiune", + "authentication": "Autentificare", + "storedCredential": "Acreditare stocată", + "authMethod": "Metodă de autentificare", + "authTypeNoneDesc": "Nu sunt stocate acreditări. Vi se va solicita un nume de utilizator și o parolă de fiecare dată când vă conectați; acestea nu sunt salvate.", + "selectCredential": "Selectați o acreditare...", + "connectionSettings": "Setări de conectare", + "displaySettings": "Setări de afișare", + "audioSettings": "Setări audio", + "rdpPerformance": "Performanța RDP", + "deviceRedirection": "Redirecționare dispozitiv", + "session": "Sesiune", + "gateway": "Poartă de acces", + "remoteApp": "RemoteApp", + "clipboard": "Clipboard", + "sessionRecording": "Înregistrarea sesiunii", + "wakeOnLan": "Wake-on-LAN", + "vncSettings": "Setări VNC", + "terminalSettings": "Setări terminal", + "rdpPort": "Port RDP", + "username": "Nume de utilizator", + "password": "Parolă", + "passwordSaved": "Parolă salvată, tastați pentru a o modifica", + "domain": "Domeniu", + "securityMode": "Mod de securitate", + "width": "Lăţime", + "height": "Înălţime", + "dpi": "DPI", + "clientName": "Numele clientului", + "initialProgram": "Program inițial", + "serverLayout": "Aspectul serverului", + "timezone": "Fus orar", + "loadBalanceInfo": "Informații despre echilibrul încărcării / Cookie", + "loadBalanceInfoDesc": "Cookie-ul RD Connection Broker pentru echilibrarea încărcării fermei RDS (de exemplu, tsv://MS Terminal Services Plugin.1.CollectionName)", + "guacdProxy": "Proxy guacd", + "guacdHostname": "Gazdă guacd", + "guacdHostnamePlaceholder": "Implicit global", + "guacdPort": "Portul Guacd", + "guacdProxyDesc": "Suprascrie instanța globală guacd pentru această conexiune. Lasă câmpul necompletat pentru a utiliza guacd-ul configurat global.", + "gatewayHostname": "Nume gazdă gateway", + "gatewayPort": "Portul Gateway", + "gatewayUsername": "Nume de utilizator Gateway", + "gatewayPassword": "Parolă gateway", + "gatewayDomain": "Domeniu Gateway", + "remoteAppProgram": "Programul RemoteApp", + "workingDirectory": "Director de lucru", + "arguments": "Argumente", + "normalizeLineEndings": "Normalizarea sfârșitului de linie", + "macAddress": "Adresă MAC", + "broadcastAddress": "Adresă de difuzare", + "udpPort": "Port UDP", + "waitTimeS": "Timp de așteptare (s)", + "driveName": "Nume unitate", + "drivePath": "Cale de acces", + "ignoreCertificate": "Ignoră certificatul", + "ignoreCertificateDesc": "Permiteți conexiuni la gazde cu certificate autosemnate", + "forceLossless": "Forța fără pierderi", + "forceLosslessDesc": "Forțează codificarea imaginilor fără pierderi (calitate mai mare, lățime de bandă mai mare)", + "disableAudio": "Dezactivați sunetul", + "disableAudioDesc": "Dezactivați tot sunetul din sesiunea la distanță", + "enableAudioInput": "Activare intrare audio (microfon)", + "enableAudioInputDesc": "Redirecționează microfonul local către sesiunea la distanță", + "wallpaper": "Tapet", + "wallpaperDesc": "Afișează imaginea de fundal a desktopului (dezactivarea îmbunătățește performanța)", + "theming": "Tematizare", + "themingDesc": "Activează teme și stiluri vizuale", + "fontSmoothing": "Netezirea fonturilor", + "fontSmoothingDesc": "Activează randarea fonturilor ClearType", + "fullWindowDrag": "Tragere pe toată ferestra", + "fullWindowDragDesc": "Afișează conținutul ferestrei la tragere", + "desktopComposition": "Compoziție desktop", + "desktopCompositionDesc": "Activează efectele Aero Glass", + "menuAnimations": "Animații de meniu", + "menuAnimationsDesc": "Activează estomparea meniului și animațiile diapozitivelor", + "disableBitmapCaching": "Dezactivați memorarea în cache a bitmap-urilor", + "disableBitmapCachingDesc": "Dezactivați memoria cache bitmap (poate ajuta la rezolvarea erorilor)", + "disableOffscreenCaching": "Dezactivați memoria cache în afara ecranului", + "disableOffscreenCachingDesc": "Dezactivați memoria cache în afara ecranului", + "disableGlyphCaching": "Dezactivați memoria cache a glifelor", + "disableGlyphCachingDesc": "Dezactivați memoria cache a glifurilor", + "enableGfx": "Activează efectele grafice", + "enableGfxDesc": "Folosește canalul grafic RemoteFX", + "enablePrinting": "Activează imprimarea", + "enablePrintingDesc": "Redirecționează imprimantele locale către sesiunea la distanță", + "enableDriveRedirection": "Activați redirecționarea unității", + "enableDriveRedirectionDesc": "Maparea unui folder local ca unitate în sesiunea la distanță", + "createDrivePath": "Creați o cale de acces", + "createDrivePathDesc": "Creează automat folderul dacă acesta nu există", + "disableDownload": "Dezactivați descărcarea", + "disableDownloadDesc": "Împiedicați descărcarea fișierelor din sesiunea la distanță", + "disableUpload": "Dezactivați încărcarea", + "disableUploadDesc": "Împiedicați încărcarea fișierelor în sesiunea la distanță", + "enableTouch": "Activează atingerea", + "enableTouchDesc": "Activează redirecționarea prin introducerea tactilă", + "consoleSession": "Sesiune consolă", + "consoleSessionDesc": "Conectați-vă la consolă (sesiunea 0) în loc de o sesiune nouă", + "sendWolPacket": "Trimiteți pachetul WOL", + "sendWolPacketDesc": "Trimiteți un pachet magic pentru a activa această gazdă înainte de conectare", + "disableCopy": "Dezactivați copierea", + "disableCopyDesc": "Împiedicați copierea textului din sesiunea la distanță", + "disablePaste": "Dezactivați lipirea", + "disablePasteDesc": "Împiedicați lipirea textului în sesiunea la distanță", + "createPathIfMissing": "Creați o cale dacă lipsește", + "createPathIfMissingDesc": "Creați automat directorul de înregistrare", + "excludeOutput": "Excludeți ieșirea", + "excludeOutputDesc": "Nu înregistrați ieșirea ecranului (doar metadate)", + "excludeMouse": "Excludeți mouse-ul", + "excludeMouseDesc": "Nu înregistrați mișcările mouse-ului", + "includeKeystrokes": "Includeți apăsările de taste", + "includeKeystrokesDesc": "Înregistrați apăsările de taste brute pe lângă ieșirea de pe ecran", + "vncPort": "Port VNC", + "vncPassword": "Parolă VNC", + "vncUsernameOptional": "Nume de utilizator (opțional)", + "vncLeaveBlank": "Lăsați necompletat dacă nu este necesar", + "cursorMode": "Mod cursor", + "swapRedBlue": "Schimbă roșu/albastru", + "swapRedBlueDesc": "Schimbarea canalelor de culoare roșu și albastru (rezolvă unele probleme de culoare)", + "readOnly": "Doar citire", + "readOnlyDesc": "Vizualizați ecranul de la distanță fără a trimite nicio intrare", + "telnetPort": "Port Telnet", + "terminalType": "Tipul terminalului", + "fontName": "Nume font", + "fontSize": "Dimensiunea fontului", + "colorScheme": "Schemă de culori", + "backspaceKey": "Tasta Backspace" + } + }, + "onboarding": { + "feature_desktop": "Desktop la distanță", + "feature_desktop_desc": "Deschideți sesiuni RDP, VNC și Telnet într-o filă, la fel ca în cazul SSH." + } +} diff --git a/plugins/remote-desktop/locales/translated/ru_RU.json b/plugins/remote-desktop/locales/translated/ru_RU.json new file mode 100644 index 000000000..d2d2f3000 --- /dev/null +++ b/plugins/remote-desktop/locales/translated/ru_RU.json @@ -0,0 +1,214 @@ +{ + "remoteDesktop": { + "connecting": "Подключение к сессии {{type}}...", + "checkingGuacd": "Проверка службы удаленного рабочего стола...", + "requestingToken": "Запрос токена подключения {{type}}...", + "openingSession": "Открытие сессии {{type}}...", + "negotiating": "Переговоры {{type}} рукопожатие...", + "sessionReady": "{{type}} сессия готова", + "connectionError": "Ошибка подключения", + "connectionFailed": "Подключение не удалось", + "failedToConnect": "Не удалось получить токен подключения", + "hostNotFound": "Хост не найден", + "noHostSelected": "Хост не выбран", + "reconnect": "Переподключиться", + "retry": "Повторить", + "guacdUnavailable": "Служба удалённого рабочего стола (guacd) недоступна. Убедитесь, что guacd запущен, доступен и правильно настроен в настройках администратора.", + "credentialPromptTitle": "Введите учетные данные RDP.", + "credentialPromptDescription": "На этом хосте настроен запрос учетных данных при подключении. Они используются только в течение этой сессии и не сохраняются.", + "connect": "Соединять", + "ctrlAltDel": "Ctrl+Alt+Del", + "files": { + "title": "Файлы диска", + "parent": "Родительский каталог", + "refresh": "Обновить", + "empty": "Эта папка пуста.", + "listFailed": "Не удалось прочитать эту папку.", + "download": "Скачать", + "downloadFailed": "Не удалось загрузить {{name}}", + "upload": "Загрузка файлов", + "uploading": "Загрузка {{name}}...", + "uploaded": "Загружено {{name}}", + "uploadFailed": "Не удалось загрузить {{name}}", + "uploadDisabled": "Загрузка файлов для этого соединения отключена.", + "driveUnavailable": "Включите перенаправление RDP-дисков перед загрузкой файлов.", + "driveNotWritable": "guacd не может записывать данные в папку на диске. Проверьте переменную GUACD_DRIVE_PATH (или путь к диску на хосте) и ее права доступа.", + "dropToUpload": "Перетащите файлы для загрузки" + }, + "toolbar": { + "ctrlAltDel": "Ctrl+Alt+Del", + "winL": "Win+L (Блокировка экрана)", + "winKey": "Клавиша Windows", + "superL": "Super+L (экран блокировки)", + "superKey": "Суперклавиша", + "super": "Супер", + "cmdL": "Cmd+L (Блокировка экрана)", + "cmdKey": "Клавиша Command", + "cmd": "Команда", + "ctrl": "Ctrl", + "alt": "Alt", + "shift": "Shift", + "win": "Win", + "stickyActive": "{{key}} (зафиксирована – кликните для отключения)", + "stickyInactive": "{{key}} (кликните для фиксации)", + "esc": "Escape", + "tab": "Tab", + "home": "Home", + "end": "End", + "pageUp": "Page Up", + "pageDown": "Page Down", + "arrowUp": "Arrow Up", + "arrowDown": "Arrow Down", + "arrowLeft": "Arrow Left", + "arrowRight": "Arrow Right", + "fnToggle": "Функциональные клавиши", + "reconnect": "Переподключить сеанс", + "collapse": "Свернуть панель", + "expand": "Развернуть панель", + "dragHandle": "Перетащите для перемещения", + "hide": "Скрыть на время текущей сессии. Чтобы отключить эту функцию навсегда, откройте «Настройки хоста» → «Общие» → «Панель подключения».", + "zoomIn": "Увеличить масштаб", + "zoomOut": "Отдалиться", + "resetZoom": "Сбросить масштаб", + "fitToScreen": "Подогнать под экран", + "switchToTrackpad": "Переключитесь в режим трекпада (перетащите для перемещения курсора, коснитесь для щелчка).", + "switchToTouch": "Переключитесь в сенсорный режим (коснитесь непосредственно того места, куда хотите нажать)." + } + }, + "hosts": { + "nativeRdpOpened": "Открыто в Windows Remote Desktop", + "nativeRdpFailed": "Не удалось открыть удаленный рабочий стол Windows.", + "openNativeRdp": "Открыть в удаленном рабочем столе Windows", + "guac": { + "connection": "Подключение", + "authentication": "Аутентификация", + "storedCredential": "Сохраненные учетные данные", + "authMethod": "Метод аутентификации", + "authTypeNoneDesc": "Учетные данные не сохраняются. При каждом подключении вам будет предлагаться ввести имя пользователя и пароль; они не сохраняются.", + "selectCredential": "Выберите учетные данные...", + "connectionSettings": "Параметры подключения", + "displaySettings": "Параметры отображения", + "audioSettings": "Параметры звука", + "rdpPerformance": "Производительность RDP", + "deviceRedirection": "Перенаправление устройств", + "session": "Сессия", + "gateway": "Шлюз", + "remoteApp": "RemoteApp", + "clipboard": "Буфер обмена", + "sessionRecording": "Запись сессии", + "wakeOnLan": "Wake-on-LAN", + "vncSettings": "Параметры VNC", + "terminalSettings": "Параметры терминала", + "rdpPort": "Порт RDP", + "username": "Имя пользователя", + "password": "Пароль", + "passwordSaved": "Пароль сохранен, введите для изменения.", + "domain": "Домен", + "securityMode": "Режим безопасности", + "width": "Ширина", + "height": "Высота", + "dpi": "DPI", + "clientName": "Имя клиента", + "initialProgram": "Начальная программа", + "serverLayout": "Раскладка сервера", + "timezone": "Часовой пояс", + "loadBalanceInfo": "Информация о балансировке нагрузки / Cookie", + "loadBalanceInfoDesc": "Cookie брокера подключений к удаленному рабочему столу для балансировки нагрузки фермы RDS (например, tsv://MS Terminal Services Plugin.1.CollectionName)", + "guacdProxy": "Прокси guacd", + "guacdHostname": "Хост guacd", + "guacdHostnamePlaceholder": "Глобальное значение по умолчанию", + "guacdPort": "Порт guacd", + "guacdProxyDesc": "Переопределить глобальный экземпляр guacd для этого соединения. Оставьте пустым для использования глобально настроенного guacd.", + "gatewayHostname": "Имя хоста шлюза", + "gatewayPort": "Порт шлюза", + "gatewayUsername": "Имя пользователя шлюза", + "gatewayPassword": "Пароль шлюза", + "gatewayDomain": "Домен шлюза", + "remoteAppProgram": "Программа RemoteApp", + "workingDirectory": "Рабочий каталог", + "arguments": "Аргументы", + "normalizeLineEndings": "Нормализовать окончания строк", + "macAddress": "MAC-адрес", + "broadcastAddress": "Широковещательный адрес", + "udpPort": "Порт UDP", + "waitTimeS": "Время ожидания (с)", + "driveName": "Имя диска", + "drivePath": "Путь к диску", + "ignoreCertificate": "Игнорировать сертификат", + "ignoreCertificateDesc": "Разрешить подключения к хостам с самоподписанными сертификатами", + "forceLossless": "Принудительно без потерь", + "forceLosslessDesc": "Принудительное кодирование изображений без потерь (более высокое качество, больший расход трафика)", + "disableAudio": "Отключить звук", + "disableAudioDesc": "Отключить весь звук в удаленном сеансе", + "enableAudioInput": "Включить аудиовход (микрофон)", + "enableAudioInputDesc": "Передавать локальный микрофон в удаленный сеанс", + "wallpaper": "Обои", + "wallpaperDesc": "Показывать обои рабочего стола (отключение повышает производительность)", + "theming": "Темы", + "themingDesc": "Включить визуальные темы и стили", + "fontSmoothing": "Сглаживание шрифтов", + "fontSmoothingDesc": "Включить рендеринг шрифтов ClearType", + "fullWindowDrag": "Перетаскивание окон с содержимым", + "fullWindowDragDesc": "Показывать содержимое окна при перетаскивании", + "desktopComposition": "Композиция рабочего стола", + "desktopCompositionDesc": "Включить эффекты Aero Glass", + "menuAnimations": "Анимации меню", + "menuAnimationsDesc": "Включить анимацию исчезновения и сдвига меню", + "disableBitmapCaching": "Отключить кеширование растровых изображений", + "disableBitmapCachingDesc": "Отключить кеш растровых изображений (может помочь при сбоях)", + "disableOffscreenCaching": "Отключить внеэкранное кеширование", + "disableOffscreenCachingDesc": "Отключить внеэкранный кеш", + "disableGlyphCaching": "Отключить кеширование глифов", + "disableGlyphCachingDesc": "Отключить кеш глифов", + "enableGfx": "Включить GFX", + "enableGfxDesc": "Использовать графический конвейер RemoteFX", + "enablePrinting": "Включить печать", + "enablePrintingDesc": "Перенаправлять локальные принтеры в удаленный сеанс", + "enableDriveRedirection": "Включить перенаправление дисков", + "enableDriveRedirectionDesc": "Подключать локальную папку как диск в удаленном сеансе", + "createDrivePath": "Создать путь к диску", + "createDrivePathDesc": "Автоматически создать папку, если она не существует", + "disableDownload": "Отключить загрузку", + "disableDownloadDesc": "Запретить загрузку файлов из удаленного сеанса", + "disableUpload": "Отключить выгрузку", + "disableUploadDesc": "Запретить выгрузку файлов в удаленный сеанс", + "enableTouch": "Включить сенсорный ввод", + "enableTouchDesc": "Включить передачу сенсорного ввода", + "consoleSession": "Консольный сеанс", + "consoleSessionDesc": "Подключиться к консоли (сеанс 0) вместо создания нового сеанса", + "sendWolPacket": "Отправить WOL-пакет", + "sendWolPacketDesc": "Отправить magic-пакет для пробуждения хоста перед подключением", + "disableCopy": "Отключить копирование", + "disableCopyDesc": "Запретить копирование текста из удаленного сеанса", + "disablePaste": "Отключить вставку", + "disablePasteDesc": "Запретить вставку текста в удаленный сеанс", + "createPathIfMissing": "Создать путь, если отсутствует", + "createPathIfMissingDesc": "Автоматически создать каталог для записей", + "excludeOutput": "Исключить вывод", + "excludeOutputDesc": "Не записывать вывод экрана (только метаданные)", + "excludeMouse": "Исключить мышь", + "excludeMouseDesc": "Не записывать движения мыши", + "includeKeystrokes": "Записывать нажатия", + "includeKeystrokesDesc": "Записывать необработанные нажатия клавиш в дополнение к выводу экрана", + "vncPort": "Порт VNC", + "vncPassword": "Пароль VNC", + "vncUsernameOptional": "Имя пользователя (необязательно)", + "vncLeaveBlank": "Оставьте пустым, если не требуется", + "cursorMode": "Режим курсора", + "swapRedBlue": "Поменять красный/синий", + "swapRedBlueDesc": "Обменять красный и синий цветовые каналы (исправляет некоторые проблемы с цветом)", + "readOnly": "Только чтение", + "readOnlyDesc": "Просмотр удаленного экрана без отправки ввода", + "telnetPort": "Порт Telnet", + "terminalType": "Тип терминала", + "fontName": "Название шрифта", + "fontSize": "Размер шрифта", + "colorScheme": "Цветовая схема", + "backspaceKey": "Клавиша Backspace" + } + }, + "onboarding": { + "feature_desktop": "Удаленный рабочий стол", + "feature_desktop_desc": "Открывайте сеансы RDP, VNC и Telnet во вкладке, как и SSH." + } +} diff --git a/plugins/remote-desktop/locales/translated/sr_SP.json b/plugins/remote-desktop/locales/translated/sr_SP.json new file mode 100644 index 000000000..3616300db --- /dev/null +++ b/plugins/remote-desktop/locales/translated/sr_SP.json @@ -0,0 +1,214 @@ +{ + "remoteDesktop": { + "connecting": "Повезивање са {{type}} сесијом...", + "checkingGuacd": "Провера услуге удаљене радне површине...", + "requestingToken": "Захтева се {{type}} токен за повезивање...", + "openingSession": "Отварање {{type}} сесије...", + "negotiating": "Преговарање {{type}} руковање...", + "sessionReady": "{{type}} сесија спремна", + "connectionError": "Грешка у повезивању", + "connectionFailed": "Повезивање није успело", + "failedToConnect": "Није успело добијање токена за повезивање", + "hostNotFound": "Хост није пронађен", + "noHostSelected": "Није изабран домаћин", + "reconnect": "Поново се повежите", + "retry": "Покушај поново", + "guacdUnavailable": "Услуга удаљеног рачунара (guacd) није доступна. Молимо вас да се уверите да је guacd покренут, доступан и правилно конфигурисан у администраторским подешавањима.", + "credentialPromptTitle": "Унесите RDP акредитиве", + "credentialPromptDescription": "Овај хост је подешен да тражи акредитиве при повезивању. Они се користе само за ову сесију и не чувају се.", + "connect": "Повежи се", + "ctrlAltDel": "Ctrl+Alt+Del", + "files": { + "title": "Датотеке на Диску", + "parent": "Надређени директоријум", + "refresh": "Освежи", + "empty": "Ова фасцикла је празна", + "listFailed": "Није успело читање ове фасцикле", + "download": "Преузми", + "downloadFailed": "Преузимање није успело {{name}}", + "upload": "Отпреми датотеке", + "uploading": "Отпремање {{name}}...", + "uploaded": "Отпремљено {{name}}", + "uploadFailed": "Није успело отпремање {{name}}", + "uploadDisabled": "Отпремања су онемогућена за ову везу", + "driveUnavailable": "Омогућите преусмеравање RDP диска пре отпремања датотека", + "driveNotWritable": "guacd не може да пише у фасциклу диска. Проверите GUACD_DRIVE_PATH (или путању диска хоста) и његове дозволе.", + "dropToUpload": "Отпустите датотеке да бисте их отпремили" + }, + "toolbar": { + "ctrlAltDel": "Ctrl+Alt+Del", + "winL": "Win+L (Закључавање екрана)", + "winKey": "Windows тастер", + "superL": "Супер+Л (Закључани екран)", + "superKey": "Супер кључ", + "super": "Супер", + "cmdL": "Cmd+L (Закључани екран)", + "cmdKey": "Командни тастер", + "cmd": "Команда", + "ctrl": "Ctrl", + "alt": "Алтернативно", + "shift": "Померање", + "win": "Победа", + "stickyActive": "{{key}} (закључано - кликните да бисте отпустили)", + "stickyInactive": "{{key}} (кликните да бисте закључали)", + "esc": "Бег", + "tab": "Таб", + "home": "Дом", + "end": "Крај", + "pageUp": "Страница нагоре", + "pageDown": "Страница надоле", + "arrowUp": "Стрелица нагоре", + "arrowDown": "Стрелица надоле", + "arrowLeft": "Стрелица лево", + "arrowRight": "Стрелица десно", + "fnToggle": "Функцијски тастери", + "reconnect": "Поновно повезивање сесије", + "collapse": "Савиј траку са алаткама", + "expand": "Прошири траку са алаткама", + "dragHandle": "Превуците да бисте променили положај", + "hide": "Сакриј за ову сесију. Да бисте га трајно онемогућили, отворите Подешавања хоста → Опште → Трака са алаткама за повезивање.", + "zoomIn": "Увећај", + "zoomOut": "Умањи", + "resetZoom": "Ресетуј зумирање", + "fitToScreen": "Прилагоди екрану", + "switchToTrackpad": "Пребаците се у режим додирне табле (превуците да бисте померили курсор, додирните да бисте кликнули)", + "switchToTouch": "Пребаците се на режим додира (додирните директно место где желите да кликнете)" + } + }, + "hosts": { + "nativeRdpOpened": "Отворено у Windows удаљеној радној површини", + "nativeRdpFailed": "Није успело отварање Windows удаљене радне површине", + "openNativeRdp": "Отвори у Windows удаљеној радној површини", + "guac": { + "connection": "Веза", + "authentication": "Аутентификација", + "storedCredential": "Сачувани акредитив", + "authMethod": "Метода овлашћења", + "authTypeNoneDesc": "Акредитиви се не чувају. Сваки пут када се повежете, биће вам затражено корисничко име и лозинка; они се не чувају.", + "selectCredential": "Изаберите акредитив...", + "connectionSettings": "Подешавања везе", + "displaySettings": "Подешавања екрана", + "audioSettings": "Подешавања звука", + "rdpPerformance": "Перформансе РДП-а", + "deviceRedirection": "Преусмеравање уређаја", + "session": "Сесија", + "gateway": "Капија", + "remoteApp": "Удаљена апликација", + "clipboard": "Међуспремник", + "sessionRecording": "Снимање сесије", + "wakeOnLan": "Wake-on-LAN", + "vncSettings": "VNC подешавања", + "terminalSettings": "Подешавања терминала", + "rdpPort": "РДП порт", + "username": "Корисничко име", + "password": "Лозинка", + "passwordSaved": "Лозинка сачувана, унесите текст да бисте је променили", + "domain": "Домен", + "securityMode": "Безбедносни режим", + "width": "Ширина", + "height": "Висина", + "dpi": "DPI", + "clientName": "Име клијента", + "initialProgram": "Почетни програм", + "serverLayout": "Распоред сервера", + "timezone": "Временска зона", + "loadBalanceInfo": "Информације о балансу оптерећења / колачић", + "loadBalanceInfoDesc": "Колачић RD Connection Broker-а за балансирање оптерећења RDS фарме (нпр. tsv://MS Terminal Services Plugin.1.CollectionName)", + "guacdProxy": "guacd прокси", + "guacdHostname": "guacd хост", + "guacdHostnamePlaceholder": "Глобално подразумевано", + "guacdPort": "ГУАЦД порт", + "guacdProxyDesc": "Замените глобалну инстанцу guacd-а за ову везу. Оставите празно да бисте користили глобално конфигурисани guacd.", + "gatewayHostname": "Име хоста мрежног пролаза", + "gatewayPort": "Порт за пролаз", + "gatewayUsername": "Корисничко име на гејтвеју", + "gatewayPassword": "Лозинка за пролаз", + "gatewayDomain": "Домен капије", + "remoteAppProgram": "Програм RemoteApp", + "workingDirectory": "Радни директоријум", + "arguments": "Аргументи", + "normalizeLineEndings": "Нормализуј завршетке линија", + "macAddress": "MAC адреса", + "broadcastAddress": "Адреса за емитовање", + "udpPort": "UDP порт", + "waitTimeS": "Време чекања (s)", + "driveName": "Назив диска", + "drivePath": "Путања диска", + "ignoreCertificate": "Игнориши сертификат", + "ignoreCertificateDesc": "Дозволи везе са хостовима са самопотписаним сертификатима", + "forceLossless": "Присилно без губитака", + "forceLosslessDesc": "Присилно кодирање слике без губитака (виши квалитет, већи пропусни опсег)", + "disableAudio": "Онемогући звук", + "disableAudioDesc": "Искључите сав звук из удаљене сесије", + "enableAudioInput": "Омогући аудио улаз (микрофон)", + "enableAudioInputDesc": "Прослеђивање локалног микрофона на удаљену сесију", + "wallpaper": "Позадина", + "wallpaperDesc": "Прикажи позадину радне површине (онемогућавање побољшава перформансе)", + "theming": "Темирање", + "themingDesc": "Омогући визуелне теме и стилове", + "fontSmoothing": "Изглађивање фонта", + "fontSmoothingDesc": "Омогући приказивање ClearType фонта", + "fullWindowDrag": "Превлачење преко целог прозора", + "fullWindowDragDesc": "Приказ садржаја прозора током превлачења", + "desktopComposition": "Композиција на радној површини", + "desktopCompositionDesc": "Омогући ефекте Aero Glass-а", + "menuAnimations": "Анимације менија", + "menuAnimationsDesc": "Омогући анимације постепеног постепеног померања менија и слајдова", + "disableBitmapCaching": "Онемогући кеширање битмапа", + "disableBitmapCachingDesc": "Искључите кеш битмапа (може помоћи код грешака)", + "disableOffscreenCaching": "Онемогући кеширање ван екрана", + "disableOffscreenCachingDesc": "Искључите кеш меморију ван екрана", + "disableGlyphCaching": "Онемогући кеширање глифова", + "disableGlyphCachingDesc": "Искључите кеш глифова", + "enableGfx": "Омогући графичке ефекте", + "enableGfxDesc": "Користите графички цевовод RemoteFX", + "enablePrinting": "Омогући штампање", + "enablePrintingDesc": "Преусмерите локалне штампаче на удаљену сесију", + "enableDriveRedirection": "Омогући преусмеравање диска", + "enableDriveRedirectionDesc": "Мапирајте локалну фасциклу као диск у удаљеној сесији", + "createDrivePath": "Креирај путању диска", + "createDrivePathDesc": "Аутоматски креирај фасциклу ако не постоји", + "disableDownload": "Онемогући преузимање", + "disableDownloadDesc": "Спречите преузимање датотека са удаљене сесије", + "disableUpload": "Онемогући отпремање", + "disableUploadDesc": "Спречите отпремање датотека на удаљену сесију", + "enableTouch": "Омогући додир", + "enableTouchDesc": "Омогући преусмеравање уноса додиром", + "consoleSession": "Конзолна сесија", + "consoleSessionDesc": "Повежите се са конзолом (сесија 0) уместо нове сесије", + "sendWolPacket": "Пошаљи WOL пакет", + "sendWolPacketDesc": "Пошаљите магични пакет да пробудите овај хост пре повезивања", + "disableCopy": "Онемогући копирање", + "disableCopyDesc": "Спречите копирање текста из удаљене сесије", + "disablePaste": "Онемогући лепљење", + "disablePasteDesc": "Спречите лепљење текста у удаљену сесију", + "createPathIfMissing": "Креирај путању ако недостаје", + "createPathIfMissingDesc": "Аутоматски креирајте директоријум за снимање", + "excludeOutput": "Искључи излаз", + "excludeOutputDesc": "Не снимај излаз екрана (само метаподаци)", + "excludeMouse": "Искључи миш", + "excludeMouseDesc": "Не снимај покрете миша", + "includeKeystrokes": "Укључи притиске на тастатури", + "includeKeystrokesDesc": "Снимање сирових притиска тастера поред излаза на екран", + "vncPort": "VNC порт", + "vncPassword": "VNC лозинка", + "vncUsernameOptional": "Корисничко име (опционо)", + "vncLeaveBlank": "Оставите празно ако није потребно", + "cursorMode": "Режим курсора", + "swapRedBlue": "Замена црвене/плаве", + "swapRedBlueDesc": "Замена црвених и плавих канала боја (решава неке проблеме са бојама)", + "readOnly": "Само за читање", + "readOnlyDesc": "Погледајте удаљени екран без слања било каквог уноса", + "telnetPort": "Телнет порт", + "terminalType": "Тип терминала", + "fontName": "Назив фонта", + "fontSize": "Величина фонта", + "colorScheme": "Шема боја", + "backspaceKey": "Тастер Backspace" + } + }, + "onboarding": { + "feature_desktop": "Удаљена радна површина", + "feature_desktop_desc": "Отворите RDP, VNC и Telnet сесије у картици, исто као и SSH." + } +} diff --git a/plugins/remote-desktop/locales/translated/sv_SE.json b/plugins/remote-desktop/locales/translated/sv_SE.json new file mode 100644 index 000000000..76ca9559c --- /dev/null +++ b/plugins/remote-desktop/locales/translated/sv_SE.json @@ -0,0 +1,214 @@ +{ + "remoteDesktop": { + "connecting": "Ansluter till {{type}} session...", + "checkingGuacd": "Kontrollerar fjärrskrivbordstjänsten...", + "requestingToken": "Begär {{type}} anslutningstoken...", + "openingSession": "Öppnar {{type}} session...", + "negotiating": "Förhandlar {{type}} handslag...", + "sessionReady": "{{type}} session klar", + "connectionError": "Anslutningsfel", + "connectionFailed": "Anslutningen misslyckades", + "failedToConnect": "Misslyckades med att hämta anslutningstoken", + "hostNotFound": "Värden hittades inte", + "noHostSelected": "Ingen värd vald", + "reconnect": "Återanslut", + "retry": "Försöka igen", + "guacdUnavailable": "Fjärrskrivbordstjänsten (guacd) är inte tillgänglig. Se till att guacd körs, är tillgängligt och korrekt konfigurerat i administratörsinställningarna.", + "credentialPromptTitle": "Ange RDP-inloggningsuppgifter", + "credentialPromptDescription": "Den här värden är inställd på att be om inloggningsuppgifter vid anslutning. De används endast för den här sessionen och sparas inte.", + "connect": "Ansluta", + "ctrlAltDel": "Ctrl+Alt+Del", + "files": { + "title": "Drive-filer", + "parent": "Föräldrakatalog", + "refresh": "Uppdatera", + "empty": "Den här mappen är tom", + "listFailed": "Kunde inte läsa den här mappen", + "download": "Ladda ner", + "downloadFailed": "Misslyckades med att ladda ner {{name}}", + "upload": "Ladda upp filer", + "uploading": "Laddar upp {{name}}...", + "uploaded": "Uppladdad {{name}}", + "uploadFailed": "Misslyckades med att ladda upp {{name}}", + "uploadDisabled": "Uppladdningar är inaktiverade för den här anslutningen", + "driveUnavailable": "Aktivera omdirigering av RDP-enheter innan du laddar upp filer", + "driveNotWritable": "guacd kan inte skriva till enhetsmappen. Kontrollera GUACD_DRIVE_PATH (eller värdens sökväg för enhet) och dess behörigheter.", + "dropToUpload": "Släpp filer för att ladda upp" + }, + "toolbar": { + "ctrlAltDel": "Ctrl+Alt+Del", + "winL": "Win+L (Låsskärm)", + "winKey": "Windows-tangenten", + "superL": "Super+L (Låsskärm)", + "superKey": "Supernyckel", + "super": "Super", + "cmdL": "Cmd+L (Låsskärm)", + "cmdKey": "Kommandotangent", + "cmd": "Kommando", + "ctrl": "Ctrl", + "alt": "Alt", + "shift": "Flytta", + "win": "Vinna", + "stickyActive": "{{key}} (låst – klicka för att släppa)", + "stickyInactive": "{{key}} (klicka för att låsa)", + "esc": "Fly", + "tab": "Flik", + "home": "Hem", + "end": "Avsluta", + "pageUp": "Sida upp", + "pageDown": "Sida ner", + "arrowUp": "Pil upp", + "arrowDown": "Pil nedåt", + "arrowLeft": "Pil vänster", + "arrowRight": "Pil höger", + "fnToggle": "Funktionstangenter", + "reconnect": "Återanslut sessionen", + "collapse": "Komprimera verktygsfältet", + "expand": "Expandera verktygsfältet", + "dragHandle": "Dra för att flytta", + "hide": "Dölj för den här sessionen. För att inaktivera det permanent, öppna Värdinställningar → Allmänt → Anslutningsverktygsfält.", + "zoomIn": "Zooma in", + "zoomOut": "Zooma ut", + "resetZoom": "Återställ zoom", + "fitToScreen": "Anpassa till skärmen", + "switchToTrackpad": "Växla till styrplatteläge (dra för att flytta markören, tryck för att klicka)", + "switchToTouch": "Växla till pekläge (tryck direkt där du vill klicka)" + } + }, + "hosts": { + "nativeRdpOpened": "Öppnad i Windows Fjärrskrivbord", + "nativeRdpFailed": "Misslyckades med att öppna Windows Fjärrskrivbord", + "openNativeRdp": "Öppna i Windows Fjärrskrivbord", + "guac": { + "connection": "Förbindelse", + "authentication": "Autentisering", + "storedCredential": "Lagrade autentiseringsuppgifter", + "authMethod": "Autentiseringsmetod", + "authTypeNoneDesc": "Inga inloggningsuppgifter lagras. Du kommer att bli ombedd att ange ett användarnamn och lösenord varje gång du ansluter; de sparas inte.", + "selectCredential": "Välj en behörighetsinloggning...", + "connectionSettings": "Anslutningsinställningar", + "displaySettings": "Skärminställningar", + "audioSettings": "Ljudinställningar", + "rdpPerformance": "RDP-prestanda", + "deviceRedirection": "Omdirigering av enhet", + "session": "Session", + "gateway": "Inkörsport", + "remoteApp": "Fjärrapp", + "clipboard": "Urklipp", + "sessionRecording": "Sessionsinspelning", + "wakeOnLan": "Wake-on-LAN", + "vncSettings": "VNC-inställningar", + "terminalSettings": "Terminalinställningar", + "rdpPort": "RDP-port", + "username": "Användarnamn", + "password": "Lösenord", + "passwordSaved": "Lösenordet sparats, skriv för att ändra", + "domain": "Domän", + "securityMode": "Säkerhetsläge", + "width": "Bredd", + "height": "Höjd", + "dpi": "DPI", + "clientName": "Klientnamn", + "initialProgram": "Inledande program", + "serverLayout": "Serverlayout", + "timezone": "Tidszon", + "loadBalanceInfo": "Information om belastningsbalans / Cookie", + "loadBalanceInfoDesc": "RD Connection Broker-cookie för lastbalansering av RDS-farm (t.ex. tsv://MS Terminal Services Plugin.1.CollectionName)", + "guacdProxy": "guacd-proxy", + "guacdHostname": "guacd-värd", + "guacdHostnamePlaceholder": "Global standard", + "guacdPort": "guacd-porten", + "guacdProxyDesc": "Åsidosätt den globala guacd-instansen för den här anslutningen. Lämna tomt om du vill använda den globalt konfigurerade guacd-instansen.", + "gatewayHostname": "Gateway-värdnamn", + "gatewayPort": "Gateway-porten", + "gatewayUsername": "Gateway-användarnamn", + "gatewayPassword": "Gateway-lösenord", + "gatewayDomain": "Gateway-domän", + "remoteAppProgram": "RemoteApp-programmet", + "workingDirectory": "Arbetskatalog", + "arguments": "Argument", + "normalizeLineEndings": "Normalisera radavslutningar", + "macAddress": "MAC-adress", + "broadcastAddress": "Sändningsadress", + "udpPort": "UDP-port", + "waitTimeS": "Väntetid (s)", + "driveName": "Enhetsnamn", + "drivePath": "Körväg", + "ignoreCertificate": "Ignorera certifikat", + "ignoreCertificateDesc": "Tillåt anslutningar till värdar med självsignerade certifikat", + "forceLossless": "Tvinga förlustfri", + "forceLosslessDesc": "Tvinga fram förlustfri bildkodning (högre kvalitet, mer bandbredd)", + "disableAudio": "Inaktivera ljud", + "disableAudioDesc": "Stäng av allt ljud från fjärrsessionen", + "enableAudioInput": "Aktivera ljudingång (mikrofon)", + "enableAudioInputDesc": "Vidarebefordra den lokala mikrofonen till fjärrsessionen", + "wallpaper": "Tapet", + "wallpaperDesc": "Visa skrivbordsbakgrund (inaktivering förbättrar prestandan)", + "theming": "Teman", + "themingDesc": "Aktivera visuella teman och stilar", + "fontSmoothing": "Utjämning av teckensnitt", + "fontSmoothingDesc": "Aktivera rendering av ClearType-teckensnitt", + "fullWindowDrag": "Drag i hela fönstret", + "fullWindowDragDesc": "Visa fönsterinnehållet när du drar", + "desktopComposition": "Skrivbordskomposition", + "desktopCompositionDesc": "Aktivera Aero Glass-effekter", + "menuAnimations": "Menyanimationer", + "menuAnimationsDesc": "Aktivera menytoning och glidande animationer", + "disableBitmapCaching": "Inaktivera bitmappscachning", + "disableBitmapCachingDesc": "Stäng av bitmappscachen (kan hjälpa till med problem)", + "disableOffscreenCaching": "Inaktivera cachelagring utanför skärmen", + "disableOffscreenCachingDesc": "Stäng av cache utanför skärmen", + "disableGlyphCaching": "Inaktivera glyf-cachning", + "disableGlyphCachingDesc": "Stäng av glyph-cache", + "enableGfx": "Aktivera GFX", + "enableGfxDesc": "Använd RemoteFX-grafikpipeline", + "enablePrinting": "Aktivera utskrift", + "enablePrintingDesc": "Omdirigera lokala skrivare till fjärrsessionen", + "enableDriveRedirection": "Aktivera omdirigering av kördata", + "enableDriveRedirectionDesc": "Mappa en lokal mapp som en enhet i fjärrsessionen", + "createDrivePath": "Skapa drivväg", + "createDrivePathDesc": "Skapa mappen automatiskt om den inte finns", + "disableDownload": "Inaktivera nedladdning", + "disableDownloadDesc": "Förhindra nedladdning av filer från fjärrsessionen", + "disableUpload": "Inaktivera uppladdning", + "disableUploadDesc": "Förhindra uppladdning av filer till fjärrsessionen", + "enableTouch": "Aktivera pekskärm", + "enableTouchDesc": "Aktivera vidarebefordran av pekinmatning", + "consoleSession": "Konsolsession", + "consoleSessionDesc": "Anslut till konsolen (session 0) istället för en ny session", + "sendWolPacket": "Skicka WOL-paket", + "sendWolPacketDesc": "Skicka ett magiskt paket för att väcka den här värden innan anslutning", + "disableCopy": "Inaktivera kopiering", + "disableCopyDesc": "Förhindra kopiering av text från fjärrsessionen", + "disablePaste": "Inaktivera inklistring", + "disablePasteDesc": "Förhindra att text klistras in i fjärrsessionen", + "createPathIfMissing": "Skapa sökväg om den saknas", + "createPathIfMissingDesc": "Skapa inspelningskatalogen automatiskt", + "excludeOutput": "Exkludera utdata", + "excludeOutputDesc": "Spela inte in skärmutdata (endast metadata)", + "excludeMouse": "Uteslut mus", + "excludeMouseDesc": "Spela inte in musrörelser", + "includeKeystrokes": "Inkludera tangenttryckningar", + "includeKeystrokesDesc": "Spela in råa tangenttryckningar utöver skärmutdata", + "vncPort": "VNC-port", + "vncPassword": "VNC-lösenord", + "vncUsernameOptional": "Användarnamn (valfritt)", + "vncLeaveBlank": "Lämna tomt om det inte behövs", + "cursorMode": "Markörläge", + "swapRedBlue": "Byt röd/blå", + "swapRedBlueDesc": "Byt ut de röda och blå färgkanalerna (åtgärdar vissa färgproblem)", + "readOnly": "Skrivskyddad", + "readOnlyDesc": "Visa fjärrskärmen utan att skicka någon inmatning", + "telnetPort": "Telnet-port", + "terminalType": "Terminaltyp", + "fontName": "Typsnittsnamn", + "fontSize": "Fontstorlek", + "colorScheme": "Färgschema", + "backspaceKey": "Backstegstangenten" + } + }, + "onboarding": { + "feature_desktop": "Fjärrskrivbord", + "feature_desktop_desc": "Öppna RDP-, VNC- och Telnet-sessioner i en flik, samma som med SSH." + } +} diff --git a/plugins/remote-desktop/locales/translated/th_TH.json b/plugins/remote-desktop/locales/translated/th_TH.json new file mode 100644 index 000000000..aee085e4e --- /dev/null +++ b/plugins/remote-desktop/locales/translated/th_TH.json @@ -0,0 +1,214 @@ +{ + "remoteDesktop": { + "connecting": "กำลังเชื่อมต่อกับเซสชัน {{type}}...", + "checkingGuacd": "กำลังตรวจสอบบริการเดสก์ท็อประยะไกล...", + "requestingToken": "กำลังขอโทเค็นการเชื่อมต่อ {{type}}...", + "openingSession": "กำลังเปิดเซสชั่น {{type}}...", + "negotiating": "กำลังเจรจาต่อรองด้วยการจับมือ {{type}}...", + "sessionReady": "{{type}} เซสชั่นพร้อมใช้งาน", + "connectionError": "ข้อผิดพลาดในการเชื่อมต่อ", + "connectionFailed": "การเชื่อมต่อล้มเหลว", + "failedToConnect": "ไม่สามารถรับโทเค็นการเชื่อมต่อได้", + "hostNotFound": "ไม่พบโฮสต์", + "noHostSelected": "ไม่ได้เลือกโฮสต์", + "reconnect": "เชื่อมต่อใหม่", + "retry": "ลองใหม่อีกครั้ง", + "guacdUnavailable": "บริการเดสก์ท็อประยะไกล (guacd) ไม่พร้อมใช้งาน โปรดตรวจสอบให้แน่ใจว่า guacd กำลังทำงาน สามารถเข้าถึงได้ และกำหนดค่าอย่างถูกต้องในการตั้งค่าผู้ดูแลระบบ", + "credentialPromptTitle": "ป้อนข้อมูลรับรอง RDP", + "credentialPromptDescription": "โฮสต์นี้ตั้งค่าให้ขอข้อมูลรับรองเมื่อเชื่อมต่อ ข้อมูลเหล่านี้จะใช้สำหรับเซสชันนี้เท่านั้นและจะไม่ถูกบันทึกไว้", + "connect": "เชื่อมต่อ", + "ctrlAltDel": "Ctrl+Alt+Del", + "files": { + "title": "ไฟล์ไดรฟ์", + "parent": "ไดเร็กทอรีผู้ปกครอง", + "refresh": "รีเฟรช", + "empty": "โฟลเดอร์นี้ว่างเปล่า", + "listFailed": "ไม่สามารถอ่านโฟลเดอร์นี้ได้", + "download": "ดาวน์โหลด", + "downloadFailed": "ไม่สามารถดาวน์โหลด {{name}} ได้", + "upload": "อัปโหลดไฟล์", + "uploading": "กำลังอัปโหลด {{name}}...", + "uploaded": "อัปโหลดแล้ว {{name}}", + "uploadFailed": "การอัปโหลดล้มเหลว {{name}}", + "uploadDisabled": "การอัปโหลดถูกปิดใช้งานสำหรับการเชื่อมต่อนี้", + "driveUnavailable": "เปิดใช้งานการส่งต่อไดรฟ์ RDP ก่อนอัปโหลดไฟล์", + "driveNotWritable": "guacd ไม่สามารถเขียนลงในโฟลเดอร์ไดรฟ์ได้ โปรดตรวจสอบ GUACD_DRIVE_PATH (หรือเส้นทางไดรฟ์ของโฮสต์) และสิทธิ์การเข้าถึง", + "dropToUpload": "ลากไฟล์เพื่ออัปโหลด" + }, + "toolbar": { + "ctrlAltDel": "Ctrl+Alt+Del", + "winL": "Win+L (หน้าจอล็อก)", + "winKey": "ปุ่ม Windows", + "superL": "Super+L (หน้าจอล็อก)", + "superKey": "ซูเปอร์คีย์", + "super": "สุดยอด", + "cmdL": "กด Cmd+L (หน้าจอล็อก)", + "cmdKey": "ปุ่มคำสั่ง", + "cmd": "ผู้บัญชาการ", + "ctrl": "Ctrl", + "alt": "อัลท์", + "shift": "กะ", + "win": "ชนะ", + "stickyActive": "{{key}} (ล็อคอยู่ - คลิกเพื่อปลดล็อค)", + "stickyInactive": "{{key}} (คลิกเพื่อล็อค)", + "esc": "หนี", + "tab": "แท็บ", + "home": "บ้าน", + "end": "จบ", + "pageUp": "เลื่อนขึ้น", + "pageDown": "เลื่อนลง", + "arrowUp": "ลูกศรขึ้น", + "arrowDown": "ลูกศรลง", + "arrowLeft": "ลูกศรซ้าย", + "arrowRight": "ลูกศรขวา", + "fnToggle": "ปุ่มฟังก์ชัน", + "reconnect": "เซสชั่นเชื่อมต่อใหม่", + "collapse": "ยุบแถบเครื่องมือ", + "expand": "ขยายแถบเครื่องมือ", + "dragHandle": "ลากเพื่อจัดตำแหน่งใหม่", + "hide": "ซ่อนไว้สำหรับการใช้งานในครั้งนี้ หากต้องการปิดใช้งานอย่างถาวร ให้เปิด การตั้งค่าโฮสต์ → ทั่วไป → แถบเครื่องมือการเชื่อมต่อ", + "zoomIn": "ซูมเข้า", + "zoomOut": "ซูมออก", + "resetZoom": "รีเซ็ตการซูม", + "fitToScreen": "พอดีกับหน้าจอ", + "switchToTrackpad": "เปลี่ยนไปใช้โหมดแทร็กแพด (ลากเพื่อเลื่อนเคอร์เซอร์ แตะเพื่อคลิก)", + "switchToTouch": "เปลี่ยนเป็นโหมดสัมผัส (แตะตรงจุดที่คุณต้องการคลิก)" + } + }, + "hosts": { + "nativeRdpOpened": "เปิดใช้งานใน Windows Remote Desktop", + "nativeRdpFailed": "ไม่สามารถเปิด Windows Remote Desktop ได้", + "openNativeRdp": "เปิดใน Windows Remote Desktop", + "guac": { + "connection": "การเชื่อมต่อ", + "authentication": "การตรวจสอบสิทธิ์", + "storedCredential": "ข้อมูลประจำตัวที่บันทึกไว้", + "authMethod": "วิธีการตรวจสอบสิทธิ์", + "authTypeNoneDesc": "ไม่มีการจัดเก็บข้อมูลประจำตัวใดๆ คุณจะต้องป้อนชื่อผู้ใช้และรหัสผ่านทุกครั้งที่เชื่อมต่อ ซึ่งจะไม่ถูกบันทึกไว้", + "selectCredential": "เลือกข้อมูลประจำตัว...", + "connectionSettings": "การตั้งค่าการเชื่อมต่อ", + "displaySettings": "การตั้งค่าการแสดงผล", + "audioSettings": "การตั้งค่าเสียง", + "rdpPerformance": "ประสิทธิภาพ RDP", + "deviceRedirection": "การเปลี่ยนเส้นทางอุปกรณ์", + "session": "การประชุม", + "gateway": "เกตเวย์", + "remoteApp": "รีโมทแอป", + "clipboard": "คลิปบอร์ด", + "sessionRecording": "การบันทึกการประชุม", + "wakeOnLan": "ปลุกเครื่องผ่าน LAN", + "vncSettings": "การตั้งค่า VNC", + "terminalSettings": "การตั้งค่าเทอร์มินัล", + "rdpPort": "พอร์ต RDP", + "username": "ชื่อผู้ใช้", + "password": "รหัสผ่าน", + "passwordSaved": "บันทึกรหัสผ่านแล้ว กรุณาพิมพ์เพื่อเปลี่ยนรหัสผ่าน", + "domain": "โดเมน", + "securityMode": "โหมดความปลอดภัย", + "width": "ความกว้าง", + "height": "ความสูง", + "dpi": "ดีพีไอ", + "clientName": "ชื่อลูกค้า", + "initialProgram": "โปรแกรมเริ่มต้น", + "serverLayout": "เค้าโครงเซิร์ฟเวอร์", + "timezone": "เขตเวลา", + "loadBalanceInfo": "ข้อมูลการปรับสมดุลโหลด / คุกกี้", + "loadBalanceInfoDesc": "คุกกี้ RD Connection Broker สำหรับการปรับสมดุลโหลดของฟาร์ม RDS (เช่น tsv://MS Terminal Services Plugin.1.CollectionName)", + "guacdProxy": "guacd Proxy", + "guacdHostname": "guacd Host", + "guacdHostnamePlaceholder": "ค่าเริ่มต้นทั่วโลก", + "guacdPort": "guacd Port", + "guacdProxyDesc": "แทนที่อินสแตนซ์ guacd ทั่วโลกสำหรับการเชื่อมต่อนี้ หากต้องการใช้ guacd ที่กำหนดค่าไว้ทั่วโลก ให้เว้นว่างไว้", + "gatewayHostname": "ชื่อโฮสต์เกตเวย์", + "gatewayPort": "พอร์ตเกตเวย์", + "gatewayUsername": "ชื่อผู้ใช้เกตเวย์", + "gatewayPassword": "รหัสผ่านเกตเวย์", + "gatewayDomain": "โดเมนเกตเวย์", + "remoteAppProgram": "โปรแกรม RemoteApp", + "workingDirectory": "ไดเร็กทอรีการทำงาน", + "arguments": "ข้อโต้แย้ง", + "normalizeLineEndings": "ปรับความยาวบรรทัดให้เป็นมาตรฐาน", + "macAddress": "ที่อยู่ MAC", + "broadcastAddress": "ที่อยู่กระจายเสียง", + "udpPort": "พอร์ต UDP", + "waitTimeS": "ระยะเวลารอคอย (วินาที)", + "driveName": "ชื่อไดรฟ์", + "drivePath": "เส้นทางขับรถ", + "ignoreCertificate": "ละเว้นใบรับรอง", + "ignoreCertificateDesc": "อนุญาตการเชื่อมต่อกับโฮสต์ที่มีใบรับรองที่ลงนามด้วยตนเอง", + "forceLossless": "บังคับการสูญเสีย", + "forceLosslessDesc": "บังคับใช้การเข้ารหัสภาพแบบไม่สูญเสียคุณภาพ (คุณภาพสูงกว่า ใช้แบนด์วิดท์มากกว่า)", + "disableAudio": "ปิดใช้งานเสียง", + "disableAudioDesc": "ปิดเสียงทั้งหมดจากการเชื่อมต่อระยะไกล", + "enableAudioInput": "เปิดใช้งานการรับเสียง (ไมโครโฟน)", + "enableAudioInputDesc": "ส่งต่อไมโครโฟนในเครื่องไปยังเซสชันระยะไกล", + "wallpaper": "วอลเปเปอร์", + "wallpaperDesc": "แสดงภาพพื้นหลังเดสก์ท็อป (การปิดใช้งานจะช่วยเพิ่มประสิทธิภาพ)", + "theming": "ธีม", + "themingDesc": "เปิดใช้งานธีมและสไตล์ภาพ", + "fontSmoothing": "การปรับความเรียบของแบบอักษร", + "fontSmoothingDesc": "เปิดใช้งานการแสดงผลฟอนต์ ClearType", + "fullWindowDrag": "ลากแบบเต็มหน้าต่าง", + "fullWindowDragDesc": "แสดงเนื้อหาในหน้าต่างขณะลาก", + "desktopComposition": "การจัดองค์ประกอบเดสก์ท็อป", + "desktopCompositionDesc": "เปิดใช้งานเอฟเฟกต์กระจก Aero", + "menuAnimations": "แอนิเมชันเมนู", + "menuAnimationsDesc": "เปิดใช้งานแอนิเมชั่นเฟดและสไลด์ของเมนู", + "disableBitmapCaching": "ปิดใช้งานการแคชภาพบิตแมป", + "disableBitmapCachingDesc": "ปิดใช้งานแคชภาพบิตแมป (อาจช่วยลดปัญหาภาพกระตุกได้)", + "disableOffscreenCaching": "ปิดใช้งานการแคชแบบออฟสกรีน", + "disableOffscreenCachingDesc": "ปิดใช้งานแคชแบบออฟไลน์", + "disableGlyphCaching": "ปิดใช้งานการแคชสัญลักษณ์", + "disableGlyphCachingDesc": "ปิดใช้งานแคชสัญลักษณ์", + "enableGfx": "เปิดใช้งาน GFX", + "enableGfxDesc": "ใช้ไปป์ไลน์กราฟิก RemoteFX", + "enablePrinting": "เปิดใช้งานการพิมพ์", + "enablePrintingDesc": "โอนย้ายเครื่องพิมพ์ในเครื่องไปยังเซสชันระยะไกล", + "enableDriveRedirection": "เปิดใช้งานการเปลี่ยนเส้นทางไดรฟ์", + "enableDriveRedirectionDesc": "แมปโฟลเดอร์ในเครื่องเป็นไดรฟ์ในเซสชันระยะไกล", + "createDrivePath": "สร้างเส้นทางไดรฟ์", + "createDrivePathDesc": "สร้างโฟลเดอร์โดยอัตโนมัติหากยังไม่มีอยู่", + "disableDownload": "ปิดใช้งานการดาวน์โหลด", + "disableDownloadDesc": "ป้องกันการดาวน์โหลดไฟล์จากการเชื่อมต่อระยะไกล", + "disableUpload": "ปิดใช้งานการอัปโหลด", + "disableUploadDesc": "ป้องกันการอัปโหลดไฟล์ไปยังเซสชันระยะไกล", + "enableTouch": "เปิดใช้งานระบบสัมผัส", + "enableTouchDesc": "เปิดใช้งานการส่งต่อข้อมูลการสัมผัส", + "consoleSession": "เซสชันคอนโซล", + "consoleSessionDesc": "เชื่อมต่อกับคอนโซล (เซสชัน 0) แทนที่จะสร้างเซสชันใหม่", + "sendWolPacket": "ส่งแพ็กเก็ต WOL", + "sendWolPacketDesc": "ส่งแพ็กเก็ตเวทมนตร์เพื่อปลุกโฮสต์นี้ก่อนเชื่อมต่อ", + "disableCopy": "ปิดใช้งานการคัดลอก", + "disableCopyDesc": "ป้องกันการคัดลอกข้อความจากเซสชันระยะไกล", + "disablePaste": "ปิดใช้งานการวาง", + "disablePasteDesc": "ป้องกันการวางข้อความลงในเซสชันระยะไกล", + "createPathIfMissing": "สร้างเส้นทางหากยังไม่มีอยู่", + "createPathIfMissingDesc": "สร้างไดเร็กทอรีสำหรับการบันทึกโดยอัตโนมัติ", + "excludeOutput": "ไม่รวมผลลัพธ์", + "excludeOutputDesc": "ห้ามบันทึกข้อมูลที่แสดงบนหน้าจอ (บันทึกเฉพาะข้อมูลเมตาเท่านั้น)", + "excludeMouse": "ไม่รวมเมาส์", + "excludeMouseDesc": "ห้ามบันทึกการเคลื่อนไหวของเมาส์", + "includeKeystrokes": "รวมการกดแป้นพิมพ์", + "includeKeystrokesDesc": "บันทึกการกดแป้นพิมพ์ดิบนอกเหนือจากข้อมูลที่แสดงผลบนหน้าจอ", + "vncPort": "พอร์ต VNC", + "vncPassword": "รหัสผ่าน VNC", + "vncUsernameOptional": "ชื่อผู้ใช้ (ไม่บังคับ)", + "vncLeaveBlank": "เว้นว่างไว้หากไม่ต้องการใช้", + "cursorMode": "โหมดเคอร์เซอร์", + "swapRedBlue": "สลับสีแดง/น้ำเงิน", + "swapRedBlueDesc": "สลับช่องสีแดงและสีน้ำเงิน (แก้ไขปัญหาเรื่องสีบางอย่าง)", + "readOnly": "อ่านอย่างเดียว", + "readOnlyDesc": "ดูหน้าจอระยะไกลโดยไม่ต้องส่งข้อมูลใดๆ", + "telnetPort": "พอร์ตเทลเน็ต", + "terminalType": "ประเภทเทอร์มินัล", + "fontName": "ชื่อแบบอักษร", + "fontSize": "ขนาดตัวอักษร", + "colorScheme": "โทนสี", + "backspaceKey": "ปุ่มลบ" + } + }, + "onboarding": { + "feature_desktop": "การเข้าถึงเดสก์ท็อประยะไกล", + "feature_desktop_desc": "เปิดเซสชัน RDP, VNC และ Telnet ในแท็บเดียวกัน เหมือนกับการเปิด SSH" + } +} diff --git a/plugins/remote-desktop/locales/translated/tr_TR.json b/plugins/remote-desktop/locales/translated/tr_TR.json new file mode 100644 index 000000000..dc4ade7b4 --- /dev/null +++ b/plugins/remote-desktop/locales/translated/tr_TR.json @@ -0,0 +1,214 @@ +{ + "remoteDesktop": { + "connecting": "{{type}} oturumuna bağlanılıyor...", + "checkingGuacd": "Uzaktan masaüstü hizmeti kontrol ediliyor...", + "requestingToken": "{{type}} bağlantı belirteci isteniyor...", + "openingSession": "{{type}} oturumu açılıyor...", + "negotiating": "{{type}} el sıkışması üzerinde pazarlık yapılıyor...", + "sessionReady": "{{type}} oturum hazır", + "connectionError": "Bağlantı hatası", + "connectionFailed": "Bağlantı başarısız", + "failedToConnect": "Bağlantı belirteci alınamadı", + "hostNotFound": "Sunucu bulunamadı", + "noHostSelected": "Sunucu seçilmedi", + "reconnect": "Yeniden bağlan", + "retry": "Yeniden dene", + "guacdUnavailable": "Uzak masaüstü hizmeti (guacd) kullanılamıyor. Lütfen guacd'nin çalıştığından, erişilebilir olduğundan ve yönetici ayarlarında düzgün yapılandırıldığından emin olun.", + "credentialPromptTitle": "RDP Kimlik Bilgilerini Girin", + "credentialPromptDescription": "Bu sunucu, bağlantı kurulurken kimlik bilgilerini isteyecek şekilde ayarlanmıştır. Bu bilgiler yalnızca bu oturum için kullanılır ve kaydedilmez.", + "connect": "Bağlamak", + "ctrlAltDel": "Ctrl+Alt+Del", + "files": { + "title": "Sürücü Dosyaları", + "parent": "Üst dizin", + "refresh": "Yenile", + "empty": "Bu klasör boş.", + "listFailed": "Bu klasör okunamadı.", + "download": "İndirmek", + "downloadFailed": "{{name}} indirme işlemi başarısız oldu.", + "upload": "Dosyaları yükle", + "uploading": "{{name}} yükleniyor...", + "uploaded": "Yüklenen {{name}}", + "uploadFailed": "{{name}} yüklenemedi.", + "uploadDisabled": "Bu bağlantı için yüklemeler devre dışı bırakıldı.", + "driveUnavailable": "Dosyaları yüklemeden önce RDP sürücü yönlendirmesini etkinleştirin.", + "driveNotWritable": "guacd sürücü klasörüne yazamıyor. GUACD_DRIVE_PATH (veya ana bilgisayarın Sürücü Yolu) ve izinlerini kontrol edin.", + "dropToUpload": "Yüklemek için dosyaları sürükleyip bırakın." + }, + "toolbar": { + "ctrlAltDel": "Ctrl+Alt+Del", + "winL": "Win+L (Ekranı Kilitle)", + "winKey": "Windows Tuşu", + "superL": "Süper+L (Kilit Ekranı)", + "superKey": "Süper Anahtar", + "super": "Süper", + "cmdL": "Cmd+L (Kilit Ekranı)", + "cmdKey": "Komut Tuşu", + "cmd": "Komut", + "ctrl": "Ctrl", + "alt": "Alt", + "shift": "Shift", + "win": "Win", + "stickyActive": "{{key}} (sabitlenmiş - bırakmak için tıklayın)", + "stickyInactive": "{{key}} (sabitlemek için tıklayın)", + "esc": "Escape", + "tab": "Tab", + "home": "Home", + "end": "End", + "pageUp": "Page Up", + "pageDown": "Page Down", + "arrowUp": "Yukarı Ok", + "arrowDown": "Aşağı Ok", + "arrowLeft": "Sol Ok", + "arrowRight": "Sağ Ok", + "fnToggle": "Fonksiyon Tuşları", + "reconnect": "Oturumu Yeniden Bağla", + "collapse": "Araç çubuğunu daralt", + "expand": "Araç çubuğunu genişlet", + "dragHandle": "Yeniden konumlandırmak için sürükle", + "hide": "Bu oturum için gizle. Kalıcı olarak devre dışı bırakmak için Sunucu Ayarları → Genel → Bağlantı Araç Çubuğu'nu açın.", + "zoomIn": "Yakınlaştır", + "zoomOut": "Uzaklaştır", + "resetZoom": "Yakınlaştırmayı sıfırla", + "fitToScreen": "Ekrana uygun", + "switchToTrackpad": "İzleme dörtlüsü moduna geçin (imleci hareket ettirmek için sürükleyin, tıklamak için dokunun)", + "switchToTouch": "Dokunmatik moda geçin (tıklamak istediğiniz yere doğrudan dokunun)" + } + }, + "hosts": { + "nativeRdpOpened": "Windows Uzaktan Masaüstü'nde açıldı", + "nativeRdpFailed": "Windows Uzaktan Masaüstü açılamadı.", + "openNativeRdp": "Windows Uzaktan Masaüstü'nde aç", + "guac": { + "connection": "Bağlantı", + "authentication": "Kimlik doğrulama", + "storedCredential": "Kayıtlı kimlik bilgisi", + "authMethod": "Kimlik doğrulama yöntemi", + "authTypeNoneDesc": "Hiçbir kimlik bilgisi saklanmaz. Her bağlantı kurduğunuzda sizden kullanıcı adı ve şifre istenecektir; bunlar kaydedilmez.", + "selectCredential": "Bir kimlik bilgisi seçin...", + "connectionSettings": "Bağlantı ayarları", + "displaySettings": "Görüntü ayarları", + "audioSettings": "Ses ayarları", + "rdpPerformance": "RDP performansı", + "deviceRedirection": "Cihaz yönlendirme", + "session": "Oturum", + "gateway": "Ağ geçidi", + "remoteApp": "RemoteApp", + "clipboard": "Pano", + "sessionRecording": "Oturum kaydı", + "wakeOnLan": "LAN üzerinden uyandırma", + "vncSettings": "VNC ayarları", + "terminalSettings": "Terminal ayarları", + "rdpPort": "RDP Portu", + "username": "Kullanıcı Adı", + "password": "Parola", + "passwordSaved": "Parola kaydedildi, değiştirmek için tuşlayın.", + "domain": "Etki Alanı", + "securityMode": "Güvenlik Modu", + "width": "Genişlik", + "height": "Yükseklik", + "dpi": "DPI", + "clientName": "İstemci Adı", + "initialProgram": "Başlangıç Programı", + "serverLayout": "Sunucu Düzeni", + "timezone": "Saat Dilimi", + "loadBalanceInfo": "Yük Dengeleme Bilgisi / Çerez", + "loadBalanceInfoDesc": "RDS grubu yük dengelemesi için RD Bağlantı Aracısı çerezi (ör. tsv://MS Terminal Services Plugin.1.CollectionName)", + "guacdProxy": "guacd Proxy", + "guacdHostname": "guacd Sunucusu", + "guacdHostnamePlaceholder": "Genel varsayılan", + "guacdPort": "guacd Portu", + "guacdProxyDesc": "Bu bağlantı için genel guacd örneğini geçersiz kıl. Genel olarak yapılandırılmış guacd'yi kullanmak için boş bırak.", + "gatewayHostname": "Ağ Geçidi Ana Bilgisayar Adı", + "gatewayPort": "Ağ Geçidi Portu", + "gatewayUsername": "Ağ Geçidi Kullanıcı Adı", + "gatewayPassword": "Ağ Geçidi Parolası", + "gatewayDomain": "Ağ Geçidi Etki Alanı", + "remoteAppProgram": "RemoteApp Programı", + "workingDirectory": "Çalışma Dizini", + "arguments": "Argümanlar", + "normalizeLineEndings": "Satır Sonlarını Normalleştir", + "macAddress": "MAC Adresi", + "broadcastAddress": "Yayın Adresi", + "udpPort": "UDP Portu", + "waitTimeS": "Bekleme Süresi (sn)", + "driveName": "Sürücü Adı", + "drivePath": "Sürücü Yolu", + "ignoreCertificate": "Sertifikayı Yoksay", + "ignoreCertificateDesc": "Kendinden imzalı sertifikalara sahip sunuculara bağlantılara izin ver", + "forceLossless": "Kayıpsız Zorla", + "forceLosslessDesc": "Kayıpsız görüntü kodlamasını zorla (daha yüksek kalite, daha fazla bant genişliği)", + "disableAudio": "Sesi Devre Dışı Bırak", + "disableAudioDesc": "Uzak oturumdaki tüm sesleri kapat", + "enableAudioInput": "Ses Girişini Etkinleştir (Mikrofon)", + "enableAudioInputDesc": "Yerel mikrofonu uzak oturuma yönlendir", + "wallpaper": "Duvar Kağıdı", + "wallpaperDesc": "Masaüstü duvar kağıdını göster (devre dışı bırakmak performansı artırır)", + "theming": "Tema", + "themingDesc": "Görsel temaları ve stilleri etkinleştir", + "fontSmoothing": "Yazı Tipi Yumuşatma", + "fontSmoothingDesc": "ClearType yazı tipi işlemeyi etkinleştir", + "fullWindowDrag": "Tam Pencere Sürükleme", + "fullWindowDragDesc": "Sürüklerken pencere içeriğini göster", + "desktopComposition": "Masaüstü Birleştirme", + "desktopCompositionDesc": "Aero cam efektlerini etkinleştir", + "menuAnimations": "Menü Animasyonları", + "menuAnimationsDesc": "Menü solma ve kayma animasyonlarını etkinleştir", + "disableBitmapCaching": "Bitmap Önbelleğini Devre Dışı Bırak", + "disableBitmapCachingDesc": "Bitmap önbelleğini kapat (grafik bozulmalarına yardımcı olabilir)", + "disableOffscreenCaching": "Ekran Dışı Önbelleğini Devre Dışı Bırak", + "disableOffscreenCachingDesc": "Ekran dışı önbelleğini kapat", + "disableGlyphCaching": "Glif Önbelleğini Devre Dışı Bırak", + "disableGlyphCachingDesc": "Glif önbelleğini kapat", + "enableGfx": "GFX'i Etkinleştir", + "enableGfxDesc": "RemoteFX grafik işlem hattını kullan", + "enablePrinting": "Yazdırmayı Etkinleştir", + "enablePrintingDesc": "Yerel yazıcıları uzak oturuma yönlendir", + "enableDriveRedirection": "Sürücü Yönlendirmesini Etkinleştir", + "enableDriveRedirectionDesc": "Yerel bir klasörü uzak oturumda sürücü olarak eşleştir", + "createDrivePath": "Sürücü Yolu Oluştur", + "createDrivePathDesc": "Klasör mevcut değilse otomatik oluştur", + "disableDownload": "İndirmeyi Devre Dışı Bırak", + "disableDownloadDesc": "Uzak oturumdan dosya indirmeyi engelle", + "disableUpload": "Yüklemeyi Devre Dışı Bırak", + "disableUploadDesc": "Uzak oturuma dosya yüklemeyi engelle", + "enableTouch": "Dokunmayı Etkinleştir", + "enableTouchDesc": "Dokunma girişi iletimini etkinleştir", + "consoleSession": "Konsol Oturumu", + "consoleSessionDesc": "Yeni oturum yerine konsola (oturum 0) bağlan", + "sendWolPacket": "WOL Paketi Gönder", + "sendWolPacketDesc": "Bağlanmadan önce bu sunucuyu uyandırmak için sihirli paket gönder", + "disableCopy": "Kopyalamayı Devre Dışı Bırak", + "disableCopyDesc": "Uzak oturumdan metin kopyalamayı engelle", + "disablePaste": "Yapıştırmayı Devre Dışı Bırak", + "disablePasteDesc": "Uzak oturuma metin yapıştırmayı engelle", + "createPathIfMissing": "Yol Yoksa Oluştur", + "createPathIfMissingDesc": "Kayıt dizinini otomatik oluştur", + "excludeOutput": "Çıktıyı Hariç Tut", + "excludeOutputDesc": "Ekran çıktısını kaydetme (yalnızca meta veri)", + "excludeMouse": "Fareyi Hariç Tut", + "excludeMouseDesc": "Fare hareketlerini kaydetme", + "includeKeystrokes": "Tuş Vuruşlarını Dahil Et", + "includeKeystrokesDesc": "Ekran çıktısına ek olarak ham tuş vuruşlarını kaydet", + "vncPort": "VNC Portu", + "vncPassword": "VNC Parolası", + "vncUsernameOptional": "Kullanıcı adı (isteğe bağlı)", + "vncLeaveBlank": "Gerekli değilse boş bırakın", + "cursorMode": "İmleç Modu", + "swapRedBlue": "Kırmızı ve Maviyi Değiştir", + "swapRedBlueDesc": "Kırmızı ve mavi renk kanallarını değiştir (bazı renk sorunlarını giderir)", + "readOnly": "Salt okunur", + "readOnlyDesc": "Hiçbir giriş göndermeden uzak ekranı görüntüle", + "telnetPort": "Telnet Portu", + "terminalType": "Terminal Türü", + "fontName": "Yazı Tipi Adı", + "fontSize": "Yazı Tipi Boyutu", + "colorScheme": "Renk Şeması", + "backspaceKey": "Geri Silme Tuşu" + } + }, + "onboarding": { + "feature_desktop": "Uzaktan masaüstü", + "feature_desktop_desc": "SSH'de olduğu gibi, RDP, VNC ve Telnet oturumlarını da bir sekmede açın." + } +} diff --git a/plugins/remote-desktop/locales/translated/uk_UA.json b/plugins/remote-desktop/locales/translated/uk_UA.json new file mode 100644 index 000000000..1f5c68279 --- /dev/null +++ b/plugins/remote-desktop/locales/translated/uk_UA.json @@ -0,0 +1,214 @@ +{ + "remoteDesktop": { + "connecting": "Підключення до сеансу {{type}}...", + "checkingGuacd": "Перевірка служби віддаленого робочого столу...", + "requestingToken": "Запитується токен з’єднання {{type}}...", + "openingSession": "Відкриття сеансу {{type}}...", + "negotiating": "Переговори {{type}} рукостискання...", + "sessionReady": "{{type}} сеанс готовий", + "connectionError": "Помилка підключення", + "connectionFailed": "Помилка підключення", + "failedToConnect": "Не вдалося отримати токен з'єднання", + "hostNotFound": "Хост не знайдено", + "noHostSelected": "Хост не вибрано", + "reconnect": "Знову підключитися", + "retry": "Повторити спробу", + "guacdUnavailable": "Служба віддаленого робочого столу (guacd) недоступна. Переконайтеся, що guacd запущено, доступно та правильно налаштовано в налаштуваннях адміністратора.", + "credentialPromptTitle": "Введіть облікові дані RDP", + "credentialPromptDescription": "Цей хост налаштовано на запит облікових даних під час підключення. Вони використовуються лише для цього сеансу та не зберігаються.", + "connect": "Підключитися", + "ctrlAltDel": "Ctrl+Alt+Del", + "files": { + "title": "Файли Диска", + "parent": "Батьківський каталог", + "refresh": "Оновити", + "empty": "Ця папка порожня", + "listFailed": "Не вдалося прочитати цю папку", + "download": "Завантажити", + "downloadFailed": "Не вдалося завантажити {{name}}", + "upload": "Завантажити файли", + "uploading": "Завантаження {{name}}...", + "uploaded": "Завантажено {{name}}", + "uploadFailed": "Не вдалося завантажити {{name}}", + "uploadDisabled": "Завантаження для цього з’єднання вимкнено", + "driveUnavailable": "Увімкніть перенаправлення диска RDP перед завантаженням файлів", + "driveNotWritable": "guacd не може записувати дані в папку диска. Перевірте GUACD_DRIVE_PATH (або шлях до диска хоста) та його дозволи.", + "dropToUpload": "Перетягніть файли для завантаження" + }, + "toolbar": { + "ctrlAltDel": "Ctrl+Alt+Del", + "winL": "Win+L (Екран блокування)", + "winKey": "Клавіша Windows", + "superL": "Супер+L (Екран блокування)", + "superKey": "Супер ключ", + "super": "Супер", + "cmdL": "Cmd+L (Екран блокування)", + "cmdKey": "Клавіша команди", + "cmd": "Команда", + "ctrl": "Ctrl", + "alt": "Альтернативний", + "shift": "Зсув", + "win": "Виграй", + "stickyActive": "{{key}} (зафіксовано - натисніть, щоб відпустити)", + "stickyInactive": "{{key}} (натисніть, щоб зафіксувати)", + "esc": "Втеча", + "tab": "Вкладка", + "home": "Дім", + "end": "Кінець", + "pageUp": "Сторінка вгору", + "pageDown": "Сторінка вниз", + "arrowUp": "Стрілка вгору", + "arrowDown": "Стрілка вниз", + "arrowLeft": "Стрілка ліворуч", + "arrowRight": "Стрілка праворуч", + "fnToggle": "Функціональні клавіші", + "reconnect": "Сеанс повторного підключення", + "collapse": "Згорнути панель інструментів", + "expand": "Розгорнути панель інструментів", + "dragHandle": "Перетягніть, щоб змінити положення", + "hide": "Приховати для цього сеансу. Щоб вимкнути його назавжди, відкрийте Параметри хоста → Загальні → Панель інструментів підключення.", + "zoomIn": "Збільшити масштаб", + "zoomOut": "Зменшити масштаб", + "resetZoom": "Скинути масштаб", + "fitToScreen": "Припасувати до екрана", + "switchToTrackpad": "Перехід у режим трекпада (перетягування для переміщення курсора, торкання для клацання)", + "switchToTouch": "Перемикання в сенсорний режим (торкайтеся безпосередньо там, де потрібно клацнути)" + } + }, + "hosts": { + "nativeRdpOpened": "Відкрито у віддаленому робочому столі Windows", + "nativeRdpFailed": "Не вдалося відкрити віддалений робочий стіл Windows", + "openNativeRdp": "Відкрити у віддаленому робочому столі Windows", + "guac": { + "connection": "З'єднання", + "authentication": "Автентифікація", + "storedCredential": "Збережені облікові дані", + "authMethod": "Метод автентифікації", + "authTypeNoneDesc": "Облікові дані не зберігаються. Вам буде запропоновано ввести ім’я користувача та пароль щоразу під час підключення; вони не зберігаються.", + "selectCredential": "Виберіть облікові дані...", + "connectionSettings": "Налаштування підключення", + "displaySettings": "Налаштування дисплея", + "audioSettings": "Налаштування аудіо", + "rdpPerformance": "Продуктивність RDP", + "deviceRedirection": "Перенаправлення пристрою", + "session": "Сесія", + "gateway": "Шлюз", + "remoteApp": "Віддалена програма", + "clipboard": "Буфер обміну", + "sessionRecording": "Запис сеансу", + "wakeOnLan": "Wake-on-LAN", + "vncSettings": "Налаштування VNC", + "terminalSettings": "Налаштування терміналу", + "rdpPort": "RDP-порт", + "username": "Ім'я користувача", + "password": "Пароль", + "passwordSaved": "Пароль збережено, введіть, щоб змінити", + "domain": "Домен", + "securityMode": "Режим безпеки", + "width": "Ширина", + "height": "Висота", + "dpi": "DPI", + "clientName": "Ім'я клієнта", + "initialProgram": "Початкова програма", + "serverLayout": "Макет сервера", + "timezone": "Часовий пояс", + "loadBalanceInfo": "Інформація про балансування навантаження / файли cookie", + "loadBalanceInfoDesc": "Файл cookie брокера підключень до робочого столу для балансування навантаження ферми RDS (наприклад, tsv://MS Terminal Services Plugin.1.CollectionName)", + "guacdProxy": "Проксі-сервер guacd", + "guacdHostname": "Хост guacd", + "guacdHostnamePlaceholder": "Глобальний за замовчуванням", + "guacdPort": "Порт GUACD", + "guacdProxyDesc": "Перевизначте глобальний екземпляр guacd для цього з’єднання. Залиште поле порожнім, щоб використовувати глобально налаштований guacd.", + "gatewayHostname": "Ім'я хоста шлюзу", + "gatewayPort": "Порт шлюзу", + "gatewayUsername": "Ім'я користувача шлюзу", + "gatewayPassword": "Пароль шлюзу", + "gatewayDomain": "Домен шлюзу", + "remoteAppProgram": "Програма віддалених додатків", + "workingDirectory": "Робочий каталог", + "arguments": "Аргументи", + "normalizeLineEndings": "Нормалізувати закінчення рядків", + "macAddress": "MAC-адреса", + "broadcastAddress": "Адреса розсилки", + "udpPort": "UDP-порт", + "waitTimeS": "Час очікування (с)", + "driveName": "Назва диска", + "drivePath": "Шлях диска", + "ignoreCertificate": "Ігнорувати сертифікат", + "ignoreCertificateDesc": "Дозволити підключення до хостів із самопідписаними сертифікатами", + "forceLossless": "Примусово без втрат", + "forceLosslessDesc": "Примусове кодування зображень без втрат (вища якість, більша пропускна здатність)", + "disableAudio": "Вимкнути аудіо", + "disableAudioDesc": "Вимкнути весь звук під час віддаленого сеансу", + "enableAudioInput": "Увімкнути аудіовхід (мікрофон)", + "enableAudioInputDesc": "Переадресація локального мікрофона на віддалений сеанс", + "wallpaper": "Шпалери", + "wallpaperDesc": "Показувати шпалери робочого столу (вимикання покращує продуктивність)", + "theming": "Тематизація", + "themingDesc": "Увімкнути візуальні теми та стилі", + "fontSmoothing": "Згладжування шрифтів", + "fontSmoothingDesc": "Увімкнути рендеринг шрифтів ClearType", + "fullWindowDrag": "Повне перетягування вікна", + "fullWindowDragDesc": "Відображати вміст вікна під час перетягування", + "desktopComposition": "Композиція робочого столу", + "desktopCompositionDesc": "Увімкнути ефекти Aero Glass", + "menuAnimations": "Анімації меню", + "menuAnimationsDesc": "Увімкнути анімацію згасання меню та слайдів", + "disableBitmapCaching": "Вимкнути кешування растрових зображень", + "disableBitmapCachingDesc": "Вимкніть кеш растрових зображень (може допомогти з глюками)", + "disableOffscreenCaching": "Вимкнути кешування поза екраном", + "disableOffscreenCachingDesc": "Вимкнути кеш поза екраном", + "disableGlyphCaching": "Вимкнути кешування гліфів", + "disableGlyphCachingDesc": "Вимкнути кеш гліфів", + "enableGfx": "Увімкнути графічні ефекти", + "enableGfxDesc": "Використовуйте графічний конвеєр RemoteFX", + "enablePrinting": "Увімкнути друк", + "enablePrintingDesc": "Перенаправити локальні принтери на віддалений сеанс", + "enableDriveRedirection": "Увімкнути перенаправлення диска", + "enableDriveRedirectionDesc": "Призначення локальної папки як диска у віддаленому сеансі", + "createDrivePath": "Створити шлях до диска", + "createDrivePathDesc": "Автоматично створювати папку, якщо її не існує", + "disableDownload": "Вимкнути завантаження", + "disableDownloadDesc": "Заборонити завантаження файлів з віддаленого сеансу", + "disableUpload": "Вимкнути завантаження", + "disableUploadDesc": "Заборонити завантаження файлів у віддалений сеанс", + "enableTouch": "Увімкнути сенсорний режим", + "enableTouchDesc": "Увімкнути переадресацію сенсорного введення", + "consoleSession": "Сеанс консолі", + "consoleSessionDesc": "Підключення до консолі (сеанс 0) замість нового сеансу", + "sendWolPacket": "Надіслати пакет WOL", + "sendWolPacketDesc": "Надіслати магічний пакет, щоб розбудити цей хост перед підключенням", + "disableCopy": "Вимкнути копіювання", + "disableCopyDesc": "Запобігти копіюванню тексту з віддаленого сеансу", + "disablePaste": "Вимкнути вставку", + "disablePasteDesc": "Запобігти вставці тексту у віддалений сеанс", + "createPathIfMissing": "Створити шлях, якщо він відсутній", + "createPathIfMissingDesc": "Автоматично створити каталог записів", + "excludeOutput": "Виключити вивід", + "excludeOutputDesc": "Не записувати вивід екрана (лише метадані)", + "excludeMouse": "Виключити мишу", + "excludeMouseDesc": "Не записувати рухи миші", + "includeKeystrokes": "Включити натискання клавіш", + "includeKeystrokesDesc": "Записуйте необроблені натискання клавіш на додаток до виводу на екран", + "vncPort": "VNC-порт", + "vncPassword": "Пароль VNC", + "vncUsernameOptional": "Ім'я користувача (необов'язково)", + "vncLeaveBlank": "Залиште порожнім, якщо не потрібно", + "cursorMode": "Режим курсора", + "swapRedBlue": "Поміняйте місцями червоний/синій", + "swapRedBlueDesc": "Поміняти місцями червоний та синій кольорові канали (виправляє деякі проблеми з кольором)", + "readOnly": "Тільки для читання", + "readOnlyDesc": "Перегляд віддаленого екрана без надсилання будь-яких вхідних даних", + "telnetPort": "Порт Telnet", + "terminalType": "Тип терміналу", + "fontName": "Назва шрифту", + "fontSize": "Розмір шрифту", + "colorScheme": "Колірна схема", + "backspaceKey": "Клавіша Backspace" + } + }, + "onboarding": { + "feature_desktop": "Віддалений робочий стіл", + "feature_desktop_desc": "Відкривати сеанси RDP, VNC та Telnet у вкладці, так само, як SSH." + } +} diff --git a/plugins/remote-desktop/locales/translated/vi_VN.json b/plugins/remote-desktop/locales/translated/vi_VN.json new file mode 100644 index 000000000..c7c5a87ab --- /dev/null +++ b/plugins/remote-desktop/locales/translated/vi_VN.json @@ -0,0 +1,214 @@ +{ + "remoteDesktop": { + "connecting": "Đang kết nối đến phiên {{type}}...", + "checkingGuacd": "Kiểm tra dịch vụ máy tính từ xa...", + "requestingToken": "Yêu cầu mã thông báo kết nối {{type}}...", + "openingSession": "Khai mạc phiên {{type}}...", + "negotiating": "Đàm phán bằng cái bắt tay {{type}}...", + "sessionReady": "{{type}} phiên đã sẵn sàng", + "connectionError": "Lỗi kết nối", + "connectionFailed": "Kết nối thất bại", + "failedToConnect": "Không lấy được mã token kết nối", + "hostNotFound": "Không tìm thấy máy chủ", + "noHostSelected": "Chưa chọn máy chủ", + "reconnect": "Kết nối lại", + "retry": "Thử lại", + "guacdUnavailable": "Dịch vụ máy tính từ xa (guacd) không khả dụng. Vui lòng đảm bảo guacd đang chạy, có thể truy cập và được cấu hình đúng trong cài đặt quản trị.", + "credentialPromptTitle": "Nhập thông tin đăng nhập RDP", + "credentialPromptDescription": "Máy chủ này được thiết lập để yêu cầu thông tin đăng nhập khi kết nối. Thông tin này chỉ được sử dụng cho phiên này và không được lưu lại.", + "connect": "Kết nối", + "ctrlAltDel": "Ctrl+Alt+Del", + "files": { + "title": "Tệp ổ đĩa", + "parent": "Thư mục cha", + "refresh": "Làm cho khỏe lại", + "empty": "Thư mục này trống", + "listFailed": "Không thể đọc thư mục này.", + "download": "Tải xuống", + "downloadFailed": "Tải xuống không thành công {{name}}", + "upload": "Tải lên tệp", + "uploading": "Đang tải lên {{name}}...", + "uploaded": "Đã tải lên {{name}}", + "uploadFailed": "Tải lên không thành công {{name}}", + "uploadDisabled": "Chức năng tải lên đã bị vô hiệu hóa cho kết nối này.", + "driveUnavailable": "Hãy bật tính năng chuyển hướng ổ đĩa RDP trước khi tải lên tệp.", + "driveNotWritable": "guacd không thể ghi vào thư mục ổ đĩa. Hãy kiểm tra GUACD_DRIVE_PATH (hoặc Đường dẫn ổ đĩa của máy chủ) và quyền truy cập của nó.", + "dropToUpload": "Kéo thả tệp để tải lên" + }, + "toolbar": { + "ctrlAltDel": "Ctrl+Alt+Del", + "winL": "Win+L (Khóa màn hình)", + "winKey": "Phím Windows", + "superL": "Super+L (Màn hình khóa)", + "superKey": "Siêu chìa khóa", + "super": "Siêu", + "cmdL": "Cmd+L (Khóa màn hình)", + "cmdKey": "Phím lệnh", + "cmd": "Lệnh", + "ctrl": "Ctrl", + "alt": "Alt", + "shift": "Shift", + "win": "Win", + "stickyActive": "{{key}} (đang giữ - nhấn để nhả)", + "stickyInactive": "{{key}} (nhấn để giữ)", + "esc": "Escape", + "tab": "Tab", + "home": "Home", + "end": "End", + "pageUp": "Page Up", + "pageDown": "Page Down", + "arrowUp": "Arrow Up", + "arrowDown": "Arrow Down", + "arrowLeft": "Arrow Left", + "arrowRight": "Arrow Right", + "fnToggle": "Phím chức năng", + "reconnect": "Kết nối lại phiên", + "collapse": "Thu gọn thanh công cụ", + "expand": "Mở rộng thanh công cụ", + "dragHandle": "Kéo để di chuyển", + "hide": "Ẩn tùy chọn này trong phiên làm việc hiện tại. Để tắt vĩnh viễn, hãy mở Cài đặt máy chủ → Chung → Thanh công cụ kết nối.", + "zoomIn": "Phóng to", + "zoomOut": "Thu nhỏ", + "resetZoom": "Đặt lại thu phóng", + "fitToScreen": "Vừa với màn hình", + "switchToTrackpad": "Chuyển sang chế độ bàn di chuột (kéo để di chuyển con trỏ, chạm để nhấp chuột)", + "switchToTouch": "Chuyển sang chế độ cảm ứng (chạm trực tiếp vào vị trí bạn muốn nhấp chuột)" + } + }, + "hosts": { + "nativeRdpOpened": "Đã mở bằng Windows Remote Desktop", + "nativeRdpFailed": "Không thể mở Windows Remote Desktop", + "openNativeRdp": "Mở bằng Windows Remote Desktop", + "guac": { + "connection": "Kết nối", + "authentication": "Xác thực", + "storedCredential": "Thông tin xác thực đã lưu", + "authMethod": "Phương thức xác thực", + "authTypeNoneDesc": "Thông tin đăng nhập của bạn không được lưu trữ. Bạn sẽ được yêu cầu nhập tên người dùng và mật khẩu mỗi khi kết nối; chúng không được lưu lại.", + "selectCredential": "Chọn thông tin xác thực...", + "connectionSettings": "Cài đặt kết nối", + "displaySettings": "Cài đặt hiển thị", + "audioSettings": "Cài đặt âm thanh", + "rdpPerformance": "Hiệu suất RDP", + "deviceRedirection": "Chuyển hướng thiết bị", + "session": "Phiên làm việc", + "gateway": "Gateway", + "remoteApp": "RemoteApp", + "clipboard": "Clipboard", + "sessionRecording": "Ghi phiên", + "wakeOnLan": "Wake-on-LAN", + "vncSettings": "Cài đặt VNC", + "terminalSettings": "Cài đặt Terminal", + "rdpPort": "Cổng RDP", + "username": "Tên người dùng", + "password": "Mật khẩu", + "passwordSaved": "Mật khẩu đã được lưu, nhập để thay đổi", + "domain": "Miền", + "securityMode": "Chế độ bảo mật", + "width": "Chiều rộng", + "height": "Chiều cao", + "dpi": "DPI", + "clientName": "Tên máy khách", + "initialProgram": "Chương trình ban đầu", + "serverLayout": "Bố cục máy chủ", + "timezone": "Múi giờ", + "loadBalanceInfo": "Thông tin cân bằng tải / Cookie", + "loadBalanceInfoDesc": "Cookie RD Connection Broker dùng cho cân bằng tải cụm RDS (vd: tsv://MS Terminal Services Plugin.1.CollectionName)", + "guacdProxy": "Proxy guacd", + "guacdHostname": "Máy chủ guacd", + "guacdHostnamePlaceholder": "Mặc định toàn cục", + "guacdPort": "Cổng guacd", + "guacdProxyDesc": "Ghi đè phiên bản guacd toàn cục cho kết nối này. Để trống để sử dụng guacd được cấu hình toàn cục.", + "gatewayHostname": "Tên máy chủ gateway", + "gatewayPort": "Cổng gateway", + "gatewayUsername": "Tên người dùng gateway", + "gatewayPassword": "Mật khẩu gateway", + "gatewayDomain": "Miền gateway", + "remoteAppProgram": "Chương trình RemoteApp", + "workingDirectory": "Thư mục làm việc", + "arguments": "Tham số", + "normalizeLineEndings": "Chuẩn hóa kết thúc dòng", + "macAddress": "Địa chỉ MAC", + "broadcastAddress": "Địa chỉ broadcast", + "udpPort": "Cổng UDP", + "waitTimeS": "Thời gian chờ (s)", + "driveName": "Tên ổ đĩa", + "drivePath": "Đường dẫn ổ đĩa", + "ignoreCertificate": "Bỏ qua chứng chỉ", + "ignoreCertificateDesc": "Cho phép kết nối đến máy chủ có chứng chỉ tự ký", + "forceLossless": "Ép buộc Lossless", + "forceLosslessDesc": "Ép buộc mã hóa ảnh không mất dữ liệu (chất lượng cao hơn, tốn băng thông)", + "disableAudio": "Tắt âm thanh", + "disableAudioDesc": "Tắt tất cả âm thanh từ phiên từ xa", + "enableAudioInput": "Bật đầu vào âm thanh (micro)", + "enableAudioInputDesc": "Chuyển tiếp micro cục bộ đến phiên từ xa", + "wallpaper": "Hình nền", + "wallpaperDesc": "Hiển thị hình nền desktop (tắt để cải thiện hiệu suất)", + "theming": "Chủ đề", + "themingDesc": "Bật chủ đề và kiểu dáng trực quan", + "fontSmoothing": "Làm mịn phông chữ", + "fontSmoothingDesc": "Bật kết xuất phông chữ ClearType", + "fullWindowDrag": "Kéo toàn bộ cửa sổ", + "fullWindowDragDesc": "Hiển thị nội dung cửa sổ khi kéo", + "desktopComposition": "Tổ hợp màn hình nền", + "desktopCompositionDesc": "Bật hiệu ứng kính Aero", + "menuAnimations": "Hiệu ứng menu", + "menuAnimationsDesc": "Bật hiệu ứng mờ và trượt của menu", + "disableBitmapCaching": "Tắt bộ nhớ đệm bitmap", + "disableBitmapCachingDesc": "Tắt bộ nhớ đệm bitmap (có thể giúp tránh lỗi hiển thị)", + "disableOffscreenCaching": "Tắt bộ nhớ đệm ngoài màn hình", + "disableOffscreenCachingDesc": "Tắt bộ nhớ đệm ngoài màn hình", + "disableGlyphCaching": "Tắt bộ nhớ đệm glyph", + "disableGlyphCachingDesc": "Tắt bộ nhớ đệm glyph", + "enableGfx": "Bật GFX", + "enableGfxDesc": "Sử dụng pipeline đồ họa RemoteFX", + "enablePrinting": "Bật in", + "enablePrintingDesc": "Chuyển hướng máy in cục bộ đến phiên từ xa", + "enableDriveRedirection": "Bật chuyển hướng ổ đĩa", + "enableDriveRedirectionDesc": "Ánh xạ thư mục cục bộ thành ổ đĩa trong phiên từ xa", + "createDrivePath": "Tạo đường dẫn ổ đĩa", + "createDrivePathDesc": "Tự động tạo thư mục nếu chưa tồn tại", + "disableDownload": "Tắt tải xuống", + "disableDownloadDesc": "Ngăn tải file từ phiên từ xa", + "disableUpload": "Tắt tải lên", + "disableUploadDesc": "Ngăn tải file lên phiên từ xa", + "enableTouch": "Bật cảm ứng", + "enableTouchDesc": "Bật chuyển tiếp đầu vào cảm ứng", + "consoleSession": "Phiên console", + "consoleSessionDesc": "Kết nối tới console (phiên 0) thay vì phiên mới", + "sendWolPacket": "Gửi gói WOL", + "sendWolPacketDesc": "Gửi gói magic để đánh thức máy trước khi kết nối", + "disableCopy": "Tắt sao chép", + "disableCopyDesc": "Ngăn sao chép văn bản từ phiên từ xa", + "disablePaste": "Tắt dán", + "disablePasteDesc": "Ngăn dán văn bản vào phiên từ xa", + "createPathIfMissing": "Tạo đường dẫn nếu thiếu", + "createPathIfMissingDesc": "Tự động tạo thư mục ghi hình", + "excludeOutput": "Loại trừ đầu ra", + "excludeOutputDesc": "Không ghi hình màn hình (chỉ metadata)", + "excludeMouse": "Loại trừ chuột", + "excludeMouseDesc": "Không ghi lại chuyển động chuột", + "includeKeystrokes": "Bao gồm thao tác phím", + "includeKeystrokesDesc": "Ghi lại thao tác phím thô cùng với đầu ra màn hình", + "vncPort": "Cổng VNC", + "vncPassword": "Mật khẩu VNC", + "vncUsernameOptional": "Tên người dùng (tùy chọn)", + "vncLeaveBlank": "Để trống nếu không cần", + "cursorMode": "Chế độ con trỏ", + "swapRedBlue": "Hoán đổi Đỏ/Xanh", + "swapRedBlueDesc": "Hoán đổi kênh màu đỏ và xanh (khắc phục một số lỗi màu)", + "readOnly": "Chỉ đọc", + "readOnlyDesc": "Xem màn hình từ xa mà không gửi đầu vào", + "telnetPort": "Cổng Telnet", + "terminalType": "Loại terminal", + "fontName": "Tên phông chữ", + "fontSize": "Cỡ chữ", + "colorScheme": "Bảng màu", + "backspaceKey": "Phím Backspace" + } + }, + "onboarding": { + "feature_desktop": "Máy tính từ xa", + "feature_desktop_desc": "Mở các phiên RDP, VNC và Telnet trong cùng một tab, tương tự như SSH." + } +} diff --git a/plugins/remote-desktop/locales/translated/zh_CN.json b/plugins/remote-desktop/locales/translated/zh_CN.json new file mode 100644 index 000000000..8c0bfff1f --- /dev/null +++ b/plugins/remote-desktop/locales/translated/zh_CN.json @@ -0,0 +1,214 @@ +{ + "remoteDesktop": { + "connecting": "正在连接到 {{type}} 会话...", + "checkingGuacd": "正在检查远程桌面服务...", + "requestingToken": "Requesting {{type}} connection token...", + "openingSession": "正在开启 {{type}} 会话...", + "negotiating": "Negotiating {{type}} handshake...", + "sessionReady": "{{type}} 会话已准备就绪", + "connectionError": "连接错误", + "connectionFailed": "连接失败", + "failedToConnect": "获取连接令牌失败", + "hostNotFound": "未找到主机", + "noHostSelected": "未选择主机", + "reconnect": "重新连接", + "retry": "重试", + "guacdUnavailable": "远程桌面服务 (guacd) 不可用。请确保 guacd 正在运行并可访问,且在管理设置中正确配置。", + "credentialPromptTitle": "输入 RDP 凭据", + "credentialPromptDescription": "此主机设置为在连接时提示输入凭据。这些凭据仅用于当前会话,不会被保存。", + "connect": "连接", + "ctrlAltDel": "Ctrl+Alt+Del", + "files": { + "title": "驱动器文件", + "parent": "父目录", + "refresh": "刷新", + "empty": "此文件夹为空。", + "listFailed": "读取此文件夹失败", + "download": "下载", + "downloadFailed": "下载失败 {{name}}", + "upload": "上传文件", + "uploading": "正在上传 {{name}}...", + "uploaded": "已上传 {{name}}", + "uploadFailed": "上传失败 {{name}}", + "uploadDisabled": "此连接已禁用上传功能", + "driveUnavailable": "上传文件前启用 RDP 驱动器重定向", + "driveNotWritable": "guacd 无法写入驱动器文件夹。请检查 GUACD_DRIVE_PATH(或主机驱动器路径)及其权限。", + "dropToUpload": "拖放文件即可上传" + }, + "toolbar": { + "ctrlAltDel": "Ctrl+Alt+Del", + "winL": "Win+L (锁定屏幕)", + "winKey": "Windows 键", + "superL": "Super+L(锁屏)", + "superKey": "超级密钥", + "super": "极好的", + "cmdL": "Cmd+L(锁屏)", + "cmdKey": "命令键", + "cmd": "命令", + "ctrl": "Ctrl", + "alt": "Alt", + "shift": "Shift", + "win": "Win", + "stickyActive": "{{key}}(已锁定 - 点击释放)", + "stickyInactive": "{{key}}(点击锁定)", + "esc": "Escape", + "tab": "Tab", + "home": "Home", + "end": "End", + "pageUp": "Page Up", + "pageDown": "Page Down", + "arrowUp": "Arrow Up", + "arrowDown": "Arrow Down", + "arrowLeft": "Arrow Left", + "arrowRight": "Arrow Right", + "fnToggle": "功能键", + "reconnect": "重新连接会话", + "collapse": "折叠工具栏", + "expand": "展开工具栏", + "dragHandle": "拖动以重新定位", + "hide": "本次会话期间隐藏。要永久禁用,请打开“主机设置”→“常规”→“连接工具栏”。", + "zoomIn": "放大", + "zoomOut": "缩小", + "resetZoom": "重置缩放", + "fitToScreen": "适应屏幕", + "switchToTrackpad": "切换到触控板模式(拖动移动光标,轻点进行点击)", + "switchToTouch": "切换到触摸模式(直接点击你想点击的地方)" + } + }, + "hosts": { + "nativeRdpOpened": "在 Windows 远程桌面中打开", + "nativeRdpFailed": "无法打开 Windows 远程桌面", + "openNativeRdp": "在 Windows 远程桌面中打开", + "guac": { + "connection": "连接", + "authentication": "认证", + "storedCredential": "已存储凭据", + "authMethod": "认证方法", + "authTypeNoneDesc": "不会存储任何凭据。每次连接时,系统都会提示您输入用户名和密码;这些信息不会被保存。", + "selectCredential": "选择凭据...", + "connectionSettings": "连接设置", + "displaySettings": "显示设置", + "audioSettings": "音频设置", + "rdpPerformance": "RDP 性能", + "deviceRedirection": "设备重定向", + "session": "会话", + "gateway": "网关", + "remoteApp": "RemoteApp", + "clipboard": "剪贴板", + "sessionRecording": "会话录制", + "wakeOnLan": "网络唤醒", + "vncSettings": "VNC 设置", + "terminalSettings": "终端设置", + "rdpPort": "RDP 端口", + "username": "用户名", + "password": "密码", + "passwordSaved": "密码已保存,输入即可更改", + "domain": "域", + "securityMode": "安全模式", + "width": "宽度", + "height": "高度", + "dpi": "DPI", + "clientName": "客户端名称", + "initialProgram": "初始程序", + "serverLayout": "服务器布局", + "timezone": "时区", + "loadBalanceInfo": "负载均衡信息 / Cookie", + "loadBalanceInfoDesc": "RD 连接代理 Cookie,用于 RDS 场负载均衡(例如 tsv://MS Terminal Services Plugin.1.CollectionName)", + "guacdProxy": "guacd 代理", + "guacdHostname": "guacd 主机", + "guacdHostnamePlaceholder": "全局默认", + "guacdPort": "guacd 端口", + "guacdProxyDesc": "为此连接覆盖全局 guacd 实例。留空则使用全局配置的 guacd。", + "gatewayHostname": "网关主机名", + "gatewayPort": "网关端口", + "gatewayUsername": "网关用户名", + "gatewayPassword": "网关密码", + "gatewayDomain": "网关域", + "remoteAppProgram": "RemoteApp 程序", + "workingDirectory": "工作目录", + "arguments": "参数", + "normalizeLineEndings": "规范化行尾", + "macAddress": "MAC 地址", + "broadcastAddress": "广播地址", + "udpPort": "UDP 端口", + "waitTimeS": "等待时间(秒)", + "driveName": "驱动器名称", + "drivePath": "驱动器路径", + "ignoreCertificate": "忽略证书", + "ignoreCertificateDesc": "允许连接到具有自签名证书的主机", + "forceLossless": "强制无损", + "forceLosslessDesc": "强制无损图像编码(质量更高,占用更多带宽)", + "disableAudio": "禁用音频", + "disableAudioDesc": "将远程会话的所有音频静音", + "enableAudioInput": "启用音频输入(麦克风)", + "enableAudioInputDesc": "将本地麦克风转发到远程会话", + "wallpaper": "壁纸", + "wallpaperDesc": "显示桌面壁纸(禁用可提高性能)", + "theming": "主题", + "themingDesc": "启用视觉主题和样式", + "fontSmoothing": "字体平滑", + "fontSmoothingDesc": "启用 ClearType 字体渲染", + "fullWindowDrag": "全窗口拖动", + "fullWindowDragDesc": "拖动时显示窗口内容", + "desktopComposition": "桌面合成", + "desktopCompositionDesc": "启用 Aero 玻璃效果", + "menuAnimations": "菜单动画", + "menuAnimationsDesc": "启用菜单淡入淡出与滑动动画", + "disableBitmapCaching": "禁用位图缓存", + "disableBitmapCachingDesc": "关闭位图缓存(可能有助于解决显示故障)", + "disableOffscreenCaching": "禁用离屏缓存", + "disableOffscreenCachingDesc": "关闭离屏缓存", + "disableGlyphCaching": "禁用字形缓存", + "disableGlyphCachingDesc": "关闭字形缓存", + "enableGfx": "启用 GFX", + "enableGfxDesc": "使用 RemoteFX 图形管道", + "enablePrinting": "启用打印", + "enablePrintingDesc": "将本地打印机重定向到远程会话", + "enableDriveRedirection": "启用驱动器重定向", + "enableDriveRedirectionDesc": "将本地文件夹映射为远程会话中的驱动器", + "createDrivePath": "创建驱动器路径", + "createDrivePathDesc": "如果文件夹不存在,则自动创建", + "disableDownload": "禁用下载", + "disableDownloadDesc": "禁止从远程会话下载文件", + "disableUpload": "禁用上传", + "disableUploadDesc": "禁止上传文件到远程会话", + "enableTouch": "启用触控", + "enableTouchDesc": "启用触控输入转发", + "consoleSession": "控制台会话", + "consoleSessionDesc": "连接到控制台(会话 0)而不是新会话", + "sendWolPacket": "发送 WOL 数据包", + "sendWolPacketDesc": "在连接前发送魔术包以唤醒此主机", + "disableCopy": "禁用复制", + "disableCopyDesc": "禁止从远程会话复制文本", + "disablePaste": "禁用粘贴", + "disablePasteDesc": "禁止粘贴文本到远程会话", + "createPathIfMissing": "如果路径不存在则创建", + "createPathIfMissingDesc": "自动创建录制目录", + "excludeOutput": "排除输出", + "excludeOutputDesc": "不录制屏幕输出(仅元数据)", + "excludeMouse": "排除鼠标", + "excludeMouseDesc": "不录制鼠标移动", + "includeKeystrokes": "包含击键", + "includeKeystrokesDesc": "除了屏幕输出外,还录制原始击键", + "vncPort": "VNC 端口", + "vncPassword": "VNC 密码", + "vncUsernameOptional": "用户名 (可选)", + "vncLeaveBlank": "如不需要请留空", + "cursorMode": "光标模式", + "swapRedBlue": "交换红/蓝", + "swapRedBlueDesc": "交换红蓝色彩通道 (可修复某些色彩问题)", + "readOnly": "只读", + "readOnlyDesc": "仅查看远程屏幕,不发送任何输入", + "telnetPort": "Telnet 端口", + "terminalType": "终端类型", + "fontName": "字体名称", + "fontSize": "字体大小", + "colorScheme": "配色方案", + "backspaceKey": "退格键" + } + }, + "onboarding": { + "feature_desktop": "远程桌面", + "feature_desktop_desc": "像 SSH 一样,在标签页中直接打开 RDP、VNC 和 Telnet 会话。" + } +} diff --git a/plugins/remote-desktop/locales/translated/zh_TW.json b/plugins/remote-desktop/locales/translated/zh_TW.json new file mode 100644 index 000000000..c42952320 --- /dev/null +++ b/plugins/remote-desktop/locales/translated/zh_TW.json @@ -0,0 +1,214 @@ +{ + "remoteDesktop": { + "connecting": "正在連線至 {{type}} 工作階段…", + "checkingGuacd": "正在檢查遠端桌面服務...", + "requestingToken": "Requesting {{type}} connection token...", + "openingSession": "正在開啟 {{type}} 會話...", + "negotiating": "Negotiating {{type}} handshake...", + "sessionReady": "{{type}} 會話已準備就緒", + "connectionError": "連線錯誤", + "connectionFailed": "連線失敗", + "failedToConnect": "無法取得連線權杖", + "hostNotFound": "找不到主機", + "noHostSelected": "未選取主機", + "reconnect": "重新連線", + "retry": "重試", + "guacdUnavailable": "遠端桌面服務 (guacd) 無法使用。請確保 guacd 正在執行且可存取,並已在管理員設定中正確設定。", + "credentialPromptTitle": "輸入 RDP 憑證", + "credentialPromptDescription": "此主機設定為在連線時提示輸入憑證。這些憑證僅用於當前會話,不會被儲存。", + "connect": "連接", + "ctrlAltDel": "Ctrl+Alt+Del", + "files": { + "title": "磁碟機檔案", + "parent": "父目錄", + "refresh": "重新整理", + "empty": "此資料夾為空。", + "listFailed": "讀取此資料夾失敗", + "download": "下載", + "downloadFailed": "下載失敗 {{name}}", + "upload": "上傳文件", + "uploading": "正在上傳 {{name}}...", + "uploaded": "已上傳 {{name}}", + "uploadFailed": "上傳失敗 {{name}}", + "uploadDisabled": "此連線已停用上傳功能", + "driveUnavailable": "上傳檔案前啟用 RDP 磁碟機重定向", + "driveNotWritable": "guacd 無法寫入磁碟機資料夾。請檢查 GUACD_DRIVE_PATH(或主機磁碟機路徑)及其權限。", + "dropToUpload": "拖放檔案即可上傳" + }, + "toolbar": { + "ctrlAltDel": "Ctrl+Alt+Del", + "winL": "Win+L (鎖定螢幕)", + "winKey": "Windows 鍵", + "superL": "Super+L(鎖定畫面)", + "superKey": "超級鑰匙", + "super": "極佳的", + "cmdL": "Cmd+L(鎖定畫面)", + "cmdKey": "命令鍵", + "cmd": "命令", + "ctrl": "Ctrl", + "alt": "Alt", + "shift": "Shift", + "win": "Win", + "stickyActive": "{{key}} (已鎖定 - 點擊釋放)", + "stickyInactive": "{{key}} (點擊鎖定)", + "esc": "Escape", + "tab": "Tab", + "home": "Home", + "end": "End", + "pageUp": "Page Up", + "pageDown": "Page Down", + "arrowUp": "向上鍵", + "arrowDown": "向下鍵", + "arrowLeft": "向左鍵", + "arrowRight": "向右鍵", + "fnToggle": "功能鍵", + "reconnect": "重新連線工作階段", + "collapse": "收合工具列", + "expand": "展開工具列", + "dragHandle": "拖曳以重新定位", + "hide": "本次會話期間隱藏。若要永久停用,請開啟「主機設定」→「一般」→「連線工具列」。", + "zoomIn": "放大", + "zoomOut": "縮小", + "resetZoom": "重置縮放", + "fitToScreen": "適應螢幕", + "switchToTrackpad": "切換到觸控板模式(拖曳移動遊標,點擊點擊)", + "switchToTouch": "切換到觸控模式(直接點擊你想點擊的地方)" + } + }, + "hosts": { + "nativeRdpOpened": "在 Windows 遠端桌面中開啟", + "nativeRdpFailed": "無法開啟 Windows 遠端桌面", + "openNativeRdp": "在 Windows 遠端桌面中開啟", + "guac": { + "connection": "連線", + "authentication": "驗證", + "storedCredential": "已儲存的憑證", + "authMethod": "驗證方法", + "authTypeNoneDesc": "不會儲存任何憑證。每次連線時,系統都會提示您輸入使用者名稱和密碼;這些資訊不會被儲存。", + "selectCredential": "選取憑證…", + "connectionSettings": "連線設定", + "displaySettings": "顯示設定", + "audioSettings": "音訊設定", + "rdpPerformance": "RDP 效能", + "deviceRedirection": "裝置重新導向", + "session": "工作階段", + "gateway": "閘道", + "remoteApp": "RemoteApp", + "clipboard": "剪貼簿", + "sessionRecording": "工作階段錄製", + "wakeOnLan": "Wake-on-LAN", + "vncSettings": "VNC 設定", + "terminalSettings": "終端機設定", + "rdpPort": "RDP 連接埠", + "username": "使用者名稱", + "password": "密碼", + "passwordSaved": "密碼已儲存,輸入即可更改", + "domain": "網域", + "securityMode": "安全模式", + "width": "寬度", + "height": "高度", + "dpi": "DPI", + "clientName": "用戶端名稱", + "initialProgram": "初始程式", + "serverLayout": "伺服器鍵盤配置", + "timezone": "時區", + "loadBalanceInfo": "負載平衡資訊 / Cookie", + "loadBalanceInfoDesc": "用於 RDS 伺服器陣列負載平衡的 RD 連線代理 Cookie (例如 tsv://MS Terminal Services Plugin.1.CollectionName)", + "guacdProxy": "guacd 代理", + "guacdHostname": "guacd 主機", + "guacdHostnamePlaceholder": "全域預設", + "guacdPort": "guacd 連接埠", + "guacdProxyDesc": "覆寫此連線的全域 guacd 執行個體。留空以使用全域設定的 guacd。", + "gatewayHostname": "閘道主機名稱", + "gatewayPort": "閘道連接埠", + "gatewayUsername": "閘道使用者名稱", + "gatewayPassword": "閘道密碼", + "gatewayDomain": "閘道網域", + "remoteAppProgram": "RemoteApp 程式", + "workingDirectory": "工作目錄", + "arguments": "引數", + "normalizeLineEndings": "正規化行尾符號", + "macAddress": "MAC 位址", + "broadcastAddress": "廣播位址", + "udpPort": "UDP 連接埠", + "waitTimeS": "等待時間 (秒)", + "driveName": "磁碟機名稱", + "drivePath": "磁碟機路徑", + "ignoreCertificate": "忽略憑證", + "ignoreCertificateDesc": "允許連線至使用自行簽署憑證的主機", + "forceLossless": "強制無損", + "forceLosslessDesc": "強制使用無損影像編碼(品質較高,頻寬需求較大)", + "disableAudio": "停用音訊", + "disableAudioDesc": "將遠端工作階段的音訊全部靜音", + "enableAudioInput": "啟用音訊輸入(麥克風)", + "enableAudioInputDesc": "將本機麥克風轉送至遠端工作階段", + "wallpaper": "桌面背景", + "wallpaperDesc": "顯示桌面背景(停用可提升效能)", + "theming": "佈景主題", + "themingDesc": "啟用視覺主題與樣式", + "fontSmoothing": "字型平滑處理", + "fontSmoothingDesc": "啟用 ClearType 字型轉譯", + "fullWindowDrag": "全視窗拖曳", + "fullWindowDragDesc": "拖曳時顯示視窗內容", + "desktopComposition": "桌面合成", + "desktopCompositionDesc": "啟用 Aero 玻璃效果", + "menuAnimations": "選單動畫", + "menuAnimationsDesc": "啟用選單淡入淡出及滑動動畫", + "disableBitmapCaching": "停用點陣圖快取", + "disableBitmapCachingDesc": "關閉點陣圖快取(可能有助於解決顯示問題)", + "disableOffscreenCaching": "停用螢幕外快取", + "disableOffscreenCachingDesc": "關閉螢幕外快取", + "disableGlyphCaching": "停用字符快取", + "disableGlyphCachingDesc": "關閉字符快取", + "enableGfx": "啟用 GFX", + "enableGfxDesc": "使用 RemoteFX 圖形管線", + "enablePrinting": "啟用列印功能", + "enablePrintingDesc": "將本機印表機重新導向至遠端工作階段", + "enableDriveRedirection": "啟用磁碟機重新導向", + "enableDriveRedirectionDesc": "在遠端工作階段中將本機資料夾對應為磁碟機", + "createDrivePath": "建立磁碟機路徑", + "createDrivePathDesc": "如果資料夾不存在則自動建立", + "disableDownload": "停用下載", + "disableDownloadDesc": "防止從遠端工作階段下載檔案", + "disableUpload": "停用上傳", + "disableUploadDesc": "防止將檔案上傳至遠端工作階段", + "enableTouch": "啟用觸控", + "enableTouchDesc": "啟用觸控輸入轉送", + "consoleSession": "主控台工作階段", + "consoleSessionDesc": "連線至主控台 (工作階段 0) 而非新工作階段", + "sendWolPacket": "傳送 WOL 封包", + "sendWolPacketDesc": "在連線前傳送魔術封包以喚醒此主機", + "disableCopy": "停用複製", + "disableCopyDesc": "防止從遠端工作階段複製文字", + "disablePaste": "停用貼上", + "disablePasteDesc": "防止將文字貼上至遠端工作階段", + "createPathIfMissing": "若路徑不存在則建立", + "createPathIfMissingDesc": "自動建立錄製目錄", + "excludeOutput": "排除輸出", + "excludeOutputDesc": "不錄製螢幕輸出 (僅中繼資料)", + "excludeMouse": "排除滑鼠", + "excludeMouseDesc": "不錄製滑鼠移動", + "includeKeystrokes": "包含按鍵輸入", + "includeKeystrokesDesc": "除了螢幕輸出外,也錄製原始按鍵輸入", + "vncPort": "VNC 連接埠", + "vncPassword": "VNC 密碼", + "vncUsernameOptional": "使用者名稱 (選用)", + "vncLeaveBlank": "若不需要則留空", + "cursorMode": "游標模式", + "swapRedBlue": "交換紅/藍", + "swapRedBlueDesc": "交換紅色與藍色色版 (修正某些色彩問題)", + "readOnly": "唯讀", + "readOnlyDesc": "僅檢視遠端螢幕,不傳送任何輸入", + "telnetPort": "Telnet 連接埠", + "terminalType": "終端機類型", + "fontName": "字型名稱", + "fontSize": "字型大小", + "colorScheme": "色彩配置", + "backspaceKey": "退格鍵" + } + }, + "onboarding": { + "feature_desktop": "遠端桌面", + "feature_desktop_desc": "像 SSH 一樣,在同一個標籤頁中開啟 RDP、VNC 和 Telnet 會話。" + } +} diff --git a/plugins/remote-desktop/manifest.json b/plugins/remote-desktop/manifest.json index 5031ff812..8ae158bd2 100644 --- a/plugins/remote-desktop/manifest.json +++ b/plugins/remote-desktop/manifest.json @@ -59,7 +59,8 @@ "labelKey": "hosts.tabTelnet", "editorTab": "telnet" } - ] + ], + "guest": true }, "locales": "locales", "platforms": ["linux", "win32", "darwin"] diff --git a/plugins/remote-desktop/src/frontend/GuacamoleApp.tsx b/plugins/remote-desktop/src/frontend/GuacamoleApp.tsx index 744b7eb60..ddc422eba 100644 --- a/plugins/remote-desktop/src/frontend/GuacamoleApp.tsx +++ b/plugins/remote-desktop/src/frontend/GuacamoleApp.tsx @@ -14,20 +14,15 @@ import { type GuacamoleDisplayHandle, type GuacamoleTouchMode, } from "./GuacamoleDisplay.tsx"; -import { - getGuacamoleTokenFromHost, - getGuacdStatus, - getSSHHosts, - logActivity, - isElectron, -} from "@/main-axios.ts"; +import { getSSHHosts, logActivity, isElectron } from "@/main-axios"; +import { getGuacamoleTokenFromHost, getGuacdStatus } from "./guacamole-api"; import { readConfiguredDimension } from "./guacamole-display-size.ts"; import { getGuacamoleToken, parseGuacamoleConfig } from "./guacamole-api"; import { resolveConnectionOrigin, type ConnectionOrigin, } from "@/lib/connection-origin.ts"; -import { useTranslation } from "react-i18next"; +import { useTranslation } from "@termix/plugin-sdk/frontend"; import { GuacamoleToolbar } from "./GuacamoleToolbar.tsx"; import { GuacamoleFileBrowser } from "./GuacamoleFileBrowser.tsx"; import { describeUploadError } from "./guacamole-filesystem.ts"; @@ -73,6 +68,8 @@ export interface GuacamoleAppHandle { isConnected: () => boolean; openShareModal: () => void; canShare: () => boolean; + /** Reconnects, from the tab bar's refresh. */ + refresh: () => void; } const GuacamoleApp = React.forwardRef( @@ -294,11 +291,15 @@ const GuacamoleAppInner = React.forwardRef< const [promptPassword, setPromptPassword] = useState(""); const [promptDomain, setPromptDomain] = useState(hostConfig.domain ?? ""); + // Assigned below, once handleReconnect exists; the shell's tab refresh calls it. + const reconnectRef = useRef<() => void>(() => {}); + useImperativeHandle(ref, () => ({ disconnect: () => displayRef.current?.disconnect(), isConnected: () => displayRef.current?.isConnected() === true, openShareModal: () => setShareModalOpen(true), canShare: () => guacamoleConnectionId !== null, + refresh: () => reconnectRef.current(), })); const fetchToken = useCallback(async (): Promise => { @@ -454,16 +455,7 @@ const GuacamoleAppInner = React.forwardRef< tokenRetryRef.current.retryNow(); }, [needsCredentialPrompt, hostConfig.domain, clearLogs]); - useEffect(() => { - if (!tabId) return; - const handler = (e: Event) => { - const { tabId: eventTabId } = (e as CustomEvent).detail; - if (eventTabId === tabId) handleReconnect(); - }; - window.addEventListener("termix:refresh-guacamole", handler); - return () => - window.removeEventListener("termix:refresh-guacamole", handler); - }, [tabId, handleReconnect]); + reconnectRef.current = handleReconnect; if (promptOpen) { return ( diff --git a/plugins/remote-desktop/src/frontend/GuacamoleDisplay.tsx b/plugins/remote-desktop/src/frontend/GuacamoleDisplay.tsx index 52ecf04b4..303dea273 100644 --- a/plugins/remote-desktop/src/frontend/GuacamoleDisplay.tsx +++ b/plugins/remote-desktop/src/frontend/GuacamoleDisplay.tsx @@ -10,8 +10,9 @@ import { } from "react"; import Guacamole from "guacamole-common-js"; import { Upload } from "lucide-react"; -import { useTranslation } from "react-i18next"; -import { getGuacamoleToken, isElectron } from "@/main-axios.ts"; +import { useTranslation } from "@termix/plugin-sdk/frontend"; +import { isElectron } from "@/main-axios"; +import { getGuacamoleToken } from "./guacamole-api"; import { getBasePath } from "@/lib/base-path.ts"; import { buildGuacamoleWebSocketBaseUrl } from "./guacamole-websocket-url.ts"; import { diff --git a/plugins/remote-desktop/src/frontend/GuacamoleFileBrowser.tsx b/plugins/remote-desktop/src/frontend/GuacamoleFileBrowser.tsx index 0ae48b7b0..594e6b55f 100644 --- a/plugins/remote-desktop/src/frontend/GuacamoleFileBrowser.tsx +++ b/plugins/remote-desktop/src/frontend/GuacamoleFileBrowser.tsx @@ -1,7 +1,7 @@ import { getErrorMessage } from "@/lib/error-message.js"; import { useCallback, useEffect, useRef, useState } from "react"; import Guacamole from "guacamole-common-js"; -import { useTranslation } from "react-i18next"; +import { useTranslation } from "@termix/plugin-sdk/frontend"; import { ArrowUp, Download, diff --git a/plugins/remote-desktop/src/frontend/GuacamoleToolbar.tsx b/plugins/remote-desktop/src/frontend/GuacamoleToolbar.tsx index 94e7597d0..5a8441f89 100644 --- a/plugins/remote-desktop/src/frontend/GuacamoleToolbar.tsx +++ b/plugins/remote-desktop/src/frontend/GuacamoleToolbar.tsx @@ -31,7 +31,7 @@ import type { GuacamoleDisplayHandle, GuacamoleTouchMode, } from "./GuacamoleDisplay.tsx"; -import { useTranslation } from "react-i18next"; +import { useTranslation } from "@termix/plugin-sdk/frontend"; import { cn } from "@/lib/utils"; import { detectRuntimeMetaKeyFamily, diff --git a/src/ui/sidebar/HostEditorGuacamoleTabs.tsx b/plugins/remote-desktop/src/frontend/HostEditorGuacamoleTabs.tsx similarity index 99% rename from src/ui/sidebar/HostEditorGuacamoleTabs.tsx rename to plugins/remote-desktop/src/frontend/HostEditorGuacamoleTabs.tsx index a7d4d472e..554cebd86 100644 --- a/src/ui/sidebar/HostEditorGuacamoleTabs.tsx +++ b/plugins/remote-desktop/src/frontend/HostEditorGuacamoleTabs.tsx @@ -1,4 +1,4 @@ -import { useTranslation } from "react-i18next"; +import { useTranslation } from "@termix/plugin-sdk/frontend"; import { Input } from "@/components/input"; import { PasswordInput } from "@/components/password-input"; import { FakeSwitch, SectionCard, SettingRow } from "@/components/section-card"; @@ -16,7 +16,7 @@ import { Zap, Cpu, } from "lucide-react"; -import type { HostEditorForm } from "./HostEditorData"; +import type { HostEditorForm } from "@/sidebar/HostEditorData"; import { Select2 } from "@/components/select2"; type HostEditorSetField = ( diff --git a/plugins/remote-desktop/src/frontend/index.mjs b/plugins/remote-desktop/src/frontend/index.mjs deleted file mode 100644 index f2edaadc6..000000000 --- a/plugins/remote-desktop/src/frontend/index.mjs +++ /dev/null @@ -1,28 +0,0 @@ -/** - * Frontend half of the remote-desktop plugin. - * - * rdp/vnc/telnet are built-in tabs owned by this plugin (see - * BUILT_IN_TABS_BY_PLUGIN in src/ui/shell/pluginLoader.ts), the same - * category ssh-terminal's "terminal" tab is in: they render through - * tabUtils.tsx's hardcoded switch rather than through registerTabComponent, - * because GuacamoleApp needs hostId/tabId/protocol/quickConnectHost/ref -- - * more props than the generic { tab } plugin surface can carry. There is - * nothing to register or unregister here; isTabTypeAvailable("rdp"/"vnc"/ - * "telnet") is what actually gates them off when this plugin is disabled. - * - * This file exists only so the plugin has a frontend entry point matching - * every other plugin's shape, ready for the day a real frontend loader - * calls register()/unregister() directly instead of pluginLoader.ts's - * hand-duplicated stopgap wiring. - */ - -export const id = "remote-desktop"; -export const tabIds = ["rdp", "vnc", "telnet"]; - -export async function register() { - // No-op: see module comment. -} - -export async function unregister() { - // No-op: see module comment. -} diff --git a/plugins/remote-desktop/src/frontend/index.tsx b/plugins/remote-desktop/src/frontend/index.tsx new file mode 100644 index 000000000..88d8df46b --- /dev/null +++ b/plugins/remote-desktop/src/frontend/index.tsx @@ -0,0 +1,307 @@ +import type { ComponentType, Ref } from "react"; +import i18next from "i18next"; +import { toast } from "sonner"; +import { + MessagesSquare, + Monitor, + MonitorUp, + MousePointerClick, + Settings, +} from "lucide-react"; +import { + useTranslation, + type HostEditorSectionProps, + type StandaloneViewProps, + type TabProps, + type TermixApp, +} from "@termix/plugin-sdk/frontend"; +import { FakeSwitch, SectionCard, SettingRow } from "@termix/plugin-sdk/ui"; +import type { Host } from "@/types/ui-types"; +import { isQuickConnectHost } from "@/sidebar/quick-connect-host"; +import GuacamoleApp, { type GuacamoleAppHandle } from "./GuacamoleApp"; +import { GuacamoleDisplay } from "./GuacamoleDisplay"; +import { + HostEditorRdpTab, + HostEditorTelnetTab, + HostEditorVncTab, +} from "./HostEditorGuacamoleTabs"; +import { getGuacamoleTokenFromHost } from "./guacamole-api"; +import { quickConnectGuacHost } from "./quick-connect-guac-host"; + +type Protocol = "rdp" | "vnc" | "telnet"; + +const PROTOCOLS: { + id: Protocol; + titleKey: string; + icon: ComponentType<{ className?: string }>; + enableKey: "enableRdp" | "enableVnc" | "enableTelnet"; + priority: number; + order: number; +}[] = [ + { + id: "rdp", + titleKey: "hosts.tabRdp", + icon: Monitor, + enableKey: "enableRdp", + priority: 50, + order: 100, + }, + { + id: "vnc", + titleKey: "hosts.tabVnc", + icon: MousePointerClick, + enableKey: "enableVnc", + priority: 40, + order: 110, + }, + { + id: "telnet", + titleKey: "hosts.tabTelnet", + icon: MessagesSquare, + enableKey: "enableTelnet", + priority: 30, + order: 120, + }, +]; + +function RemoteDesktopTab({ tab, host, isVisible, handleRef }: TabProps) { + const shellHost = host as unknown as Host; + return ( + } + hostId={String(host?.id ?? "")} + tabId={tab.id} + protocol={tab.type as Protocol} + isVisible={isVisible} + quickConnectHost={ + isQuickConnectHost(shellHost) + ? quickConnectGuacHost(shellHost) + : undefined + } + /> + ); +} + +function RemoteDesktopStandalone({ hostId, view }: StandaloneViewProps) { + return ; +} + +/** What collab rooms and shared-session links draw a stream with. */ +function RemoteDisplay({ + token, + protocol, + isVisible, + onConnect, + onError, +}: { + token: string; + protocol: Protocol; + isVisible: boolean; + onConnect?: () => void; + onError?: (error: string) => void; +}) { + return ( + + ); +} + +/** Applies one remote desktop field and stops inheriting user defaults. */ +function useGuacFieldSetter( + updateForm: HostEditorSectionProps["updateForm"], +): (key: string, value: unknown) => void { + return (key, value) => + updateForm((current) => ({ + inheritRemoteDesktopDefaults: false, + guacamoleConfig: { + ...((current.guacamoleConfig as Record) ?? {}), + [key]: value, + }, + })); +} + +function RdpSection(props: HostEditorSectionProps) { + const { t } = useTranslation(); + const setGuacField = useGuacFieldSetter(props.updateForm); + return ( + <> + } + > + + + props.setField("inheritRemoteDesktopDefaults", value) + } + /> + + + + + ); +} + +function VncSection(props: HostEditorSectionProps) { + const setGuacField = useGuacFieldSetter(props.updateForm); + return ( + + ); +} + +function TelnetSection(props: HostEditorSectionProps) { + const setGuacField = useGuacFieldSetter(props.updateForm); + return ( + + ); +} + +const SECTIONS: Record> = { + rdp: RdpSection, + vnc: VncSection, + telnet: TelnetSection, +}; + +async function openNativeRdp(host: Record): Promise { + const t = (key: string) => i18next.t(`remote-desktop:${key}`); + try { + const result = await window.electronAPI.openNativeRdp({ + host: String(host.ip), + port: (host.rdpPort as number | undefined) ?? 3389, + username: host.rdpUser as string | undefined, + domain: host.domain as string | undefined, + }); + if (result.success) toast.success(t("hosts.nativeRdpOpened")); + else toast.error(result.error || t("hosts.nativeRdpFailed")); + } catch { + toast.error(t("hosts.nativeRdpFailed")); + } +} + +export function activate(app: TermixApp): void { + // Guest pages only draw shared streams. + app.registerSlotContribution("session.remoteDisplay", { + actionId: "remote-desktop.display", + titleKey: "hosts.tabRdp", + kind: "component", + component: RemoteDisplay as unknown as ComponentType< + Record + >, + }); + if (app.guest) return; + + // Mints a token for presenting a host in a collab room. + app.registerAction( + "session.remoteDisplay.token", + async (hostId: number, origin: unknown, protocol: Protocol) => { + const response = await getGuacamoleTokenFromHost( + hostId, + origin as Parameters[1], + protocol, + ); + return response.guacamoleConnectionId + ? { + token: response.token, + connectionId: response.guacamoleConnectionId, + } + : null; + }, + ); + + for (const protocol of PROTOCOLS) { + app.registerTab(protocol.id, RemoteDesktopTab, { + icon: protocol.icon, + titleKey: protocol.titleKey, + requiresHost: true, + noHostMessageKey: "remoteDesktop.noHostSelected", + persistent: true, + session: true, + restore: (host) => !!host[protocol.enableKey], + activityTypes: [protocol.id], + standalone: RemoteDesktopStandalone, + preload: () => import("./GuacamoleApp"), + }); + + app.registerHostAction({ + id: protocol.id, + titleKey: protocol.titleKey, + icon: protocol.icon, + kind: "connect", + priority: protocol.priority, + order: protocol.order, + tabType: protocol.id, + copyUrlView: protocol.id, + when: (host) => !!host[protocol.enableKey], + }); + + app.registerHostEditorSection({ + id: protocol.id, + group: "top", + titleKey: protocol.titleKey, + icon: protocol.icon, + order: protocol.order / 5, + visible: (protocols) => !!protocols[protocol.enableKey], + component: SECTIONS[protocol.id], + }); + } + + // The desktop app on Windows can hand RDP to the system client instead. + if (window.electronAPI?.isElectron) { + let disposed = false; + app.onDispose(() => { + disposed = true; + }); + window.electronAPI + .getPlatform() + .then((platform: string) => { + if (disposed || platform !== "win32") return; + app.registerHostAction({ + id: "rdp-native", + titleKey: "hosts.openNativeRdp", + icon: MonitorUp, + kind: "open", + order: 105, + when: (host) => !!host.enableRdp, + run: (host) => void openNativeRdp(host), + }); + }) + .catch(() => {}); + } + + app.registerSlotContribution("onboarding.features", { + actionId: "remote-desktop.feature", + titleKey: "onboarding.feature_desktop", + descriptionKey: "onboarding.feature_desktop_desc", + icon: Monitor, + }); +} diff --git a/plugins/remote-desktop/src/frontend/quick-connect-guac-host.ts b/plugins/remote-desktop/src/frontend/quick-connect-guac-host.ts new file mode 100644 index 000000000..488d9c8f5 --- /dev/null +++ b/plugins/remote-desktop/src/frontend/quick-connect-guac-host.ts @@ -0,0 +1,19 @@ +import type { Host } from "@/types/ui-types"; +import type { GuacamoleQuickHost } from "./GuacamoleApp"; + +/** The slice of a quick-connect host that GuacamoleApp mints a token from. */ +export function quickConnectGuacHost(host: Host): GuacamoleQuickHost { + return { + name: host.name, + ip: host.ip, + connectionType: host.enableVnc ? "vnc" : "rdp", + domain: host.domain, + rdpPort: host.rdpPort, + vncPort: host.vncPort, + rdpAuthType: host.rdpAuthType, + rdpUser: host.rdpUser, + rdpPassword: host.rdpPassword, + vncUser: host.vncUser, + vncPassword: host.vncPassword, + }; +} diff --git a/plugins/remote-desktop/tests/frontend/activate.test.tsx b/plugins/remote-desktop/tests/frontend/activate.test.tsx new file mode 100644 index 000000000..814097280 --- /dev/null +++ b/plugins/remote-desktop/tests/frontend/activate.test.tsx @@ -0,0 +1,53 @@ +import { afterEach, describe, expect, it } from "vitest"; +import { + renderWithApp, + type RenderedPluginApp, +} from "@termix/plugin-sdk/testing"; +import type { PluginManifest } from "@termix/plugin-sdk/manifest"; +import * as plugin from "../../src/frontend/index"; +import manifestJson from "../../manifest.json"; +import locales from "../../locales/en.json"; + +const manifest = manifestJson as unknown as PluginManifest; + +const declared = (views?: Array<{ id: string }>) => + (views ?? []).map((view) => view.id).sort(); + +let rendered: RenderedPluginApp | null = null; + +afterEach(async () => { + await rendered?.deactivate(); + rendered = null; +}); + +describe(`${manifest.id} activate`, () => { + it("activates and registers only views its manifest declares", async () => { + rendered = await renderWithApp(plugin, { manifest, locales }); + const contributes = manifest.contributes as unknown as Record< + string, + Array<{ id: string }> | undefined + >; + const tabs = declared(contributes.tabs); + // A rail panel may reuse one of the plugin's tab ids. + const panels = [...declared(contributes.panels), ...tabs]; + const cards = declared(contributes.dashboardCards); + for (const id of rendered.registered.tabs()) expect(tabs).toContain(id); + for (const id of rendered.registered.panels()) expect(panels).toContain(id); + for (const id of rendered.registered.dashboardCards()) { + expect(cards).toContain(id); + } + }); + + it("removes everything it registered on deactivate", async () => { + const app = await renderWithApp(plugin, { manifest, locales }); + await app.deactivate(); + expect(app.registered.tabs()).toEqual([]); + expect(app.registered.panels()).toEqual([]); + expect(app.registered.railItems()).toEqual([]); + expect(app.registered.hostActions()).toEqual([]); + expect(app.registered.hostEditorSections()).toEqual([]); + expect(app.registered.dashboardCards()).toEqual([]); + expect(app.registered.settingsComponents()).toEqual([]); + expect(app.registered.actions()).toEqual([]); + }); +}); diff --git a/plugins/remote-desktop/tests/frontend/quick-connect-guac-host.test.ts b/plugins/remote-desktop/tests/frontend/quick-connect-guac-host.test.ts new file mode 100644 index 000000000..3b3a1189c --- /dev/null +++ b/plugins/remote-desktop/tests/frontend/quick-connect-guac-host.test.ts @@ -0,0 +1,41 @@ +import { describe, expect, it } from "vitest"; +import { createQuickConnectHost } from "@/sidebar/quick-connect-host"; +import { quickConnectGuacHost } from "../../src/frontend/quick-connect-guac-host"; + +describe("quickConnectGuacHost", () => { + it("carries an RDP quick connect's address and credentials", () => { + const host = createQuickConnectHost({ + ip: "10.0.0.2", + port: 3390, + username: "admin", + authType: "password", + password: "pw", + protocol: "rdp", + domain: "CORP", + }); + expect(quickConnectGuacHost(host)).toMatchObject({ + ip: "10.0.0.2", + connectionType: "rdp", + rdpPort: 3390, + rdpUser: "admin", + rdpPassword: "pw", + domain: "CORP", + }); + }); + + it("puts a VNC quick connect's password on the VNC fields", () => { + const host = createQuickConnectHost({ + ip: "10.0.0.3", + port: 5901, + username: "", + authType: "password", + password: "vncpw", + protocol: "vnc", + }); + expect(quickConnectGuacHost(host)).toMatchObject({ + connectionType: "vnc", + vncPort: 5901, + vncPassword: "vncpw", + }); + }); +}); diff --git a/plugins/ssh-terminal/manifest.json b/plugins/ssh-terminal/manifest.json index 67bae89ca..b9c5de326 100644 --- a/plugins/ssh-terminal/manifest.json +++ b/plugins/ssh-terminal/manifest.json @@ -27,13 +27,21 @@ "id": "terminal", "titleKey": "nav.terminal", "icon": "SquareTerminal", - "openFrom": ["rail", "host-context-menu", "palette"] + "openFrom": ["host-context-menu", "palette"] } ], "actionSlots": [ { "id": "terminal.toolbar", "accepts": ["button"] + }, + { + "id": "terminal.dock", + "accepts": ["component"] + }, + { + "id": "terminal.overlay", + "accepts": ["component"] } ] }, diff --git a/plugins/ssh-terminal/src/frontend/index.mjs b/plugins/ssh-terminal/src/frontend/index.mjs deleted file mode 100644 index ea44a68d4..000000000 --- a/plugins/ssh-terminal/src/frontend/index.mjs +++ /dev/null @@ -1,49 +0,0 @@ -/** - * Frontend half of the ssh-terminal plugin. - * - * Registers the existing Terminal component through the extension seams that - * already exist in the shell (registerRailItem / registerTabComponent). The - * component itself is unchanged and still lives in src/ui/features/terminal - - * this only controls whether the shell knows about it. - * - * register() is called when the plugin is enabled, unregister() when it is - * disabled, so the tab and rail entry appear and disappear with the plugin. - */ - -export const id = "ssh-terminal"; -export const tabId = "terminal"; -export const toolbarSlotId = "terminal.toolbar"; - -export async function register({ - registerRailItem, - registerTabComponent, - declareActionSlot, - icons, -}) { - registerTabComponent(tabId, () => - import("@/features/terminal/Terminal").then((m) => ({ - default: m.Terminal, - })), - ); - - registerRailItem({ - id: tabId, - icon: icons.SquareTerminal, - labelKey: "nav.terminal", - kind: "tab", - }); - - // Offers other plugins a place in the terminal toolbar. The terminal does - // not know or care who fills it. - declareActionSlot({ id: toolbarSlotId, accepts: ["button"] }); -} - -export async function unregister({ - unregisterRailItem, - unregisterTabComponent, - undeclareActionSlot, -}) { - unregisterRailItem(tabId); - unregisterTabComponent(tabId); - undeclareActionSlot(toolbarSlotId); -} diff --git a/plugins/ssh-terminal/src/frontend/index.tsx b/plugins/ssh-terminal/src/frontend/index.tsx new file mode 100644 index 000000000..87aed4eee --- /dev/null +++ b/plugins/ssh-terminal/src/frontend/index.tsx @@ -0,0 +1,66 @@ +import type { ComponentType } from "react"; +import { Terminal } from "lucide-react"; +import type { + StandaloneViewProps, + TabProps, + TermixApp, +} from "@termix/plugin-sdk/frontend"; +import { + TerminalTabContent, + loadTerminal, +} from "@/features/terminal/TerminalTabContent"; +import TerminalApp from "@/features/terminal/TerminalApp"; +import { + TERMINAL_DOCK_SLOT, + TERMINAL_OVERLAY_SLOT, + TERMINAL_TOOLBAR_SLOT, +} from "@/features/terminal/terminal-slots"; + +/** `?view=terminal` full-screen links. */ +function TerminalStandalone({ hostId, params }: StandaloneViewProps) { + return ( + + ); +} + +/** + * The SSH terminal. Its component still lives in core until the terminal's + * own Phase B step; this plugin decides whether the shell offers it. + */ +export function activate(app: TermixApp): void { + app.registerTab( + "terminal", + TerminalTabContent as unknown as ComponentType, + { + icon: Terminal, + titleKey: "nav.terminal", + persistent: true, + session: true, + restore: (host) => !!host.enableSsh, + activityTypes: ["terminal"], + standalone: TerminalStandalone, + preload: loadTerminal, + }, + ); + + app.registerHostAction({ + id: "terminal", + titleKey: "nav.terminal", + icon: Terminal, + kind: "connect", + priority: 100, + order: 10, + tabType: "terminal", + copyUrlView: "terminal", + when: (host) => !!host.enableSsh && host.enableTerminal !== false, + }); + + // Places other plugins can fill: toolbar buttons, a docked side panel and + // overlays that follow the session's connection flow. + app.declareActionSlot({ id: TERMINAL_TOOLBAR_SLOT, accepts: ["button"] }); + app.declareActionSlot({ id: TERMINAL_DOCK_SLOT, accepts: ["component"] }); + app.declareActionSlot({ id: TERMINAL_OVERLAY_SLOT, accepts: ["component"] }); +} diff --git a/plugins/ssh-terminal/tests/frontend/activate.test.tsx b/plugins/ssh-terminal/tests/frontend/activate.test.tsx new file mode 100644 index 000000000..814097280 --- /dev/null +++ b/plugins/ssh-terminal/tests/frontend/activate.test.tsx @@ -0,0 +1,53 @@ +import { afterEach, describe, expect, it } from "vitest"; +import { + renderWithApp, + type RenderedPluginApp, +} from "@termix/plugin-sdk/testing"; +import type { PluginManifest } from "@termix/plugin-sdk/manifest"; +import * as plugin from "../../src/frontend/index"; +import manifestJson from "../../manifest.json"; +import locales from "../../locales/en.json"; + +const manifest = manifestJson as unknown as PluginManifest; + +const declared = (views?: Array<{ id: string }>) => + (views ?? []).map((view) => view.id).sort(); + +let rendered: RenderedPluginApp | null = null; + +afterEach(async () => { + await rendered?.deactivate(); + rendered = null; +}); + +describe(`${manifest.id} activate`, () => { + it("activates and registers only views its manifest declares", async () => { + rendered = await renderWithApp(plugin, { manifest, locales }); + const contributes = manifest.contributes as unknown as Record< + string, + Array<{ id: string }> | undefined + >; + const tabs = declared(contributes.tabs); + // A rail panel may reuse one of the plugin's tab ids. + const panels = [...declared(contributes.panels), ...tabs]; + const cards = declared(contributes.dashboardCards); + for (const id of rendered.registered.tabs()) expect(tabs).toContain(id); + for (const id of rendered.registered.panels()) expect(panels).toContain(id); + for (const id of rendered.registered.dashboardCards()) { + expect(cards).toContain(id); + } + }); + + it("removes everything it registered on deactivate", async () => { + const app = await renderWithApp(plugin, { manifest, locales }); + await app.deactivate(); + expect(app.registered.tabs()).toEqual([]); + expect(app.registered.panels()).toEqual([]); + expect(app.registered.railItems()).toEqual([]); + expect(app.registered.hostActions()).toEqual([]); + expect(app.registered.hostEditorSections()).toEqual([]); + expect(app.registered.dashboardCards()).toEqual([]); + expect(app.registered.settingsComponents()).toEqual([]); + expect(app.registered.actions()).toEqual([]); + }); +}); diff --git a/plugins/tailscale/locales/en.json b/plugins/tailscale/locales/en.json index 0967ef424..2dda22191 100644 --- a/plugins/tailscale/locales/en.json +++ b/plugins/tailscale/locales/en.json @@ -1 +1,54 @@ -{} +{ + "permissions": { + "devices.view": { + "title": "View tailnet devices", + "description": "See the devices on the connected tailnet." + } + }, + "settings": { + "group": { + "api": "Tailscale API", + "devices": "Tailnet" + }, + "apiKey": { + "label": "API key", + "description": "Used to list the devices on your tailnet. Works with a Tailscale or Headscale key.", + "placeholder": "tskey-api-... / hskey-api-..." + }, + "apiBaseUrl": { + "label": "API base URL", + "description": "Leave empty for Tailscale. Set this to point at a Headscale instance.", + "placeholder": "https://api.tailscale.com/api/v2" + }, + "devices": { + "label": "Device list", + "checking": "Checking the tailnet...", + "noKey": "No API key set yet.", + "error": "Could not reach the tailnet. Check the API key.", + "count": "{{count}} device reachable", + "count_other": "{{count}} devices reachable", + "refresh": "Check" + } + }, + "nav": { + "tailscale": "Tailscale" + }, + "hosts": { + "tailscaleUsernameHint": "This must be a Unix user your Tailscale identity is granted in the tailnet's SSH ACL, not necessarily root.", + "tailscaleDeviceSelect": "Select Tailscale device", + "tailscaleDeviceSelectPlaceholder": "Select a device...", + "tailscaleNoApiKey": "No Tailscale API key configured. Add one in Admin Settings to enable device discovery.", + "tailscaleDocsLink": "View docs", + "tailscaleLoadingDevices": "Loading devices...", + "tailscaleDeviceLoadFailed": "Failed to load Tailscale devices. Check the API URL and network connection.", + "tailscaleNoDevices": "No devices found in your tailnet.", + "tailscaleDeviceAutoFill": "Selecting a device will auto-fill the host IP address." + }, + "terminal": { + "tailscaleCheckRequired": "Tailscale Authentication Required", + "tailscaleCheckDescription": "Tailscale SSH requires an additional check. Authenticate in your browser to continue.", + "tailscaleCheckOpenBrowser": "Open Browser to Authenticate", + "tailscaleCheckWaiting": "Waiting for Tailscale authentication...", + "tailscaleCheckTimeout": "Tailscale authentication timed out. Please try again." + } +} diff --git a/plugins/tailscale/locales/translated/af_ZA.json b/plugins/tailscale/locales/translated/af_ZA.json new file mode 100644 index 000000000..ec17d3c6d --- /dev/null +++ b/plugins/tailscale/locales/translated/af_ZA.json @@ -0,0 +1,20 @@ +{ + "hosts": { + "tailscaleUsernameHint": "Dit moet 'n Unix-gebruiker wees aan wie jou Tailscale-identiteit in die tailnet se SSH ACL toegestaan word, nie noodwendig root nie.", + "tailscaleDeviceSelect": "Kies Tailscale-toestel", + "tailscaleDeviceSelectPlaceholder": "Kies 'n toestel...", + "tailscaleNoApiKey": "Geen Tailscale API-sleutel gekonfigureer nie. Voeg een by in Admin-instellings om toestelontdekking te aktiveer.", + "tailscaleDocsLink": "Bekyk dokumente", + "tailscaleLoadingDevices": "Laai toestelle...", + "tailscaleDeviceLoadFailed": "Kon nie Tailscale-toestelle laai nie. Kontroleer die API-URL en netwerkverbinding.", + "tailscaleNoDevices": "Geen toestelle in jou tailnet gevind nie.", + "tailscaleDeviceAutoFill": "As jy 'n toestel kies, sal die gasheer-IP-adres outomaties ingevul word." + }, + "terminal": { + "tailscaleCheckRequired": "Stertskaal-verifikasie vereis", + "tailscaleCheckDescription": "Tailscale SSH vereis 'n bykomende kontrole. Verifieer in jou blaaier om voort te gaan.", + "tailscaleCheckOpenBrowser": "Maak blaaier oop om te verifieer", + "tailscaleCheckWaiting": "Wag vir Tailscale-verifikasie...", + "tailscaleCheckTimeout": "Tailscale-verifikasie het verstryk. Probeer asseblief weer." + } +} diff --git a/plugins/tailscale/locales/translated/ar_SA.json b/plugins/tailscale/locales/translated/ar_SA.json new file mode 100644 index 000000000..de8fd7557 --- /dev/null +++ b/plugins/tailscale/locales/translated/ar_SA.json @@ -0,0 +1,20 @@ +{ + "hosts": { + "tailscaleUsernameHint": "يجب أن يكون هذا مستخدمًا لنظام Unix، حيث يتم منح هوية Tailscale الخاصة بك في قائمة التحكم بالوصول SSH الخاصة بشبكة tailnet، وليس بالضرورة المستخدم الجذر.", + "tailscaleDeviceSelect": "اختيار جهاز Tailscale", + "tailscaleDeviceSelectPlaceholder": "اختر جهازًا...", + "tailscaleNoApiKey": "لم يتم تكوين مفتاح API لـ Tailscale. أضف واحدًا في إعدادات المسؤول لتمكين اكتشاف الأجهزة.", + "tailscaleDocsLink": "عرض المستندات", + "tailscaleLoadingDevices": "جارٍ تحميل الأجهزة...", + "tailscaleDeviceLoadFailed": "فشل تحميل أجهزة Tailscale. يرجى التحقق من عنوان URL الخاص بواجهة برمجة التطبيقات (API) واتصال الشبكة.", + "tailscaleNoDevices": "لم يتم العثور على أجهزة في tailnet الخاص بك.", + "tailscaleDeviceAutoFill": "سيؤدي تحديد جهاز إلى تعبئة عنوان IP للمضيف تلقائيًا." + }, + "terminal": { + "tailscaleCheckRequired": "يلزم التحقق من الهوية على مستوى ذيل الطائرة", + "tailscaleCheckDescription": "يتطلب Tailscale SSH إجراء فحص إضافي. قم بتسجيل الدخول إلى متصفحك للمتابعة.", + "tailscaleCheckOpenBrowser": "افتح المتصفح للمصادقة", + "tailscaleCheckWaiting": "في انتظار مصادقة Tailscale...", + "tailscaleCheckTimeout": "انتهت مهلة مصادقة Tailscale. يرجى المحاولة مرة أخرى." + } +} diff --git a/plugins/tailscale/locales/translated/bg_BG.json b/plugins/tailscale/locales/translated/bg_BG.json new file mode 100644 index 000000000..b17437676 --- /dev/null +++ b/plugins/tailscale/locales/translated/bg_BG.json @@ -0,0 +1,20 @@ +{ + "hosts": { + "tailscaleUsernameHint": "Това трябва да е Unix потребител, чиято самоличност на Tailscale е предоставена в SSH ACL на tailnet, не е задължително root.", + "tailscaleDeviceSelect": "Изберете устройство за Tailscale", + "tailscaleDeviceSelectPlaceholder": "Изберете устройство...", + "tailscaleNoApiKey": "Няма конфигуриран ключ за Tailscale API. Добавете такъв в настройките на администратора, за да активирате откриването на устройства.", + "tailscaleDocsLink": "Преглед на документи", + "tailscaleLoadingDevices": "Зареждане на устройства...", + "tailscaleDeviceLoadFailed": "Зареждането на устройствата Tailscale не бе успешно. Проверете URL адреса на API и мрежовата връзка.", + "tailscaleNoDevices": "Няма намерени устройства във вашата мрежа за контакт.", + "tailscaleDeviceAutoFill": "Избирането на устройство ще попълни автоматично IP адреса на хоста." + }, + "terminal": { + "tailscaleCheckRequired": "Изисква се удостоверяване на Tailscale", + "tailscaleCheckDescription": "Tailscale SSH изисква допълнителна проверка. Удостоверете се в браузъра си, за да продължите.", + "tailscaleCheckOpenBrowser": "Отворете браузъра за удостоверяване", + "tailscaleCheckWaiting": "Чака се удостоверяване на Tailscale...", + "tailscaleCheckTimeout": "Времето за изчакване на удостоверяването на Tailscale изтече. Моля, опитайте отново." + } +} diff --git a/plugins/tailscale/locales/translated/bn_BD.json b/plugins/tailscale/locales/translated/bn_BD.json new file mode 100644 index 000000000..9596a17bd --- /dev/null +++ b/plugins/tailscale/locales/translated/bn_BD.json @@ -0,0 +1,20 @@ +{ + "hosts": { + "tailscaleUsernameHint": "এটি অবশ্যই একজন ইউনিক্স ব্যবহারকারী হতে হবে, যার মাধ্যমে আপনার টেইলনেট-এর SSH ACL-এ আপনার টেইলস্কেল পরিচয়কে অনুমতি দেওয়া হয়; এটি রুট হওয়া আবশ্যক নয়।", + "tailscaleDeviceSelect": "টেইলস্কেল ডিভাইস নির্বাচন করুন", + "tailscaleDeviceSelectPlaceholder": "একটি ডিভাইস নির্বাচন করুন...", + "tailscaleNoApiKey": "কোনো টেইলস্কেল এপিআই কী কনফিগার করা নেই। ডিভাইস ডিসকভারি সক্ষম করতে অ্যাডমিন সেটিংসে একটি যোগ করুন।", + "tailscaleDocsLink": "নথি দেখুন", + "tailscaleLoadingDevices": "ডিভাইস লোড হচ্ছে...", + "tailscaleDeviceLoadFailed": "টেইলস্কেল ডিভাইসগুলো লোড করা সম্ভব হয়নি। এপিআই ইউআরএল এবং নেটওয়ার্ক সংযোগ যাচাই করুন।", + "tailscaleNoDevices": "আপনার টেইলনেটে কোনো ডিভাইস খুঁজে পাওয়া যায়নি।", + "tailscaleDeviceAutoFill": "ডিভাইস নির্বাচন করলে হোস্ট আইপি অ্যাড্রেসটি স্বয়ংক্রিয়ভাবে পূরণ হয়ে যাবে।" + }, + "terminal": { + "tailscaleCheckRequired": "টেইলস্কেল প্রমাণীকরণ আবশ্যক", + "tailscaleCheckDescription": "টেইলস্কেল SSH-এর জন্য একটি অতিরিক্ত যাচাইকরণ প্রয়োজন। চালিয়ে যাওয়ার জন্য আপনার ব্রাউজারে প্রমাণীকরণ করুন।", + "tailscaleCheckOpenBrowser": "প্রমাণীকরণের জন্য ব্রাউজার খুলুন", + "tailscaleCheckWaiting": "টেইলস্কেল প্রমাণীকরণের জন্য অপেক্ষা করা হচ্ছে...", + "tailscaleCheckTimeout": "টেইলস্কেল প্রমাণীকরণের সময়সীমা শেষ হয়ে গেছে। অনুগ্রহ করে আবার চেষ্টা করুন।" + } +} diff --git a/plugins/tailscale/locales/translated/ca_ES.json b/plugins/tailscale/locales/translated/ca_ES.json new file mode 100644 index 000000000..8563a940e --- /dev/null +++ b/plugins/tailscale/locales/translated/ca_ES.json @@ -0,0 +1,20 @@ +{ + "hosts": { + "tailscaleUsernameHint": "Aquest ha de ser un usuari d'Unix; la teva identitat Tailscale està atorgada a l'ACL SSH de la xarxa principal, no necessàriament un usuari root.", + "tailscaleDeviceSelect": "Selecciona el dispositiu Tailscale", + "tailscaleDeviceSelectPlaceholder": "Selecciona un dispositiu...", + "tailscaleNoApiKey": "No hi ha cap clau d'API de Tailscale configurada. Afegeix-ne una a la configuració de l'administrador per habilitar la detecció de dispositius.", + "tailscaleDocsLink": "Veure documents", + "tailscaleLoadingDevices": "S'estan carregant els dispositius...", + "tailscaleDeviceLoadFailed": "No s'han pogut carregar els dispositius Tailscale. Comproveu l'URL de l'API i la connexió de xarxa.", + "tailscaleNoDevices": "No s'han trobat dispositius a la xarxa de cua.", + "tailscaleDeviceAutoFill": "En seleccionar un dispositiu, l'adreça IP de l'amfitrió s'omplirà automàticament." + }, + "terminal": { + "tailscaleCheckRequired": "Autenticació a escala final requerida", + "tailscaleCheckDescription": "L'SSH a escala de punta requereix una comprovació addicional. Autentiqueu-vos al navegador per continuar.", + "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." + } +} diff --git a/plugins/tailscale/locales/translated/cs_CZ.json b/plugins/tailscale/locales/translated/cs_CZ.json new file mode 100644 index 000000000..645e7487a --- /dev/null +++ b/plugins/tailscale/locales/translated/cs_CZ.json @@ -0,0 +1,20 @@ +{ + "hosts": { + "tailscaleUsernameHint": "Musí se jednat o uživatele Unixu, kterému je vaše identita Tailscale udělena v SSH ACL tailnetu, nikoli nutně o uživatele root.", + "tailscaleDeviceSelect": "Vyberte zařízení Tailscale", + "tailscaleDeviceSelectPlaceholder": "Vyberte zařízení...", + "tailscaleNoApiKey": "Není nakonfigurován žádný klíč Tailscale API. Přidejte jej v nastavení správce, abyste povolili vyhledávání zařízení.", + "tailscaleDocsLink": "Zobrazit dokumenty", + "tailscaleLoadingDevices": "Načítání zařízení...", + "tailscaleDeviceLoadFailed": "Nepodařilo se načíst zařízení Tailscale. Zkontrolujte URL API a síťové připojení.", + "tailscaleNoDevices": "Ve vaší koncové síti nebyla nalezena žádná zařízení.", + "tailscaleDeviceAutoFill": "Výběrem zařízení se automaticky vyplní IP adresa hostitele." + }, + "terminal": { + "tailscaleCheckRequired": "Vyžadováno ověřování Tailscale", + "tailscaleCheckDescription": "Tailscale SSH vyžaduje dodatečnou kontrolu. Pro pokračování se ověřte ve svém prohlížeči.", + "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." + } +} diff --git a/plugins/tailscale/locales/translated/da_DK.json b/plugins/tailscale/locales/translated/da_DK.json new file mode 100644 index 000000000..23000ca9b --- /dev/null +++ b/plugins/tailscale/locales/translated/da_DK.json @@ -0,0 +1,20 @@ +{ + "hosts": { + "tailscaleUsernameHint": "Dette skal være en Unix-bruger, som din Tailscale-identitet er tildelt i tailnets SSH ACL, ikke nødvendigvis root.", + "tailscaleDeviceSelect": "Vælg Tailscale-enhed", + "tailscaleDeviceSelectPlaceholder": "Vælg en enhed...", + "tailscaleNoApiKey": "Ingen Tailscale API-nøgle konfigureret. Tilføj en i administratorindstillinger for at aktivere enhedsregistrering.", + "tailscaleDocsLink": "Se dokumenter", + "tailscaleLoadingDevices": "Indlæser enheder...", + "tailscaleDeviceLoadFailed": "Kunne ikke indlæse Tailscale-enheder. Kontroller API-URL'en og netværksforbindelsen.", + "tailscaleNoDevices": "Ingen enheder fundet i dit tailnet.", + "tailscaleDeviceAutoFill": "Hvis du vælger en enhed, udfyldes værtens IP-adresse automatisk." + }, + "terminal": { + "tailscaleCheckRequired": "Tailscale-godkendelse påkrævet", + "tailscaleCheckDescription": "Tailscale SSH kræver en yderligere kontrol. Godkend i din browser for at fortsætte.", + "tailscaleCheckOpenBrowser": "Åbn browseren for at godkende", + "tailscaleCheckWaiting": "Venter på Tailscale-godkendelse...", + "tailscaleCheckTimeout": "Tailscale-godkendelsen er udløbet. Prøv igen." + } +} diff --git a/plugins/tailscale/locales/translated/de_DE.json b/plugins/tailscale/locales/translated/de_DE.json new file mode 100644 index 000000000..ba33133ea --- /dev/null +++ b/plugins/tailscale/locales/translated/de_DE.json @@ -0,0 +1,20 @@ +{ + "hosts": { + "tailscaleUsernameHint": "Es muss sich um einen Unix-Benutzer handeln, dem Ihre Tailscale-Identität in der SSH-ACL des Tailnets gewährt wird, nicht unbedingt um den Root-Benutzer.", + "tailscaleDeviceSelect": "Tailscale-Gerät auswählen", + "tailscaleDeviceSelectPlaceholder": "Gerät auswählen...", + "tailscaleNoApiKey": "Kein Tailscale API-Schlüssel konfiguriert. Fügen Sie einen in den Admin-Einstellungen hinzu, um die Geräteerkennung zu aktivieren.", + "tailscaleDocsLink": "Dokumentation anzeigen", + "tailscaleLoadingDevices": "Geräte werden geladen...", + "tailscaleDeviceLoadFailed": "Die Tailscale-Geräte konnten nicht geladen werden. Bitte überprüfen Sie die API-URL und die Netzwerkverbindung.", + "tailscaleNoDevices": "Keine Geräte in Ihrem Tailnet gefunden.", + "tailscaleDeviceAutoFill": "Die Auswahl eines Geräts füllt die Host-IP-Adresse automatisch aus." + }, + "terminal": { + "tailscaleCheckRequired": "Tailscale-Authentifizierung erforderlich", + "tailscaleCheckDescription": "Tailscale SSH erfordert eine zusätzliche Überprüfung. Authentifizieren Sie sich in Ihrem Browser, um fortzufahren.", + "tailscaleCheckOpenBrowser": "Öffnen Sie den Browser zur Authentifizierung", + "tailscaleCheckWaiting": "Warten auf Tailscale-Authentifizierung...", + "tailscaleCheckTimeout": "Die Tailscale-Authentifizierung ist fehlgeschlagen. Bitte versuchen Sie es erneut." + } +} diff --git a/plugins/tailscale/locales/translated/el_GR.json b/plugins/tailscale/locales/translated/el_GR.json new file mode 100644 index 000000000..e313c5040 --- /dev/null +++ b/plugins/tailscale/locales/translated/el_GR.json @@ -0,0 +1,20 @@ +{ + "hosts": { + "tailscaleUsernameHint": "Αυτός πρέπει να είναι χρήστης Unix. Η ταυτότητα Tailscale σας έχει εκχωρηθεί στο SSH ACL του tailnet, όχι απαραίτητα root.", + "tailscaleDeviceSelect": "Επιλογή συσκευής κλίμακας ουράς", + "tailscaleDeviceSelectPlaceholder": "Επιλέξτε μια συσκευή...", + "tailscaleNoApiKey": "Δεν έχει ρυθμιστεί κλειδί API Tailscale. Προσθέστε ένα στις Ρυθμίσεις διαχειριστή για να ενεργοποιήσετε την ανακάλυψη συσκευών.", + "tailscaleDocsLink": "Προβολή εγγράφων", + "tailscaleLoadingDevices": "Φόρτωση συσκευών...", + "tailscaleDeviceLoadFailed": "Αποτυχία φόρτωσης συσκευών Tailscale. Ελέγξτε τη διεύθυνση URL του API και τη σύνδεση δικτύου.", + "tailscaleNoDevices": "Δεν βρέθηκαν συσκευές στο tailnet σας.", + "tailscaleDeviceAutoFill": "Η επιλογή μιας συσκευής θα συμπληρώσει αυτόματα τη διεύθυνση IP του κεντρικού υπολογιστή." + }, + "terminal": { + "tailscaleCheckRequired": "Απαιτείται έλεγχος ταυτότητας κλίμακας ουράς", + "tailscaleCheckDescription": "Το Tailscale SSH απαιτεί έναν επιπλέον έλεγχο. Επαληθεύστε τον κωδικό σας στο πρόγραμμα περιήγησής σας για να συνεχίσετε.", + "tailscaleCheckOpenBrowser": "Άνοιγμα προγράμματος περιήγησης για έλεγχο ταυτότητας", + "tailscaleCheckWaiting": "Αναμονή για έλεγχο ταυτότητας Tailscale...", + "tailscaleCheckTimeout": "Το χρονικό όριο ελέγχου ταυτότητας κλίμακας έληξε. Δοκιμάστε ξανά." + } +} diff --git a/plugins/tailscale/locales/translated/es_ES.json b/plugins/tailscale/locales/translated/es_ES.json new file mode 100644 index 000000000..71cb90cbb --- /dev/null +++ b/plugins/tailscale/locales/translated/es_ES.json @@ -0,0 +1,20 @@ +{ + "hosts": { + "tailscaleUsernameHint": "Debe tratarse de un usuario de Unix cuya identidad de Tailscale se concede en la ACL SSH de tailnet, no necesariamente como root.", + "tailscaleDeviceSelect": "Seleccionar dispositivo Tailscale", + "tailscaleDeviceSelectPlaceholder": "Seleccione un dispositivo...", + "tailscaleNoApiKey": "No se ha configurado ninguna clave de API de Tailscale. Añada una en Ajustes de administración para habilitar el descubrimiento de dispositivos.", + "tailscaleDocsLink": "Ver documentación", + "tailscaleLoadingDevices": "Cargando dispositivos...", + "tailscaleDeviceLoadFailed": "No se pudieron cargar los dispositivos Tailscale. Compruebe la URL de la API y la conexión de red.", + "tailscaleNoDevices": "No se han encontrado dispositivos en tu tailnet.", + "tailscaleDeviceAutoFill": "Al seleccionar un dispositivo se rellenará automáticamente la dirección IP del host." + }, + "terminal": { + "tailscaleCheckRequired": "Se requiere autenticación de Tailscale.", + "tailscaleCheckDescription": "Tailscale SSH requiere una verificación adicional. Autentícate en tu navegador para continuar.", + "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." + } +} diff --git a/plugins/tailscale/locales/translated/fi_FI.json b/plugins/tailscale/locales/translated/fi_FI.json new file mode 100644 index 000000000..ca8566346 --- /dev/null +++ b/plugins/tailscale/locales/translated/fi_FI.json @@ -0,0 +1,20 @@ +{ + "hosts": { + "tailscaleUsernameHint": "Tämän on oltava Unix-käyttäjä, jolle Tailscale-identiteettisi on myönnetty tailnetin SSH ACL:ssä, ei välttämättä pääkäyttäjä.", + "tailscaleDeviceSelect": "Valitse Tailscale-laite", + "tailscaleDeviceSelectPlaceholder": "Valitse laite...", + "tailscaleNoApiKey": "Tailscale API -avainta ei ole määritetty. Lisää sellainen järjestelmänvalvojan asetuksissa, jotta laitteiden löytäminen on mahdollista.", + "tailscaleDocsLink": "Näytä dokumentit", + "tailscaleLoadingDevices": "Laitteita ladataan...", + "tailscaleDeviceLoadFailed": "Tailscale-laitteiden lataus epäonnistui. Tarkista API-URL-osoite ja verkkoyhteys.", + "tailscaleNoDevices": "Hätäverkostasi ei löytynyt laitteita.", + "tailscaleDeviceAutoFill": "Laitteen valinta täyttää isännän IP-osoitteen automaattisesti." + }, + "terminal": { + "tailscaleCheckRequired": "Tailscale-todennus vaaditaan", + "tailscaleCheckDescription": "Tailscale SSH vaatii lisätarkistuksen. Jatka tunnistautumalla selaimessasi.", + "tailscaleCheckOpenBrowser": "Avaa selain todennusta varten", + "tailscaleCheckWaiting": "Odotetaan Tailscale-todennusta...", + "tailscaleCheckTimeout": "Tailscale-todennus aikakatkaistiin. Yritä uudelleen." + } +} diff --git a/plugins/tailscale/locales/translated/fr_FR.json b/plugins/tailscale/locales/translated/fr_FR.json new file mode 100644 index 000000000..f254b15ff --- /dev/null +++ b/plugins/tailscale/locales/translated/fr_FR.json @@ -0,0 +1,20 @@ +{ + "hosts": { + "tailscaleUsernameHint": "Il doit s'agir d'un utilisateur Unix auquel votre identité Tailscale est attribuée dans la liste de contrôle d'accès SSH du réseau Tailnet, pas nécessairement root.", + "tailscaleDeviceSelect": "Sélectionner un appareil Tailscale", + "tailscaleDeviceSelectPlaceholder": "Sélectionner un appareil...", + "tailscaleNoApiKey": "Aucune clé API Tailscale configurée. Ajoutez-en une dans les paramètres d'administration pour activer la découverte d'appareils.", + "tailscaleDocsLink": "Voir la documentation", + "tailscaleLoadingDevices": "Chargement des appareils...", + "tailscaleDeviceLoadFailed": "Impossible de charger les périphériques Tailscale. Vérifiez l'URL de l'API et votre connexion réseau.", + "tailscaleNoDevices": "Aucun appareil trouvé dans votre tailnet.", + "tailscaleDeviceAutoFill": "La sélection d’un appareil remplira automatiquement l’adresse IP de l’hôte." + }, + "terminal": { + "tailscaleCheckRequired": "Authentification Tailscale requise", + "tailscaleCheckDescription": "Tailscale SSH requiert une vérification supplémentaire. Authentifiez-vous dans votre navigateur pour continuer.", + "tailscaleCheckOpenBrowser": "Ouvrez votre navigateur pour vous authentifier.", + "tailscaleCheckWaiting": "En attente de l'authentification Tailscale...", + "tailscaleCheckTimeout": "L'authentification Tailscale a expiré. Veuillez réessayer." + } +} diff --git a/plugins/tailscale/locales/translated/he_IL.json b/plugins/tailscale/locales/translated/he_IL.json new file mode 100644 index 000000000..ec11ffd09 --- /dev/null +++ b/plugins/tailscale/locales/translated/he_IL.json @@ -0,0 +1,20 @@ +{ + "hosts": { + "tailscaleUsernameHint": "זה חייב להיות משתמש יוניקס שזהות Tailscale שלך מוענקת לו ב-SSH ACL של tailnet, לאו דווקא root.", + "tailscaleDeviceSelect": "בחר מכשיר Tailscale", + "tailscaleDeviceSelectPlaceholder": "בחר מכשיר...", + "tailscaleNoApiKey": "לא הוגדר מפתח API של Tailscale. הוסף אחד בהגדרות הניהול כדי לאפשר גילוי מכשירים.", + "tailscaleDocsLink": "הצג מסמכים", + "tailscaleLoadingDevices": "טוען מכשירים...", + "tailscaleDeviceLoadFailed": "טעינת התקני Tailscale נכשלה. בדוק את כתובת ה-URL של ה-API ואת חיבור הרשת.", + "tailscaleNoDevices": "לא נמצאו מכשירים ברשת הזנב שלך.", + "tailscaleDeviceAutoFill": "בחירת מכשיר תמלא אוטומטית את כתובת ה-IP של המארח." + }, + "terminal": { + "tailscaleCheckRequired": "נדרש אימות של Tailscale", + "tailscaleCheckDescription": "‏SSH של Tailscale דורש בדיקה נוספת. יש לבצע אימות בדפדפן כדי להמשיך.", + "tailscaleCheckOpenBrowser": "פתח את הדפדפן כדי לאמת", + "tailscaleCheckWaiting": "ממתין לאימות Tailscale...", + "tailscaleCheckTimeout": "אימות Tailscale הסתיים. אנא נסה שוב." + } +} diff --git a/plugins/tailscale/locales/translated/hi_IN.json b/plugins/tailscale/locales/translated/hi_IN.json new file mode 100644 index 000000000..ff7246bd1 --- /dev/null +++ b/plugins/tailscale/locales/translated/hi_IN.json @@ -0,0 +1,20 @@ +{ + "hosts": { + "tailscaleUsernameHint": "यह एक यूनिक्स उपयोगकर्ता होना चाहिए जिसे टेलनेट के एसएसएच एसीएल में आपकी टेलस्केल पहचान प्रदान की गई हो, जरूरी नहीं कि यह रूट हो।", + "tailscaleDeviceSelect": "Tailscale डिवाइस चुनें", + "tailscaleDeviceSelectPlaceholder": "एक डिवाइस चुनें...", + "tailscaleNoApiKey": "कोई Tailscale API कुंजी कॉन्फ़िगर नहीं की गई है। डिवाइस खोज सक्षम करने के लिए व्यवस्थापक सेटिंग में एक जोड़ें।", + "tailscaleDocsLink": "दस्तावेज़ देखें", + "tailscaleLoadingDevices": "उपकरण लोड हो रहे हैं...", + "tailscaleDeviceLoadFailed": "टेलस्केल डिवाइस लोड करने में विफल। कृपया एपीआई यूआरएल और नेटवर्क कनेक्शन की जांच करें।", + "tailscaleNoDevices": "आपके टेलनेट में कोई उपकरण नहीं मिला।", + "tailscaleDeviceAutoFill": "डिवाइस चुनने पर होस्ट IP पता स्वतः भर जाएगा।" + }, + "terminal": { + "tailscaleCheckRequired": "टेलस्केल प्रमाणीकरण आवश्यक है", + "tailscaleCheckDescription": "Tailscale SSH के लिए एक अतिरिक्त जांच की आवश्यकता है। जारी रखने के लिए अपने ब्राउज़र में प्रमाणीकरण करें।", + "tailscaleCheckOpenBrowser": "प्रमाणीकरण के लिए ब्राउज़र खोलें", + "tailscaleCheckWaiting": "टेलस्केल प्रमाणीकरण की प्रतीक्षा की जा रही है...", + "tailscaleCheckTimeout": "टेलस्केल प्रमाणीकरण का समय समाप्त हो गया। कृपया पुनः प्रयास करें।" + } +} diff --git a/plugins/tailscale/locales/translated/hu_HU.json b/plugins/tailscale/locales/translated/hu_HU.json new file mode 100644 index 000000000..d50fbdea4 --- /dev/null +++ b/plugins/tailscale/locales/translated/hu_HU.json @@ -0,0 +1,20 @@ +{ + "hosts": { + "tailscaleUsernameHint": "Ennek Unix felhasználónak kell lennie, akinek a Tailscale identitását a tailnet SSH ACL-jében adták meg, nem feltétlenül root felhasználónak.", + "tailscaleDeviceSelect": "Tailscale eszköz kiválasztása", + "tailscaleDeviceSelectPlaceholder": "Válasszon egy eszközt...", + "tailscaleNoApiKey": "Nincs konfigurálva Tailscale API-kulcs. Adjon hozzá egyet az adminisztrátori beállításokban az eszközfelderítés engedélyezéséhez.", + "tailscaleDocsLink": "Dokumentumok megtekintése", + "tailscaleLoadingDevices": "Eszközök betöltése...", + "tailscaleDeviceLoadFailed": "Nem sikerült betölteni a Tailscale eszközöket. Ellenőrizze az API URL-t és a hálózati kapcsolatot.", + "tailscaleNoDevices": "Nem találhatók eszközök a hátsó hálózatban.", + "tailscaleDeviceAutoFill": "Egy eszköz kiválasztása automatikusan kitölti a gazdagép IP-címét." + }, + "terminal": { + "tailscaleCheckRequired": "Tailscale hitelesítés szükséges", + "tailscaleCheckDescription": "A Tailscale SSH további ellenőrzést igényel. A folytatáshoz hitelesítse magát a böngészőjében.", + "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." + } +} diff --git a/plugins/tailscale/locales/translated/id_ID.json b/plugins/tailscale/locales/translated/id_ID.json new file mode 100644 index 000000000..b54adebd1 --- /dev/null +++ b/plugins/tailscale/locales/translated/id_ID.json @@ -0,0 +1,20 @@ +{ + "hosts": { + "tailscaleUsernameHint": "Ini harus berupa pengguna Unix yang identitas Tailscale Anda diberikan dalam ACL SSH tailnet, tidak harus root.", + "tailscaleDeviceSelect": "Pilih perangkat Tailscale", + "tailscaleDeviceSelectPlaceholder": "Pilih perangkat...", + "tailscaleNoApiKey": "Belum ada kunci API Tailscale yang dikonfigurasi. Tambahkan satu di Pengaturan Admin untuk mengaktifkan penemuan perangkat.", + "tailscaleDocsLink": "Lihat dokumen", + "tailscaleLoadingDevices": "Memuat perangkat...", + "tailscaleDeviceLoadFailed": "Gagal memuat perangkat Tailscale. Periksa URL API dan koneksi jaringan.", + "tailscaleNoDevices": "Tidak ada perangkat yang terdeteksi di tailnet Anda.", + "tailscaleDeviceAutoFill": "Memilih perangkat akan secara otomatis mengisi alamat IP host." + }, + "terminal": { + "tailscaleCheckRequired": "Diperlukan Otentikasi Sisik Ekor", + "tailscaleCheckDescription": "Tailscale SSH memerlukan pemeriksaan tambahan. Lakukan otentikasi di browser Anda untuk melanjutkan.", + "tailscaleCheckOpenBrowser": "Buka Browser untuk Melakukan Otentikasi", + "tailscaleCheckWaiting": "Menunggu autentikasi Tailscale...", + "tailscaleCheckTimeout": "Autentikasi Tailscale habis waktu. Silakan coba lagi." + } +} diff --git a/plugins/tailscale/locales/translated/it_IT.json b/plugins/tailscale/locales/translated/it_IT.json new file mode 100644 index 000000000..c37688dc2 --- /dev/null +++ b/plugins/tailscale/locales/translated/it_IT.json @@ -0,0 +1,20 @@ +{ + "hosts": { + "tailscaleUsernameHint": "Deve trattarsi di un utente Unix a cui è concessa l'identità Tailscale nell'ACL SSH di Tailnet, non necessariamente root.", + "tailscaleDeviceSelect": "Seleziona dispositivo Tailscale", + "tailscaleDeviceSelectPlaceholder": "Seleziona un dispositivo...", + "tailscaleNoApiKey": "Nessuna chiave API Tailscale configurata. Aggiungine una in Impostazioni amministratore per abilitare il rilevamento dispositivi.", + "tailscaleDocsLink": "Visualizza documentazione", + "tailscaleLoadingDevices": "Caricamento dispositivi...", + "tailscaleDeviceLoadFailed": "Impossibile caricare i dispositivi Tailscale. Verificare l'URL dell'API e la connessione di rete.", + "tailscaleNoDevices": "Nessun dispositivo trovato nel tuo tailnet.", + "tailscaleDeviceAutoFill": "Selezionando un dispositivo l'indirizzo IP dell'host verrà compilato automaticamente." + }, + "terminal": { + "tailscaleCheckRequired": "Autenticazione Tailscale richiesta", + "tailscaleCheckDescription": "Tailscale SSH richiede un controllo aggiuntivo. Autenticati nel tuo browser per continuare.", + "tailscaleCheckOpenBrowser": "Apri il browser per autenticarti", + "tailscaleCheckWaiting": "In attesa dell'autenticazione di Tailscale...", + "tailscaleCheckTimeout": "Autenticazione di Tailscale scaduta. Riprova." + } +} diff --git a/plugins/tailscale/locales/translated/ja_JP.json b/plugins/tailscale/locales/translated/ja_JP.json new file mode 100644 index 000000000..be8fd5368 --- /dev/null +++ b/plugins/tailscale/locales/translated/ja_JP.json @@ -0,0 +1,20 @@ +{ + "hosts": { + "tailscaleUsernameHint": "これは、tailnetのSSH ACLでTailscaleのIDが付与されているUnixユーザーである必要があり、必ずしもrootである必要はありません。", + "tailscaleDeviceSelect": "Tailscaleデバイスを選択", + "tailscaleDeviceSelectPlaceholder": "デバイスを選択...", + "tailscaleNoApiKey": "Tailscale APIキーが設定されていません。デバイス検出を有効にするには、管理者設定で追加してください。", + "tailscaleDocsLink": "ドキュメントを表示", + "tailscaleLoadingDevices": "デバイスを読み込み中...", + "tailscaleDeviceLoadFailed": "Tailscaleデバイスの読み込みに失敗しました。API URLとネットワーク接続を確認してください。", + "tailscaleNoDevices": "テールネットにデバイスが見つかりません。", + "tailscaleDeviceAutoFill": "デバイスを選択するとホストIPアドレスが自動入力されます。" + }, + "terminal": { + "tailscaleCheckRequired": "テールスケール認証が必要です", + "tailscaleCheckDescription": "TailscaleのSSH接続には追加の認証が必要です。ブラウザで認証を行ってから続行してください。", + "tailscaleCheckOpenBrowser": "認証のためにブラウザを開く", + "tailscaleCheckWaiting": "Tailscaleの認証を待っています...", + "tailscaleCheckTimeout": "Tailscaleの認証がタイムアウトしました。もう一度お試しください。" + } +} diff --git a/plugins/tailscale/locales/translated/ko_KR.json b/plugins/tailscale/locales/translated/ko_KR.json new file mode 100644 index 000000000..264cd8654 --- /dev/null +++ b/plugins/tailscale/locales/translated/ko_KR.json @@ -0,0 +1,20 @@ +{ + "hosts": { + "tailscaleUsernameHint": "이 값은 Tailscale ID가 Tailnet의 SSH ACL에 부여된 Unix 사용자여야 하며, 반드시 root일 필요는 없습니다.", + "tailscaleDeviceSelect": "Tailscale 기기 선택", + "tailscaleDeviceSelectPlaceholder": "기기 선택...", + "tailscaleNoApiKey": "Tailscale API 키가 구성되지 않았습니다. 기기 검색을 활성화하려면 관리자 설정에서 추가하세요.", + "tailscaleDocsLink": "문서 보기", + "tailscaleLoadingDevices": "장치를 불러오는 중...", + "tailscaleDeviceLoadFailed": "Tailscale 장치를 불러오는 데 실패했습니다. API URL과 네트워크 연결을 확인하세요.", + "tailscaleNoDevices": "테일넷에서 장치를 찾을 수 없습니다.", + "tailscaleDeviceAutoFill": "장치를 선택하면 호스트 IP 주소가 자동으로 채워집니다." + }, + "terminal": { + "tailscaleCheckRequired": "Tailscale 인증이 필요합니다.", + "tailscaleCheckDescription": "Tailscale SSH는 추가 인증이 필요합니다. 계속하려면 브라우저에서 인증하십시오.", + "tailscaleCheckOpenBrowser": "인증하려면 브라우저를 여세요", + "tailscaleCheckWaiting": "Tailscale 인증을 기다리는 중...", + "tailscaleCheckTimeout": "Tailscale 인증 시간이 초과되었습니다. 다시 시도해 주세요." + } +} diff --git a/plugins/tailscale/locales/translated/nl_NL.json b/plugins/tailscale/locales/translated/nl_NL.json new file mode 100644 index 000000000..55dfab20f --- /dev/null +++ b/plugins/tailscale/locales/translated/nl_NL.json @@ -0,0 +1,20 @@ +{ + "hosts": { + "tailscaleUsernameHint": "Dit moet een Unix-gebruiker zijn die aan uw Tailscale-identiteit is toegekend in de SSH-toegangsregel van het tailnet, niet per se root.", + "tailscaleDeviceSelect": "Selecteer het Tailscale-apparaat", + "tailscaleDeviceSelectPlaceholder": "Selecteer een apparaat...", + "tailscaleNoApiKey": "Er is geen Tailscale API-sleutel geconfigureerd. Voeg er een toe in de beheerdersinstellingen om apparaatdetectie in te schakelen.", + "tailscaleDocsLink": "Documenten bekijken", + "tailscaleLoadingDevices": "Apparaten laden...", + "tailscaleDeviceLoadFailed": "Het laden van Tailscale-apparaten is mislukt. Controleer de API-URL en de netwerkverbinding.", + "tailscaleNoDevices": "Geen apparaten gevonden in uw achternet.", + "tailscaleDeviceAutoFill": "Als je een apparaat selecteert, wordt het IP-adres van de host automatisch ingevuld." + }, + "terminal": { + "tailscaleCheckRequired": "Tailscale-authenticatie vereist", + "tailscaleCheckDescription": "Tailscale SSH vereist een extra controle. Authenticeer in uw browser om verder te gaan.", + "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." + } +} diff --git a/plugins/tailscale/locales/translated/no_NO.json b/plugins/tailscale/locales/translated/no_NO.json new file mode 100644 index 000000000..80601ec09 --- /dev/null +++ b/plugins/tailscale/locales/translated/no_NO.json @@ -0,0 +1,20 @@ +{ + "hosts": { + "tailscaleUsernameHint": "Dette må være en Unix-bruker som Tailscale-identiteten din er gitt i tailnets SSH ACL, ikke nødvendigvis root.", + "tailscaleDeviceSelect": "Velg Tailscale-enhet", + "tailscaleDeviceSelectPlaceholder": "Velg en enhet...", + "tailscaleNoApiKey": "Ingen Tailscale API-nøkkel konfigurert. Legg til en i administratorinnstillingene for å aktivere enhetsgjenkjenning.", + "tailscaleDocsLink": "Vis dokumenter", + "tailscaleLoadingDevices": "Laster inn enheter ...", + "tailscaleDeviceLoadFailed": "Kunne ikke laste inn Tailscale-enheter. Sjekk API-URL-en og nettverkstilkoblingen.", + "tailscaleNoDevices": "Ingen enheter funnet i halenettverket ditt.", + "tailscaleDeviceAutoFill": "Hvis du velger en enhet, fylles verts-IP-adressen automatisk ut." + }, + "terminal": { + "tailscaleCheckRequired": "Tailscale-autentisering kreves", + "tailscaleCheckDescription": "Tailscale SSH krever en ekstra sjekk. Autentiser i nettleseren din for å fortsette.", + "tailscaleCheckOpenBrowser": "Åpne nettleseren for å autentisere", + "tailscaleCheckWaiting": "Venter på Tailscale-autentisering...", + "tailscaleCheckTimeout": "Tailscale-autentiseringen er tidsavbrutt. Prøv på nytt." + } +} diff --git a/plugins/tailscale/locales/translated/pl_PL.json b/plugins/tailscale/locales/translated/pl_PL.json new file mode 100644 index 000000000..ecefdc425 --- /dev/null +++ b/plugins/tailscale/locales/translated/pl_PL.json @@ -0,0 +1,20 @@ +{ + "hosts": { + "tailscaleUsernameHint": "Musi to być użytkownik systemu Unix, któremu Twoja tożsamość Tailscale została przyznana w ACL SSH sieci tailnet, niekoniecznie root.", + "tailscaleDeviceSelect": "Wybierz urządzenie Tailscale", + "tailscaleDeviceSelectPlaceholder": "Wybierz urządzenie...", + "tailscaleNoApiKey": "Nie skonfigurowano klucza API Tailscale. Dodaj go w Ustawieniach administratora, aby włączyć wykrywanie urządzeń.", + "tailscaleDocsLink": "Zobacz dokumentację", + "tailscaleLoadingDevices": "Ładowanie urządzeń...", + "tailscaleDeviceLoadFailed": "Nie udało się załadować urządzeń Tailscale. Sprawdź adres URL API i połączenie sieciowe.", + "tailscaleNoDevices": "Nie znaleziono urządzeń w Twojej sieci tailnet.", + "tailscaleDeviceAutoFill": "Wybranie urządzenia spowoduje automatyczne wypełnienie adresu IP hosta." + }, + "terminal": { + "tailscaleCheckRequired": "Wymagane uwierzytelnienie Tailscale", + "tailscaleCheckDescription": "Tailscale SSH wymaga dodatkowej weryfikacji. Uwierzytelnij się w przeglądarce, aby kontynuować.", + "tailscaleCheckOpenBrowser": "Otwórz przeglądarkę, aby uwierzytelnić", + "tailscaleCheckWaiting": "Oczekiwanie na uwierzytelnienie Tailscale...", + "tailscaleCheckTimeout": "Upłynął limit czasu uwierzytelniania Tailscale. Spróbuj ponownie." + } +} diff --git a/plugins/tailscale/locales/translated/pt_BR.json b/plugins/tailscale/locales/translated/pt_BR.json new file mode 100644 index 000000000..9ab5b1086 --- /dev/null +++ b/plugins/tailscale/locales/translated/pt_BR.json @@ -0,0 +1,20 @@ +{ + "hosts": { + "tailscaleUsernameHint": "Este deve ser um usuário Unix cuja identidade Tailscale é concedida na ACL SSH da tailnet, não necessariamente o usuário root.", + "tailscaleDeviceSelect": "Selecione o dispositivo Tailscale", + "tailscaleDeviceSelectPlaceholder": "Selecione um dispositivo...", + "tailscaleNoApiKey": "Nenhuma chave de API do Tailscale configurada. Adicione uma nas Configurações de Administrador para habilitar a descoberta de dispositivos.", + "tailscaleDocsLink": "Ver documentos", + "tailscaleLoadingDevices": "Carregando dispositivos...", + "tailscaleDeviceLoadFailed": "Falha ao carregar os dispositivos Tailscale. Verifique o URL da API e a conexão de rede.", + "tailscaleNoDevices": "Nenhum dispositivo encontrado em sua rede traseira.", + "tailscaleDeviceAutoFill": "Ao selecionar um dispositivo, o endereço IP do host será preenchido automaticamente." + }, + "terminal": { + "tailscaleCheckRequired": "Autenticação Tailscale necessária", + "tailscaleCheckDescription": "O Tailscale SSH requer uma verificação adicional. Autentique-se no seu navegador para continuar.", + "tailscaleCheckOpenBrowser": "Abra o navegador para autenticar.", + "tailscaleCheckWaiting": "Aguardando autenticação do Tailscale...", + "tailscaleCheckTimeout": "A autenticação no Tailscale expirou. Tente novamente." + } +} diff --git a/plugins/tailscale/locales/translated/pt_PT.json b/plugins/tailscale/locales/translated/pt_PT.json new file mode 100644 index 000000000..fc6cc11a6 --- /dev/null +++ b/plugins/tailscale/locales/translated/pt_PT.json @@ -0,0 +1,20 @@ +{ + "hosts": { + "tailscaleUsernameHint": "Este deve ser um utilizador Unix cuja identidade Tailscale é concedida na ACL SSH da tailnet, não necessariamente o utilizador root.", + "tailscaleDeviceSelect": "Selecionar dispositivo Tailscale", + "tailscaleDeviceSelectPlaceholder": "Selecionar um dispositivo...", + "tailscaleNoApiKey": "Nenhuma chave de API Tailscale configurada. Adicione uma nas Definições de Administrador para ativar a descoberta de dispositivos.", + "tailscaleDocsLink": "Ver documentação", + "tailscaleLoadingDevices": "A carregar dispositivos...", + "tailscaleDeviceLoadFailed": "Falha ao carregar os dispositivos Tailscale. Verifique o URL da API e a ligação de rede.", + "tailscaleNoDevices": "Nenhum dispositivo encontrado na sua tailnet.", + "tailscaleDeviceAutoFill": "Selecionar um dispositivo preencherá automaticamente o endereço IP do host." + }, + "terminal": { + "tailscaleCheckRequired": "Autenticação Tailscale necessária", + "tailscaleCheckDescription": "O Tailscale SSH requer uma verificação adicional. Autentique-se no seu browser para continuar.", + "tailscaleCheckOpenBrowser": "Abra o browser para autenticar.", + "tailscaleCheckWaiting": "Aguarda-se autenticação do Tailscale...", + "tailscaleCheckTimeout": "A autenticação no Tailscale expirou. Tente novamente." + } +} diff --git a/plugins/tailscale/locales/translated/ro_RO.json b/plugins/tailscale/locales/translated/ro_RO.json new file mode 100644 index 000000000..88d9ebca7 --- /dev/null +++ b/plugins/tailscale/locales/translated/ro_RO.json @@ -0,0 +1,20 @@ +{ + "hosts": { + "tailscaleUsernameHint": "Acesta trebuie să fie un utilizator Unix căruia îi este acordată identitatea Tailscale în ACL-ul SSH al rețelei tailnet, nu neapărat root.", + "tailscaleDeviceSelect": "Selectați dispozitivul Tailscale", + "tailscaleDeviceSelectPlaceholder": "Selectați un dispozitiv...", + "tailscaleNoApiKey": "Nu este configurată nicio cheie API Tailscale. Adăugați una în Setările de administrare pentru a activa descoperirea dispozitivelor.", + "tailscaleDocsLink": "Vizualizați documentele", + "tailscaleLoadingDevices": "Se încarcă dispozitivele...", + "tailscaleDeviceLoadFailed": "Nu s-au putut încărca dispozitivele Tailscale. Verificați adresa URL API și conexiunea la rețea.", + "tailscaleNoDevices": "Nu s-au găsit dispozitive în rețeaua ta de coadă.", + "tailscaleDeviceAutoFill": "Selectarea unui dispozitiv va completa automat adresa IP a gazdei." + }, + "terminal": { + "tailscaleCheckRequired": "Autentificare la scară mică necesară", + "tailscaleCheckDescription": "SSH-ul Tailscale necesită o verificare suplimentară. Autentificați-vă în browser pentru a continua.", + "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." + } +} diff --git a/plugins/tailscale/locales/translated/ru_RU.json b/plugins/tailscale/locales/translated/ru_RU.json new file mode 100644 index 000000000..9a47b9dbc --- /dev/null +++ b/plugins/tailscale/locales/translated/ru_RU.json @@ -0,0 +1,20 @@ +{ + "hosts": { + "tailscaleUsernameHint": "Это должен быть пользователь Unix, которому предоставлена идентификация Tailscale в списке контроля доступа SSH сети TailNet, а не обязательно root.", + "tailscaleDeviceSelect": "Выберите устройство Tailscale", + "tailscaleDeviceSelectPlaceholder": "Выберите устройство...", + "tailscaleNoApiKey": "Ключ API Tailscale не настроен. Добавьте его в настройках администратора, чтобы включить обнаружение устройств.", + "tailscaleDocsLink": "Документация", + "tailscaleLoadingDevices": "Загрузка устройств...", + "tailscaleDeviceLoadFailed": "Не удалось загрузить устройства Tailscale. Проверьте URL-адрес API и сетевое соединение.", + "tailscaleNoDevices": "В вашем tailnet не найдено устройств.", + "tailscaleDeviceAutoFill": "При выборе устройства IP-адрес хоста будет заполнен автоматически." + }, + "terminal": { + "tailscaleCheckRequired": "Требуется аутентификация Tailscale", + "tailscaleCheckDescription": "Для работы Tailscale SSH требуется дополнительная проверка. Для продолжения выполните аутентификацию в браузере.", + "tailscaleCheckOpenBrowser": "Откройте браузер для аутентификации.", + "tailscaleCheckWaiting": "Ожидание аутентификации Tailscale...", + "tailscaleCheckTimeout": "Время ожидания аутентификации Tailscale истекло. Пожалуйста, попробуйте еще раз." + } +} diff --git a/plugins/tailscale/locales/translated/sr_SP.json b/plugins/tailscale/locales/translated/sr_SP.json new file mode 100644 index 000000000..2f823dcc5 --- /dev/null +++ b/plugins/tailscale/locales/translated/sr_SP.json @@ -0,0 +1,20 @@ +{ + "hosts": { + "tailscaleUsernameHint": "Ово мора бити Unix корисник чији је идентитет на Tailscale-у додељен у SSH ACL-у Tailnet-а, не нужно root.", + "tailscaleDeviceSelect": "Изаберите уређај Tailscale", + "tailscaleDeviceSelectPlaceholder": "Изаберите уређај...", + "tailscaleNoApiKey": "Није конфигурисан Tailscale API кључ. Додајте га у администраторским подешавањима да бисте омогућили откривање уређаја.", + "tailscaleDocsLink": "Прикажи документе", + "tailscaleLoadingDevices": "Учитавање уређаја...", + "tailscaleDeviceLoadFailed": "Учитавање Tailscale уређаја није успело. Проверите API URL и мрежну везу.", + "tailscaleNoDevices": "Није пронађен ниједан уређај у вашој мрежи.", + "tailscaleDeviceAutoFill": "Избором уређаја ће се аутоматски попунити ИП адреса хоста." + }, + "terminal": { + "tailscaleCheckRequired": "Потребна је аутентификација на таилскалу", + "tailscaleCheckDescription": "Tailscale SSH захтева додатну проверу. Аутентификујте се у прегледачу да бисте наставили.", + "tailscaleCheckOpenBrowser": "Отворите прегледач за аутентификацију", + "tailscaleCheckWaiting": "Чекање на Tailscale аутентификацију...", + "tailscaleCheckTimeout": "Временско ограничење за аутентификацију Tailscale-а је истекло. Молимо покушајте поново." + } +} diff --git a/plugins/tailscale/locales/translated/sv_SE.json b/plugins/tailscale/locales/translated/sv_SE.json new file mode 100644 index 000000000..70eaf08bc --- /dev/null +++ b/plugins/tailscale/locales/translated/sv_SE.json @@ -0,0 +1,20 @@ +{ + "hosts": { + "tailscaleUsernameHint": "Detta måste vara en Unix-användare som din Tailscale-identitet är beviljad i tailnätets SSH ACL, inte nödvändigtvis root.", + "tailscaleDeviceSelect": "Välj Tailscale-enhet", + "tailscaleDeviceSelectPlaceholder": "Välj en enhet...", + "tailscaleNoApiKey": "Ingen Tailscale API-nyckel konfigurerad. Lägg till en i administratörsinställningarna för att aktivera enhetsidentifiering.", + "tailscaleDocsLink": "Visa dokument", + "tailscaleLoadingDevices": "Laddar enheter...", + "tailscaleDeviceLoadFailed": "Misslyckades med att läsa in Tailscale-enheter. Kontrollera API-URL:en och nätverksanslutningen.", + "tailscaleNoDevices": "Inga enheter hittades i ditt tailnet.", + "tailscaleDeviceAutoFill": "Om du väljer en enhet fylls värdens IP-adress automatiskt i." + }, + "terminal": { + "tailscaleCheckRequired": "Tailscale-autentisering krävs", + "tailscaleCheckDescription": "Tailscale SSH kräver en ytterligare kontroll. Autentisera i din webbläsare för att fortsätta.", + "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." + } +} diff --git a/plugins/tailscale/locales/translated/th_TH.json b/plugins/tailscale/locales/translated/th_TH.json new file mode 100644 index 000000000..3c29439f4 --- /dev/null +++ b/plugins/tailscale/locales/translated/th_TH.json @@ -0,0 +1,20 @@ +{ + "hosts": { + "tailscaleUsernameHint": "ผู้ใช้งานนี้ต้องเป็นผู้ใช้ Unix ที่ได้รับสิทธิ์การใช้งาน Tailscale ใน SSH ACL ของ tailnet ไม่จำเป็นต้องเป็น root เสมอไป", + "tailscaleDeviceSelect": "เลือกอุปกรณ์ Tailscale", + "tailscaleDeviceSelectPlaceholder": "เลือกอุปกรณ์...", + "tailscaleNoApiKey": "ไม่ได้กำหนดค่าคีย์ API ของ Tailscale ไว้ โปรดเพิ่มคีย์ใน การตั้งค่าผู้ดูแลระบบ เพื่อเปิดใช้งานการค้นหาอุปกรณ์", + "tailscaleDocsLink": "ดูเอกสาร", + "tailscaleLoadingDevices": "กำลังโหลดอุปกรณ์...", + "tailscaleDeviceLoadFailed": "ไม่สามารถโหลดอุปกรณ์ Tailscale ได้ โปรดตรวจสอบ URL API และการเชื่อมต่อเครือข่าย", + "tailscaleNoDevices": "ไม่พบอุปกรณ์ใดๆ ในเครือข่ายของคุณ", + "tailscaleDeviceAutoFill": "การเลือกอุปกรณ์จะทำให้ระบบกรอกที่อยู่ IP ของโฮสต์โดยอัตโนมัติ" + }, + "terminal": { + "tailscaleCheckRequired": "จำเป็นต้องยืนยันตัวตนด้วย Tailscale", + "tailscaleCheckDescription": "การเชื่อมต่อ Tailscale SSH ต้องการการตรวจสอบเพิ่มเติม โปรดยืนยันตัวตนในเบราว์เซอร์ของคุณเพื่อดำเนินการต่อ", + "tailscaleCheckOpenBrowser": "เปิดเบราว์เซอร์เพื่อยืนยันตัวตน", + "tailscaleCheckWaiting": "กำลังรอการยืนยันตัวตนจาก Tailscale...", + "tailscaleCheckTimeout": "การตรวจสอบสิทธิ์ Tailscale หมดเวลา โปรดลองอีกครั้ง" + } +} diff --git a/plugins/tailscale/locales/translated/tr_TR.json b/plugins/tailscale/locales/translated/tr_TR.json new file mode 100644 index 000000000..dea00bdf3 --- /dev/null +++ b/plugins/tailscale/locales/translated/tr_TR.json @@ -0,0 +1,20 @@ +{ + "hosts": { + "tailscaleUsernameHint": "Bu, Tailscale kimliğinizin tailnet'in SSH erişim kontrol listesinde (ACL) verildiği bir Unix kullanıcısı olmalıdır, mutlaka root olması gerekmez.", + "tailscaleDeviceSelect": "Tailscale cihazı seçin", + "tailscaleDeviceSelectPlaceholder": "Bir cihaz seçin...", + "tailscaleNoApiKey": "Tailscale API anahtarı yapılandırılmamış. Cihaz keşfini etkinleştirmek için Yönetici Ayarları'ndan bir tane ekleyin.", + "tailscaleDocsLink": "Dokümanları görüntüle", + "tailscaleLoadingDevices": "Aygıtlar yükleniyor...", + "tailscaleDeviceLoadFailed": "Tailscale cihazları yüklenemedi. API URL'sini ve ağ bağlantısını kontrol edin.", + "tailscaleNoDevices": "Tailnet'inizde aygıt bulunamadı.", + "tailscaleDeviceAutoFill": "Bir aygıt seçmek, host IP adresini otomatik dolduracaktır." + }, + "terminal": { + "tailscaleCheckRequired": "Tailscale Kimlik Doğrulaması Gerekli", + "tailscaleCheckDescription": "Tailscale SSH ek bir doğrulama gerektiriyor. Devam etmek için tarayıcınızda kimlik doğrulaması yapın.", + "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." + } +} diff --git a/plugins/tailscale/locales/translated/uk_UA.json b/plugins/tailscale/locales/translated/uk_UA.json new file mode 100644 index 000000000..bbc6ae3d0 --- /dev/null +++ b/plugins/tailscale/locales/translated/uk_UA.json @@ -0,0 +1,20 @@ +{ + "hosts": { + "tailscaleUsernameHint": "Це має бути користувач Unix, якому надано ідентифікатор Tailscale у SSH ACL tailnet, не обов'язково root.", + "tailscaleDeviceSelect": "Виберіть пристрій Tailscale", + "tailscaleDeviceSelectPlaceholder": "Виберіть пристрій...", + "tailscaleNoApiKey": "Ключ API Tailscale не налаштовано. Додайте його в налаштуваннях адміністратора, щоб увімкнути виявлення пристроїв.", + "tailscaleDocsLink": "Переглянути документи", + "tailscaleLoadingDevices": "Завантаження пристроїв...", + "tailscaleDeviceLoadFailed": "Не вдалося завантажити пристрої Tailscale. Перевірте URL-адресу API та мережеве з’єднання.", + "tailscaleNoDevices": "У вашій мережі не знайдено жодних пристроїв.", + "tailscaleDeviceAutoFill": "Вибір пристрою призведе до автоматичного заповнення IP-адреси хоста." + }, + "terminal": { + "tailscaleCheckRequired": "Потрібна автентифікація Tailscale", + "tailscaleCheckDescription": "Для Tailscale SSH потрібна додаткова перевірка. Щоб продовжити, автентифікуйтеся у своєму браузері.", + "tailscaleCheckOpenBrowser": "Відкрийте браузер для автентифікації", + "tailscaleCheckWaiting": "Очікування автентифікації Tailscale...", + "tailscaleCheckTimeout": "Час очікування автентифікації Tailscale минув. Будь ласка, спробуйте ще раз." + } +} diff --git a/plugins/tailscale/locales/translated/vi_VN.json b/plugins/tailscale/locales/translated/vi_VN.json new file mode 100644 index 000000000..1e019f82b --- /dev/null +++ b/plugins/tailscale/locales/translated/vi_VN.json @@ -0,0 +1,20 @@ +{ + "hosts": { + "tailscaleUsernameHint": "Đây phải là người dùng Unix mà danh tính Tailscale của bạn được cấp trong ACL SSH của tailnet, không nhất thiết phải là người dùng root.", + "tailscaleDeviceSelect": "Chọn thiết bị Tailscale", + "tailscaleDeviceSelectPlaceholder": "Chọn thiết bị...", + "tailscaleNoApiKey": "Chưa cấu hình khóa API Tailscale. Thêm một khóa trong Cài đặt Quản trị để bật khám phá thiết bị.", + "tailscaleDocsLink": "Xem tài liệu", + "tailscaleLoadingDevices": "Đang tải thiết bị...", + "tailscaleDeviceLoadFailed": "Không thể tải thiết bị Tailscale. Vui lòng kiểm tra URL API và kết nối mạng.", + "tailscaleNoDevices": "Không tìm thấy thiết bị nào trong tailnet của bạn.", + "tailscaleDeviceAutoFill": "Chọn thiết bị sẽ tự động điền địa chỉ IP máy chủ." + }, + "terminal": { + "tailscaleCheckRequired": "Cần xác thực Tailscale", + "tailscaleCheckDescription": "Tailscale SSH yêu cầu kiểm tra bổ sung. Vui lòng xác thực trong trình duyệt của bạn để tiếp tục.", + "tailscaleCheckOpenBrowser": "Mở trình duyệt để xác thực.", + "tailscaleCheckWaiting": "Đang chờ xác thực Tailscale...", + "tailscaleCheckTimeout": "Quá trình xác thực Tailscale đã hết hạn. Vui lòng thử lại." + } +} diff --git a/plugins/tailscale/locales/translated/zh_CN.json b/plugins/tailscale/locales/translated/zh_CN.json new file mode 100644 index 000000000..7e88d4c00 --- /dev/null +++ b/plugins/tailscale/locales/translated/zh_CN.json @@ -0,0 +1,20 @@ +{ + "hosts": { + "tailscaleUsernameHint": "这必须是您在 Tailscale 身份中被授予的 Unix 用户,但不一定是 root 用户。", + "tailscaleDeviceSelect": "选择 Tailscale 设备", + "tailscaleDeviceSelectPlaceholder": "选择设备...", + "tailscaleNoApiKey": "未配置 Tailscale API 密钥。请在管理设置中添加一个以启用设备发现。", + "tailscaleDocsLink": "查看文档", + "tailscaleLoadingDevices": "正在加载设备...", + "tailscaleDeviceLoadFailed": "加载 Tailscale 设备失败。请检查 API URL 和网络连接。", + "tailscaleNoDevices": "在您的 tailnet 中未找到设备。", + "tailscaleDeviceAutoFill": "选择设备将自动填充主机 IP 地址。" + }, + "terminal": { + "tailscaleCheckRequired": "需要 Tailscale 身份验证", + "tailscaleCheckDescription": "Tailscale SSH 需要进行额外的验证。请在浏览器中进行身份验证以继续。", + "tailscaleCheckOpenBrowser": "打开浏览器进行身份验证", + "tailscaleCheckWaiting": "正在等待 Tailscale 身份验证……", + "tailscaleCheckTimeout": "Tailscale 身份验证超时,请重试。" + } +} diff --git a/plugins/tailscale/locales/translated/zh_TW.json b/plugins/tailscale/locales/translated/zh_TW.json new file mode 100644 index 000000000..52c0fd1a1 --- /dev/null +++ b/plugins/tailscale/locales/translated/zh_TW.json @@ -0,0 +1,20 @@ +{ + "hosts": { + "tailscaleUsernameHint": "這必須是您在 Tailscale 身分中被授予的 Unix 用戶,但不一定是 root 用戶。", + "tailscaleDeviceSelect": "選取 Tailscale 裝置", + "tailscaleDeviceSelectPlaceholder": "選取裝置...", + "tailscaleNoApiKey": "未設定 Tailscale API 金鑰。請在管理設定中新增一個以啟用裝置探索。", + "tailscaleDocsLink": "檢視文件", + "tailscaleLoadingDevices": "正在載入裝置...", + "tailscaleDeviceLoadFailed": "載入 Tailscale 設備失敗。請檢查 API URL 和網路連線。", + "tailscaleNoDevices": "在您的 tailnet 中找不到裝置。", + "tailscaleDeviceAutoFill": "選取裝置將自動填入主機 IP 位址。" + }, + "terminal": { + "tailscaleCheckRequired": "需要 Tailscale 身份驗證", + "tailscaleCheckDescription": "Tailscale SSH 需要額外的驗證。請在瀏覽器中進行身份驗證以繼續。", + "tailscaleCheckOpenBrowser": "開啟瀏覽器進行身份驗證", + "tailscaleCheckWaiting": "正在等待 Tailscale 身份驗證…", + "tailscaleCheckTimeout": "Tailscale身份驗證逾時,請重試。" + } +} diff --git a/plugins/tailscale/manifest.json b/plugins/tailscale/manifest.json index 2e2dd4be1..28935015c 100644 --- a/plugins/tailscale/manifest.json +++ b/plugins/tailscale/manifest.json @@ -21,6 +21,13 @@ "ui:surface" ], "contributes": { + "panels": [ + { + "id": "tailscale", + "titleKey": "nav.tailscale", + "icon": "Radar" + } + ], "permissions": [ { "name": "devices.view", diff --git a/plugins/tailscale/src/frontend/TailscaleAuthEditor.tsx b/plugins/tailscale/src/frontend/TailscaleAuthEditor.tsx new file mode 100644 index 000000000..11eb0502e --- /dev/null +++ b/plugins/tailscale/src/frontend/TailscaleAuthEditor.tsx @@ -0,0 +1,122 @@ +import { useEffect, useState } from "react"; +import { + useTranslation, + type SshAuthEditorProps, +} from "@termix/plugin-sdk/frontend"; +import { Select2 } from "@termix/plugin-sdk/ui"; +import { getTailscaleDevices } from "./tailscale-api"; + +interface Device { + id: string; + name: string; + hostname: string; + addresses: string[]; + os: string; + lastSeen: string; +} + +function tailnetAddress(device: Device): string { + return ( + device.addresses.find((address) => address.startsWith("100.")) ?? + device.addresses[0] ?? + "" + ); +} + +/** + * The host editor's "tailscale" auth method: pick a tailnet device and its + * address fills the host's IP. + */ +export function TailscaleAuthEditor({ form, setField }: SshAuthEditorProps) { + const { t } = useTranslation(); + const [devices, setDevices] = useState([]); + const [hasApiKey, setHasApiKey] = useState(false); + const [loading, setLoading] = useState(true); + const [failed, setFailed] = useState(false); + + useEffect(() => { + let cancelled = false; + setLoading(true); + setFailed(false); + getTailscaleDevices() + .then((result) => { + if (cancelled) return; + setDevices(result?.devices ?? []); + setHasApiKey(result?.hasApiKey ?? false); + setFailed(!!result?.error); + }) + .catch(() => { + if (!cancelled) setFailed(true); + }) + .finally(() => { + if (!cancelled) setLoading(false); + }); + return () => { + cancelled = true; + }; + }, []); + + const ip = String(form.ip ?? ""); + + return ( +
+
+ + + {t("hosts.tailscaleDocsLink")} + +
+ {loading ? ( +

+ {t("hosts.tailscaleLoadingDevices")} +

+ ) : failed ? ( +

+ {t("hosts.tailscaleDeviceLoadFailed")} +

+ ) : !hasApiKey ? ( +

+ {t("hosts.tailscaleNoApiKey")} +

+ ) : devices.length === 0 ? ( +

+ {t("hosts.tailscaleNoDevices")} +

+ ) : ( + <> + device.addresses.includes(ip))?.id ?? "" + } + onChange={(event) => { + const device = devices.find( + (item) => item.id === event.target.value, + ); + if (device) setField("ip", tailnetAddress(device)); + }} + > + + {devices.map((device) => ( + + ))} + +

+ {t("hosts.tailscaleDeviceAutoFill")} +

+ + )} +
+ ); +} diff --git a/plugins/tailscale/src/frontend/TailscaleCheckDialog.tsx b/plugins/tailscale/src/frontend/TailscaleCheckDialog.tsx index 2cdb6f1bf..1cbe4c237 100644 --- a/plugins/tailscale/src/frontend/TailscaleCheckDialog.tsx +++ b/plugins/tailscale/src/frontend/TailscaleCheckDialog.tsx @@ -1,7 +1,7 @@ import React from "react"; import { Button } from "@/components/button.tsx"; import { Shield, ExternalLink, Loader2 } from "lucide-react"; -import { useTranslation } from "react-i18next"; +import { useTranslation } from "@termix/plugin-sdk/frontend"; interface TailscaleCheckDialogProps { isOpen: boolean; diff --git a/plugins/tailscale/src/frontend/TailscaleCheckOverlay.tsx b/plugins/tailscale/src/frontend/TailscaleCheckOverlay.tsx new file mode 100644 index 000000000..971880e2a --- /dev/null +++ b/plugins/tailscale/src/frontend/TailscaleCheckOverlay.tsx @@ -0,0 +1,101 @@ +import { useEffect, useRef, useState } from "react"; +import { useTranslation } from "@termix/plugin-sdk/frontend"; +import type { TerminalOverlayProps } from "@/features/terminal/terminal-slots"; +import { TailscaleCheckDialog } from "./TailscaleCheckDialog"; + +/** How long Tailscale may hold a connection open waiting on approval. */ +const CHECK_TIMEOUT_MS = 30 * 60 * 1000; + +interface CheckState { + authUrl: string; + message?: string; + stage: "prompt" | "waiting"; +} + +/** + * Tailscale SSH can hold a connection open until the user approves it in a + * browser. The terminal's server messages say when, and this pauses the + * connect timeout and shows the approval link meanwhile. + */ +export function TailscaleCheckOverlay({ + subscribe, + holdConnectTimeout, + fail, + disconnect, + backgroundColor, +}: TerminalOverlayProps) { + const { t } = useTranslation(); + const [check, setCheck] = useState(null); + const timerRef = useRef | null>(null); + const heldRef = useRef(false); + + useEffect(() => { + const release = () => { + if (timerRef.current) clearTimeout(timerRef.current); + timerRef.current = null; + if (heldRef.current) { + heldRef.current = false; + holdConnectTimeout(false); + } + setCheck(null); + }; + + const unsubscribe = subscribe((message) => { + if (message.type === "tailscale_check_required") { + if (!heldRef.current) { + heldRef.current = true; + holdConnectTimeout(true); + } + setCheck({ + authUrl: typeof message.url === "string" ? message.url : "", + message: + typeof message.message === "string" ? message.message : undefined, + stage: "prompt", + }); + if (timerRef.current) clearTimeout(timerRef.current); + timerRef.current = setTimeout(() => { + release(); + fail(t("terminal.tailscaleCheckTimeout")); + }, CHECK_TIMEOUT_MS); + } else if ( + message.type === "tailscale_check_completed" || + message.type === "session_closed" + ) { + release(); + } + }); + + return () => { + unsubscribe(); + release(); + }; + }, [subscribe, holdConnectTimeout, fail, t]); + + if (!check) return null; + + return ( + { + if (timerRef.current) clearTimeout(timerRef.current); + timerRef.current = null; + if (heldRef.current) { + heldRef.current = false; + holdConnectTimeout(false); + } + setCheck(null); + disconnect(); + }} + onOpenUrl={() => { + window.open(check.authUrl, "_blank"); + setCheck((current) => + current ? { ...current, stage: "waiting" } : null, + ); + }} + backgroundColor={backgroundColor} + /> + ); +} diff --git a/plugins/tailscale/src/frontend/TailscaleDevicesPanel.tsx b/plugins/tailscale/src/frontend/TailscaleDevicesPanel.tsx index 06ffcf371..dd1b347e9 100644 --- a/plugins/tailscale/src/frontend/TailscaleDevicesPanel.tsx +++ b/plugins/tailscale/src/frontend/TailscaleDevicesPanel.tsx @@ -1,11 +1,11 @@ import { useEffect, useState } from "react"; -import { useTranslation } from "react-i18next"; +import { useTranslation } from "@termix/plugin-sdk/frontend"; import { Loader2, RefreshCw, Terminal } from "lucide-react"; import { Button } from "@/components/button"; import { Input } from "@/components/input"; import type { Host } from "@/types/ui-types"; import { getTailscaleDevices } from "./tailscale-api"; -import { createQuickConnectHost } from "../../../../src/ui/sidebar/quick-connect-host"; +import { createQuickConnectHost } from "@/sidebar/quick-connect-host"; interface TailscaleDevice { id: string; diff --git a/src/ui/settings/components/TailscaleDevicesStatus.tsx b/plugins/tailscale/src/frontend/TailscaleDevicesStatus.tsx similarity index 86% rename from src/ui/settings/components/TailscaleDevicesStatus.tsx rename to plugins/tailscale/src/frontend/TailscaleDevicesStatus.tsx index 6a0a0f9ef..ef8062fb9 100644 --- a/src/ui/settings/components/TailscaleDevicesStatus.tsx +++ b/plugins/tailscale/src/frontend/TailscaleDevicesStatus.tsx @@ -10,12 +10,11 @@ */ import { useCallback, useEffect, useState } from "react"; -import { useTranslation } from "react-i18next"; +import { useTranslation } from "@termix/plugin-sdk/frontend"; import { Loader2, RefreshCw } from "lucide-react"; import { Button } from "@/components/button"; -import { pluginKey } from "@/lib/plugin-i18n"; -import type { SettingsComponentProps } from "../settings-components"; -import { getTailscaleDevices } from "../../../../plugins/tailscale/src/frontend/tailscale-api"; +import type { SettingsComponentProps } from "@termix/plugin-sdk/frontend"; +import { getTailscaleDevices } from "./tailscale-api"; type Status = | { kind: "loading" } @@ -53,7 +52,7 @@ export function TailscaleDevicesStatus({ running }: SettingsComponentProps) { void load(); }, [load]); - const label = (key: string) => t(pluginKey("tailscale", key)); + const label = (key: string) => t(key); return (
@@ -66,7 +65,7 @@ export function TailscaleDevicesStatus({ running }: SettingsComponentProps) { {status.kind === "no-key" && label("settings.devices.noKey")} {status.kind === "error" && label("settings.devices.error")} {status.kind === "ok" && - t(pluginKey("tailscale", "settings.devices.count"), { + t("settings.devices.count", { count: status.count, })} diff --git a/plugins/tailscale/src/frontend/index.mjs b/plugins/tailscale/src/frontend/index.mjs deleted file mode 100644 index f2c443370..000000000 --- a/plugins/tailscale/src/frontend/index.mjs +++ /dev/null @@ -1,40 +0,0 @@ -/** - * Frontend half of the tailscale plugin. - * - * TailscaleDevicesPanel is a left-sidebar railView panel (opened from the - * rail, not a Tab), the same shape as FleetsPanel/QuickConnectPanel. None of - * those go through registerRailItem/registerTabComponent either -- per - * src/ui/shell/pluginLoader.ts's own comment, a rail-view panel like this is - * rendered directly by AppShell.tsx rather than registered at runtime. - * TailscaleDevicesPanel is reached today through a direct relative import in - * AppShell.tsx (../../plugins/tailscale/frontend/TailscaleDevicesPanel), not - * through register() below. - * - * register()/unregister() still follow the same shape every other plugin's - * frontend entry does, so this is ready the moment a real frontend plugin - * loader exists -- see plugins/ssh-terminal/frontend/index.mjs and - * src/ui/tests/sidebar/plugin-extension-seam.test.tsx, which says outright - * "there is no plugin loader yet". - * - * TailscaleCheckDialog is not registered here at all: it is rendered - * directly by src/ui/features/terminal/Terminal.tsx (owned by ssh-terminal), - * driven by raw WS message types on the terminal socket. There is no - * dialog-registration extension point for that today, so this plugin ships - * the component as a plain module ssh-terminal imports by path. - */ - -export const id = "tailscale"; -export const railViewId = "tailscale"; - -export async function register({ registerRailItem, icons }) { - registerRailItem?.({ - id: railViewId, - icon: icons.Radar, - labelKey: "nav.tailscale", - separatorAfter: true, - }); -} - -export async function unregister({ unregisterRailItem }) { - unregisterRailItem?.(railViewId); -} diff --git a/plugins/tailscale/src/frontend/index.tsx b/plugins/tailscale/src/frontend/index.tsx new file mode 100644 index 000000000..790a7cd32 --- /dev/null +++ b/plugins/tailscale/src/frontend/index.tsx @@ -0,0 +1,52 @@ +import type { ComponentType } from "react"; +import { Radar } from "lucide-react"; +import type { PanelProps, TermixApp } from "@termix/plugin-sdk/frontend"; +import type { Host } from "@/types/ui-types"; +import { TailscaleDevicesPanel } from "./TailscaleDevicesPanel"; +import { TailscaleDevicesStatus } from "./TailscaleDevicesStatus"; +import { TailscaleAuthEditor } from "./TailscaleAuthEditor"; +import { TailscaleCheckOverlay } from "./TailscaleCheckOverlay"; + +function Panel({ shell }: PanelProps) { + return ( + + shell.openTab( + host as unknown as Parameters[0], + type, + ) + } + /> + ); +} + +export function activate(app: TermixApp): void { + app.registerRailItem({ + id: "tailscale", + icon: Radar, + titleKey: "nav.tailscale", + after: "macros", + order: 20, + }); + app.registerPanel("tailscale", Panel); + + app.registerSettingsComponent("devices", TailscaleDevicesStatus); + + // "tailscale" as a host's SSH auth method: pick a device from the tailnet. + app.registerSshAuthEditor({ + authType: "tailscale", + titleKey: "nav.tailscale", + hintKey: "hosts.tailscaleUsernameHint", + component: TailscaleAuthEditor, + }); + + // Approval prompts while Tailscale SSH holds a connection open. + app.registerSlotContribution("terminal.overlay", { + actionId: "tailscale.check", + titleKey: "terminal.tailscaleCheckRequired", + kind: "component", + component: TailscaleCheckOverlay as unknown as ComponentType< + Record + >, + }); +} diff --git a/plugins/tailscale/tests/frontend/activate.test.tsx b/plugins/tailscale/tests/frontend/activate.test.tsx new file mode 100644 index 000000000..814097280 --- /dev/null +++ b/plugins/tailscale/tests/frontend/activate.test.tsx @@ -0,0 +1,53 @@ +import { afterEach, describe, expect, it } from "vitest"; +import { + renderWithApp, + type RenderedPluginApp, +} from "@termix/plugin-sdk/testing"; +import type { PluginManifest } from "@termix/plugin-sdk/manifest"; +import * as plugin from "../../src/frontend/index"; +import manifestJson from "../../manifest.json"; +import locales from "../../locales/en.json"; + +const manifest = manifestJson as unknown as PluginManifest; + +const declared = (views?: Array<{ id: string }>) => + (views ?? []).map((view) => view.id).sort(); + +let rendered: RenderedPluginApp | null = null; + +afterEach(async () => { + await rendered?.deactivate(); + rendered = null; +}); + +describe(`${manifest.id} activate`, () => { + it("activates and registers only views its manifest declares", async () => { + rendered = await renderWithApp(plugin, { manifest, locales }); + const contributes = manifest.contributes as unknown as Record< + string, + Array<{ id: string }> | undefined + >; + const tabs = declared(contributes.tabs); + // A rail panel may reuse one of the plugin's tab ids. + const panels = [...declared(contributes.panels), ...tabs]; + const cards = declared(contributes.dashboardCards); + for (const id of rendered.registered.tabs()) expect(tabs).toContain(id); + for (const id of rendered.registered.panels()) expect(panels).toContain(id); + for (const id of rendered.registered.dashboardCards()) { + expect(cards).toContain(id); + } + }); + + it("removes everything it registered on deactivate", async () => { + const app = await renderWithApp(plugin, { manifest, locales }); + await app.deactivate(); + expect(app.registered.tabs()).toEqual([]); + expect(app.registered.panels()).toEqual([]); + expect(app.registered.railItems()).toEqual([]); + expect(app.registered.hostActions()).toEqual([]); + expect(app.registered.hostEditorSections()).toEqual([]); + expect(app.registered.dashboardCards()).toEqual([]); + expect(app.registered.settingsComponents()).toEqual([]); + expect(app.registered.actions()).toEqual([]); + }); +}); diff --git a/plugins/web-endpoint/locales/en.json b/plugins/web-endpoint/locales/en.json index 0967ef424..300f5a0bf 100644 --- a/plugins/web-endpoint/locales/en.json +++ b/plugins/web-endpoint/locales/en.json @@ -1 +1,52 @@ -{} +{ + "webEndpoint": { + "noHostSelected": "No host selected", + "notFound": "This endpoint no longer exists.", + "tunnelUnreachableFromBrowser": "This endpoint tunnels to 127.0.0.1 on the machine running Termix, which your browser cannot reach. Set the endpoint's Bind Host to an address that machine answers on, such as 0.0.0.0, and give it a fixed Local Port.", + "tunnelSharesSessionCookie": "Opening this tunnel would send your Termix session to the tunnelled service, because your browser would reach it at the same hostname Termix is served from. Cookies ignore the port, so the two cannot be told apart. Use the Termix desktop app, or open Termix at localhost.", + "directSharesSessionCookie": "Opening this endpoint would send your Termix session to it, because your browser reaches it at the same site Termix is served from. Cookies ignore the port, so a different port is not a different identity. Use the Termix desktop app, or serve this web UI from a different hostname.", + "retry": "Retry", + "reload": "Reload", + "copyUrl": "Copy URL", + "urlCopied": "URL copied", + "copyFailed": "Failed to copy URL", + "openExternally": "Open externally", + "isolationUnavailable": "This browser cannot isolate web endpoints from your Termix session. Use a browser with credentialless iframe support.", + "isolationNotice": "Embedded pages use an isolated session. For pages requiring storage or popup sign-in, use an isolated window in the desktop app.", + "openIsolatedWindow": "Open isolated window" + }, + "hosts": { + "tabWebUi": "Web UI", + "webUiEndpointLabel": "Endpoint {{number}}", + "webUiIntegration": "Web UI", + "webUiEndpointsSection": "Endpoints", + "webUiRequirementsText": "A direct endpoint is opened by your browser, so its port must be reachable from here. An SSH tunnel is opened by Termix over this host's SSH connection instead, so the port only has to be reachable from the host.", + "enableWebUi": "Enable web endpoints", + "enableWebUiDesc": "Open this host's web interfaces from the sidebar.", + "webUiAddEndpoint": "Add endpoint", + "webUiAddress": "Address", + "webUiOpening": "Opening", + "webUiBindHostDesc": "Where the backend binds the forward. Leave blank for 127.0.0.1, which only the machine running Termix can reach.", + "webUiBindHostExposed": "This address is reachable beyond the Termix machine, so anyone who can reach the port gets this web UI with no login.", + "webUiLocalPort": "Local Port", + "webUiLocalPortAuto": "Automatic", + "webUiLocalPortDesc": "Which port the forward listens on. Leave blank to let the system pick, or set one when the port has to be known in advance, such as a container that publishes it.", + "webUiNewEndpointLabel": "New endpoint", + "webUiLabel": "Label", + "webUiScheme": "Scheme", + "webUiPort": "Port", + "webUiPath": "Path", + "webUiAccess": "Access", + "webUiAccessDirect": "Direct", + "webUiAccessTunnel": "SSH tunnel", + "webUiAccessTunnelUnavailable": "An SSH tunnel needs SSH enabled on this host and a connection origin of this device.", + "webUiRender": "Open in", + "webUiRenderExternal": "Isolated desktop window", + "webUiRenderEmbedded": "Termix tab", + "webUiRenderEmbeddedDesc": "Embedding is best effort: some web interfaces refuse to load in a frame, and a login that relies on same-site cookies may loop. The external browser always works.", + "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" + } +} diff --git a/plugins/web-endpoint/locales/translated/af_ZA.json b/plugins/web-endpoint/locales/translated/af_ZA.json new file mode 100644 index 000000000..cc714d7e4 --- /dev/null +++ b/plugins/web-endpoint/locales/translated/af_ZA.json @@ -0,0 +1,52 @@ +{ + "webEndpoint": { + "noHostSelected": "Geen gasheer gekies nie", + "notFound": "Hierdie eindpunt bestaan nie meer nie.", + "tunnelUnreachableFromBrowser": "Hierdie eindpunt tonnel na 127.0.0.1 op die masjien wat Termix gebruik, wat jou blaaier nie kan bereik nie. Stel die eindpunt se Bind Host na 'n adres waarop die masjien antwoord, soos 0.0.0.0, en gee dit 'n vaste Lokale Poort.", + "tunnelSharesSessionCookie": "As jy hierdie tonnel oopmaak, sal jou Termix-sessie na die getunnelde diens gestuur word, want jou blaaier sal dit bereik by dieselfde gasheernaam waarvandaan Termix bedien word. Koekies ignoreer die poort, dus kan die twee nie van mekaar onderskei word nie. Gebruik die Termix-lessenaar-app, of maak Termix oop by localhost.", + "directSharesSessionCookie": "As jy hierdie eindpunt oopmaak, sal jou Termix-sessie daarnatoe gestuur word, want jou blaaier bereik dit op dieselfde webwerf waarvandaan Termix bedien word. Koekies ignoreer die poort, dus is 'n ander poort nie 'n ander identiteit nie. Gebruik die Termix-lessenaartoepassing of bedien hierdie web-UI vanaf 'n ander gasheernaam.", + "retry": "Probeer weer", + "reload": "Herlaai", + "copyUrl": "Kopieer URL", + "urlCopied": "URL gekopieer", + "copyFailed": "Kon nie URL kopieer nie", + "openExternally": "Maak ekstern oop", + "isolationUnavailable": "Hierdie blaaier kan nie web-eindpunte van jou Termix-sessie isoleer nie. Gebruik 'n blaaier met ondersteuning vir iframes sonder geloofsbriewe.", + "isolationNotice": "Ingeslote bladsye gebruik 'n geïsoleerde sessie. Vir bladsye wat berging of opspring-aanmelding benodig, gebruik 'n geïsoleerde venster in die rekenaarprogram.", + "openIsolatedWindow": "Maak geïsoleerde venster oop" + }, + "hosts": { + "tabWebUi": "Web-UI", + "webUiEndpointLabel": "Eindpunt {{number}}", + "webUiIntegration": "Web-UI", + "webUiEndpointsSection": "Eindpunte", + "webUiRequirementsText": "'n Direkte eindpunt word deur jou blaaier oopgemaak, dus moet die poort daarvan van hier af bereikbaar wees. 'n SSH-tonnel word eerder deur Termix oor hierdie gasheer se SSH-verbinding oopgemaak, dus hoef die poort slegs vanaf die gasheer bereikbaar te wees.", + "enableWebUi": "Aktiveer web-eindpunte", + "enableWebUiDesc": "Maak hierdie gasheer se webkoppelvlakke vanaf die sybalk oop.", + "webUiAddEndpoint": "Voeg eindpunt by", + "webUiAddress": "Adres", + "webUiOpening": "Opening", + "webUiBindHostDesc": "Waar die agterkant die voorwaartse kant bind. Los leeg vir 127.0.0.1, wat slegs die masjien wat Termix gebruik, kan bereik.", + "webUiBindHostExposed": "Hierdie adres is bereikbaar buite die Termix-masjien, so enigiemand wat die poort kan bereik, kry hierdie web-UI sonder om aan te meld.", + "webUiLocalPort": "Plaaslike Hawe", + "webUiLocalPortAuto": "Outomaties", + "webUiLocalPortDesc": "Na watter poort die aanstuurder luister. Los leeg om die stelsel toe te laat om te kies, of stel een wanneer die poort vooraf bekend moet wees, soos 'n houer wat dit publiseer.", + "webUiNewEndpointLabel": "Nuwe eindpunt", + "webUiLabel": "Etiket", + "webUiScheme": "Skema", + "webUiPort": "Hawe", + "webUiPath": "Pad", + "webUiAccess": "Toegang", + "webUiAccessDirect": "Direkte", + "webUiAccessTunnel": "SSH-tonnel", + "webUiAccessTunnelUnavailable": "'n SSH-tonnel benodig SSH geaktiveer op hierdie gasheer en 'n verbindingsoorsprong van hierdie toestel.", + "webUiRender": "Maak oop in", + "webUiRenderExternal": "Geïsoleerde lessenaarvenster", + "webUiRenderEmbedded": "Termix-oortjie", + "webUiRenderEmbeddedDesc": "Inbedding is die beste poging: sommige webkoppelvlakke weier om in 'n raam te laai, en 'n aanmelding wat op dieselfde-webwerf-koekies staatmaak, kan 'n lus vorm. Die eksterne blaaier werk altyd.", + "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" + } +} diff --git a/plugins/web-endpoint/locales/translated/ar_SA.json b/plugins/web-endpoint/locales/translated/ar_SA.json new file mode 100644 index 000000000..e23cc1a7b --- /dev/null +++ b/plugins/web-endpoint/locales/translated/ar_SA.json @@ -0,0 +1,52 @@ +{ + "webEndpoint": { + "noHostSelected": "لم يتم تحديد أي مضيف", + "notFound": "لم تعد هذه النقطة النهائية موجودة.", + "tunnelUnreachableFromBrowser": "تتصل هذه النقطة الطرفية بالعنوان 127.0.0.1 على الجهاز الذي يُشغّل Termix، وهو عنوان لا يمكن لمتصفحك الوصول إليه. عيّن عنوان \"Bind Host\" لهذه النقطة الطرفية إلى عنوان يستجيب له الجهاز، مثل 0.0.0.0، وحدّد لها منفذًا محليًا ثابتًا.", + "tunnelSharesSessionCookie": "سيؤدي فتح هذا النفق إلى توجيه جلسة Termix الخاصة بك إلى الخدمة المُمرَّرة عبر النفق، لأن متصفحك سيصل إليها عبر نفس اسم المضيف الذي يُقدَّم منه Termix. تتجاهل ملفات تعريف الارتباط رقم المنفذ، لذا لا يمكن التمييز بينهما. استخدم تطبيق Termix لسطح المكتب، أو افتح Termix على localhost.", + "directSharesSessionCookie": "سيؤدي فتح هذه النقطة النهائية إلى توجيه جلسة Termix الخاصة بك إليها، لأن متصفحك يصل إليها من نفس الموقع الذي يُقدّم منه Termix. تتجاهل ملفات تعريف الارتباط رقم المنفذ، لذا فإن استخدام منفذ مختلف لا يعني تغيير الهوية. استخدم تطبيق Termix لسطح المكتب، أو قم بتشغيل واجهة المستخدم الرسومية هذه من اسم مضيف مختلف.", + "retry": "إعادة المحاولة", + "reload": "أعد تحميل الصفحة", + "copyUrl": "انسخ الرابط", + "urlCopied": "تم نسخ الرابط", + "copyFailed": "فشل نسخ عنوان URL", + "openExternally": "افتح خارجياً", + "isolationUnavailable": "لا يستطيع هذا المتصفح عزل نقاط نهاية الويب عن جلسة Termix الخاصة بك. استخدم متصفحًا يدعم الإطارات المضمنة بدون بيانات اعتماد.", + "isolationNotice": "تستخدم الصفحات المضمنة جلسة معزولة. أما بالنسبة للصفحات التي تتطلب تخزينًا أو تسجيل دخول منبثق، فاستخدم نافذة معزولة في تطبيق سطح المكتب.", + "openIsolatedWindow": "نافذة مفتوحة معزولة" + }, + "hosts": { + "tabWebUi": "واجهة المستخدم على الويب", + "webUiEndpointLabel": "نقطة النهاية {{number}}", + "webUiIntegration": "واجهة المستخدم على الويب", + "webUiEndpointsSection": "نقاط النهاية", + "webUiRequirementsText": "يفتح متصفحك نقطة نهاية مباشرة، لذا يجب أن يكون منفذها قابلاً للوصول من هنا. أما Termix فيفتح نفق SSH عبر اتصال SSH الخاص بهذا المضيف، لذا يكفي أن يكون المنفذ قابلاً للوصول من المضيف نفسه.", + "enableWebUi": "تفعيل نقاط نهاية الويب", + "enableWebUiDesc": "افتح واجهات الويب الخاصة بهذا المضيف من الشريط الجانبي.", + "webUiAddEndpoint": "إضافة نقطة نهاية", + "webUiAddress": "عنوان", + "webUiOpening": "افتتاح", + "webUiBindHostDesc": "حيث يقوم الخادم الخلفي بربط التوجيه الأمامي. اترك هذا الحقل فارغًا للعنوان 127.0.0.1، والذي لا يمكن الوصول إليه إلا من خلال الجهاز الذي يُشغّل برنامج Termix.", + "webUiBindHostExposed": "يمكن الوصول إلى هذا العنوان من خارج جهاز Termix، لذا فإن أي شخص يمكنه الوصول إلى المنفذ سيحصل على واجهة المستخدم هذه عبر الويب دون الحاجة إلى تسجيل الدخول.", + "webUiLocalPort": "الميناء المحلي", + "webUiLocalPortAuto": "معادلة", + "webUiLocalPortDesc": "ما هو المنفذ الذي يستمع إليه التوجيه؟ اتركه فارغًا ليختاره النظام، أو حدد واحدًا عندما يكون من الضروري معرفة المنفذ مسبقًا، كما هو الحال في حاوية تنشره.", + "webUiNewEndpointLabel": "نقطة نهاية جديدة", + "webUiLabel": "ملصق", + "webUiScheme": "مخطط", + "webUiPort": "ميناء", + "webUiPath": "طريق", + "webUiAccess": "وصول", + "webUiAccessDirect": "مباشر", + "webUiAccessTunnel": "نفق SSH", + "webUiAccessTunnelUnavailable": "يتطلب نفق SSH تمكين SSH على هذا المضيف ومصدر اتصال من هذا الجهاز.", + "webUiRender": "افتح في", + "webUiRenderExternal": "نافذة سطح المكتب المعزولة", + "webUiRenderEmbedded": "علامة تبويب Termix", + "webUiRenderEmbeddedDesc": "يُعدّ تضمين المحتوى أفضل محاولة ممكنة: فبعض واجهات الويب ترفض التحميل داخل إطار، وقد تتكرر عملية تسجيل الدخول التي تعتمد على ملفات تعريف الارتباط الخاصة بالموقع نفسه. أما المتصفح الخارجي فيعمل دائمًا.", + "webUiIgnoreCert": "السماح بشهادة غير صالحة", + "webUiIgnoreCertDesc": "نقاط النهاية المباشرة فقط. تم إعفاء نقاط نهاية Loopback بالفعل، لذا لن يكون لهذا أي تأثير على نقاط نهاية النفق.", + "webUiRemoveEndpoint": "إزالة نقطة النهاية", + "webUiOpenFailed": "فشل فتح نقطة نهاية الويب" + } +} diff --git a/plugins/web-endpoint/locales/translated/bg_BG.json b/plugins/web-endpoint/locales/translated/bg_BG.json new file mode 100644 index 000000000..85bc7d6b7 --- /dev/null +++ b/plugins/web-endpoint/locales/translated/bg_BG.json @@ -0,0 +1,52 @@ +{ + "webEndpoint": { + "noHostSelected": "Няма избран хост", + "notFound": "Тази крайна точка вече не съществува.", + "tunnelUnreachableFromBrowser": "Тази крайна точка се свързва с 127.0.0.1 на машината, на която работи Termix, до която вашият браузър не може да достигне. Задайте Bind Host на крайната точка на адрес, на който машината отговаря, например 0.0.0.0, и му дайте фиксиран локален порт.", + "tunnelSharesSessionCookie": "Отварянето на този тунел ще изпрати вашата Termix сесия към тунелираната услуга, защото вашият браузър ще я достигне на същото име на хост, от което се обслужва Termix. „Бисквитките“ игнорират порта, така че двете не могат да бъдат разграничени. Използвайте настолното приложение Termix или отворете Termix на localhost.", + "directSharesSessionCookie": "Отварянето на тази крайна точка ще изпрати вашата Termix сесия към нея, защото вашият браузър достига до нея на същия сайт, от който се обслужва Termix. „Бисквитките“ игнорират порта, така че различен порт не е различна идентичност. Използвайте настолното приложение Termix или обслужвайте този уеб потребителски интерфейс от различно име на хост.", + "retry": "Опитай отново", + "reload": "Презареждане", + "copyUrl": "Копиране на URL адрес", + "urlCopied": "URL адресът е копиран", + "copyFailed": "Копирането на URL адреса не бе успешно", + "openExternally": "Отворено външно", + "isolationUnavailable": "Този браузър не може да изолира уеб крайни точки от вашата Termix сесия. Използвайте браузър с поддръжка на iframe без идентификационни данни.", + "isolationNotice": "Вградените страници използват изолирана сесия. За страници, изискващи място за съхранение или изскачащ вход, използвайте изолиран прозорец в настолното приложение.", + "openIsolatedWindow": "Отворен изолиран прозорец" + }, + "hosts": { + "tabWebUi": "Уеб потребителски интерфейс", + "webUiEndpointLabel": "Крайна точка {{number}}", + "webUiIntegration": "Уеб потребителски интерфейс", + "webUiEndpointsSection": "Крайни точки", + "webUiRequirementsText": "Директна крайна точка се отваря от вашия браузър, така че портът ѝ трябва да е достъпен оттук. Вместо това Termix отваря SSH тунел през SSH връзката на този хост, така че портът трябва да е достъпен само от хоста.", + "enableWebUi": "Активиране на уеб крайни точки", + "enableWebUiDesc": "Отворете уеб интерфейсите на този хост от страничната лента.", + "webUiAddEndpoint": "Добавяне на крайна точка", + "webUiAddress": "Адрес", + "webUiOpening": "Откриване", + "webUiBindHostDesc": "Където бекендът свързва пренасочващия сървър. Оставете празно за 127.0.0.1, до който може да достигне само машината, на която работи Termix.", + "webUiBindHostExposed": "Този адрес е достъпен отвъд машината Termix, така че всеки, който може да достигне порта, получава този уеб интерфейс без вход.", + "webUiLocalPort": "Локален порт", + "webUiLocalPortAuto": "Автоматично", + "webUiLocalPortDesc": "На кой порт слуша пренасочването. Оставете празно, за да позволите на системата да избере, или задайте порт, когато портът трябва да бъде известен предварително, например контейнер, който го публикува.", + "webUiNewEndpointLabel": "Нова крайна точка", + "webUiLabel": "Етикет", + "webUiScheme": "Схема", + "webUiPort": "Порт", + "webUiPath": "Път", + "webUiAccess": "Достъп", + "webUiAccessDirect": "Директно", + "webUiAccessTunnel": "SSH тунел", + "webUiAccessTunnelUnavailable": "SSH тунелът изисква SSH да е активиран на този хост и произход на връзката на това устройство.", + "webUiRender": "Отвори в", + "webUiRenderExternal": "Изолиран прозорец на работния плот", + "webUiRenderEmbedded": "раздел Термикс", + "webUiRenderEmbeddedDesc": "Вграждането е най-добрият начин: някои уеб интерфейси отказват да се заредят в кадър и влизане, което разчита на „бисквитки“ на същия сайт, може да се зацикли. Външният браузър винаги работи.", + "webUiIgnoreCert": "Разрешаване на невалиден сертификат", + "webUiIgnoreCertDesc": "Само директни крайни точки. Loopback вече е изключен, така че това няма ефект върху крайните точки на тунела.", + "webUiRemoveEndpoint": "Премахване на крайната точка", + "webUiOpenFailed": "Неуспешно отваряне на уеб крайната точка" + } +} diff --git a/plugins/web-endpoint/locales/translated/bn_BD.json b/plugins/web-endpoint/locales/translated/bn_BD.json new file mode 100644 index 000000000..e98cc8aa6 --- /dev/null +++ b/plugins/web-endpoint/locales/translated/bn_BD.json @@ -0,0 +1,52 @@ +{ + "webEndpoint": { + "noHostSelected": "কোন হোস্ট নির্বাচন করা হয়নি", + "notFound": "এই এন্ডপয়েন্টটি আর বিদ্যমান নেই।", + "tunnelUnreachableFromBrowser": "এই এন্ডপয়েন্টটি Termix চালিত মেশিনের 127.0.0.1-এ টানেল করে, যেখানে আপনার ব্রাউজার পৌঁছাতে পারে না। এন্ডপয়েন্টটির বাইন্ড হোস্ট এমন একটি অ্যাড্রেসে সেট করুন যেখান থেকে ওই মেশিনটি সাড়া দেয়, যেমন 0.0.0.0, এবং এটিকে একটি নির্দিষ্ট লোকাল পোর্ট দিন।", + "tunnelSharesSessionCookie": "এই টানেলটি খুললে আপনার টার্মিক্স সেশনটি টানেল করা পরিষেবাতে চলে যাবে, কারণ আপনার ব্রাউজারটি সেই একই হোস্টনেমে পরিষেবাটি পাবে যেখান থেকে টার্মিক্স পরিবেশিত হয়। কুকি পোর্টকে উপেক্ষা করে, তাই এই দুটিকে আলাদা করা যায় না। টার্মিক্স ডেস্কটপ অ্যাপ ব্যবহার করুন, অথবা লোকালহোস্টে টার্মিক্স খুলুন।", + "directSharesSessionCookie": "এই এন্ডপয়েন্টটি খুললে আপনার টার্মিক্স সেশনটি সেখানে চলে যাবে, কারণ আপনার ব্রাউজারটি সেই একই সাইট থেকে এটিতে পৌঁছায় যেখান থেকে টার্মিক্স পরিবেশিত হয়। কুকি পোর্টকে উপেক্ষা করে, তাই একটি ভিন্ন পোর্ট কোনো ভিন্ন পরিচয় নয়। টার্মিক্স ডেস্কটপ অ্যাপ ব্যবহার করুন, অথবা এই ওয়েব ইউআইটি একটি ভিন্ন হোস্টনেম থেকে পরিবেশন করুন।", + "retry": "পুনরায় চেষ্টা করুন", + "reload": "পুনরায় লোড করুন", + "copyUrl": "ইউআরএল কপি করুন", + "urlCopied": "URL কপি করা হয়েছে", + "copyFailed": "URL কপি করতে ব্যর্থ হয়েছে", + "openExternally": "বাইরে খুলুন", + "isolationUnavailable": "এই ব্রাউজারটি আপনার টারমিক্স সেশন থেকে ওয়েব এন্ডপয়েন্টগুলোকে আলাদা করতে পারে না। ক্রেডেনশিয়ালবিহীন আইফ্রেম সমর্থন করে এমন একটি ব্রাউজার ব্যবহার করুন।", + "isolationNotice": "এমবেডেড পেজগুলো একটি আইসোলেটেড সেশন ব্যবহার করে। যেসব পেজের জন্য স্টোরেজ বা পপ-আপ সাইন-ইন প্রয়োজন, সেগুলোর জন্য ডেস্কটপ অ্যাপে একটি আইসোলেটেড উইন্ডো ব্যবহার করুন।", + "openIsolatedWindow": "বিচ্ছিন্ন জানালা খুলুন" + }, + "hosts": { + "tabWebUi": "ওয়েব UI", + "webUiEndpointLabel": "শেষবিন্দু {{number}}", + "webUiIntegration": "ওয়েব UI", + "webUiEndpointsSection": "এন্ডপয়েন্ট", + "webUiRequirementsText": "আপনার ব্রাউজার একটি সরাসরি এন্ডপয়েন্ট খোলে, তাই এর পোর্টটি এখান থেকে অ্যাক্সেসযোগ্য হতে হবে। এর পরিবর্তে, Termix এই হোস্টের SSH সংযোগের মাধ্যমে একটি SSH টানেল খোলে, তাই পোর্টটি শুধুমাত্র হোস্ট থেকে অ্যাক্সেসযোগ্য হলেই চলে।", + "enableWebUi": "ওয়েব এন্ডপয়েন্টগুলি সক্ষম করুন", + "enableWebUiDesc": "সাইডবার থেকে এই হোস্টের ওয়েব ইন্টারফেসগুলো খুলুন।", + "webUiAddEndpoint": "এন্ডপয়েন্ট যোগ করুন", + "webUiAddress": "ঠিকানা", + "webUiOpening": "উদ্বোধন", + "webUiBindHostDesc": "যেখানে ব্যাকএন্ড ফরওয়ার্ডটি বাইন্ড করে। 127.0.0.1-এর জন্য এই স্থানটি খালি রাখুন, কারণ শুধুমাত্র Termix চালিত মেশিনটিই এখানে পৌঁছাতে পারে।", + "webUiBindHostExposed": "এই অ্যাড্রেসটি টারমিক্স মেশিনের বাইরেও অ্যাক্সেসযোগ্য, তাই যে কেউ পোর্টটিতে অ্যাক্সেস করতে পারলেই কোনো লগইন ছাড়াই এই ওয়েব UI-টি ব্যবহার করতে পারবে।", + "webUiLocalPort": "স্থানীয় বন্দর", + "webUiLocalPortAuto": "স্বয়ংক্রিয়", + "webUiLocalPortDesc": "ফরওয়ার্ডটি কোন পোর্টে শুনবে। সিস্টেমকে বেছে নিতে দেওয়ার জন্য এটি খালি রাখুন, অথবা যখন পোর্টটি আগে থেকে জানা প্রয়োজন, যেমন কোনো কন্টেইনার যা এটি প্রকাশ করে, তখন একটি সেট করুন।", + "webUiNewEndpointLabel": "নতুন এন্ডপয়েন্ট", + "webUiLabel": "লেবেল", + "webUiScheme": "পরিকল্পনা", + "webUiPort": "বন্দর", + "webUiPath": "পথ", + "webUiAccess": "অ্যাক্সেস", + "webUiAccessDirect": "সরাসরি", + "webUiAccessTunnel": "এসএসএইচ টানেল", + "webUiAccessTunnelUnavailable": "একটি SSH টানেলের জন্য এই হোস্টে SSH সক্রিয় থাকতে হবে এবং সংযোগের উৎস হিসেবে এই ডিভাইসটি প্রয়োজন।", + "webUiRender": "খুলুন", + "webUiRenderExternal": "বিচ্ছিন্ন ডেস্কটপ উইন্ডো", + "webUiRenderEmbedded": "টার্মিক্স ট্যাব", + "webUiRenderEmbeddedDesc": "এমবেডিং-এর ক্ষেত্রে সর্বোচ্চ চেষ্টা করা হয়: কিছু ওয়েব ইন্টারফেস ফ্রেমে লোড হতে চায় না, এবং একই-সাইট কুকির উপর নির্ভরশীল লগইন একটি লুপে আটকে যেতে পারে। বাহ্যিক ব্রাউজারটি সবসময় কাজ করে।", + "webUiIgnoreCert": "অবৈধ সার্টিফিকেট অনুমোদন করুন", + "webUiIgnoreCertDesc": "শুধুমাত্র ডাইরেক্ট এন্ডপয়েন্টগুলোর জন্য প্রযোজ্য। লুপব্যাক ইতিমধ্যে অব্যাহতিপ্রাপ্ত, তাই টানেল এন্ডপয়েন্টগুলোর উপর এর কোনো প্রভাব নেই।", + "webUiRemoveEndpoint": "এন্ডপয়েন্ট সরান", + "webUiOpenFailed": "ওয়েব এন্ডপয়েন্ট খুলতে ব্যর্থ হয়েছে" + } +} diff --git a/plugins/web-endpoint/locales/translated/ca_ES.json b/plugins/web-endpoint/locales/translated/ca_ES.json new file mode 100644 index 000000000..895ace6a6 --- /dev/null +++ b/plugins/web-endpoint/locales/translated/ca_ES.json @@ -0,0 +1,52 @@ +{ + "webEndpoint": { + "noHostSelected": "No s'ha seleccionat cap amfitrió", + "notFound": "Aquest punt final ja no existeix.", + "tunnelUnreachableFromBrowser": "Aquest punt final connecta a 127.0.0.1 a la màquina que executa Termix, a la qual el navegador no pot arribar. Establiu l'amfitrió d'enllaç del punt final a una adreça a la qual la màquina respongui, com ara 0.0.0.0, i doneu-li un port local fix.", + "tunnelSharesSessionCookie": "Si obriu aquest túnel, la vostra sessió de Termix s'enviaria al servei tunelitzat, perquè el vostre navegador hi arribaria amb el mateix nom d'amfitrió des del qual es serveix Termix. Les galetes ignoren el port, de manera que no es poden distingir. Feu servir l'aplicació d'escriptori de Termix o obriu Termix a localhost.", + "directSharesSessionCookie": "Si obriu aquest punt final, la vostra sessió de Termix s'hi enviaria, perquè el vostre navegador hi arriba al mateix lloc des d'on es serveix Termix. Les galetes ignoren el port, de manera que un port diferent no és una identitat diferent. Feu servir l'aplicació d'escriptori de Termix o serviu aquesta interfície d'usuari web des d'un nom d'amfitrió diferent.", + "retry": "Torna-ho a intentar", + "reload": "Torna a carregar", + "copyUrl": "Copia l'URL", + "urlCopied": "URL copiada", + "copyFailed": "No s'ha pogut copiar l'URL", + "openExternally": "Obre externament", + "isolationUnavailable": "Aquest navegador no pot aïllar els punts finals web de la vostra sessió de Termix. Feu servir un navegador que admeti iframes sense credencials.", + "isolationNotice": "Les pàgines incrustades utilitzen una sessió aïllada. Per a les pàgines que requereixen emmagatzematge o inici de sessió emergent, utilitzeu una finestra aïllada a l'aplicació d'escriptori.", + "openIsolatedWindow": "Finestra aïllada oberta" + }, + "hosts": { + "tabWebUi": "Interfície d'usuari web", + "webUiEndpointLabel": "Punt final {{number}}", + "webUiIntegration": "Interfície d'usuari web", + "webUiEndpointsSection": "Punts finals", + "webUiRequirementsText": "El navegador obre un punt final directe, de manera que el seu port ha de ser accessible des d'aquí. Termix obre un túnel SSH a través de la connexió SSH d'aquest host, de manera que el port només ha de ser accessible des de l'host.", + "enableWebUi": "Habilita els punts finals web", + "enableWebUiDesc": "Obriu les interfícies web d'aquest amfitrió des de la barra lateral.", + "webUiAddEndpoint": "Afegeix un punt final", + "webUiAddress": "Adreça", + "webUiOpening": "Obertura", + "webUiBindHostDesc": "On el backend enllaça amb el forward. Deixeu en blanc per a 127.0.0.1, que només pot assolir la màquina que executa Termix.", + "webUiBindHostExposed": "Aquesta adreça és accessible més enllà de la màquina Termix, de manera que qualsevol persona que pugui accedir al port obté aquesta interfície web sense necessitat d'iniciar sessió.", + "webUiLocalPort": "Port local", + "webUiLocalPortAuto": "Automàtic", + "webUiLocalPortDesc": "Port on escolta el reenviament. Deixeu-ho en blanc perquè el sistema el seleccioni o definiu-ne un quan el port s'hagi de conèixer per endavant, com ara un contenidor que el publica.", + "webUiNewEndpointLabel": "Nou punt final", + "webUiLabel": "Etiqueta", + "webUiScheme": "Esquema", + "webUiPort": "Port", + "webUiPath": "Camí", + "webUiAccess": "Accés", + "webUiAccessDirect": "Directe", + "webUiAccessTunnel": "Túnel SSH", + "webUiAccessTunnelUnavailable": "Un túnel SSH necessita SSH habilitat en aquest host i un origen de connexió d'aquest dispositiu.", + "webUiRender": "Obre en", + "webUiRenderExternal": "Finestra d'escriptori aïllada", + "webUiRenderEmbedded": "Pestanya Termix", + "webUiRenderEmbeddedDesc": "La incrustació és el millor esforç: algunes interfícies web es neguen a carregar-se en un marc i un inici de sessió que depèn de les galetes del mateix lloc pot repetir-se. El navegador extern sempre funciona.", + "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." + } +} diff --git a/plugins/web-endpoint/locales/translated/cs_CZ.json b/plugins/web-endpoint/locales/translated/cs_CZ.json new file mode 100644 index 000000000..e5544d4e7 --- /dev/null +++ b/plugins/web-endpoint/locales/translated/cs_CZ.json @@ -0,0 +1,52 @@ +{ + "webEndpoint": { + "noHostSelected": "Nebyl vybrán žádný hostitel", + "notFound": "Tento koncový bod již neexistuje.", + "tunnelUnreachableFromBrowser": "Tento koncový bod se tunelově připojuje k adrese 127.0.0.1 na počítači se spuštěným programem Termix, ke které se váš prohlížeč nemůže dostat. Nastavte Bind Host koncového bodu na adresu, na které počítač odpovídá, například 0.0.0.0, a přidělte mu pevný lokální port.", + "tunnelSharesSessionCookie": "Otevřením tohoto tunelu by se vaše relace Termixu odeslala na tunelovanou službu, protože by se k ní váš prohlížeč dostal na stejném hostitelském názvu, ze kterého je Termix obsluhován. Soubory cookie ignorují port, takže tyto dva servery nelze od sebe rozlišit. Použijte desktopovou aplikaci Termix nebo otevřete Termix na localhostu.", + "directSharesSessionCookie": "Otevřením tohoto koncového bodu by se vaše relace Termixu odeslala na něj, protože váš prohlížeč se k němu připojuje na stejném webu, ze kterého je Termix obsluhován. Soubory cookie port ignorují, takže jiný port nepředstavuje jinou identitu. Použijte desktopovou aplikaci Termix nebo toto webové uživatelské rozhraní obsluhujte z jiného názvu hostitele.", + "retry": "Zkusit znovu", + "reload": "Znovu načíst", + "copyUrl": "Kopírovat URL", + "urlCopied": "URL zkopírována", + "copyFailed": "Kopírování adresy URL se nezdařilo", + "openExternally": "Otevřít externě", + "isolationUnavailable": "Tento prohlížeč nedokáže izolovat webové koncové body od vaší relace Termix. Použijte prohlížeč s podporou iframe bez přihlašovacích údajů.", + "isolationNotice": "Vložené stránky používají izolovanou relaci. Pro stránky vyžadující úložiště nebo vyskakovací přihlášení použijte v desktopové aplikaci izolované okno.", + "openIsolatedWindow": "Otevřené izolované okno" + }, + "hosts": { + "tabWebUi": "Webové uživatelské rozhraní", + "webUiEndpointLabel": "Koncový bod {{number}}", + "webUiIntegration": "Webové uživatelské rozhraní", + "webUiEndpointsSection": "Koncové body", + "webUiRequirementsText": "Prohlížeč otevírá přímý koncový bod, takže jeho port musí být odtud dosažitelný. Termix místo toho otevírá SSH tunel přes SSH připojení tohoto hostitele, takže port musí být dostupný pouze z hostitele.", + "enableWebUi": "Povolit webové koncové body", + "enableWebUiDesc": "Otevřete webová rozhraní tohoto hostitele z postranního panelu.", + "webUiAddEndpoint": "Přidat koncový bod", + "webUiAddress": "Adresa", + "webUiOpening": "Otevírací", + "webUiBindHostDesc": "Kam se backend váže s forwardem. Pro 127.0.0.1, ke které má přístup pouze počítač se systémem Termix, nechte prázdné.", + "webUiBindHostExposed": "Tato adresa je dosažitelná i mimo počítač Termix, takže kdokoli, kdo má přístup k portu, získá toto webové rozhraní bez nutnosti přihlášení.", + "webUiLocalPort": "Místní port", + "webUiLocalPortAuto": "Automatický", + "webUiLocalPortDesc": "Na kterém portu naslouchá forwarding. Ponechte prázdné, pokud chcete, aby si systém vybral, nebo nastavte port, pokud musí být port znám předem, například v případě kontejneru, který jej publikuje.", + "webUiNewEndpointLabel": "Nový koncový bod", + "webUiLabel": "Označení", + "webUiScheme": "Systém", + "webUiPort": "Přístav", + "webUiPath": "Cesta", + "webUiAccess": "Přístup", + "webUiAccessDirect": "Řídit", + "webUiAccessTunnel": "SSH tunel", + "webUiAccessTunnelUnavailable": "SSH tunel vyžaduje povolené SSH na tomto hostiteli a původ připojení na tomto zařízení.", + "webUiRender": "Otevřít v", + "webUiRenderExternal": "Izolované okno plochy", + "webUiRenderEmbedded": "Záložka Termix", + "webUiRenderEmbeddedDesc": "Vkládání je nejlepším řešením: některá webová rozhraní se odmítají načíst v rámci a přihlášení, které se spoléhá na soubory cookie stejného webu, se může zacyklit. Externí prohlížeč funguje vždy.", + "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" + } +} diff --git a/plugins/web-endpoint/locales/translated/da_DK.json b/plugins/web-endpoint/locales/translated/da_DK.json new file mode 100644 index 000000000..4a7db0a2e --- /dev/null +++ b/plugins/web-endpoint/locales/translated/da_DK.json @@ -0,0 +1,52 @@ +{ + "webEndpoint": { + "noHostSelected": "Ingen vært valgt", + "notFound": "Dette slutpunkt findes ikke længere.", + "tunnelUnreachableFromBrowser": "Dette endpoint tunnelerer til 127.0.0.1 på den maskine, der kører Termix, som din browser ikke kan nå. Indstil endpointens Bind Host til en adresse, som maskinen svarer på, f.eks. 0.0.0.0, og giv den en fast lokal port.", + "tunnelSharesSessionCookie": "Åbning af denne tunnel ville sende din Termix-session til den tunnelerede tjeneste, fordi din browser ville nå den på det samme værtsnavn, som Termix serveres fra. Cookies ignorerer porten, så de to kan ikke skelnes fra hinanden. Brug Termix-desktopappen, eller åbn Termix på localhost.", + "directSharesSessionCookie": "Åbning af dette slutpunkt ville sende din Termix-session til det, fordi din browser når det på det samme sted, som Termix serveres fra. Cookies ignorerer porten, så en anden port er ikke en anden identitet. Brug Termix-desktopappen, eller server denne webgrænseflade fra et andet værtsnavn.", + "retry": "Prøv igen", + "reload": "Genindlæs", + "copyUrl": "Kopiér URL", + "urlCopied": "URL kopieret", + "copyFailed": "Kunne ikke kopiere URL'en", + "openExternally": "Åbn eksternt", + "isolationUnavailable": "Denne browser kan ikke isolere web-slutpunkter fra din Termix-session. Brug en browser med understøttelse af iframes uden legitimationsoplysninger.", + "isolationNotice": "Integrerede sider bruger en isoleret session. For sider, der kræver lagerplads eller pop op-login, skal du bruge et isoleret vindue i desktop-appen.", + "openIsolatedWindow": "Åbn isoleret vindue" + }, + "hosts": { + "tabWebUi": "Webgrænseflade", + "webUiEndpointLabel": "Endepunkt {{number}}", + "webUiIntegration": "Webgrænseflade", + "webUiEndpointsSection": "Endepunkter", + "webUiRequirementsText": "Et direkte slutpunkt åbnes af din browser, så dens port skal kunne nås herfra. En SSH-tunnel åbnes i stedet af Termix over denne værts SSH-forbindelse, så porten skal kun kunne nås fra værten.", + "enableWebUi": "Aktivér webslutpunkter", + "enableWebUiDesc": "Åbn denne værts webgrænseflader fra sidebjælken.", + "webUiAddEndpoint": "Tilføj slutpunkt", + "webUiAddress": "Adresse", + "webUiOpening": "Åbning", + "webUiBindHostDesc": "Hvor backend binder forward. Lad feltet 127.0.0.1 stå tomt, som kun den maskine, der kører Termix, kan nå.", + "webUiBindHostExposed": "Denne adresse kan nås ud over Termix-maskinen, så alle, der kan nå porten, får denne webgrænseflade uden login.", + "webUiLocalPort": "Lokal havn", + "webUiLocalPortAuto": "Automatisk", + "webUiLocalPortDesc": "Hvilken port videresendelsen lytter på. Lad feltet stå tomt for at lade systemet vælge, eller angiv en port, når porten skal være kendt på forhånd, f.eks. en container, der udgiver den.", + "webUiNewEndpointLabel": "Nyt slutpunkt", + "webUiLabel": "Mærke", + "webUiScheme": "Ordning", + "webUiPort": "Havn", + "webUiPath": "Sti", + "webUiAccess": "Adgang", + "webUiAccessDirect": "Direkte", + "webUiAccessTunnel": "SSH-tunnel", + "webUiAccessTunnelUnavailable": "En SSH-tunnel kræver, at SSH er aktiveret på denne vært, og at denne enhed har en forbindelsesoprindelse.", + "webUiRender": "Åbn om", + "webUiRenderExternal": "Isoleret skrivebordsvindue", + "webUiRenderEmbedded": "Termix-fanen", + "webUiRenderEmbeddedDesc": "Indlejring er den bedste løsning: nogle webgrænseflader nægter at indlæse i en frame, og et login, der er afhængig af cookies fra samme websted, kan gå i løkke. Den eksterne browser fungerer altid.", + "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" + } +} diff --git a/plugins/web-endpoint/locales/translated/de_DE.json b/plugins/web-endpoint/locales/translated/de_DE.json new file mode 100644 index 000000000..4daaea2f4 --- /dev/null +++ b/plugins/web-endpoint/locales/translated/de_DE.json @@ -0,0 +1,52 @@ +{ + "webEndpoint": { + "noHostSelected": "Kein Host ausgewählt", + "notFound": "Dieser Endpunkt existiert nicht mehr.", + "tunnelUnreachableFromBrowser": "Dieser Endpunkt leitet eine Verbindung zu 127.0.0.1 auf dem Rechner weiter, auf dem Termix ausgeführt wird. Ihr Browser kann diese Adresse nicht erreichen. Legen Sie für den Endpunkt als Bind-Host eine Adresse fest, unter der dieser Rechner antwortet, z. B. 0.0.0.0, und weisen Sie ihm einen festen lokalen Port zu.", + "tunnelSharesSessionCookie": "Durch das Öffnen dieses Tunnels wird Ihre Termix-Sitzung an den getunnelten Dienst weitergeleitet, da Ihr Browser diesen unter demselben Hostnamen erreicht, unter dem Termix bereitgestellt wird. Cookies ignorieren den Port, daher können die beiden nicht unterschieden werden. Verwenden Sie die Termix-Desktop-App oder öffnen Sie Termix auf localhost.", + "directSharesSessionCookie": "Wenn Sie diesen Endpunkt öffnen, wird Ihre Termix-Sitzung dorthin gesendet, da Ihr Browser ihn über dieselbe Website erreicht, von der auch Termix bereitgestellt wird. Cookies ignorieren den Port, daher bedeutet ein anderer Port keine andere Identität. Verwenden Sie die Termix-Desktop-App oder stellen Sie diese Web-Oberfläche über einen anderen Hostnamen bereit.", + "retry": "Wiederholen", + "reload": "Neu laden", + "copyUrl": "URL kopieren", + "urlCopied": "URL kopiert", + "copyFailed": "URL konnte nicht kopiert werden", + "openExternally": "Von außen öffnen", + "isolationUnavailable": "Dieser Browser kann Web-Endpunkte nicht von Ihrer Termix-Sitzung isolieren. Verwenden Sie einen Browser, der iFrames ohne Anmeldeinformationen unterstützt.", + "isolationNotice": "Eingebettete Seiten verwenden eine separate Sitzung. Für Seiten, die Speicherplatz benötigen oder eine Popup-Anmeldung erfordern, verwenden Sie ein separates Fenster in der Desktop-App.", + "openIsolatedWindow": "Isoliertes Fenster öffnen" + }, + "hosts": { + "tabWebUi": "Web-Benutzeroberfläche", + "webUiEndpointLabel": "Endpunkt {{number}}", + "webUiIntegration": "Web-Benutzeroberfläche", + "webUiEndpointsSection": "Endpunkte", + "webUiRequirementsText": "Ihr Browser öffnet einen direkten Endpunkt, daher muss dessen Port von hier aus erreichbar sein. Termix öffnet stattdessen einen SSH-Tunnel über die SSH-Verbindung dieses Hosts, sodass der Port nur vom Host aus erreichbar sein muss.", + "enableWebUi": "Web-Endpunkte aktivieren", + "enableWebUiDesc": "Öffnen Sie die Web-Oberflächen dieses Hosts über die Seitenleiste.", + "webUiAddEndpoint": "Endpunkt hinzufügen", + "webUiAddress": "Adresse", + "webUiOpening": "Öffnung", + "webUiBindHostDesc": "Hier bindet das Backend das Forwarding. Lassen Sie das Feld für 127.0.0.1 leer, da diese Adresse nur von dem Rechner aus erreichbar ist, auf dem Termix läuft.", + "webUiBindHostExposed": "Diese Adresse ist auch außerhalb des Termix-Rechners erreichbar, sodass jeder, der den Port erreichen kann, diese Web-Oberfläche ohne Anmeldung aufrufen kann.", + "webUiLocalPort": "Lokaler Hafen", + "webUiLocalPortAuto": "Automatisch", + "webUiLocalPortDesc": "Auf welchem Port der Forwarder lauscht. Lassen Sie das Feld leer, damit das System einen Port auswählt, oder geben Sie einen Port an, wenn dieser im Voraus bekannt sein muss, z. B. von einem Container, der ihn veröffentlicht.", + "webUiNewEndpointLabel": "Neuer Endpunkt", + "webUiLabel": "Etikett", + "webUiScheme": "Schema", + "webUiPort": "Hafen", + "webUiPath": "Weg", + "webUiAccess": "Zugang", + "webUiAccessDirect": "Direkt", + "webUiAccessTunnel": "SSH-Tunnel", + "webUiAccessTunnelUnavailable": "Für einen SSH-Tunnel muss SSH auf diesem Host aktiviert sein und dieses Gerät als Verbindungsursprung verwendet werden.", + "webUiRender": "Öffnen in", + "webUiRenderExternal": "Isoliertes Desktop-Fenster", + "webUiRenderEmbedded": "Termix-Registerkarte", + "webUiRenderEmbeddedDesc": "Die Einbettung funktioniert nach bestem Bemühen: Manche Web-Oberflächen lassen sich nicht in einem Frame laden, und ein Login, der auf Same-Site-Cookies basiert, kann in einer Endlosschleife hängen bleiben. Der externe Browser funktioniert immer.", + "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." + } +} diff --git a/plugins/web-endpoint/locales/translated/el_GR.json b/plugins/web-endpoint/locales/translated/el_GR.json new file mode 100644 index 000000000..5c6225607 --- /dev/null +++ b/plugins/web-endpoint/locales/translated/el_GR.json @@ -0,0 +1,52 @@ +{ + "webEndpoint": { + "noHostSelected": "Δεν έχει επιλεγεί κεντρικός υπολογιστής", + "notFound": "Αυτό το τελικό σημείο δεν υπάρχει πλέον.", + "tunnelUnreachableFromBrowser": "Αυτό το τελικό σημείο συνδέεται με την διεύθυνση 127.0.0.1 στον υπολογιστή που εκτελεί το Termix, στην οποία δεν μπορεί να φτάσει το πρόγραμμα περιήγησής σας. Ορίστε τον Bind Host του τελικού σημείου σε μια διεύθυνση στην οποία απαντά ο υπολογιστής, όπως 0.0.0.0, και δώστε του μια σταθερή τοπική θύρα.", + "tunnelSharesSessionCookie": "Το άνοιγμα αυτής της σήραγγας θα στείλει την συνεδρία σας στο Termix στην υπηρεσία που βρίσκεται σε σήραγγα, επειδή το πρόγραμμα περιήγησής σας θα φτάσει σε αυτήν με το ίδιο όνομα κεντρικού υπολογιστή από το οποίο εξυπηρετείται το Termix. Τα cookies αγνοούν τη θύρα, επομένως δεν είναι δυνατή η διάκριση μεταξύ των δύο. Χρησιμοποιήστε την εφαρμογή Termix για υπολογιστές ή ανοίξτε το Termix στο localhost.", + "directSharesSessionCookie": "Το άνοιγμα αυτού του τελικού σημείου θα στείλει την περίοδο λειτουργίας του Termix σε αυτό, επειδή το πρόγραμμα περιήγησής σας φτάνει σε αυτό από τον ίδιο ιστότοπο από τον οποίο παρέχεται το Termix. Τα cookies αγνοούν τη θύρα, επομένως μια διαφορετική θύρα δεν αποτελεί διαφορετική ταυτότητα. Χρησιμοποιήστε την εφαρμογή Termix για υπολογιστές ή εκτελέστε αυτό το περιβάλλον χρήστη ιστού από διαφορετικό όνομα κεντρικού υπολογιστή.", + "retry": "Δοκιμάζω πάλι", + "reload": "Γεμίζω πάλι", + "copyUrl": "Αντιγραφή URL", + "urlCopied": "Η διεύθυνση URL αντιγράφηκε", + "copyFailed": "Η αντιγραφή της διεύθυνσης URL απέτυχε", + "openExternally": "Άνοιγμα εξωτερικά", + "isolationUnavailable": "Αυτό το πρόγραμμα περιήγησης δεν μπορεί να απομονώσει τα τελικά σημεία ιστού από την περίοδο λειτουργίας Termix. Χρησιμοποιήστε ένα πρόγραμμα περιήγησης με υποστήριξη iframe χωρίς διαπιστευτήρια.", + "isolationNotice": "Οι ενσωματωμένες σελίδες χρησιμοποιούν μια απομονωμένη περίοδο σύνδεσης. Για σελίδες που απαιτούν χώρο αποθήκευσης ή σύνδεση σε αναδυόμενο παράθυρο, χρησιμοποιήστε ένα απομονωμένο παράθυρο στην εφαρμογή για υπολογιστές.", + "openIsolatedWindow": "Άνοιγμα απομονωμένου παραθύρου" + }, + "hosts": { + "tabWebUi": "Διεπαφή χρήστη ιστού", + "webUiEndpointLabel": "Τελικό σημείο {{number}}", + "webUiIntegration": "Διεπαφή χρήστη ιστού", + "webUiEndpointsSection": "Τελικά σημεία", + "webUiRequirementsText": "Ένα άμεσο τελικό σημείο ανοίγει από το πρόγραμμα περιήγησής σας, επομένως η θύρα του πρέπει να είναι προσβάσιμη από εδώ. Μια σήραγγα SSH ανοίγει από το Termix μέσω της σύνδεσης SSH αυτού του κεντρικού υπολογιστή, επομένως η θύρα πρέπει να είναι προσβάσιμη μόνο από τον κεντρικό υπολογιστή.", + "enableWebUi": "Ενεργοποίηση τελικών σημείων ιστού", + "enableWebUiDesc": "Ανοίξτε τις διεπαφές ιστού αυτού του κεντρικού υπολογιστή από την πλαϊνή γραμμή.", + "webUiAddEndpoint": "Προσθήκη τελικού σημείου", + "webUiAddress": "Διεύθυνση", + "webUiOpening": "Ανοιγμα", + "webUiBindHostDesc": "Όπου το backend συνδέει το forward. Αφήστε κενό για το 127.0.0.1, το οποίο μπορεί να φτάσει μόνο το μηχάνημα που εκτελεί το Termix.", + "webUiBindHostExposed": "Αυτή η διεύθυνση είναι προσβάσιμη πέρα από το μηχάνημα Termix, επομένως όποιος μπορεί να φτάσει στη θύρα λαμβάνει αυτό το περιβάλλον χρήστη ιστού χωρίς σύνδεση.", + "webUiLocalPort": "Τοπικό Λιμάνι", + "webUiLocalPortAuto": "Αυτόματο", + "webUiLocalPortDesc": "Σε ποια θύρα ακούει η προώθηση. Αφήστε το κενό για να επιλέξει το σύστημα ή ορίστε μία όταν η θύρα πρέπει να είναι γνωστή εκ των προτέρων, όπως ένα κοντέινερ που τη δημοσιεύει.", + "webUiNewEndpointLabel": "Νέο τελικό σημείο", + "webUiLabel": "Επιγραφή", + "webUiScheme": "Σχέδιο", + "webUiPort": "Λιμάνι", + "webUiPath": "Μονοπάτι", + "webUiAccess": "Πρόσβαση", + "webUiAccessDirect": "Απευθείας", + "webUiAccessTunnel": "Σήραγγα SSH", + "webUiAccessTunnelUnavailable": "Μια σήραγγα SSH απαιτεί ενεργοποιημένο SSH σε αυτόν τον κεντρικό υπολογιστή και μια προέλευση σύνδεσης αυτής της συσκευής.", + "webUiRender": "Άνοιγμα σε", + "webUiRenderExternal": "Απομονωμένο παράθυρο επιφάνειας εργασίας", + "webUiRenderEmbedded": "Καρτέλα Termix", + "webUiRenderEmbeddedDesc": "Η ενσωμάτωση είναι η καλύτερη δυνατή προσπάθεια: ορισμένες διεπαφές ιστού αρνούνται να φορτώσουν σε ένα πλαίσιο και μια σύνδεση που βασίζεται σε cookies του ίδιου ιστότοπου ενδέχεται να επαναλαμβάνεται. Το εξωτερικό πρόγραμμα περιήγησης λειτουργεί πάντα.", + "webUiIgnoreCert": "Να επιτρέπεται το μη έγκυρο πιστοποιητικό", + "webUiIgnoreCertDesc": "Μόνο άμεσα τελικά σημεία. Η επαναφορά μέσω βρόχου εξαιρείται ήδη, επομένως αυτό δεν έχει καμία επίδραση στα τελικά σημεία σήραγγας.", + "webUiRemoveEndpoint": "Αφαίρεση τελικού σημείου", + "webUiOpenFailed": "Αποτυχία ανοίγματος του τελικού σημείου ιστού" + } +} diff --git a/plugins/web-endpoint/locales/translated/es_ES.json b/plugins/web-endpoint/locales/translated/es_ES.json new file mode 100644 index 000000000..e8aa5b455 --- /dev/null +++ b/plugins/web-endpoint/locales/translated/es_ES.json @@ -0,0 +1,52 @@ +{ + "webEndpoint": { + "noHostSelected": "No se ha seleccionado ningún host.", + "notFound": "Este punto final ya no existe.", + "tunnelUnreachableFromBrowser": "Este punto final se conecta mediante túnel a la dirección IP 127.0.0.1 de la máquina que ejecuta Termix, a la que su navegador no puede acceder. Configure el host de enlace del punto final con una dirección a la que la máquina responda, como 0.0.0.0, y asígnele un puerto local fijo.", + "tunnelSharesSessionCookie": "Al abrir este túnel, tu sesión de Termix se conectará al servicio tunelizado, ya que tu navegador accederá a él a través del mismo nombre de host desde el que se sirve Termix. Las cookies no tienen en cuenta el puerto, por lo que no se puede distinguir entre ambos. Usa la aplicación de escritorio de Termix o abre Termix en localhost.", + "directSharesSessionCookie": "Al abrir este punto final, tu sesión de Termix se redirigirá a él, ya que tu navegador lo alcanza desde el mismo sitio donde se sirve Termix. Las cookies ignoran el puerto, por lo que un puerto diferente no implica una identidad diferente. Usa la aplicación de escritorio de Termix o accede a esta interfaz web desde un nombre de host diferente.", + "retry": "Rever", + "reload": "Recargar", + "copyUrl": "Copiar URL", + "urlCopied": "URL copiada", + "copyFailed": "Error al copiar la URL", + "openExternally": "Abrir externamente", + "isolationUnavailable": "Este navegador no puede aislar los puntos finales web de su sesión de Termix. Utilice un navegador compatible con iframes sin credenciales.", + "isolationNotice": "Las páginas integradas utilizan una sesión aislada. Para las páginas que requieren almacenamiento o inicio de sesión emergente, utilice una ventana aislada en la aplicación de escritorio.", + "openIsolatedWindow": "Abrir ventana aislada" + }, + "hosts": { + "tabWebUi": "Interfaz de usuario web", + "webUiEndpointLabel": "Punto final {{number}}", + "webUiIntegration": "Interfaz de usuario web", + "webUiEndpointsSection": "Puntos finales", + "webUiRequirementsText": "Tu navegador abre un punto final directo, por lo que su puerto debe ser accesible desde aquí. En cambio, Termix abre un túnel SSH a través de la conexión SSH de este host, por lo que el puerto solo tiene que ser accesible desde el host.", + "enableWebUi": "Habilitar puntos finales web", + "enableWebUiDesc": "Abra las interfaces web de este host desde la barra lateral.", + "webUiAddEndpoint": "Agregar punto final", + "webUiAddress": "DIRECCIÓN", + "webUiOpening": "Apertura", + "webUiBindHostDesc": "Donde el backend enlaza el forward. Deje en blanco para 127.0.0.1, al que solo puede acceder la máquina que ejecuta Termix.", + "webUiBindHostExposed": "Esta dirección es accesible desde fuera de la máquina Termix, por lo que cualquiera que pueda acceder al puerto obtiene esta interfaz web sin necesidad de iniciar sesión.", + "webUiLocalPort": "Puerto local", + "webUiLocalPortAuto": "Automático", + "webUiLocalPortDesc": "En qué puerto escucha el reenvío. Déjelo en blanco para que el sistema lo seleccione automáticamente, o establezca uno cuando sea necesario conocer el puerto de antemano, como en el caso de un contenedor que lo publica.", + "webUiNewEndpointLabel": "Nuevo punto final", + "webUiLabel": "Etiqueta", + "webUiScheme": "Esquema", + "webUiPort": "Puerto", + "webUiPath": "Camino", + "webUiAccess": "Acceso", + "webUiAccessDirect": "Directo", + "webUiAccessTunnel": "Túnel SSH", + "webUiAccessTunnelUnavailable": "Para que exista un túnel SSH, es necesario que SSH esté habilitado en este host y que el origen de la conexión sea este dispositivo.", + "webUiRender": "Abrir en", + "webUiRenderExternal": "Ventana de escritorio aislada", + "webUiRenderEmbedded": "pestaña Termix", + "webUiRenderEmbeddedDesc": "La incrustación es un intento desesperado: algunas interfaces web se niegan a cargarse dentro de un marco, y un inicio de sesión que dependa de cookies del mismo sitio puede entrar en un bucle. El navegador externo siempre funciona.", + "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." + } +} diff --git a/plugins/web-endpoint/locales/translated/fi_FI.json b/plugins/web-endpoint/locales/translated/fi_FI.json new file mode 100644 index 000000000..2dbaa468f --- /dev/null +++ b/plugins/web-endpoint/locales/translated/fi_FI.json @@ -0,0 +1,52 @@ +{ + "webEndpoint": { + "noHostSelected": "Ei valittua isäntää", + "notFound": "Tätä päätepistettä ei ole enää olemassa.", + "tunnelUnreachableFromBrowser": "Tämä päätepiste muodostaa tunnelin Termixiä käyttävän koneen osoitteeseen 127.0.0.1, johon selaimesi ei pääse. Aseta päätepisteen Bind Host -arvoksi osoitteen, jolla kone vastaa, kuten 0.0.0.0, ja anna sille kiinteä paikallinen portti.", + "tunnelSharesSessionCookie": "Tämän tunnelin avaaminen lähettäisi Termix-istuntosi tunneloituun palveluun, koska selaimesi päätyisi siihen samalla isäntänimellä, josta Termixiä palvellaan. Evästeet jättävät portin huomiotta, joten niitä ei voida erottaa toisistaan. Käytä Termix-työpöytäsovellusta tai avaa Termix paikallisessa koneessa.", + "directSharesSessionCookie": "Tämän päätepisteen avaaminen lähettäisi Termix-istuntosi siihen, koska selaimesi käyttää sitä samalla sivustolla, josta Termixiä käytetään. Evästeet eivät huomioi porttia, joten eri portti ei ole eri identiteetti. Käytä Termix-työpöytäsovellusta tai käytä tätä verkkokäyttöliittymää eri isäntänimellä.", + "retry": "Yritä uudelleen", + "reload": "Lataa uudelleen", + "copyUrl": "Kopioi URL-osoite", + "urlCopied": "URL-osoite kopioitu", + "copyFailed": "URL-osoitteen kopiointi epäonnistui", + "openExternally": "Avaa ulkopuolelta", + "isolationUnavailable": "Tämä selain ei voi eristää verkkopäätepisteitä Termix-istunnostasi. Käytä selainta, joka tukee tunnistetiedotonta iframe-kehystä.", + "isolationNotice": "Upotetut sivut käyttävät eristettyä istuntoa. Sivuille, jotka vaativat tallennustilaa tai ponnahdusikkunakirjautumista, käytä eristettyä ikkunaa työpöytäsovelluksessa.", + "openIsolatedWindow": "Avaa eristetty ikkuna" + }, + "hosts": { + "tabWebUi": "Verkkokäyttöliittymä", + "webUiEndpointLabel": "Päätepiste {{number}}", + "webUiIntegration": "Verkkokäyttöliittymä", + "webUiEndpointsSection": "Päätepisteet", + "webUiRequirementsText": "Selaimesi avaa suoran päätepisteen, joten sen portin on oltava tavoitettavissa täältä. Termix avaa SSH-tunnelin tämän isännän SSH-yhteyden kautta, joten portin on oltava tavoitettavissa vain isännästä.", + "enableWebUi": "Ota käyttöön verkkopäätepisteet", + "enableWebUiDesc": "Avaa tämän isännän web-käyttöliittymät sivupalkista.", + "webUiAddEndpoint": "Lisää päätepiste", + "webUiAddress": "Osoite", + "webUiOpening": "Avaaminen", + "webUiBindHostDesc": "Mihin taustajärjestelmä sitoo eteenpäin suuntautuvan järjestelmän. Jätä tyhjäksi 127.0.0.1, johon vain Termixiä suorittava kone pääsee käsiksi.", + "webUiBindHostExposed": "Tämä osoite on saavutettavissa Termix-koneen ulkopuolelta, joten kuka tahansa, joka pääsee portin kautta, saa tämän web-käyttöliittymän ilman kirjautumista.", + "webUiLocalPort": "Paikallinen satama", + "webUiLocalPortAuto": "Automaattinen", + "webUiLocalPortDesc": "Mitä porttia edelleenlähetys kuuntelee. Jätä tyhjäksi, jos haluat järjestelmän valitsevan portin, tai aseta portti etukäteen, kuten esimerkiksi säilö, joka julkaisee sen.", + "webUiNewEndpointLabel": "Uusi päätepiste", + "webUiLabel": "Tarra", + "webUiScheme": "Järjestelmä", + "webUiPort": "Portti", + "webUiPath": "Polku", + "webUiAccess": "Pääsy", + "webUiAccessDirect": "Suoraan", + "webUiAccessTunnel": "SSH-tunneli", + "webUiAccessTunnelUnavailable": "SSH-tunneli vaatii SSH:n käyttöönoton tällä isännöintikoneella ja yhteyden alkuperän tällä laitteella.", + "webUiRender": "Avaa", + "webUiRenderExternal": "Eristetty työpöytäikkuna", + "webUiRenderEmbedded": "Termix-välilehti", + "webUiRenderEmbeddedDesc": "Upottaminen on parasta: jotkin verkkoliittymät kieltäytyvät latautumasta kehykseen, ja saman sivuston evästeisiin perustuva kirjautuminen voi tapahtua silmukassa. Ulkoinen selain toimii aina.", + "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" + } +} diff --git a/plugins/web-endpoint/locales/translated/fr_FR.json b/plugins/web-endpoint/locales/translated/fr_FR.json new file mode 100644 index 000000000..c1deb487a --- /dev/null +++ b/plugins/web-endpoint/locales/translated/fr_FR.json @@ -0,0 +1,52 @@ +{ + "webEndpoint": { + "noHostSelected": "Aucun hôte sélectionné", + "notFound": "Ce point de terminaison n'existe plus.", + "tunnelUnreachableFromBrowser": "Ce point de terminaison établit un tunnel vers l'adresse 127.0.0.1 sur la machine exécutant Termix, adresse inaccessible à votre navigateur. Configurez l'hôte de liaison du point de terminaison sur une adresse à laquelle la machine répond, par exemple 0.0.0.0, et attribuez-lui un port local fixe.", + "tunnelSharesSessionCookie": "L'ouverture de ce tunnel redirigerait votre session Termix vers le service tunnelisé, car votre navigateur y accéderait via le même nom d'hôte que celui utilisé par Termix. Les cookies ignorent le port, il est donc impossible de les distinguer. Utilisez l'application de bureau Termix ou ouvrez Termix en local.", + "directSharesSessionCookie": "Ouvrir ce point de terminaison redirigerait votre session Termix vers celui-ci, car votre navigateur y accède depuis le même site que celui où Termix est hébergé. Les cookies ignorent le port ; un port différent ne constitue donc pas une identité différente. Utilisez l’application de bureau Termix ou hébergez cette interface web depuis un autre nom d’hôte.", + "retry": "Réessayer", + "reload": "Recharger", + "copyUrl": "Copier l'URL", + "urlCopied": "URL copiée", + "copyFailed": "Impossible de copier l'URL", + "openExternally": "Ouvrir en externe", + "isolationUnavailable": "Ce navigateur ne permet pas d'isoler les points de terminaison Web de votre session Termix. Veuillez utiliser un navigateur compatible avec les iframes sans authentification.", + "isolationNotice": "Les pages intégrées utilisent une session isolée. Pour les pages nécessitant un stockage ou une connexion via une fenêtre contextuelle, utilisez une fenêtre isolée dans l'application de bureau.", + "openIsolatedWindow": "Ouvrir une fenêtre isolée" + }, + "hosts": { + "tabWebUi": "Interface utilisateur Web", + "webUiEndpointLabel": "Point de terminaison {{number}}", + "webUiIntegration": "Interface utilisateur Web", + "webUiEndpointsSection": "Points d'extrémité", + "webUiRequirementsText": "Votre navigateur ouvre un point de terminaison direct ; son port doit donc être accessible depuis ici. Termix, quant à lui, ouvre un tunnel SSH via la connexion SSH de cet hôte ; le port doit donc seulement être accessible depuis l'hôte.", + "enableWebUi": "Activer les points de terminaison Web", + "enableWebUiDesc": "Ouvrez les interfaces web de cet hébergeur depuis la barre latérale.", + "webUiAddEndpoint": "Ajouter un point de terminaison", + "webUiAddress": "Adresse", + "webUiOpening": "Ouverture", + "webUiBindHostDesc": "Où le serveur d'arrière-plan lie le serveur de transfert. Laissez vide pour 127.0.0.1, adresse accessible uniquement par la machine exécutant Termix.", + "webUiBindHostExposed": "Cette adresse est accessible au-delà de la machine Termix, donc toute personne pouvant accéder au port obtient cette interface web sans avoir à se connecter.", + "webUiLocalPort": "Port local", + "webUiLocalPortAuto": "Automatique", + "webUiLocalPortDesc": "Port d'écoute du serveur de redirection. Laissez ce champ vide pour laisser le système choisir le port, ou spécifiez-en un si celui-ci doit être connu à l'avance, par exemple pour un conteneur qui le publie.", + "webUiNewEndpointLabel": "Nouveau point de terminaison", + "webUiLabel": "Étiquette", + "webUiScheme": "Schème", + "webUiPort": "Port", + "webUiPath": "Chemin", + "webUiAccess": "Accéder", + "webUiAccessDirect": "Direct", + "webUiAccessTunnel": "Tunnel SSH", + "webUiAccessTunnelUnavailable": "Un tunnel SSH nécessite que SSH soit activé sur cet hôte et que la connexion provienne de cet appareil.", + "webUiRender": "Ouvrir dans", + "webUiRenderExternal": "Fenêtre de bureau isolée", + "webUiRenderEmbedded": "Onglet Termix", + "webUiRenderEmbeddedDesc": "L'intégration est possible dans les meilleures conditions : certaines interfaces web refusent de se charger dans un cadre, et une connexion reposant sur les cookies du même site peut générer une boucle. Le navigateur externe fonctionne toujours.", + "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" + } +} diff --git a/plugins/web-endpoint/locales/translated/he_IL.json b/plugins/web-endpoint/locales/translated/he_IL.json new file mode 100644 index 000000000..44de7367a --- /dev/null +++ b/plugins/web-endpoint/locales/translated/he_IL.json @@ -0,0 +1,52 @@ +{ + "webEndpoint": { + "noHostSelected": "לא נבחר מארח", + "notFound": "נקודת קצה זו אינה קיימת עוד.", + "tunnelUnreachableFromBrowser": "נקודת קצה זו עוברת ל-127.0.0.1 במחשב בו פועל Termix, שאליה הדפדפן שלך אינו יכול להגיע. הגדר את Bind Host של נקודת הקצה לכתובת שעליה המכונה עונה, כגון 0.0.0.0, ותן לה יציאה מקומית קבועה.", + "tunnelSharesSessionCookie": "פתיחת מנהרה זו תשלח את סשן Termix שלך לשירות המנהר, מכיוון שהדפדפן שלך יגיע אליו באותו שם מארח שממנו Termix מוגש. קובצי Cookie מתעלמים מהפורט, כך שלא ניתן להבחין ביניהם. השתמש באפליקציית שולחן העבודה של Termix, או פתח את Termix ב-localhost.", + "directSharesSessionCookie": "פתיחת נקודת קצה זו תשלח אליה את סשן Termix שלך, מכיוון שהדפדפן שלך מגיע אליה באותו אתר שממנו Termix מוגש. קובצי Cookie מתעלמים מהפורט, כך שפורט שונה אינו זהות שונה. השתמש באפליקציית שולחן העבודה של Termix, או שרת ממשק משתמש אינטרנט זה משם מארח אחר.", + "retry": "נסה שוב", + "reload": "לִטעוֹן מִחָדָשׁ", + "copyUrl": "העתקת כתובת URL", + "urlCopied": "כתובת האתר הועתקה", + "copyFailed": "נכשלה העתקת כתובת ה-URL", + "openExternally": "פתוח חיצונית", + "isolationUnavailable": "דפדפן זה אינו יכול לבודד נקודות קצה של אינטרנט מהפעלת Termix שלך. השתמש בדפדפן עם תמיכה ב-iframe ללא אישורים.", + "isolationNotice": "דפים מוטמעים משתמשים בהפעלה מבודדת. עבור דפים הדורשים אחסון או כניסה קופצת, השתמשו בחלון מבודד באפליקציית שולחן העבודה.", + "openIsolatedWindow": "פתח חלון מבודד" + }, + "hosts": { + "tabWebUi": "ממשק משתמש אינטרנטי", + "webUiEndpointLabel": "נקודת קצה {{number}}", + "webUiIntegration": "ממשק משתמש אינטרנטי", + "webUiEndpointsSection": "נקודות קצה", + "webUiRequirementsText": "נקודת קצה ישירה נפתחת על ידי הדפדפן שלך, כך שהפורט שלה חייב להיות נגיש מכאן. מנהרת SSH נפתחת על ידי Termix דרך חיבור ה-SSH של מחשב מארח זה, כך שהפורט צריך להיות נגיש רק מהמארח.", + "enableWebUi": "הפעלת נקודות קצה של האינטרנט", + "enableWebUiDesc": "פתח את ממשקי האינטרנט של מארח זה מסרגל הצד.", + "webUiAddEndpoint": "הוסף נקודת קצה", + "webUiAddress": "כְּתוֹבֶת", + "webUiOpening": "פְּתִיחָה", + "webUiBindHostDesc": "היכן שה-backend קושר את forward. השאר ריק עבור 127.0.0.1, שאליו רק מכונה שמריץ את Termix יכולה להגיע.", + "webUiBindHostExposed": "כתובת זו נגישה מעבר למכונת ה-Termix, כך שכל מי שיכול להגיע לפורט מקבל ממשק משתמש אינטרנטי זה ללא צורך בכניסה.", + "webUiLocalPort": "נמל מקומי", + "webUiLocalPortAuto": "אוֹטוֹמָטִי", + "webUiLocalPortDesc": "באיזה פורט ההעברה מאזינה. השאר ריק כדי לאפשר למערכת לבחור, או הגדר פורט כאשר יש לדעת מראש את הפורט, כגון קונטיינר שמפרסם אותו.", + "webUiNewEndpointLabel": "נקודת קצה חדשה", + "webUiLabel": "מַדבֵּקָה", + "webUiScheme": "תָכְנִית", + "webUiPort": "נָמָל", + "webUiPath": "נָתִיב", + "webUiAccess": "גִישָׁה", + "webUiAccessDirect": "יָשִׁיר", + "webUiAccessTunnel": "מנהרת SSH", + "webUiAccessTunnelUnavailable": "מנהרת SSH דורשת הפעלת SSH במארח זה ומקור חיבור של מכשיר זה.", + "webUiRender": "פתח ב", + "webUiRenderExternal": "חלון שולחן עבודה מבודד", + "webUiRenderEmbedded": "לשונית טרמיקס", + "webUiRenderEmbeddedDesc": "הטמעה היא המאמץ הטוב ביותר: חלק ממשקי האינטרנט מסרבים להיטען בתוך מסגרת, וכניסה שמסתמכת על קובצי Cookie של אותו אתר עלולה לבצע לולאה. הדפדפן החיצוני תמיד עובד.", + "webUiIgnoreCert": "אפשר אישור לא חוקי", + "webUiIgnoreCertDesc": "נקודות קצה ישירות בלבד. לולאה חוזרת כבר פטורה, כך שאין לכך השפעה על נקודות קצה של המנהרה.", + "webUiRemoveEndpoint": "הסר את נקודת הקצה", + "webUiOpenFailed": "נכשלה פתיחת נקודת הקצה של האינטרנט" + } +} diff --git a/plugins/web-endpoint/locales/translated/hi_IN.json b/plugins/web-endpoint/locales/translated/hi_IN.json new file mode 100644 index 000000000..8de98f681 --- /dev/null +++ b/plugins/web-endpoint/locales/translated/hi_IN.json @@ -0,0 +1,52 @@ +{ + "webEndpoint": { + "noHostSelected": "कोई होस्ट चयनित नहीं है", + "notFound": "यह एंडपॉइंट अब मौजूद नहीं है।", + "tunnelUnreachableFromBrowser": "यह एंडपॉइंट टर्मिक्स चलाने वाली मशीन पर 127.0.0.1 पोर्ट से टनल करता है, जिस तक आपका ब्राउज़र नहीं पहुँच सकता। एंडपॉइंट के बाइंड होस्ट को उस मशीन के किसी ऐसे पते पर सेट करें जिस पर वह प्रतिक्रिया देती हो, जैसे कि 0.0.0.0, और इसे एक निश्चित लोकल पोर्ट दें।", + "tunnelSharesSessionCookie": "इस टनल को खोलने से आपका टर्मिक्स सेशन टनल की गई सेवा पर चला जाएगा, क्योंकि आपका ब्राउज़र उसी होस्टनेम से सेवा प्राप्त करेगा जिससे टर्मिक्स संचालित होता है। कुकीज़ पोर्ट को अनदेखा करती हैं, इसलिए दोनों में अंतर नहीं किया जा सकता। टर्मिक्स डेस्कटॉप ऐप का उपयोग करें, या टर्मिक्स को लोकलहोस्ट पर खोलें।", + "directSharesSessionCookie": "इस एंडपॉइंट को खोलने से आपका टर्मिक्स सेशन इस पर चला जाएगा, क्योंकि आपका ब्राउज़र उसी साइट से इस तक पहुंचता है जहां से टर्मिक्स संचालित होता है। कुकीज़ पोर्ट को अनदेखा करती हैं, इसलिए अलग पोर्ट का मतलब अलग पहचान नहीं है। टर्मिक्स डेस्कटॉप ऐप का उपयोग करें, या इस वेब यूआई को किसी अन्य होस्टनेम से संचालित करें।", + "retry": "पुन: प्रयास करें", + "reload": "पुनः लोड करें", + "copyUrl": "यूआरएल कॉपी करें", + "urlCopied": "यूआरएल कॉपी हो गया", + "copyFailed": "यूआरएल कॉपी करने में विफल", + "openExternally": "बाहरी रूप से खोलें", + "isolationUnavailable": "यह ब्राउज़र आपके टर्मिक्स सेशन से वेब एंडपॉइंट्स को अलग नहीं कर सकता। क्रेडेंशियललेस आईफ्रेम सपोर्ट वाले ब्राउज़र का उपयोग करें।", + "isolationNotice": "एम्बेडेड पेज एक अलग सेशन का उपयोग करते हैं। स्टोरेज या पॉपअप साइन-इन की आवश्यकता वाले पेजों के लिए, डेस्कटॉप ऐप में एक अलग विंडो का उपयोग करें।", + "openIsolatedWindow": "पृथक विंडो खोलें" + }, + "hosts": { + "tabWebUi": "वेब यूआई", + "webUiEndpointLabel": "एंडपॉइंट {{number}}", + "webUiIntegration": "वेब यूआई", + "webUiEndpointsSection": "अंतिमबिंदुओं", + "webUiRequirementsText": "आपके ब्राउज़र द्वारा एक डायरेक्ट एंडपॉइंट खोला जाता है, इसलिए इसका पोर्ट यहाँ से पहुँच योग्य होना चाहिए। इसके विपरीत, टर्मिक्स द्वारा इस होस्ट के SSH कनेक्शन पर एक SSH टनल खोला जाता है, इसलिए पोर्ट का होस्ट से पहुँच योग्य होना ही आवश्यक है।", + "enableWebUi": "वेब एंडपॉइंट्स को सक्षम करें", + "enableWebUiDesc": "साइडबार से इस होस्ट के वेब इंटरफेस खोलें।", + "webUiAddEndpoint": "एंडपॉइंट जोड़ें", + "webUiAddress": "पता", + "webUiOpening": "प्रारंभिक", + "webUiBindHostDesc": "जहां बैकएंड फॉरवर्ड को बाइंड करता है। 127.0.0.1 के लिए इसे खाली छोड़ दें, क्योंकि केवल टर्मिक्स चलाने वाली मशीन ही इस तक पहुंच सकती है।", + "webUiBindHostExposed": "यह पता टर्मिक्स मशीन से परे भी पहुंच योग्य है, इसलिए जो कोई भी पोर्ट तक पहुंच सकता है, उसे बिना लॉगिन किए यह वेब यूआई मिल जाता है।", + "webUiLocalPort": "स्थानीय बंदरगाह", + "webUiLocalPortAuto": "स्वचालित", + "webUiLocalPortDesc": "यह फ़ॉरवर्ड किस पोर्ट पर सुनता है। सिस्टम को चुनने देने के लिए इसे खाली छोड़ दें, या यदि पोर्ट पहले से ज्ञात होना आवश्यक हो, जैसे कि इसे प्रकाशित करने वाला कोई कंटेनर, तो एक पोर्ट सेट करें।", + "webUiNewEndpointLabel": "नया एंडपॉइंट", + "webUiLabel": "लेबल", + "webUiScheme": "योजना", + "webUiPort": "पत्तन", + "webUiPath": "पथ", + "webUiAccess": "पहुँच", + "webUiAccessDirect": "प्रत्यक्ष", + "webUiAccessTunnel": "एसएसएच सुरंग", + "webUiAccessTunnelUnavailable": "एसएसएच टनल के लिए इस होस्ट पर एसएसएच सक्षम होना और इस डिवाइस का कनेक्शन स्रोत होना आवश्यक है।", + "webUiRender": "में खोलें", + "webUiRenderExternal": "पृथक डेस्कटॉप विंडो", + "webUiRenderEmbedded": "टर्मिक्स टैब", + "webUiRenderEmbeddedDesc": "एम्बेडिंग एक सर्वोत्तम प्रयास है: कुछ वेब इंटरफेस फ्रेम में लोड होने से इनकार कर देते हैं, और समान साइट कुकीज़ पर निर्भर लॉगिन लूप में फंस सकता है। बाहरी ब्राउज़र हमेशा काम करता है।", + "webUiIgnoreCert": "अमान्य प्रमाणपत्र की अनुमति दें", + "webUiIgnoreCertDesc": "केवल डायरेक्ट एंडपॉइंट्स के लिए। लूपबैक पहले से ही छूट प्राप्त है, इसलिए इसका टनल एंडपॉइंट्स पर कोई प्रभाव नहीं पड़ता।", + "webUiRemoveEndpoint": "एंडपॉइंट हटाएँ", + "webUiOpenFailed": "वेब एंडपॉइंट खोलने में विफल।" + } +} diff --git a/plugins/web-endpoint/locales/translated/hu_HU.json b/plugins/web-endpoint/locales/translated/hu_HU.json new file mode 100644 index 000000000..bf9c19153 --- /dev/null +++ b/plugins/web-endpoint/locales/translated/hu_HU.json @@ -0,0 +1,52 @@ +{ + "webEndpoint": { + "noHostSelected": "Nincs kiválasztva gazdagép", + "notFound": "Ez a végpont már nem létezik.", + "tunnelUnreachableFromBrowser": "Ez a végpont a Termixet futtató gépen található 127.0.0.1 címre csatlakozik, amelyet a böngésződ nem tud elérni. Állítsd be a végpont Bind Host értékét egy olyan címre, amelyen a gép válaszol, például 0.0.0.0, és adj meg neki egy fix Local Port értéket.", + "tunnelSharesSessionCookie": "Ennek az alagútnak a megnyitása a Termix munkamenetet a bújtatott szolgáltatáshoz küldené, mivel a böngésződ ugyanazon a hosztnéven érné el, amelyről a Termix is kiszolgálja. A sütik figyelmen kívül hagyják a portot, így a kettőt nem lehet megkülönböztetni. Használd a Termix asztali alkalmazást, vagy nyisd meg a Termixet a localhost címen.", + "directSharesSessionCookie": "Ennek a végpontnak a megnyitása a Termix munkamenetet ide küldené, mivel a böngésződ ugyanazon a helyen éri el, ahonnan a Termix is kiszolgálható. A sütik figyelmen kívül hagyják a portot, így egy másik port nem jelent másik identitást. Használd a Termix asztali alkalmazást, vagy szolgáltasd ki ezt a webes felhasználói felületet egy másik hostname-ről.", + "retry": "Újrapróbálkozás", + "reload": "Újratöltés", + "copyUrl": "URL másolása", + "urlCopied": "URL másolva", + "copyFailed": "Nem sikerült másolni az URL-t", + "openExternally": "Külsőleg nyitott", + "isolationUnavailable": "Ez a böngésző nem tudja elkülöníteni a webes végpontokat a Termix-munkamenettől. Használjon hitelesítő adatok nélküli iframe-támogatással rendelkező böngészőt.", + "isolationNotice": "A beágyazott oldalak elszigetelt munkamenetet használnak. A tárhelyet vagy felugró bejelentkezést igénylő oldalakhoz használjon egy elszigetelt ablakot az asztali alkalmazásban.", + "openIsolatedWindow": "Nyitott elszigetelt ablak" + }, + "hosts": { + "tabWebUi": "Webes felhasználói felület", + "webUiEndpointLabel": "Végpont {{number}}", + "webUiIntegration": "Webes felhasználói felület", + "webUiEndpointsSection": "Végpontok", + "webUiRequirementsText": "A böngésződ egy közvetlen végpontot nyit meg, így annak portjának elérhetőnek kell lennie innen. Ehelyett a Termix egy SSH alagutat nyit meg a gazdagép SSH kapcsolatán keresztül, így a portnak csak a gazdagépről kell elérhetőnek lennie.", + "enableWebUi": "Webes végpontok engedélyezése", + "enableWebUiDesc": "Nyissa meg a gazdagép webes felületeit az oldalsávból.", + "webUiAddEndpoint": "Végpont hozzáadása", + "webUiAddress": "Cím", + "webUiOpening": "Nyílás", + "webUiBindHostDesc": "Ahol a háttérrendszer a továbbító rendszert köti. Hagyja üresen a 127.0.0.1 mezőt, amelyet csak a Termixet futtató gép tud elérni.", + "webUiBindHostExposed": "Ez a cím elérhető a Termix gépen kívül is, így bárki, aki el tudja érni a portot, bejelentkezés nélkül megkapja ezt a webes felhasználói felületet.", + "webUiLocalPort": "Helyi kikötő", + "webUiLocalPortAuto": "Automatikus", + "webUiLocalPortDesc": "Melyik porton figyel a továbbító. Hagyja üresen, ha a rendszer szeretné kiválasztani, vagy állítson be egyet, ha a portot előre ismerni kell, például egy konténer esetében, amely közzéteszi azt.", + "webUiNewEndpointLabel": "Új végpont", + "webUiLabel": "Címke", + "webUiScheme": "Rendszer", + "webUiPort": "Kikötő", + "webUiPath": "Útvonal", + "webUiAccess": "Hozzáférés", + "webUiAccessDirect": "Közvetlen", + "webUiAccessTunnel": "SSH alagút", + "webUiAccessTunnelUnavailable": "Egy SSH-alagúthoz engedélyezni kell az SSH-t ezen a gazdagépen, és ennek az eszköznek a kapcsolatának forrását kell tartalmaznia.", + "webUiRender": "Nyitva tartás", + "webUiRenderExternal": "Elszigetelt asztali ablak", + "webUiRenderEmbedded": "Termix fül", + "webUiRenderEmbeddedDesc": "A beágyazás a legjobb megoldás: egyes webes felületek nem töltődnek be keretben, és az azonos webhelyen található sütikre támaszkodó bejelentkezés ciklusba kerülhet. A külső böngésző mindig működik.", + "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" + } +} diff --git a/plugins/web-endpoint/locales/translated/id_ID.json b/plugins/web-endpoint/locales/translated/id_ID.json new file mode 100644 index 000000000..a6a87648d --- /dev/null +++ b/plugins/web-endpoint/locales/translated/id_ID.json @@ -0,0 +1,52 @@ +{ + "webEndpoint": { + "noHostSelected": "Tidak ada pembawa acara yang dipilih.", + "notFound": "Endpoint ini sudah tidak ada lagi.", + "tunnelUnreachableFromBrowser": "Endpoint ini membuat terowongan ke 127.0.0.1 pada mesin yang menjalankan Termix, yang tidak dapat dijangkau oleh browser Anda. Atur Bind Host endpoint ke alamat yang dapat diakses oleh mesin tersebut, misalnya 0.0.0.0, dan berikan Local Port tetap.", + "tunnelSharesSessionCookie": "Membuka terowongan ini akan mengirim sesi Termix Anda ke layanan yang di-tunnel, karena browser Anda akan mengaksesnya di hostname yang sama dengan tempat Termix disajikan. Cookie mengabaikan port, sehingga keduanya tidak dapat dibedakan. Gunakan aplikasi desktop Termix, atau buka Termix di localhost.", + "directSharesSessionCookie": "Membuka endpoint ini akan mengirim sesi Termix Anda ke sana, karena browser Anda mengaksesnya di situs yang sama tempat Termix disajikan. Cookie mengabaikan port, jadi port yang berbeda bukan berarti identitas yang berbeda. Gunakan aplikasi desktop Termix, atau sajikan UI web ini dari hostname yang berbeda.", + "retry": "Mencoba kembali", + "reload": "Muat ulang", + "copyUrl": "Salin URL", + "urlCopied": "URL disalin", + "copyFailed": "Gagal menyalin URL", + "openExternally": "Buka secara eksternal", + "isolationUnavailable": "Browser ini tidak dapat mengisolasi endpoint web dari sesi Termix Anda. Gunakan browser yang mendukung iframe tanpa kredensial.", + "isolationNotice": "Halaman yang disematkan menggunakan sesi terisolasi. Untuk halaman yang memerlukan penyimpanan atau masuk melalui jendela pop-up, gunakan jendela terisolasi di aplikasi desktop.", + "openIsolatedWindow": "Buka jendela terisolasi" + }, + "hosts": { + "tabWebUi": "Antarmuka pengguna web", + "webUiEndpointLabel": "Titik akhir {{number}}", + "webUiIntegration": "Antarmuka pengguna web", + "webUiEndpointsSection": "Titik akhir", + "webUiRequirementsText": "Titik akhir langsung dibuka oleh browser Anda, jadi port-nya harus dapat dijangkau dari sini. Sebaliknya, terowongan SSH dibuka oleh Termix melalui koneksi SSH host ini, sehingga port tersebut hanya perlu dapat dijangkau dari host.", + "enableWebUi": "Aktifkan titik akhir web", + "enableWebUiDesc": "Buka antarmuka web host ini dari bilah sisi.", + "webUiAddEndpoint": "Tambahkan titik akhir", + "webUiAddress": "Alamat", + "webUiOpening": "Pembukaan", + "webUiBindHostDesc": "Di sinilah backend mengikat forward. Biarkan kosong untuk 127.0.0.1, yang hanya dapat diakses oleh mesin yang menjalankan Termix.", + "webUiBindHostExposed": "Alamat ini dapat diakses di luar mesin Termix, sehingga siapa pun yang dapat mengakses port tersebut akan mendapatkan antarmuka web ini tanpa perlu login.", + "webUiLocalPort": "Pelabuhan Lokal", + "webUiLocalPortAuto": "Otomatis", + "webUiLocalPortDesc": "Port mana yang digunakan oleh penerusan untuk mendengarkan. Biarkan kosong agar sistem memilih, atau atur satu jika port harus diketahui sebelumnya, seperti kontainer yang mempublikasikannya.", + "webUiNewEndpointLabel": "Titik akhir baru", + "webUiLabel": "Label", + "webUiScheme": "Skema", + "webUiPort": "Pelabuhan", + "webUiPath": "Jalur", + "webUiAccess": "Mengakses", + "webUiAccessDirect": "Langsung", + "webUiAccessTunnel": "Terowongan SSH", + "webUiAccessTunnelUnavailable": "Terowongan SSH membutuhkan SSH yang diaktifkan pada host ini dan asal koneksi dari perangkat ini.", + "webUiRender": "Buka di", + "webUiRenderExternal": "Jendela desktop terisolasi", + "webUiRenderEmbedded": "Tab Termix", + "webUiRenderEmbeddedDesc": "Penyematan dilakukan dengan upaya terbaik: beberapa antarmuka web menolak untuk dimuat dalam bingkai, dan login yang bergantung pada cookie situs yang sama mungkin berulang. Browser eksternal selalu berfungsi.", + "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." + } +} diff --git a/plugins/web-endpoint/locales/translated/it_IT.json b/plugins/web-endpoint/locales/translated/it_IT.json new file mode 100644 index 000000000..6e612fbdf --- /dev/null +++ b/plugins/web-endpoint/locales/translated/it_IT.json @@ -0,0 +1,52 @@ +{ + "webEndpoint": { + "noHostSelected": "Nessun host selezionato", + "notFound": "Questo endpoint non esiste più.", + "tunnelUnreachableFromBrowser": "Questo endpoint crea un tunnel verso 127.0.0.1 sulla macchina su cui è in esecuzione Termix, indirizzo che il tuo browser non può raggiungere. Imposta il Bind Host dell'endpoint su un indirizzo a cui la macchina risponde, ad esempio 0.0.0.0, e assegnagli una porta locale fissa.", + "tunnelSharesSessionCookie": "L'apertura di questo tunnel indirizzerebbe la tua sessione Termix al servizio tunnelizzato, poiché il tuo browser lo raggiungerebbe tramite lo stesso hostname da cui viene erogato il servizio Termix. I cookie ignorano la porta, quindi i due non possono essere distinti. Utilizza l'applicazione desktop di Termix oppure apri Termix all'indirizzo localhost.", + "directSharesSessionCookie": "L'apertura di questo endpoint invierebbe la tua sessione Termix ad esso, poiché il tuo browser lo raggiunge dallo stesso sito da cui viene erogato il servizio Termix. I cookie ignorano la porta, quindi una porta diversa non corrisponde a un'identità diversa. Utilizza l'applicazione desktop di Termix oppure esegui questa interfaccia web da un hostname diverso.", + "retry": "Riprova", + "reload": "Ricaricare", + "copyUrl": "Copia URL", + "urlCopied": "URL copiato", + "copyFailed": "Impossibile copiare l'URL", + "openExternally": "Apri esternamente", + "isolationUnavailable": "Questo browser non è in grado di isolare gli endpoint web dalla sessione Termix. Utilizza un browser che supporti gli iframe senza credenziali.", + "isolationNotice": "Le pagine incorporate utilizzano una sessione isolata. Per le pagine che richiedono l'archiviazione dei dati o l'accesso tramite popup, utilizzare una finestra isolata nell'applicazione desktop.", + "openIsolatedWindow": "Apri finestra isolata" + }, + "hosts": { + "tabWebUi": "Interfaccia utente web", + "webUiEndpointLabel": "Punto finale {{number}}", + "webUiIntegration": "Interfaccia utente web", + "webUiEndpointsSection": "Punti terminali", + "webUiRequirementsText": "Un endpoint diretto viene aperto dal tuo browser, quindi la sua porta deve essere raggiungibile da qui. Termix, invece, apre un tunnel SSH sulla connessione SSH di questo host, quindi la porta deve essere raggiungibile solo dall'host.", + "enableWebUi": "Endpoint web abilitati", + "enableWebUiDesc": "Apri le interfacce web di questo host dalla barra laterale.", + "webUiAddEndpoint": "Aggiungi endpoint", + "webUiAddress": "Indirizzo", + "webUiOpening": "Apertura", + "webUiBindHostDesc": "Dove il backend si collega al forward. Lascia vuoto il campo 127.0.0.1, a cui può accedere solo la macchina su cui è in esecuzione Termix.", + "webUiBindHostExposed": "Questo indirizzo è raggiungibile anche al di fuori del server Termix, quindi chiunque riesca ad accedere alla porta può utilizzare questa interfaccia web senza bisogno di effettuare il login.", + "webUiLocalPort": "Porto locale", + "webUiLocalPortAuto": "Automatico", + "webUiLocalPortDesc": "Quale porta deve rimanere in ascolto il server di inoltro. Lasciare vuoto per consentire al sistema di sceglierla automaticamente, oppure specificarne una quando la porta deve essere nota in anticipo, ad esempio per un container che la pubblica.", + "webUiNewEndpointLabel": "Nuovo endpoint", + "webUiLabel": "Etichetta", + "webUiScheme": "Schema", + "webUiPort": "Porta", + "webUiPath": "Sentiero", + "webUiAccess": "Accesso", + "webUiAccessDirect": "Diretto", + "webUiAccessTunnel": "Tunnel SSH", + "webUiAccessTunnelUnavailable": "Per creare un tunnel SSH è necessario che SSH sia abilitato su questo host e che l'origine della connessione sia questo dispositivo.", + "webUiRender": "Apri in", + "webUiRenderExternal": "Finestra del desktop isolata", + "webUiRenderEmbedded": "scheda Termix", + "webUiRenderEmbeddedDesc": "L'incorporamento è un tentativo quantomeno efficace: alcune interfacce web si rifiutano di caricarsi in un frame e un login che si basa sui cookie dello stesso sito potrebbe generare un loop. Il browser esterno funziona sempre.", + "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" + } +} diff --git a/plugins/web-endpoint/locales/translated/ja_JP.json b/plugins/web-endpoint/locales/translated/ja_JP.json new file mode 100644 index 000000000..89f4c06ce --- /dev/null +++ b/plugins/web-endpoint/locales/translated/ja_JP.json @@ -0,0 +1,52 @@ +{ + "webEndpoint": { + "noHostSelected": "ホストが選択されていません", + "notFound": "このエンドポイントは既に存在しません。", + "tunnelUnreachableFromBrowser": "このエンドポイントは、Termixを実行しているマシン上の127.0.0.1にトンネル接続しますが、このアドレスにはブラウザからアクセスできません。エンドポイントのバインドホストを、そのマシンが応答するアドレス(例:0.0.0.0)に設定し、固定のローカルポートを指定してください。", + "tunnelSharesSessionCookie": "このトンネルを開くと、ブラウザがTermixと同じホスト名でアクセスするため、Termixセッションはトンネル化されたサービスに送信されます。Cookieはポート番号を無視するため、両者を区別することはできません。Termixデスクトップアプリを使用するか、localhostでTermixを開いてください。", + "directSharesSessionCookie": "このエンドポイントを開くと、ブラウザがTermixと同じサイトからアクセスするため、Termixセッションがそこに送信されます。Cookieはポート番号を無視するため、ポート番号が異なっても別のIDとはみなされません。Termixデスクトップアプリを使用するか、別のホスト名からこのWeb UIを提供してください。", + "retry": "リトライ", + "reload": "リロード", + "copyUrl": "URLをコピー", + "urlCopied": "URLがコピーされました", + "copyFailed": "URLのコピーに失敗しました", + "openExternally": "外部に開く", + "isolationUnavailable": "このブラウザでは、WebエンドポイントをTermixセッションから分離できません。認証情報不要のiframeをサポートするブラウザを使用してください。", + "isolationNotice": "埋め込みページは独立したセッションを使用します。ストレージが必要なページやポップアップによるサインインが必要な場合は、デスクトップアプリで独立したウィンドウを使用してください。", + "openIsolatedWindow": "隔離されたウィンドウを開く" + }, + "hosts": { + "tabWebUi": "Web UI", + "webUiEndpointLabel": "エンドポイント {{number}}", + "webUiIntegration": "Web UI", + "webUiEndpointsSection": "エンドポイント", + "webUiRequirementsText": "ブラウザによって直接エンドポイントが開かれるため、そのポートはブラウザからアクセス可能である必要があります。一方、TermixはこのホストのSSH接続を介してSSHトンネルを開くため、ポートはホストからのみアクセス可能であればよいのです。", + "enableWebUi": "Webエンドポイントを有効にする", + "enableWebUiDesc": "サイドバーからこのホストのウェブインターフェースを開いてください。", + "webUiAddEndpoint": "エンドポイントを追加する", + "webUiAddress": "住所", + "webUiOpening": "オープニング", + "webUiBindHostDesc": "バックエンドがフォワードをバインドする場所です。Termixを実行しているマシンのみがアクセスできる127.0.0.1の場合は空白のままにしてください。", + "webUiBindHostExposed": "このアドレスはTermixマシン以外からもアクセスできるため、このポートにアクセスできる人であれば誰でもログインなしでこのWeb UIにアクセスできます。", + "webUiLocalPort": "地元の港", + "webUiLocalPortAuto": "自動", + "webUiLocalPortDesc": "フォワーディングがリッスンするポートを指定します。システムに選択させる場合は空欄のままにし、ポートを事前に知っておく必要がある場合(例えば、ポートを公開するコンテナなど)はポート番号を指定してください。", + "webUiNewEndpointLabel": "新しいエンドポイント", + "webUiLabel": "ラベル", + "webUiScheme": "スキーム", + "webUiPort": "ポート", + "webUiPath": "パス", + "webUiAccess": "アクセス", + "webUiAccessDirect": "直接", + "webUiAccessTunnel": "SSHトンネル", + "webUiAccessTunnelUnavailable": "SSHトンネルには、このホストでSSHが有効になっており、接続元がこのデバイスである必要があります。", + "webUiRender": "開く", + "webUiRenderExternal": "分離されたデスクトップウィンドウ", + "webUiRenderEmbedded": "テルミックス錠", + "webUiRenderEmbeddedDesc": "埋め込みはベストエフォート型です。一部のWebインターフェースはフレーム内での読み込みを拒否し、同一サイトCookieに依存するログイン処理はループする可能性があります。外部ブラウザは常に正常に動作します。", + "webUiIgnoreCert": "無効な証明書を許可する", + "webUiIgnoreCertDesc": "直接エンドポイントのみが対象です。ループバックは既に対象外となっているため、トンネルエンドポイントには影響しません。", + "webUiRemoveEndpoint": "エンドポイントを削除", + "webUiOpenFailed": "ウェブエンドポイントを開くのに失敗しました" + } +} diff --git a/plugins/web-endpoint/locales/translated/ko_KR.json b/plugins/web-endpoint/locales/translated/ko_KR.json new file mode 100644 index 000000000..8c296dd24 --- /dev/null +++ b/plugins/web-endpoint/locales/translated/ko_KR.json @@ -0,0 +1,52 @@ +{ + "webEndpoint": { + "noHostSelected": "호스트가 선택되지 않았습니다.", + "notFound": "이 엔드포인트는 더 이상 존재하지 않습니다.", + "tunnelUnreachableFromBrowser": "이 엔드포인트는 브라우저에서 접근할 수 없는 Termix 실행 머신의 127.0.0.1 주소로 터널링합니다. 엔드포인트의 바인드 호스트를 해당 머신이 응답하는 주소(예: 0.0.0.0)로 설정하고 고정된 로컬 포트를 지정하십시오.", + "tunnelSharesSessionCookie": "이 터널을 열면 브라우저가 Termix가 제공되는 호스트 이름과 동일한 호스트 이름으로 접속하게 되므로 Termix 세션이 터널링된 서비스로 전송됩니다. 쿠키는 포트 번호를 무시하므로 둘을 구분할 수 없습니다. Termix 데스크톱 앱을 사용하거나 localhost에서 Termix를 실행하세요.", + "directSharesSessionCookie": "이 엔드포인트를 열면 브라우저가 Termix가 제공되는 동일한 사이트에서 해당 엔드포인트에 접속하기 때문에 Termix 세션이 해당 엔드포인트로 전송됩니다. 쿠키는 포트 번호를 무시하므로 다른 포트 번호를 사용한다고 해서 다른 ID를 의미하는 것은 아닙니다. Termix 데스크톱 앱을 사용하거나 다른 호스트 이름에서 이 웹 UI를 제공하십시오.", + "retry": "다시 해 보다", + "reload": "재장전", + "copyUrl": "URL 복사", + "urlCopied": "URL이 복사되었습니다", + "copyFailed": "URL 복사에 실패했습니다", + "openExternally": "외부에서 열기", + "isolationUnavailable": "이 브라우저는 웹 엔드포인트를 Termix 세션에서 분리할 수 없습니다. 자격 증명 없이 iframe을 지원하는 브라우저를 사용하십시오.", + "isolationNotice": "내장 페이지는 격리된 세션을 사용합니다. 저장 공간이나 팝업 로그인이 필요한 페이지의 경우 데스크톱 앱에서 격리된 창을 사용하십시오.", + "openIsolatedWindow": "격리된 창을 엽니다" + }, + "hosts": { + "tabWebUi": "웹 UI", + "webUiEndpointLabel": "엔드포인트 {{number}}", + "webUiIntegration": "웹 UI", + "webUiEndpointsSection": "엔드포인트", + "webUiRequirementsText": "브라우저에서 직접 엔드포인트가 열리므로 해당 포트에 브라우저에서 접근할 수 있어야 합니다. Termix는 이 호스트의 SSH 연결을 통해 SSH 터널을 열므로 해당 포트는 호스트에서만 접근할 수 있으면 됩니다.", + "enableWebUi": "웹 엔드포인트를 활성화합니다.", + "enableWebUiDesc": "사이드바에서 이 호스트의 웹 인터페이스를 엽니다.", + "webUiAddEndpoint": "엔드포인트 추가", + "webUiAddress": "주소", + "webUiOpening": "열기", + "webUiBindHostDesc": "백엔드가 포워드를 바인딩하는 위치입니다. 127.0.0.1은 Termix가 실행되는 머신만 접근할 수 있으므로 비워 두십시오.", + "webUiBindHostExposed": "이 주소는 Termix 장비 외에서도 접근 가능하므로, 해당 포트에 접속할 수 있는 사람은 누구나 로그인 없이 이 웹 UI에 접속할 수 있습니다.", + "webUiLocalPort": "현지 항구", + "webUiLocalPortAuto": "오토매틱", + "webUiLocalPortDesc": "포트 포워딩이 수신 대기할 포트를 지정합니다. 시스템에서 자동으로 선택하도록 하려면 비워 두거나, 포트를 미리 알아야 하는 컨테이너(예: 포트를 공개하는 컨테이너)의 경우 포트를 설정하십시오.", + "webUiNewEndpointLabel": "새로운 엔드포인트", + "webUiLabel": "상표", + "webUiScheme": "계획", + "webUiPort": "포트", + "webUiPath": "길", + "webUiAccess": "입장", + "webUiAccessDirect": "직접", + "webUiAccessTunnel": "SSH 터널", + "webUiAccessTunnelUnavailable": "SSH 터널을 사용하려면 해당 호스트에서 SSH가 활성화되어 있어야 하고 연결 시작 장치가 이 장치여야 합니다.", + "webUiRender": "열기", + "webUiRenderExternal": "격리된 데스크톱 창", + "webUiRenderEmbedded": "터믹스 탭", + "webUiRenderEmbeddedDesc": "임베딩은 최선을 다하는 방식입니다. 일부 웹 인터페이스는 프레임 내에서 로드되지 않을 수 있으며, 동일 사이트 쿠키에 의존하는 로그인은 무한 루프에 빠질 수 있습니다. 외부 브라우저는 항상 정상적으로 작동합니다.", + "webUiIgnoreCert": "유효하지 않은 인증서를 허용합니다", + "webUiIgnoreCertDesc": "직접 연결 엔드포인트에만 적용됩니다. 루프백은 이미 제외되어 있으므로 터널 엔드포인트에는 영향을 미치지 않습니다.", + "webUiRemoveEndpoint": "엔드포인트를 제거합니다.", + "webUiOpenFailed": "웹 엔드포인트를 열 수 없습니다." + } +} diff --git a/plugins/web-endpoint/locales/translated/nl_NL.json b/plugins/web-endpoint/locales/translated/nl_NL.json new file mode 100644 index 000000000..74a54a876 --- /dev/null +++ b/plugins/web-endpoint/locales/translated/nl_NL.json @@ -0,0 +1,52 @@ +{ + "webEndpoint": { + "noHostSelected": "Geen host geselecteerd", + "notFound": "Dit eindpunt bestaat niet meer.", + "tunnelUnreachableFromBrowser": "Dit eindpunt tunnelt naar 127.0.0.1 op de machine waarop Termix draait, een adres dat uw browser niet kan bereiken. Stel de Bind Host van het eindpunt in op een adres waarop die machine reageert, bijvoorbeeld 0.0.0.0, en geef het een vaste lokale poort.", + "tunnelSharesSessionCookie": "Door deze tunnel te openen, wordt uw Termix-sessie naar de getunnelde service gestuurd, omdat uw browser deze via dezelfde hostnaam bereikt als waar Termix wordt aangeboden. Cookies negeren de poort, dus de twee zijn niet van elkaar te onderscheiden. Gebruik de Termix-desktopapp of open Termix op localhost.", + "directSharesSessionCookie": "Het openen van dit eindpunt stuurt uw Termix-sessie ernaartoe, omdat uw browser het benadert via dezelfde site waar Termix wordt aangeboden. Cookies negeren de poort, dus een andere poort betekent niet dat er een andere identiteit is. Gebruik de Termix-desktopapp of bied deze webinterface aan via een andere hostnaam.", + "retry": "Opnieuw proberen", + "reload": "Herladen", + "copyUrl": "URL kopiëren", + "urlCopied": "URL gekopieerd", + "copyFailed": "Het kopiëren van de URL is mislukt.", + "openExternally": "Extern openen", + "isolationUnavailable": "Deze browser kan web-endpoints niet isoleren van uw Termix-sessie. Gebruik een browser met ondersteuning voor iframes zonder inloggegevens.", + "isolationNotice": "Ingesloten pagina's gebruiken een geïsoleerde sessie. Voor pagina's die opslag of een pop-upaanmelding vereisen, gebruikt u een geïsoleerd venster in de desktop-app.", + "openIsolatedWindow": "Een geïsoleerd venster openen" + }, + "hosts": { + "tabWebUi": "Web-UI", + "webUiEndpointLabel": "Eindpunt {{number}}", + "webUiIntegration": "Web-UI", + "webUiEndpointsSection": "Eindpunten", + "webUiRequirementsText": "Uw browser opent een rechtstreeks eindpunt, dus de poort moet vanaf hier bereikbaar zijn. Termix opent in plaats daarvan een SSH-tunnel via de SSH-verbinding van deze host, dus de poort hoeft alleen vanaf de host bereikbaar te zijn.", + "enableWebUi": "Web-eindpunten inschakelen", + "enableWebUiDesc": "Open de webinterfaces van deze host via de zijbalk.", + "webUiAddEndpoint": "Eindpunt toevoegen", + "webUiAddress": "Adres", + "webUiOpening": "Opening", + "webUiBindHostDesc": "Waar de backend de forward verbindt. Laat dit veld leeg voor 127.0.0.1, dat alleen bereikbaar is vanaf de machine waarop Termix draait.", + "webUiBindHostExposed": "Dit adres is bereikbaar vanaf elke locatie buiten de Termix-machine, dus iedereen die de poort kan bereiken, krijgt toegang tot deze webinterface zonder in te loggen.", + "webUiLocalPort": "Lokale haven", + "webUiLocalPortAuto": "Automatisch", + "webUiLocalPortDesc": "Op welke poort luistert de forwarder? Laat dit veld leeg om het systeem zelf een poort te laten kiezen, of stel er een in als de poort van tevoren bekend moet zijn, bijvoorbeeld omdat een container deze publiceert.", + "webUiNewEndpointLabel": "Nieuw eindpunt", + "webUiLabel": "Label", + "webUiScheme": "Schema", + "webUiPort": "Haven", + "webUiPath": "Pad", + "webUiAccess": "Toegang", + "webUiAccessDirect": "Direct", + "webUiAccessTunnel": "SSH-tunnel", + "webUiAccessTunnelUnavailable": "Voor een SSH-tunnel is het nodig dat SSH op deze host is ingeschakeld en dat de verbinding afkomstig is van dit apparaat.", + "webUiRender": "Openen in", + "webUiRenderExternal": "Geïsoleerd bureaubladvenster", + "webUiRenderEmbedded": "Termix-tabblad", + "webUiRenderEmbeddedDesc": "Het inbedden is een poging naar beste vermogen: sommige webinterfaces weigeren te laden in een frame, en een inlogproces dat afhankelijk is van cookies van dezelfde website kan in een oneindige lus terechtkomen. De externe browser werkt altijd.", + "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." + } +} diff --git a/plugins/web-endpoint/locales/translated/no_NO.json b/plugins/web-endpoint/locales/translated/no_NO.json new file mode 100644 index 000000000..7610bb9a5 --- /dev/null +++ b/plugins/web-endpoint/locales/translated/no_NO.json @@ -0,0 +1,52 @@ +{ + "webEndpoint": { + "noHostSelected": "Ingen vert valgt", + "notFound": "Dette endepunktet finnes ikke lenger.", + "tunnelUnreachableFromBrowser": "Dette endepunktet tunnelerer til 127.0.0.1 på maskinen som kjører Termix, som nettleseren din ikke kan nå. Sett endepunktets Bind Host til en adresse som maskinen svarer på, for eksempel 0.0.0.0, og gi det en fast lokal port.", + "tunnelSharesSessionCookie": "Å åpne denne tunnelen vil sende Termix-økten din til den tunnelerte tjenesten, fordi nettleseren din vil nå den på samme vertsnavn som Termix betjenes fra. Informasjonskapsler ignorerer porten, så de to kan ikke skilles fra hverandre. Bruk Termix-skrivebordsappen, eller åpne Termix på localhost.", + "directSharesSessionCookie": "Å åpne dette endepunktet vil sende Termix-økten din til det, fordi nettleseren din når det på samme sted som Termix serveres fra. Informasjonskapsler ignorerer porten, så en annen port er ikke en annen identitet. Bruk Termix-skrivebordsappen, eller server dette nettgrensesnittet fra et annet vertsnavn.", + "retry": "Prøv på nytt", + "reload": "Last inn på nytt", + "copyUrl": "Kopier URL", + "urlCopied": "URL-en er kopiert", + "copyFailed": "Kunne ikke kopiere URL-en", + "openExternally": "Åpne eksternt", + "isolationUnavailable": "Denne nettleseren kan ikke isolere nettendepunkter fra Termix-økten din. Bruk en nettleser med støtte for iframe uten legitimasjon.", + "isolationNotice": "Innebygde sider bruker en isolert økt. For sider som krever lagring eller popup-pålogging, bruk et isolert vindu i skrivebordsappen.", + "openIsolatedWindow": "Åpne isolert vindu" + }, + "hosts": { + "tabWebUi": "Nettgrensesnitt", + "webUiEndpointLabel": "Endepunkt {{number}}", + "webUiIntegration": "Nettgrensesnitt", + "webUiEndpointsSection": "Endepunkter", + "webUiRequirementsText": "Et direkte endepunkt åpnes av nettleseren din, så porten må kunne nås herfra. En SSH-tunnel åpnes i stedet av Termix over denne vertens SSH-tilkobling, så porten trenger bare å kunne nås fra verten.", + "enableWebUi": "Aktiver nettendepunkter", + "enableWebUiDesc": "Åpne denne vertens nettgrensesnitt fra sidefeltet.", + "webUiAddEndpoint": "Legg til endepunkt", + "webUiAddress": "Adresse", + "webUiOpening": "Åpning", + "webUiBindHostDesc": "Der backend binder forward. La stå tomt for 127.0.0.1, som bare maskinen som kjører Termix kan nå.", + "webUiBindHostExposed": "Denne adressen er tilgjengelig utenfor Termix-maskinen, så alle som kan nå porten får dette nettgrensesnittet uten innlogging.", + "webUiLocalPort": "Lokal havn", + "webUiLocalPortAuto": "Automatisk", + "webUiLocalPortDesc": "Hvilken port videresendingen lytter på. La stå tomt for å la systemet velge, eller angi en når porten må være kjent på forhånd, for eksempel en container som publiserer den.", + "webUiNewEndpointLabel": "Nytt endepunkt", + "webUiLabel": "Merkelapp", + "webUiScheme": "Ordning", + "webUiPort": "Havn", + "webUiPath": "Sti", + "webUiAccess": "Adgang", + "webUiAccessDirect": "Direkte", + "webUiAccessTunnel": "SSH-tunnel", + "webUiAccessTunnelUnavailable": "En SSH-tunnel krever at SSH er aktivert på denne verten og at denne enheten har en tilkoblingsopprinnelse.", + "webUiRender": "Åpne om", + "webUiRenderExternal": "Isolert skrivebordsvindu", + "webUiRenderEmbedded": "Termix-fanen", + "webUiRenderEmbeddedDesc": "Innbygging er det beste alternativet: noen nettgrensesnitt nekter å laste inn i en ramme, og en pålogging som er avhengig av informasjonskapsler fra samme nettsted kan gå i løkker. Den eksterne nettleseren fungerer alltid.", + "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" + } +} diff --git a/plugins/web-endpoint/locales/translated/pl_PL.json b/plugins/web-endpoint/locales/translated/pl_PL.json new file mode 100644 index 000000000..1ee76631f --- /dev/null +++ b/plugins/web-endpoint/locales/translated/pl_PL.json @@ -0,0 +1,52 @@ +{ + "webEndpoint": { + "noHostSelected": "Nie wybrano hosta", + "notFound": "Ten punkt końcowy już nie istnieje.", + "tunnelUnreachableFromBrowser": "Ten punkt końcowy tuneluje do adresu 127.0.0.1 na komputerze z uruchomionym programem Termix, do którego Twoja przeglądarka nie może się dodzwonić. Ustaw hosta powiązania punktu końcowego na adres, pod którym odpowiada komputer, na przykład 0.0.0.0, i nadaj mu stały port lokalny.", + "tunnelSharesSessionCookie": "Otwarcie tego tunelu spowoduje wysłanie sesji Termix do usługi tunelowanej, ponieważ przeglądarka połączy się z nią pod tą samą nazwą hosta, z której obsługiwany jest Termix. Pliki cookie ignorują port, więc nie da się ich rozróżnić. Użyj aplikacji desktopowej Termix lub otwórz Termix na komputerze lokalnym.", + "directSharesSessionCookie": "Otwarcie tego punktu końcowego spowoduje wysłanie do niego sesji Termix, ponieważ przeglądarka dociera do niego z tej samej witryny, z której obsługiwany jest Termix. Pliki cookie ignorują port, więc inny port nie oznacza innej tożsamości. Użyj aplikacji desktopowej Termix lub obsługuj ten interfejs użytkownika z innej nazwy hosta.", + "retry": "Spróbować ponownie", + "reload": "Przeładować", + "copyUrl": "Kopiuj adres URL", + "urlCopied": "Skopiowano adres URL", + "copyFailed": "Nie udało się skopiować adresu URL", + "openExternally": "Otwórz zewnętrznie", + "isolationUnavailable": "Ta przeglądarka nie może odizolować punktów końcowych od sesji Termix. Użyj przeglądarki obsługującej ramki iframe bez uwierzytelniania.", + "isolationNotice": "Strony osadzone korzystają z odizolowanej sesji. W przypadku stron wymagających pamięci masowej lub logowania przez wyskakujące okienko, należy użyć odizolowanego okna w aplikacji na komputerze.", + "openIsolatedWindow": "Otwórz odizolowane okno" + }, + "hosts": { + "tabWebUi": "Interfejs użytkownika sieci Web", + "webUiEndpointLabel": "Punkt końcowy {{number}}", + "webUiIntegration": "Interfejs użytkownika sieci Web", + "webUiEndpointsSection": "Punkty końcowe", + "webUiRequirementsText": "Przeglądarka otwiera bezpośredni punkt końcowy, więc jego port musi być dostępny z tego miejsca. Zamiast tego, Termix otwiera tunel SSH przez połączenie SSH tego hosta, więc port musi być dostępny tylko z hosta.", + "enableWebUi": "Włącz punkty końcowe sieci Web", + "enableWebUiDesc": "Otwórz interfejsy sieciowe tego hosta z paska bocznego.", + "webUiAddEndpoint": "Dodaj punkt końcowy", + "webUiAddress": "Adres", + "webUiOpening": "Otwór", + "webUiBindHostDesc": "Gdzie backend łączy forward. Pozostaw puste pole dla adresu 127.0.0.1, do którego dostęp ma tylko komputer z uruchomionym Termixem.", + "webUiBindHostExposed": "Do tego adresu można dotrzeć z poziomu maszyny Termix, więc każdy, kto ma dostęp do portu, otrzymuje ten internetowy interfejs użytkownika bez konieczności logowania.", + "webUiLocalPort": "Port lokalny", + "webUiLocalPortAuto": "Automatyczny", + "webUiLocalPortDesc": "Na którym porcie nasłuchuje przekierowanie. Pozostaw puste, aby system sam wybrał port, lub wpisz go, jeśli port musi być znany z wyprzedzeniem, np. w przypadku kontenera, który go publikuje.", + "webUiNewEndpointLabel": "Nowy punkt końcowy", + "webUiLabel": "Etykieta", + "webUiScheme": "Schemat", + "webUiPort": "Port", + "webUiPath": "Ścieżka", + "webUiAccess": "Dostęp", + "webUiAccessDirect": "Bezpośredni", + "webUiAccessTunnel": "Tunel SSH", + "webUiAccessTunnelUnavailable": "Tunel SSH wymaga włączonego protokołu SSH na tym hoście i źródła połączenia tego urządzenia.", + "webUiRender": "Otwórz w", + "webUiRenderExternal": "Odizolowane okno pulpitu", + "webUiRenderEmbedded": "Karta Termix", + "webUiRenderEmbeddedDesc": "Osadzanie jest zalecane z najwyższą starannością: niektóre interfejsy internetowe odmawiają załadowania w ramce, a logowanie oparte na plikach cookie tej samej witryny może się zapętlić. Zewnętrzna przeglądarka zawsze działa.", + "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" + } +} diff --git a/plugins/web-endpoint/locales/translated/pt_BR.json b/plugins/web-endpoint/locales/translated/pt_BR.json new file mode 100644 index 000000000..77bc99d7e --- /dev/null +++ b/plugins/web-endpoint/locales/translated/pt_BR.json @@ -0,0 +1,52 @@ +{ + "webEndpoint": { + "noHostSelected": "Nenhum host selecionado", + "notFound": "Este endpoint não existe mais.", + "tunnelUnreachableFromBrowser": "Este endpoint estabelece um túnel para 127.0.0.1 na máquina que executa o Termix, endereço que seu navegador não consegue acessar. Defina o Host de Vinculação do endpoint para um endereço que a máquina responda, como 0.0.0.0, e atribua a ele uma Porta Local fixa.", + "tunnelSharesSessionCookie": "Abrir este túnel enviará sua sessão do Termix para o serviço tunelado, pois seu navegador o acessará pelo mesmo nome de host de onde o Termix é servido. Os cookies ignoram a porta, portanto, os dois não podem ser diferenciados. Use o aplicativo Termix para desktop ou abra o Termix em localhost.", + "directSharesSessionCookie": "Abrir este endpoint enviará sua sessão do Termix para ele, pois seu navegador o acessa no mesmo site que serve o Termix. Os cookies ignoram a porta, portanto, uma porta diferente não representa uma identidade diferente. Use o aplicativo Termix para desktop ou acesse esta interface web a partir de um nome de host diferente.", + "retry": "Tentar novamente", + "reload": "Recarregar", + "copyUrl": "Copiar URL", + "urlCopied": "URL copiada", + "copyFailed": "Falha ao copiar o URL", + "openExternally": "Abrir externamente", + "isolationUnavailable": "Este navegador não consegue isolar os endpoints da web da sua sessão do Termix. Use um navegador com suporte a iframes sem credenciais.", + "isolationNotice": "As páginas incorporadas usam uma sessão isolada. Para páginas que exigem armazenamento ou login em janela pop-up, use uma janela isolada no aplicativo para desktop.", + "openIsolatedWindow": "Janela isolada aberta" + }, + "hosts": { + "tabWebUi": "Interface de usuário web", + "webUiEndpointLabel": "Ponto final {{number}}", + "webUiIntegration": "Interface de usuário web", + "webUiEndpointsSection": "Pontos finais", + "webUiRequirementsText": "Um endpoint direto é aberto pelo seu navegador, portanto, a porta dele precisa estar acessível a partir daqui. Em vez disso, o Termix abre um túnel SSH sobre a conexão SSH deste host, então a porta só precisa estar acessível a partir do host.", + "enableWebUi": "Habilitar endpoints da web", + "enableWebUiDesc": "Abra as interfaces web deste host a partir da barra lateral.", + "webUiAddEndpoint": "Adicionar ponto final", + "webUiAddress": "Endereço", + "webUiOpening": "Abertura", + "webUiBindHostDesc": "Onde o servidor de backend vincula o encaminhamento. Deixe em branco para 127.0.0.1, que somente a máquina que executa o Termix pode acessar.", + "webUiBindHostExposed": "Este endereço é acessível além da máquina Termix, portanto, qualquer pessoa que consiga acessar a porta obtém esta interface web sem necessidade de login.", + "webUiLocalPort": "Porto local", + "webUiLocalPortAuto": "Automático", + "webUiLocalPortDesc": "Em qual porta o encaminhamento escuta. Deixe em branco para que o sistema escolha, ou defina uma quando a porta precisar ser conhecida antecipadamente, como no caso de um contêiner que a publica.", + "webUiNewEndpointLabel": "Novo ponto final", + "webUiLabel": "Rótulo", + "webUiScheme": "Plano", + "webUiPort": "Porta", + "webUiPath": "Caminho", + "webUiAccess": "Acesso", + "webUiAccessDirect": "Direto", + "webUiAccessTunnel": "túnel SSH", + "webUiAccessTunnelUnavailable": "Um túnel SSH requer que o SSH esteja habilitado neste host e que a origem da conexão seja este dispositivo.", + "webUiRender": "Abrir em", + "webUiRenderExternal": "janela de área de trabalho isolada", + "webUiRenderEmbedded": "guia Termix", + "webUiRenderEmbeddedDesc": "A incorporação é feita da melhor maneira possível: algumas interfaces web se recusam a carregar em um frame, e um login que depende de cookies do mesmo site pode entrar em loop. O navegador externo sempre funciona.", + "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" + } +} diff --git a/plugins/web-endpoint/locales/translated/pt_PT.json b/plugins/web-endpoint/locales/translated/pt_PT.json new file mode 100644 index 000000000..23860ec89 --- /dev/null +++ b/plugins/web-endpoint/locales/translated/pt_PT.json @@ -0,0 +1,52 @@ +{ + "webEndpoint": { + "noHostSelected": "Nenhum host selecionado", + "notFound": "Este endpoint já não existe.", + "tunnelUnreachableFromBrowser": "Este endpoint estabelece um túnel para 127.0.0.1 na máquina que executa o Termix, endereço que o seu browser não consegue aceder. Defina o Host de Ligação do endpoint para um endereço que a máquina responda, como por exemplo 0.0.0.0, e atribua-lhe uma Porta Local fixa.", + "tunnelSharesSessionCookie": "A abertura deste túnel enviará a sua sessão do Termix para o serviço tunelado, uma vez que o seu browser irá aceder-lhe pelo mesmo nome de host a partir do qual o Termix é servido. Os cookies ignoram a porta, pelo que os dois não podem ser diferenciados. Utilize a aplicação Termix para desktop ou abra o Termix em localhost.", + "directSharesSessionCookie": "Abrir este endpoint irá enviar a sua sessão do Termix para o mesmo, uma vez que o seu browser acede ao mesmo no mesmo site que serve o Termix. Os cookies ignoram a porta, pelo que uma porta diferente não representa uma identidade diferente. Utilize a aplicação Termix para desktop ou aceda a esta interface web a partir de um nome de host diferente.", + "retry": "Tentar novamente", + "reload": "Recarregar", + "copyUrl": "Copiar URL", + "urlCopied": "URL copiado", + "copyFailed": "Falha ao copiar o URL", + "openExternally": "Abrir externamente", + "isolationUnavailable": "Este browser não consegue isolar os endpoints web da sua sessão Termix. Utilize um browser com suporte para iframes sem credenciais.", + "isolationNotice": "As páginas incorporadas utilizam uma sessão isolada. Para páginas que exijam armazenamento ou login em janela pop-up, utilize uma janela isolada na aplicação para desktop.", + "openIsolatedWindow": "Janela isolada aberta" + }, + "hosts": { + "tabWebUi": "Interface de utilizador web", + "webUiEndpointLabel": "Ponto final {{number}}", + "webUiIntegration": "Interface de utilizador web", + "webUiEndpointsSection": "Pontos finais", + "webUiRequirementsText": "Um endpoint direto é aberto pelo seu browser, pelo que a porta do mesmo precisa de estar acessível a partir daqui. Em vez disso, o Termix abre um túnel SSH sobre a ligação SSH deste host, pelo que a porta só precisa de estar acessível a partir do host.", + "enableWebUi": "Ativar endpoints da web", + "enableWebUiDesc": "Abra as interfaces web deste host a partir da barra lateral.", + "webUiAddEndpoint": "Adicionar ponto final", + "webUiAddress": "Morada", + "webUiOpening": "Abertura", + "webUiBindHostDesc": "Onde o servidor de backend liga o encaminhamento. Deixe em branco para 127.0.0.1, que apenas a máquina que executa o Termix pode aceder.", + "webUiBindHostExposed": "Este endereço é acessível para além da máquina Termix, pelo que qualquer pessoa que consiga aceder à porta obtém esta interface web sem necessidade de login.", + "webUiLocalPort": "Porto local", + "webUiLocalPortAuto": "Automático", + "webUiLocalPortDesc": "Em que porta o encaminhamento escuta. Deixe em branco para que o sistema escolha, ou defina uma porta quando é necessário saber a porta antecipadamente, como no caso de um contentor que a publica.", + "webUiNewEndpointLabel": "Novo ponto final", + "webUiLabel": "Etiqueta", + "webUiScheme": "Plano", + "webUiPort": "Porto", + "webUiPath": "Percurso", + "webUiAccess": "Acesso", + "webUiAccessDirect": "Direto", + "webUiAccessTunnel": "túnel SSH", + "webUiAccessTunnelUnavailable": "Um túnel SSH requer que o SSH esteja activado neste host e que a origem da ligação seja este dispositivo.", + "webUiRender": "Abrir em", + "webUiRenderExternal": "janela de área de trabalho isolada", + "webUiRenderEmbedded": "guia Termix", + "webUiRenderEmbeddedDesc": "A incorporação é feita da melhor forma possível: algumas interfaces web recusam-se a carregar num frame, e um login que dependa de cookies do mesmo site pode entrar em loop. O browser externo funciona sempre.", + "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" + } +} diff --git a/plugins/web-endpoint/locales/translated/ro_RO.json b/plugins/web-endpoint/locales/translated/ro_RO.json new file mode 100644 index 000000000..7aa3bd105 --- /dev/null +++ b/plugins/web-endpoint/locales/translated/ro_RO.json @@ -0,0 +1,52 @@ +{ + "webEndpoint": { + "noHostSelected": "Nicio gazdă selectată", + "notFound": "Acest punct final nu mai există.", + "tunnelUnreachableFromBrowser": "Acest punct final face tunel către 127.0.0.1 pe mașina care rulează Termix, pe care browserul dvs. nu o poate accesa. Setați Bind Host-ul punctului final la o adresă la care mașina răspunde, cum ar fi 0.0.0.0, și atribuiți-i un Port Local fix.", + "tunnelSharesSessionCookie": "Deschiderea acestui tunel ar trimite sesiunea Termix către serviciul tunelat, deoarece browserul dvs. l-ar accesa la același nume de gazdă de pe care este servit Termix. Cookie-urile ignoră portul, deci cele două nu pot fi diferențiate. Folosește aplicația desktop Termix sau deschide Termix la localhost.", + "directSharesSessionCookie": "Deschiderea acestui endpoint ar trimite sesiunea Termix către acesta, deoarece browserul dvs. îl accesează pe același site de pe care este servit Termix. Cookie-urile ignoră portul, deci un port diferit nu reprezintă o identitate diferită. Folosiți aplicația desktop Termix sau serviți această interfață web de pe un nume de gazdă diferit.", + "retry": "Reîncercați", + "reload": "Reîncărcare", + "copyUrl": "Copiați adresa URL", + "urlCopied": "Adresa URL copiată", + "copyFailed": "Nu s-a putut copia adresa URL", + "openExternally": "Deschis la exterior", + "isolationUnavailable": "Acest browser nu poate izola endpoint-urile web de sesiunea ta Termix. Folosește un browser cu suport iframe fără credențiale.", + "isolationNotice": "Paginile încorporate utilizează o sesiune izolată. Pentru paginile care necesită spațiu de stocare sau conectare pop-up, utilizați o fereastră izolată în aplicația desktop.", + "openIsolatedWindow": "Deschideți o fereastră izolată" + }, + "hosts": { + "tabWebUi": "Interfață web", + "webUiEndpointLabel": "Punct final {{number}}", + "webUiIntegration": "Interfață web", + "webUiEndpointsSection": "Puncte finale", + "webUiRequirementsText": "Un punct final direct este deschis de browserul dvs., deci portul său trebuie să fie accesibil de aici. Un tunel SSH este deschis de Termix prin conexiunea SSH a acestei gazde, deci portul trebuie să fie accesibil doar de la gazdă.", + "enableWebUi": "Activează punctele de terminare web", + "enableWebUiDesc": "Deschideți interfețele web ale acestei gazde din bara laterală.", + "webUiAddEndpoint": "Adăugați un punct final", + "webUiAddress": "Adresa", + "webUiOpening": "Deschidere", + "webUiBindHostDesc": "Unde backend-ul leagă forward-ul. Lăsați necompletat pentru 127.0.0.1, pe care doar mașina care rulează Termix îl poate accesa.", + "webUiBindHostExposed": "Această adresă este accesibilă dincolo de mașina Termix, așa că oricine poate accesa portul primește această interfață web fără a fi nevoie de autentificare.", + "webUiLocalPort": "Port local", + "webUiLocalPortAuto": "Automat", + "webUiLocalPortDesc": "Portul pe care ascultă redirecționarea. Lăsați necompletat pentru a permite sistemului să aleagă sau setați unul atunci când portul trebuie cunoscut în avans, cum ar fi un container care îl publică.", + "webUiNewEndpointLabel": "Punct final nou", + "webUiLabel": "Eticheta", + "webUiScheme": "Sistem", + "webUiPort": "Port", + "webUiPath": "Cale", + "webUiAccess": "Acces", + "webUiAccessDirect": "Direct", + "webUiAccessTunnel": "Tunel SSH", + "webUiAccessTunnelUnavailable": "Un tunel SSH necesită SSH activat pe această gazdă și o origine a conexiunii pentru acest dispozitiv.", + "webUiRender": "Deschide în", + "webUiRenderExternal": "Fereastră izolată a desktopului", + "webUiRenderEmbedded": "Tabulă Termix", + "webUiRenderEmbeddedDesc": "Integrarea este cea mai bună metodă: unele interfețe web refuză să se încarce într-un cadru, iar o conectare care se bazează pe cookie-uri de pe același site se poate repeta. Browserul extern funcționează întotdeauna.", + "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" + } +} diff --git a/plugins/web-endpoint/locales/translated/ru_RU.json b/plugins/web-endpoint/locales/translated/ru_RU.json new file mode 100644 index 000000000..71a5f40ae --- /dev/null +++ b/plugins/web-endpoint/locales/translated/ru_RU.json @@ -0,0 +1,52 @@ +{ + "webEndpoint": { + "noHostSelected": "Хост не выбран", + "notFound": "Данная конечная точка больше не существует.", + "tunnelUnreachableFromBrowser": "Эта конечная точка туннелирует на 127.0.0.1 на машине, где запущен Termix, но ваш браузер к ней не имеет доступа. Установите в качестве параметра Bind Host адрес, на который машина отвечает, например, 0.0.0.0, и укажите фиксированный локальный порт.", + "tunnelSharesSessionCookie": "Открытие этого туннеля направит вашу сессию Termix к туннелированному сервису, поскольку ваш браузер будет обращаться к нему по тому же имени хоста, с которого обслуживается Termix. Файлы cookie игнорируют порт, поэтому их невозможно различить. Используйте настольное приложение Termix или откройте Termix по адресу localhost.", + "directSharesSessionCookie": "Открытие этой конечной точки перенаправит вашу сессию Termix на неё, поскольку ваш браузер обращается к ней через тот же сайт, с которого обслуживается Termix. Файлы cookie игнорируют порт, поэтому другой порт не означает другой идентификатор. Используйте настольное приложение Termix или разместите этот веб-интерфейс с другого имени хоста.", + "retry": "Повторить попытку", + "reload": "Перезагрузка", + "copyUrl": "Скопировать URL", + "urlCopied": "URL скопирован", + "copyFailed": "Не удалось скопировать URL.", + "openExternally": "Открыть извне", + "isolationUnavailable": "Этот браузер не может изолировать веб-интерфейсы от вашей сессии Termix. Используйте браузер с поддержкой iframe без учетных данных.", + "isolationNotice": "Встроенные страницы используют изолированную сессию. Для страниц, требующих хранения данных или всплывающего окна авторизации, используйте изолированное окно в настольном приложении.", + "openIsolatedWindow": "Открытое изолированное окно" + }, + "hosts": { + "tabWebUi": "Веб-интерфейс", + "webUiEndpointLabel": "Конечная точка {{number}}", + "webUiIntegration": "Веб-интерфейс", + "webUiEndpointsSection": "Конечные точки", + "webUiRequirementsText": "Ваш браузер открывает прямую конечную точку, поэтому её порт должен быть доступен отсюда. Termix же открывает SSH-туннель через SSH-соединение этого хоста, поэтому порт должен быть доступен только с этого хоста.", + "enableWebUi": "Включить веб-конечные точки", + "enableWebUiDesc": "Откройте веб-интерфейс этого хостинг-провайдера из боковой панели.", + "webUiAddEndpoint": "Добавить конечную точку", + "webUiAddress": "Адрес", + "webUiOpening": "Открытие", + "webUiBindHostDesc": "Где бэкэнд привязывает переадресацию. Оставьте поле пустым для IP-адреса 127.0.0.1, к которому может получить доступ только компьютер, на котором запущен Termix.", + "webUiBindHostExposed": "Этот адрес доступен за пределами машины Termix, поэтому любой, кто может получить доступ к этому порту, получает доступ к веб-интерфейсу без авторизации.", + "webUiLocalPort": "Местный порт", + "webUiLocalPortAuto": "Автоматический", + "webUiLocalPortDesc": "На каком порту будет прослушивать переадресация? Оставьте поле пустым, чтобы система выбрала его сама, или задайте порт заранее, например, если он должен быть известен контейнеру, который его публикует.", + "webUiNewEndpointLabel": "Новая конечная точка", + "webUiLabel": "Этикетка", + "webUiScheme": "Схема", + "webUiPort": "Порт", + "webUiPath": "Путь", + "webUiAccess": "Доступ", + "webUiAccessDirect": "Прямой", + "webUiAccessTunnel": "SSH-туннель", + "webUiAccessTunnelUnavailable": "Для создания SSH-туннеля необходимо включить SSH на этом хосте и указать источник соединения на этом устройстве.", + "webUiRender": "Открыть в", + "webUiRenderExternal": "Изолированное окно рабочего стола", + "webUiRenderEmbedded": "Термикс вкладка", + "webUiRenderEmbeddedDesc": "Встраивание осуществляется по принципу «максимальной эффективности»: некоторые веб-интерфейсы отказываются загружаться во фрейме, а вход в систему, использующий файлы cookie того же сайта, может зацикливаться. Внешний браузер всегда работает.", + "webUiIgnoreCert": "Разрешить использование недействительного сертификата", + "webUiIgnoreCertDesc": "Только прямые конечные точки. Замыкания (loopback) уже исключены, поэтому это не влияет на туннельные конечные точки.", + "webUiRemoveEndpoint": "Удалить конечную точку", + "webUiOpenFailed": "Не удалось открыть веб-интерфейс." + } +} diff --git a/plugins/web-endpoint/locales/translated/sr_SP.json b/plugins/web-endpoint/locales/translated/sr_SP.json new file mode 100644 index 000000000..06ea6134d --- /dev/null +++ b/plugins/web-endpoint/locales/translated/sr_SP.json @@ -0,0 +1,52 @@ +{ + "webEndpoint": { + "noHostSelected": "Није изабран домаћин", + "notFound": "Ова крајња тачка више не постоји.", + "tunnelUnreachableFromBrowser": "Ова крајња тачка се повезује са адресом 127.0.0.1 на машини на којој је покренут Termix, коју ваш прегледач не може да досегне. Поставите Bind Host крајње тачке на адресу на коју машина одговара, као што је 0.0.0.0, и доделите јој фиксни локални порт.", + "tunnelSharesSessionCookie": "Отварањем овог тунела ваша Termix сесија би се послала тунелираном сервису, јер би је ваш прегледач дохватио на истом имену хоста са ког се Termix служи. Колачићи игноришу порт, тако да се та два не могу разликовати. Користите Termix десктоп апликацију или отворите Termix на localhost.", + "directSharesSessionCookie": "Отварањем ове крајње тачке би се ваша Termix сесија послала на њу, јер ваш прегледач до ње долази на истој локацији са које се Termix служи. Колачићи игноришу порт, тако да други порт није други идентитет. Користите Termix десктоп апликацију или служите овом веб корисничком интерфејсу са другог имена хоста.", + "retry": "Покушај поново", + "reload": "Поново учитај", + "copyUrl": "Копирај УРЛ", + "urlCopied": "URL је копиран", + "copyFailed": "Копирање URL-а није успело", + "openExternally": "Отвори споља", + "isolationUnavailable": "Овај прегледач не може да изолује веб крајње тачке од ваше Termix сесије. Користите прегледач са подршком за iframe без акредитива.", + "isolationNotice": "Уграђене странице користе изоловану сесију. За странице које захтевају складиштење или искачуће пријављивање, користите изоловани прозор у апликацији за рачунаре.", + "openIsolatedWindow": "Отвори изоловани прозор" + }, + "hosts": { + "tabWebUi": "Веб кориснички интерфејс", + "webUiEndpointLabel": "Крајња тачка {{number}}", + "webUiIntegration": "Веб кориснички интерфејс", + "webUiEndpointsSection": "Крајње тачке", + "webUiRequirementsText": "Директну крајњу тачку отвара ваш прегледач, тако да њен порт мора бити доступан одавде. Уместо тога, Termix отвара SSH тунел преко SSH везе овог хоста, тако да порт мора бити доступан само са хоста.", + "enableWebUi": "Омогући веб крајње тачке", + "enableWebUiDesc": "Отворите веб интерфејсе овог хоста са бочне траке.", + "webUiAddEndpoint": "Додај крајњу тачку", + "webUiAddress": "Адреса", + "webUiOpening": "Отварање", + "webUiBindHostDesc": "Где се бекенд повезује са преусмеравањем. Оставите празно за 127.0.0.1, до којег може да дође само машина на којој је покренут Termix.", + "webUiBindHostExposed": "Ова адреса је доступна изван Termix машине, тако да свако ко може да дође до порта добија овај веб интерфејс без пријављивања.", + "webUiLocalPort": "Локални порт", + "webUiLocalPortAuto": "Аутоматски", + "webUiLocalPortDesc": "На ком порту преусмеравање слуша. Оставите празно да би систем изабрао или подесите порт када порт мора бити познат унапред, као што је контејнер који га објављује.", + "webUiNewEndpointLabel": "Нова крајња тачка", + "webUiLabel": "Ознака", + "webUiScheme": "Шема", + "webUiPort": "Лука", + "webUiPath": "Путања", + "webUiAccess": "Приступ", + "webUiAccessDirect": "Директно", + "webUiAccessTunnel": "SSH тунел", + "webUiAccessTunnelUnavailable": "SSH тунел захтева омогућен SSH на овом хосту и порекло везе са овог уређаја.", + "webUiRender": "Отвори у", + "webUiRenderExternal": "Изоловани прозор радне површине", + "webUiRenderEmbedded": "Термикс картица", + "webUiRenderEmbeddedDesc": "Уграђивање је најбољи начин: неки веб интерфејси одбијају да се учитају у оквиру, а пријава која се ослања на колачиће истог сајта може да се понови у петљи. Спољни прегледач увек ради.", + "webUiIgnoreCert": "Дозволи неважећи сертификат", + "webUiIgnoreCertDesc": "Само директне крајње тачке. Повратна петља је већ изузета, тако да ово нема утицаја на крајње тачке тунела.", + "webUiRemoveEndpoint": "Уклони крајњу тачку", + "webUiOpenFailed": "Отварање веб крајње тачке није успело" + } +} diff --git a/plugins/web-endpoint/locales/translated/sv_SE.json b/plugins/web-endpoint/locales/translated/sv_SE.json new file mode 100644 index 000000000..1b7a6aa74 --- /dev/null +++ b/plugins/web-endpoint/locales/translated/sv_SE.json @@ -0,0 +1,52 @@ +{ + "webEndpoint": { + "noHostSelected": "Ingen värd vald", + "notFound": "Denna slutpunkt finns inte längre.", + "tunnelUnreachableFromBrowser": "Denna slutpunkt tunnlar till 127.0.0.1 på maskinen som kör Termix, vilket din webbläsare inte kan nå. Ställ in slutpunktens Bind Host till en adress som maskinen svarar på, till exempel 0.0.0.0, och ge den en fast lokal port.", + "tunnelSharesSessionCookie": "Om du öppnar den här tunneln skickas din Termix-session till den tunnelerade tjänsten, eftersom din webbläsare skulle nå den på samma värdnamn som Termix serveras från. Cookies ignorerar porten, så de två kan inte skiljas åt. Använd Termix-skrivbordsappen eller öppna Termix på localhost.", + "directSharesSessionCookie": "Att öppna den här slutpunkten skulle skicka din Termix-session till den, eftersom din webbläsare når den på samma plats som Termix serveras från. Cookies ignorerar porten, så en annan port är inte en annan identitet. Använd Termix-skrivbordsappen eller servera detta webbgränssnitt från ett annat värdnamn.", + "retry": "Försöka igen", + "reload": "Ladda om", + "copyUrl": "Kopiera URL", + "urlCopied": "URL kopierad", + "copyFailed": "Misslyckades med att kopiera URL:en", + "openExternally": "Öppna externt", + "isolationUnavailable": "Den här webbläsaren kan inte isolera webbslutpunkter från din Termix-session. Använd en webbläsare med stöd för iframe utan autentiseringsuppgifter.", + "isolationNotice": "Inbäddade sidor använder en isolerad session. För sidor som kräver lagring eller popup-inloggning, använd ett isolerat fönster i skrivbordsappen.", + "openIsolatedWindow": "Öppna isolerade fönster" + }, + "hosts": { + "tabWebUi": "Webbgränssnitt", + "webUiEndpointLabel": "Slutpunkt {{number}}", + "webUiIntegration": "Webbgränssnitt", + "webUiEndpointsSection": "Slutpunkter", + "webUiRequirementsText": "En direkt slutpunkt öppnas av din webbläsare, så dess port måste kunna nås härifrån. En SSH-tunnel öppnas istället av Termix över den här värdens SSH-anslutning, så porten behöver bara kunna nås från värden.", + "enableWebUi": "Aktivera webbslutpunkter", + "enableWebUiDesc": "Öppna den här värdens webbgränssnitt från sidofältet.", + "webUiAddEndpoint": "Lägg till slutpunkt", + "webUiAddress": "Adress", + "webUiOpening": "Öppning", + "webUiBindHostDesc": "Där backend binder forwarden. Lämna tomt för 127.0.0.1, som endast maskinen som kör Termix kan nå.", + "webUiBindHostExposed": "Den här adressen är nåbar bortom Termix-maskinen, så alla som kan nå porten får detta webbgränssnitt utan inloggning.", + "webUiLocalPort": "Lokal hamn", + "webUiLocalPortAuto": "Automatisk", + "webUiLocalPortDesc": "Vilken port vidarebefordran lyssnar på. Lämna tomt för att låta systemet välja, eller ange en port när porten måste vara känd i förväg, till exempel en container som publicerar den.", + "webUiNewEndpointLabel": "Ny slutpunkt", + "webUiLabel": "Märka", + "webUiScheme": "Schema", + "webUiPort": "Hamn", + "webUiPath": "Väg", + "webUiAccess": "Tillträde", + "webUiAccessDirect": "Direkt", + "webUiAccessTunnel": "SSH-tunnel", + "webUiAccessTunnelUnavailable": "En SSH-tunnel kräver att SSH är aktiverat på den här värden och att den här enheten har ett anslutningsursprung.", + "webUiRender": "Öppna om", + "webUiRenderExternal": "Isolerat skrivbordsfönster", + "webUiRenderEmbedded": "Termix-fliken", + "webUiRenderEmbeddedDesc": "Inbäddning är det bästa alternativet: vissa webbgränssnitt vägrar att laddas i en ram, och en inloggning som förlitar sig på cookies från samma webbplats kan loopa. Den externa webbläsaren fungerar alltid.", + "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" + } +} diff --git a/plugins/web-endpoint/locales/translated/th_TH.json b/plugins/web-endpoint/locales/translated/th_TH.json new file mode 100644 index 000000000..8dd61bf31 --- /dev/null +++ b/plugins/web-endpoint/locales/translated/th_TH.json @@ -0,0 +1,52 @@ +{ + "webEndpoint": { + "noHostSelected": "ไม่ได้เลือกโฮสต์", + "notFound": "ปลายทางนี้ไม่มีอยู่อีกต่อไปแล้ว", + "tunnelUnreachableFromBrowser": "ปลายทางนี้จะเชื่อมต่อผ่านอุโมงค์ไปยัง 127.0.0.1 บนเครื่องที่ใช้งาน Termix ซึ่งเบราว์เซอร์ของคุณไม่สามารถเข้าถึงได้ ตั้งค่า Bind Host ของปลายทางนี้เป็นที่อยู่ IP ที่เครื่องจะตอบสนอง เช่น 0.0.0.0 และกำหนด Local Port ให้คงที่", + "tunnelSharesSessionCookie": "การเปิดอุโมงค์นี้จะส่งเซสชัน Termix ของคุณไปยังบริการผ่านอุโมงค์ เนื่องจากเบราว์เซอร์ของคุณจะเข้าถึงบริการนั้นด้วยชื่อโฮสต์เดียวกับที่ Termix ให้บริการ คุกกี้จะไม่สนใจพอร์ต ดังนั้นจึงไม่สามารถแยกแยะความแตกต่างระหว่างทั้งสองได้ ใช้แอป Termix บนเดสก์ท็อป หรือเปิด Termix ที่ localhost", + "directSharesSessionCookie": "การเปิดเอนด์พอยต์นี้จะส่งเซสชัน Termix ของคุณไปยังเอนด์พอยต์นี้ เนื่องจากเบราว์เซอร์ของคุณเข้าถึงเอนด์พอยต์นี้จากเว็บไซต์เดียวกับที่ Termix ให้บริการ คุกกี้จะไม่สนใจพอร์ต ดังนั้นพอร์ตที่ต่างกันจึงไม่ได้หมายถึงตัวตนที่ต่างกัน ใช้แอปพลิเคชัน Termix บนเดสก์ท็อป หรือให้บริการเว็บ UI นี้จากชื่อโฮสต์อื่น", + "retry": "ลองใหม่อีกครั้ง", + "reload": "โหลดซ้ำ", + "copyUrl": "คัดลอก URL", + "urlCopied": "คัดลอก URL แล้ว", + "copyFailed": "ไม่สามารถคัดลอก URL ได้", + "openExternally": "เปิดจากภายนอก", + "isolationUnavailable": "เบราว์เซอร์นี้ไม่สามารถแยกเว็บเอนด์พอยต์ออกจากเซสชัน Termix ของคุณได้ โปรดใช้เบราว์เซอร์ที่รองรับ iframe แบบไม่ต้องใส่ข้อมูลรับรอง", + "isolationNotice": "หน้าเว็บที่ฝังอยู่จะใช้เซสชันแยกต่างหาก สำหรับหน้าเว็บที่ต้องการพื้นที่จัดเก็บข้อมูลหรือการลงชื่อเข้าใช้แบบป๊อปอัพ ให้ใช้หน้าต่างแยกต่างหากในแอปพลิเคชันบนเดสก์ท็อป", + "openIsolatedWindow": "เปิดหน้าต่างแยกต่างหาก" + }, + "hosts": { + "tabWebUi": "ส่วนติดต่อผู้ใช้บนเว็บ", + "webUiEndpointLabel": "จุดสิ้นสุด {{number}}", + "webUiIntegration": "ส่วนติดต่อผู้ใช้บนเว็บ", + "webUiEndpointsSection": "จุดสิ้นสุด", + "webUiRequirementsText": "เบราว์เซอร์ของคุณจะเปิดปลายทางโดยตรง ดังนั้นพอร์ตจะต้องสามารถเข้าถึงได้จากที่นี่ แต่หากใช้ Termix จะเปิดอุโมงค์ SSH ผ่านการเชื่อมต่อ SSH ของโฮสต์นี้แทน ดังนั้นพอร์ตจึงไม่จำเป็นต้องสามารถเข้าถึงได้จากโฮสต์เพียงอย่างเดียว", + "enableWebUi": "เปิดใช้งานเอนด์พอยต์เว็บ", + "enableWebUiDesc": "เปิดหน้าเว็บของโฮสต์นี้จากแถบด้านข้าง", + "webUiAddEndpoint": "เพิ่มเอนด์พอยต์", + "webUiAddress": "ที่อยู่", + "webUiOpening": "เปิด", + "webUiBindHostDesc": "ตรงส่วนที่แบ็กเอนด์เชื่อมต่อกับส่วนหน้า เว้นว่างไว้สำหรับ 127.0.0.1 ซึ่งมีเพียงเครื่องที่ใช้งาน Termix เท่านั้นที่สามารถเข้าถึงได้", + "webUiBindHostExposed": "ที่อยู่เว็บนี้สามารถเข้าถึงได้จากภายนอกเครื่อง Termix ดังนั้นใครก็ตามที่สามารถเข้าถึงพอร์ตนี้จะสามารถเข้าถึงเว็บ UI นี้ได้โดยไม่ต้องล็อกอิน", + "webUiLocalPort": "ท่าเรือท้องถิ่น", + "webUiLocalPortAuto": "อัตโนมัติ", + "webUiLocalPortDesc": "พอร์ตที่ตัวส่งต่อรับฟังอยู่ เว้นว่างไว้เพื่อให้ระบบเลือก หรือระบุพอร์ตเมื่อจำเป็นต้องทราบพอร์ตล่วงหน้า เช่น คอนเทนเนอร์ที่เผยแพร่พอร์ตนั้น", + "webUiNewEndpointLabel": "จุดเชื่อมต่อใหม่", + "webUiLabel": "ฉลาก", + "webUiScheme": "โครงการ", + "webUiPort": "ท่าเรือ", + "webUiPath": "เส้นทาง", + "webUiAccess": "เข้าถึง", + "webUiAccessDirect": "โดยตรง", + "webUiAccessTunnel": "อุโมงค์ SSH", + "webUiAccessTunnelUnavailable": "การสร้างอุโมงค์ SSH จำเป็นต้องเปิดใช้งาน SSH บนโฮสต์นี้ และต้องมีอุปกรณ์นี้เป็นแหล่งกำเนิดการเชื่อมต่อ", + "webUiRender": "เปิดใน", + "webUiRenderExternal": "หน้าต่างเดสก์ท็อปแบบแยกเดี่ยว", + "webUiRenderEmbedded": "แท็บเทอร์มิกซ์", + "webUiRenderEmbeddedDesc": "การฝังเนื้อหาทำได้ดีที่สุดเท่าที่จะทำได้: อินเทอร์เฟซเว็บบางอย่างอาจไม่สามารถโหลดในเฟรมได้ และการเข้าสู่ระบบที่อาศัยคุกกี้ในเว็บไซต์เดียวกันอาจวนลูป แต่เบราว์เซอร์ภายนอกใช้งานได้เสมอ", + "webUiIgnoreCert": "อนุญาตให้ใช้ใบรับรองที่ไม่ถูกต้อง", + "webUiIgnoreCertDesc": "เฉพาะปลายทางที่เชื่อมต่อโดยตรงเท่านั้น การเชื่อมต่อแบบ Loopback ได้รับการยกเว้นอยู่แล้ว ดังนั้นจึงไม่มีผลกระทบต่อปลายทางแบบ Tunnel", + "webUiRemoveEndpoint": "ลบจุดสิ้นสุด", + "webUiOpenFailed": "ไม่สามารถเปิดเว็บเอนด์พอยต์ได้" + } +} diff --git a/plugins/web-endpoint/locales/translated/tr_TR.json b/plugins/web-endpoint/locales/translated/tr_TR.json new file mode 100644 index 000000000..721c55628 --- /dev/null +++ b/plugins/web-endpoint/locales/translated/tr_TR.json @@ -0,0 +1,52 @@ +{ + "webEndpoint": { + "noHostSelected": "Sunucu seçilmedi.", + "notFound": "Bu uç nokta artık mevcut değil.", + "tunnelUnreachableFromBrowser": "Bu uç nokta, tarayıcınızın erişemediği Termix'i çalıştıran makinedeki 127.0.0.1 adresine tünel oluşturur. Uç noktanın Bağlantı Ana Bilgisayarını, bu makinenin yanıt verdiği bir adrese (örneğin 0.0.0.0) ayarlayın ve sabit bir Yerel Bağlantı Noktası verin.", + "tunnelSharesSessionCookie": "Bu tüneli açmak, Termix oturumunuzu tünellenmiş servise yönlendirecektir, çünkü tarayıcınız Termix'in sunulduğu aynı ana bilgisayar adından ona ulaşacaktır. Çerezler bağlantı noktasını dikkate almaz, bu nedenle ikisi birbirinden ayırt edilemez. Termix masaüstü uygulamasını kullanın veya Termix'i localhost'ta açın.", + "directSharesSessionCookie": "Bu uç noktayı açmak, Termix oturumunuzu ona yönlendirecektir, çünkü tarayıcınız Termix'in sunulduğu aynı siteden ona ulaşır. Çerezler bağlantı noktasını dikkate almaz, bu nedenle farklı bir bağlantı noktası farklı bir kimlik anlamına gelmez. Termix masaüstü uygulamasını kullanın veya bu web arayüzünü farklı bir ana bilgisayar adından sunun.", + "retry": "Tekrar dene", + "reload": "Yeniden yükle", + "copyUrl": "URL'yi kopyala", + "urlCopied": "URL kopyalandı", + "copyFailed": "URL kopyalama başarısız oldu.", + "openExternally": "Harici olarak açın", + "isolationUnavailable": "Bu tarayıcı, web uç noktalarını Termix oturumunuzdan izole edemez. Kimlik bilgisi gerektirmeyen iframe desteği olan bir tarayıcı kullanın.", + "isolationNotice": "Gömülü sayfalar ayrı bir oturum kullanır. Depolama gerektiren veya açılır pencereyle oturum açma işlemi gerektiren sayfalar için masaüstü uygulamasında ayrı bir pencere kullanın.", + "openIsolatedWindow": "İzole edilmiş pencereyi açın" + }, + "hosts": { + "tabWebUi": "Web arayüzü", + "webUiEndpointLabel": "Uç nokta {{number}}", + "webUiIntegration": "Web arayüzü", + "webUiEndpointsSection": "Uç noktalar", + "webUiRequirementsText": "Tarayıcınız tarafından doğrudan bir uç nokta açılır, bu nedenle bağlantı noktasının buradan erişilebilir olması gerekir. Bunun yerine Termix, bu sunucunun SSH bağlantısı üzerinden bir SSH tüneli açar, bu nedenle bağlantı noktasının yalnızca sunucudan erişilebilir olması yeterlidir.", + "enableWebUi": "Web uç noktalarını etkinleştirin", + "enableWebUiDesc": "Bu sunucunun web arayüzlerini yan menüden açın.", + "webUiAddEndpoint": "Uç nokta ekle", + "webUiAddress": "Adres", + "webUiOpening": "Açılış", + "webUiBindHostDesc": "Arka uç, ön ucu birbirine bağlar. Sadece Termix'i çalıştıran makinenin erişebileceği 127.0.0.1 için boş bırakın.", + "webUiBindHostExposed": "Bu adrese Termix makinesinin ötesinden de erişilebildiği için, porta erişebilen herkes giriş yapmadan bu web arayüzüne ulaşabilir.", + "webUiLocalPort": "Yerel Liman", + "webUiLocalPortAuto": "Otomatik", + "webUiLocalPortDesc": "Yönlendiricinin hangi porttan dinleyeceğini belirtin. Sistemin seçmesine izin vermek için boş bırakın veya portun önceden bilinmesi gerektiğinde (örneğin, portun yayınlandığı bir konteyner gibi) bir port belirleyin.", + "webUiNewEndpointLabel": "Yeni uç nokta", + "webUiLabel": "Etiket", + "webUiScheme": "Plan", + "webUiPort": "Liman", + "webUiPath": "Yol", + "webUiAccess": "Erişim", + "webUiAccessDirect": "Doğrudan", + "webUiAccessTunnel": "SSH tüneli", + "webUiAccessTunnelUnavailable": "SSH tüneli için bu sunucuda SSH'nin etkinleştirilmiş olması ve bağlantı kaynağının bu cihaz olması gerekmektedir.", + "webUiRender": "Şurada aç", + "webUiRenderExternal": "Yalıtılmış masaüstü penceresi", + "webUiRenderEmbedded": "Termix tableti", + "webUiRenderEmbeddedDesc": "Gömme işlemi en iyi çaba prensibine dayanır: bazı web arayüzleri bir çerçeve içinde yüklenmeyi reddeder ve aynı site çerezlerine dayanan bir oturum açma işlemi döngüye girebilir. Harici tarayıcı her zaman çalışır.", + "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ı." + } +} diff --git a/plugins/web-endpoint/locales/translated/uk_UA.json b/plugins/web-endpoint/locales/translated/uk_UA.json new file mode 100644 index 000000000..45070ea09 --- /dev/null +++ b/plugins/web-endpoint/locales/translated/uk_UA.json @@ -0,0 +1,52 @@ +{ + "webEndpoint": { + "noHostSelected": "Хост не вибрано", + "notFound": "Цієї кінцевої точки більше не існує.", + "tunnelUnreachableFromBrowser": "Ця кінцева точка тунелює до 127.0.0.1 на машині з Termix, до якої ваш браузер не може дістатися. Встановіть для хоста прив'язки кінцевої точки адресу, на яку відповідає машина, наприклад, 0.0.0.0, і надайте їй фіксований локальний порт.", + "tunnelSharesSessionCookie": "Відкриття цього тунелю перенаправить ваш сеанс Termix до тунельованого сервісу, оскільки ваш браузер досягне його на тому ж імені хоста, з якого обслуговується Termix. Файли cookie ігнорують порт, тому їх не можна розрізнити. Скористайтеся десктопним застосунком Termix або відкрийте Termix на localhost.", + "directSharesSessionCookie": "Відкриття цієї кінцевої точки призведе до перенаправлення вашого сеансу Termix на неї, оскільки ваш браузер звертається до нього на тому ж сайті, з якого обслуговується Termix. Файли cookie ігнорують порт, тому інший порт не є іншою ідентифікатором. Використовуйте настільний додаток Termix або обслуговуйте цей веб-інтерфейс з іншого імені хоста.", + "retry": "Повторити спробу", + "reload": "Перезавантажити", + "copyUrl": "Копіювати URL-адресу", + "urlCopied": "URL-адресу скопійовано", + "copyFailed": "Не вдалося скопіювати URL-адресу", + "openExternally": "Відкрити зовні", + "isolationUnavailable": "Цей браузер не може ізолювати кінцеві точки веб-сайту від вашого сеансу Termix. Використовуйте браузер із підтримкою iframe без облікових даних.", + "isolationNotice": "Вбудовані сторінки використовують ізольований сеанс. Для сторінок, що потребують сховища або спливаючого входу, використовуйте ізольоване вікно в настільному додатку.", + "openIsolatedWindow": "Відкрите ізольоване вікно" + }, + "hosts": { + "tabWebUi": "Веб-інтерфейс", + "webUiEndpointLabel": "Кінцева точка {{number}}", + "webUiIntegration": "Веб-інтерфейс", + "webUiEndpointsSection": "Кінцеві точки", + "webUiRequirementsText": "Ваш браузер відкривається прямою кінцевою точкою, тому її порт має бути доступним звідси. Натомість Termix відкриває SSH-тунель через SSH-з'єднання цього хоста, тому порт має бути доступним лише з хоста.", + "enableWebUi": "Увімкнути веб-кінцеві точки", + "enableWebUiDesc": "Відкрийте веб-інтерфейси цього хоста з бічної панелі.", + "webUiAddEndpoint": "Додати кінцеву точку", + "webUiAddress": "Адреса", + "webUiOpening": "Відкриття", + "webUiBindHostDesc": "Де серверна частина зв'язується з пересиланням. Залиште поле порожнім для 127.0.0.1, до якого може отримати доступ лише машина з Termix.", + "webUiBindHostExposed": "Ця адреса доступна за межами машини Termix, тому кожен, хто може отримати доступ до порту, отримає цей веб-інтерфейс без входу в систему.", + "webUiLocalPort": "Локальний порт", + "webUiLocalPortAuto": "Автоматичний", + "webUiLocalPortDesc": "На якому порту прослуховується переадресація. Залиште поле порожнім, щоб дозволити системі вибрати, або встановіть порт, якщо порт має бути відомий заздалегідь, наприклад, контейнер, який його публікує.", + "webUiNewEndpointLabel": "Нова кінцева точка", + "webUiLabel": "Мітка", + "webUiScheme": "Схема", + "webUiPort": "Порт", + "webUiPath": "Шлях", + "webUiAccess": "Доступ", + "webUiAccessDirect": "Прямий", + "webUiAccessTunnel": "SSH-тунель", + "webUiAccessTunnelUnavailable": "Для SSH-тунелю потрібно ввімкнути SSH на цьому хості та встановити джерело з'єднання на цьому пристрої.", + "webUiRender": "Відкрити в", + "webUiRenderExternal": "Ізольоване вікно робочого столу", + "webUiRenderEmbedded": "Вкладка Termix", + "webUiRenderEmbeddedDesc": "Вбудовування – найкращий спосіб: деякі веб-інтерфейси відмовляються завантажуватися у фреймі, а вхід, який залежить від файлів cookie того ж сайту, може зациклюватися. Зовнішній браузер завжди працює.", + "webUiIgnoreCert": "Дозволити недійсний сертифікат", + "webUiIgnoreCertDesc": "Тільки прямі кінцеві точки. Зациклення вже виключено, тому це не впливає на кінцеві точки тунелю.", + "webUiRemoveEndpoint": "Видалити кінцеву точку", + "webUiOpenFailed": "Не вдалося відкрити кінцеву точку веб-сайту" + } +} diff --git a/plugins/web-endpoint/locales/translated/vi_VN.json b/plugins/web-endpoint/locales/translated/vi_VN.json new file mode 100644 index 000000000..71d0af477 --- /dev/null +++ b/plugins/web-endpoint/locales/translated/vi_VN.json @@ -0,0 +1,52 @@ +{ + "webEndpoint": { + "noHostSelected": "Chưa chọn máy chủ nào", + "notFound": "Điểm cuối này không còn tồn tại nữa.", + "tunnelUnreachableFromBrowser": "Điểm cuối này tạo đường hầm đến 127.0.0.1 trên máy đang chạy Termix, mà trình duyệt của bạn không thể truy cập được. Hãy đặt Bind Host của điểm cuối thành một địa chỉ mà máy đó phản hồi, chẳng hạn như 0.0.0.0, và gán cho nó một Cổng cục bộ cố định.", + "tunnelSharesSessionCookie": "Việc mở đường hầm này sẽ chuyển phiên Termix của bạn đến dịch vụ được tạo đường hầm, vì trình duyệt của bạn sẽ truy cập dịch vụ đó bằng cùng tên máy chủ mà Termix được phục vụ. Cookie bỏ qua cổng, vì vậy không thể phân biệt được hai dịch vụ này. Hãy sử dụng ứng dụng Termix dành cho máy tính để bàn hoặc mở Termix tại localhost.", + "directSharesSessionCookie": "Việc mở điểm cuối này sẽ gửi phiên Termix của bạn đến đó, vì trình duyệt của bạn truy cập nó từ cùng một trang web mà Termix được cung cấp. Cookie bỏ qua cổng, vì vậy một cổng khác không có nghĩa là một danh tính khác. Hãy sử dụng ứng dụng Termix dành cho máy tính để bàn, hoặc cung cấp giao diện người dùng web này từ một tên máy chủ khác.", + "retry": "Thử lại", + "reload": "Tải lại", + "copyUrl": "Sao chép URL", + "urlCopied": "URL đã được sao chép", + "copyFailed": "Không thể sao chép URL", + "openExternally": "Mở từ bên ngoài", + "isolationUnavailable": "Trình duyệt này không thể tách biệt các điểm cuối web khỏi phiên Termix của bạn. Hãy sử dụng trình duyệt hỗ trợ iframe không cần thông tin đăng nhập.", + "isolationNotice": "Các trang nhúng sử dụng một phiên riêng biệt. Đối với các trang yêu cầu lưu trữ hoặc đăng nhập bằng cửa sổ bật lên, hãy sử dụng một cửa sổ riêng biệt trong ứng dụng dành cho máy tính để bàn.", + "openIsolatedWindow": "Cửa sổ riêng biệt đang mở" + }, + "hosts": { + "tabWebUi": "Giao diện người dùng web", + "webUiEndpointLabel": "Điểm cuối {{number}}", + "webUiIntegration": "Giao diện người dùng web", + "webUiEndpointsSection": "Điểm cuối", + "webUiRequirementsText": "Trình duyệt của bạn sẽ mở một điểm cuối trực tiếp, vì vậy cổng của nó phải có thể truy cập được từ đây. Thay vào đó, Termix sẽ mở một đường hầm SSH thông qua kết nối SSH của máy chủ này, vì vậy cổng chỉ cần có thể truy cập được từ máy chủ đó.", + "enableWebUi": "Kích hoạt các điểm cuối web", + "enableWebUiDesc": "Mở giao diện web của máy chủ này từ thanh bên.", + "webUiAddEndpoint": "Thêm điểm cuối", + "webUiAddress": "Địa chỉ", + "webUiOpening": "Khai mạc", + "webUiBindHostDesc": "Đây là nơi phần máy chủ liên kết với phần máy khách. Để trống trường 127.0.0.1, chỉ máy chạy Termix mới có thể truy cập được.", + "webUiBindHostExposed": "Địa chỉ này có thể truy cập được từ bên ngoài máy Termix, vì vậy bất kỳ ai có thể truy cập được cổng này đều có thể sử dụng giao diện web này mà không cần đăng nhập.", + "webUiLocalPort": "Cảng địa phương", + "webUiLocalPortAuto": "Tự động", + "webUiLocalPortDesc": "Chọn cổng mà bản ghi chuyển tiếp lắng nghe. Để trống để hệ thống tự chọn, hoặc đặt một cổng khi cần biết trước cổng, ví dụ như một container công bố cổng đó.", + "webUiNewEndpointLabel": "Điểm cuối mới", + "webUiLabel": "Nhãn", + "webUiScheme": "Cơ chế", + "webUiPort": "Cảng", + "webUiPath": "Con đường", + "webUiAccess": "Truy cập", + "webUiAccessDirect": "Trực tiếp", + "webUiAccessTunnel": "Đường hầm SSH", + "webUiAccessTunnelUnavailable": "Đường hầm SSH cần có SSH được bật trên máy chủ này và nguồn kết nối là thiết bị này.", + "webUiRender": "Mở trong", + "webUiRenderExternal": "Cửa sổ màn hình nền riêng biệt", + "webUiRenderEmbedded": "Viên nén Termix", + "webUiRenderEmbeddedDesc": "Việc nhúng trang web chỉ mang tính chất tham khảo: một số giao diện web từ chối tải trong khung, và quá trình đăng nhập dựa vào cookie cùng trang có thể bị lặp lại. Trình duyệt bên ngoài luôn hoạt động bình thường.", + "webUiIgnoreCert": "Cho phép chứng chỉ không hợp lệ", + "webUiIgnoreCertDesc": "Chỉ áp dụng cho các điểm cuối trực tiếp. Giao diện vòng lặp đã được miễn trừ, vì vậy điều này không ảnh hưởng đến các điểm cuối đường hầm.", + "webUiRemoveEndpoint": "Xóa điểm cuối", + "webUiOpenFailed": "Không thể mở điểm cuối web" + } +} diff --git a/plugins/web-endpoint/locales/translated/zh_CN.json b/plugins/web-endpoint/locales/translated/zh_CN.json new file mode 100644 index 000000000..45ad8102d --- /dev/null +++ b/plugins/web-endpoint/locales/translated/zh_CN.json @@ -0,0 +1,52 @@ +{ + "webEndpoint": { + "noHostSelected": "未选择主机", + "notFound": "此端点已不存在。", + "tunnelUnreachableFromBrowser": "此端点通过隧道连接到运行 Termix 的机器上的 127.0.0.1,您的浏览器无法直接访问该地址。请将此端点的绑定主机设置为该机器可以响应的地址,例如 0.0.0.0,并为其指定一个固定的本地端口。", + "tunnelSharesSessionCookie": "打开此隧道会将您的 Termix 会话发送到隧道服务,因为您的浏览器将通过与 Termix 服务相同的主机名访问该服务。Cookie 会忽略端口号,因此无法区分两者。请使用 Termix 桌面应用程序,或在本地主机上打开 Termix。", + "directSharesSessionCookie": "打开此端点会将您的 Termix 会话发送到该端点,因为您的浏览器访问的是 Termix 所在的同一站点。Cookie 会忽略端口号,因此不同的端口号并不代表不同的身份。请使用 Termix 桌面应用程序,或使用不同的主机名访问此 Web UI。", + "retry": "重试", + "reload": "重新加载", + "copyUrl": "复制链接", + "urlCopied": "复制的网址", + "copyFailed": "复制 URL 失败", + "openExternally": "向外开放", + "isolationUnavailable": "此浏览器无法将 Web 端点与您的 Termix 会话隔离。请使用支持无需凭据即可访问 iframe 的浏览器。", + "isolationNotice": "嵌入式页面使用独立的会话。对于需要存储数据或弹出式登录的页面,请在桌面应用程序中使用独立的窗口。", + "openIsolatedWindow": "打开隔离窗口" + }, + "hosts": { + "tabWebUi": "Web 用户界面", + "webUiEndpointLabel": "端点 {{number}}", + "webUiIntegration": "Web 用户界面", + "webUiEndpointsSection": "终点", + "webUiRequirementsText": "浏览器会打开一个直接端点,因此其端口必须可从此处访问。而 Termix 则会通过此主机的 SSH 连接打开一个 SSH 隧道,因此该端口只需可从主机访问即可。", + "enableWebUi": "启用 Web 端点", + "enableWebUiDesc": "从侧边栏打开此主机的网页界面。", + "webUiAddEndpoint": "添加端点", + "webUiAddress": "地址", + "webUiOpening": "开场", + "webUiBindHostDesc": "后端绑定到前向路由的位置。如果是 127.0.0.1,则留空,因为只有运行 Termix 的机器才能访问该地址。", + "webUiBindHostExposed": "该地址在 Termix 机器之外也是可访问的,因此任何能够访问该端口的人都可以无需登录即可使用此 Web UI。", + "webUiLocalPort": "本地港口", + "webUiLocalPortAuto": "自动的", + "webUiLocalPortDesc": "转发监听哪个端口。留空让系统自动选择,或者在需要预先知道端口的情况下(例如容器发布端口时)设置一个端口。", + "webUiNewEndpointLabel": "新端点", + "webUiLabel": "标签", + "webUiScheme": "方案", + "webUiPort": "港口", + "webUiPath": "小路", + "webUiAccess": "使用权", + "webUiAccessDirect": "直接的", + "webUiAccessTunnel": "SSH隧道", + "webUiAccessTunnelUnavailable": "SSH隧道需要在此主机上启用SSH,并且连接源必须为该设备。", + "webUiRender": "打开", + "webUiRenderExternal": "隔离的桌面窗口", + "webUiRenderEmbedded": "Termix 选项卡", + "webUiRenderEmbeddedDesc": "嵌入功能只能尽力而为:某些网页界面无法在框架中加载,依赖同站点 Cookie 的登录可能会陷入循环。外部浏览器始终有效。", + "webUiIgnoreCert": "允许无效证书", + "webUiIgnoreCertDesc": "仅限直接端点。环回接口已获豁免,因此对隧道端点没有影响。", + "webUiRemoveEndpoint": "移除端点", + "webUiOpenFailed": "打开 Web 端点失败" + } +} diff --git a/plugins/web-endpoint/locales/translated/zh_TW.json b/plugins/web-endpoint/locales/translated/zh_TW.json new file mode 100644 index 000000000..93a434a5d --- /dev/null +++ b/plugins/web-endpoint/locales/translated/zh_TW.json @@ -0,0 +1,52 @@ +{ + "webEndpoint": { + "noHostSelected": "未選擇主機", + "notFound": "此端點已不存在。", + "tunnelUnreachableFromBrowser": "此端點透過隧道連接到執行 Termix 的機器上的 127.0.0.1,您的瀏覽器無法直接存取該位址。請將此端點的綁定主機設定為該機器可以回應的位址,例如 0.0.0.0,並為其指定一個固定的本機連接埠。", + "tunnelSharesSessionCookie": "開啟此隧道會將您的 Termix 工作階段傳送至隧道服務,因為您的瀏覽器將透過與 Termix 服務相同的主機名稱存取該服務。 Cookie 會忽略連接埠號,因此無法區分兩者。請使用 Termix 桌面應用程序,或在本機上開啟 Termix。", + "directSharesSessionCookie": "開啟此端點會將您的 Termix 會話傳送到該端點,因為您的瀏覽器造訪的是 Termix 所在的相同網站。 Cookie 會忽略連接埠號,因此不同的連接埠號碼並不代表不同的身分。請使用 Termix 桌面應用程序,或使用不同的主機名稱存取此 Web UI。", + "retry": "重試", + "reload": "重新載入", + "copyUrl": "複製連結", + "urlCopied": "複製的網址", + "copyFailed": "複製 URL 失敗", + "openExternally": "向外開放", + "isolationUnavailable": "此瀏覽器無法將 Web 端點與您的 Termix 工作階段隔離。請使用支援無需憑證的 iframe 的瀏覽器。", + "isolationNotice": "嵌入式頁面使用獨立的會話。對於需要儲存資料或彈出式登入的頁面,請在桌面應用程式中使用獨立的視窗。", + "openIsolatedWindow": "打開隔離視窗" + }, + "hosts": { + "tabWebUi": "Web 使用者介面", + "webUiEndpointLabel": "端點 {{number}}", + "webUiIntegration": "Web 使用者介面", + "webUiEndpointsSection": "終點", + "webUiRequirementsText": "瀏覽器會開啟直接端點,因此其連接埠必須可從此處存取。而 Termix 則會透過此主機的 SSH 連線開啟一個 SSH 隧道,因此該連接埠只需可從主機存取即可。", + "enableWebUi": "啟用 Web 端點", + "enableWebUiDesc": "從側邊欄開啟此主機的網頁介面。", + "webUiAddEndpoint": "新增端點", + "webUiAddress": "地址", + "webUiOpening": "開場", + "webUiBindHostDesc": "後端綁定到前向路由的位置。如果是 127.0.0.1,則留空,因為只有執行 Termix 的機器才能存取該位址。", + "webUiBindHostExposed": "該位址在 Termix 機器之外也是可存取的,因此任何能夠存取該連接埠的人都可以無需登入即可使用此 Web UI。", + "webUiLocalPort": "本地港口", + "webUiLocalPortAuto": "自動的", + "webUiLocalPortDesc": "轉送監聽哪個連接埠。留空讓系統自動選擇,或在需要預先知道連接埠的情況下(例如容器發佈連接埠時)設定一個連接埠。", + "webUiNewEndpointLabel": "新端點", + "webUiLabel": "標籤", + "webUiScheme": "方案", + "webUiPort": "港口", + "webUiPath": "小路", + "webUiAccess": "使用權", + "webUiAccessDirect": "直接的", + "webUiAccessTunnel": "SSH隧道", + "webUiAccessTunnelUnavailable": "SSH隧道需要在此主機上啟用SSH,且連線來源必須為該裝置。", + "webUiRender": "打開", + "webUiRenderExternal": "隔離的桌面視窗", + "webUiRenderEmbedded": "Termix 選項卡", + "webUiRenderEmbeddedDesc": "嵌入功能只能盡力而為:某些網頁介面無法在框架中加載,依賴同網站 Cookie 的登入可能會陷入循環。外部瀏覽器始終有效。", + "webUiIgnoreCert": "允許無效證書", + "webUiIgnoreCertDesc": "僅限直接端點。環回介面已獲豁免,因此對隧道端點沒有影響。", + "webUiRemoveEndpoint": "移除端點", + "webUiOpenFailed": "開啟 Web 端點失敗" + } +} diff --git a/src/ui/sidebar/HostEditorWebUiSection.tsx b/plugins/web-endpoint/src/frontend/HostEditorWebUiSection.tsx similarity index 98% rename from src/ui/sidebar/HostEditorWebUiSection.tsx rename to plugins/web-endpoint/src/frontend/HostEditorWebUiSection.tsx index f0b2f3d40..c713a0a5f 100644 --- a/src/ui/sidebar/HostEditorWebUiSection.tsx +++ b/plugins/web-endpoint/src/frontend/HostEditorWebUiSection.tsx @@ -1,10 +1,10 @@ import { Globe } from "lucide-react"; -import { useTranslation } from "react-i18next"; +import { useTranslation } from "@termix/plugin-sdk/frontend"; import { isElectron } from "@/lib/electron"; import { webEndpointRefusalReason, type WebEndpointRefusalReason, -} from "../../../plugins/web-endpoint/src/frontend/web-endpoint-url"; +} from "./web-endpoint-url"; import { Button } from "@/components/button"; import { Input } from "@/components/input"; import { Checkbox } from "@/components/checkbox"; @@ -28,7 +28,7 @@ import { isWebEndpointPortValid, webEndpointErrorKey, webEndpointRowError, -} from "../../../plugins/web-endpoint/src/frontend/web-endpoint-validation"; +} from "./web-endpoint-validation"; /** * crypto.randomUUID is undefined outside a secure context, so a plain-http web diff --git a/plugins/web-endpoint/src/frontend/HostWebUiTab.tsx b/plugins/web-endpoint/src/frontend/HostWebUiTab.tsx new file mode 100644 index 000000000..38d13bcd2 --- /dev/null +++ b/plugins/web-endpoint/src/frontend/HostWebUiTab.tsx @@ -0,0 +1,66 @@ +import { useEffect, useState } from "react"; +import { resolveConnectionOrigin } from "@/lib/connection-origin"; +import type { HostEditorForm, HostProtocols } from "@/sidebar/HostEditorData"; +import { HostEditorWebUiSection } from "./HostEditorWebUiSection"; + +type SetHostField = ( + key: K, + value: HostEditorForm[K], +) => void; + +/** + * Owns the async connection-origin resolution for the Web UI tab's tunnel + * gate, then hands the resolved boolean to the presentational section. + * + * tunnelAvailable = enableSsh && originIsLocal. Deliberately NOT gated on + * isElectron(): the forward binds wherever the backend runs, exactly as the + * server tunnels feature does, and a web deployment reaches it at the host + * serving Termix provided the endpoint opted out of a loopback bind. Gating + * this on the desktop would be stricter than the tunnels feature it mirrors. + * + * connectionType is passed as "ssh" deliberately: a tunnel endpoint always + * rides an SSH connection, and "ssh" keeps resolveConnectionOrigin out of its + * RDP/VNC/Telnet guacamole special case, which always resolves to "remote". + * + * The origin state lives here rather than in HostEditor.tsx, which is already + * very long; this follows HostEditorGeneralTab's precedent of taking + * `protocols` as a prop and gating its own connection-origin control. + * + * Note the deliberate asymmetry with the sidebar: the sidebar entry appears on + * enableWebUi alone, because a direct endpoint needs no SSH -- but Web UI is + * an SSH sub-tab, so a host with SSH disabled cannot configure endpoints at + * all. That is the accepted behaviour, not an oversight. + */ +export function HostWebUiTab({ + form, + setField, + protocols, +}: { + form: HostEditorForm; + setField: SetHostField; + protocols: HostProtocols; +}) { + const [originIsLocal, setOriginIsLocal] = useState(false); + + useEffect(() => { + let cancelled = false; + void resolveConnectionOrigin({ + connectionType: "ssh", + connectionOrigin: form.connectionOrigin, + }).then((origin) => { + if (!cancelled) setOriginIsLocal(origin === "local"); + }); + return () => { + cancelled = true; + }; + }, [form.connectionOrigin]); + + return ( + void} + /> + ); +} diff --git a/plugins/web-endpoint/src/frontend/WebEndpointTab.tsx b/plugins/web-endpoint/src/frontend/WebEndpointTab.tsx index 310f53a25..18da0417e 100644 --- a/plugins/web-endpoint/src/frontend/WebEndpointTab.tsx +++ b/plugins/web-endpoint/src/frontend/WebEndpointTab.tsx @@ -1,5 +1,5 @@ import { useCallback, useEffect, useRef, useState } from "react"; -import { useTranslation } from "react-i18next"; +import { useTranslation } from "@termix/plugin-sdk/frontend"; import { Globe, RotateCw } from "lucide-react"; import { toast } from "sonner"; import { diff --git a/plugins/web-endpoint/src/frontend/index.mjs b/plugins/web-endpoint/src/frontend/index.mjs deleted file mode 100644 index 2c1ab8454..000000000 --- a/plugins/web-endpoint/src/frontend/index.mjs +++ /dev/null @@ -1,39 +0,0 @@ -/** - * Frontend half of the web-endpoint plugin. - * - * Registers the endpoint viewer tab through the existing registerTabComponent - * seam the same way network-topology's frontend does. - * - * HostEditorWebUiSection stays in src/ui/sidebar/ rather than moving here, and - * is not registered through registerHostEditorTab: it is a section inside the - * host editor's existing General tab, not a tab of its own, and it takes the - * same {form, setField} pair every other host editor field does -- those types - * (HostEditorForm, the setField signature) are core types HostEditor.tsx owns, - * the same reason docker leaves HostDockerTab in core rather than copying it - * into plugins/docker. - * - * register() is called when the plugin is enabled, unregister() when it is - * disabled. As of this change neither is actually invoked anywhere yet -- see - * src/ui/shell/pluginLoader.ts and - * src/ui/tests/sidebar/plugin-extension-seam.test.tsx, which says outright - * "there is no plugin loader yet" for the frontend half. Until one exists the - * tab is rendered directly by tabUtils.tsx and merely gated on the plugin's - * enabled state through BUILT_IN_TABS_BY_PLUGIN. This file follows the same - * shape every other plugin's frontend entry does so it is ready the moment a - * real loader lands. - */ - -export const id = "web-endpoint"; -export const tabId = "web-endpoint"; - -export async function register({ registerTabComponent }) { - registerTabComponent?.(tabId, () => - import("./WebEndpointTab.tsx").then((m) => ({ - default: m.WebEndpointTab, - })), - ); -} - -export async function unregister({ unregisterTabComponent }) { - unregisterTabComponent?.(tabId); -} diff --git a/plugins/web-endpoint/src/frontend/index.tsx b/plugins/web-endpoint/src/frontend/index.tsx new file mode 100644 index 000000000..b09c2c2ca --- /dev/null +++ b/plugins/web-endpoint/src/frontend/index.tsx @@ -0,0 +1,117 @@ +import { Globe } from "lucide-react"; +import i18next from "i18next"; +import { toast } from "sonner"; +import type { + HostEditorSectionProps, + PluginHostRecord, + ShellApi, + TabProps, + TermixApp, +} from "@termix/plugin-sdk/frontend"; +import type { Host } from "@/types/ui-types"; +import type { WebEndpoint } from "@/types"; +import { WebEndpointTab } from "./WebEndpointTab"; +import { HostWebUiTab } from "./HostWebUiTab"; +import { openWebEndpointExternally } from "./web-endpoint-api"; + +const TAB_TYPE = "web-endpoint"; + +function endpointsOf(host: PluginHostRecord): WebEndpoint[] { + if (!host.enableWebUi) return []; + const config = host.webUiConfig as { endpoints?: WebEndpoint[] } | undefined; + return config?.endpoints ?? []; +} + +function openEndpoint( + host: PluginHostRecord, + endpoint: WebEndpoint, + shell: ShellApi, +): void { + if (endpoint.render === "external") { + // No tab at all: the real browser opens it. On the desktop the main + // process routes it to shell.openExternal. + openWebEndpointExternally( + host as unknown as { id: string; ip: string }, + endpoint, + ).catch((error: unknown) => { + toast.error( + error instanceof Error + ? error.message + : i18next.t("web-endpoint:hosts.webUiOpenFailed"), + ); + }); + return; + } + shell.openTab(host, TAB_TYPE, { + label: endpoint.label, + data: { endpointId: endpoint.id }, + }); +} + +function EndpointTab({ host, tab }: TabProps) { + // Resolved against the host on every render, so an endpoint deleted while + // its tab is open shows a plain message instead of throwing. + const endpointId = tab.data?.endpointId; + return ( + + ); +} + +function WebUiSection({ form, setField, protocols }: HostEditorSectionProps) { + return ( + [0]["setField"]} + protocols={ + protocols as unknown as Parameters[0]["protocols"] + } + /> + ); +} + +export function activate(app: TermixApp): void { + app.registerTab(TAB_TYPE, EndpointTab, { + icon: Globe, + titleKey: "hosts.tabWebUi", + requiresHost: true, + noHostMessageKey: "webEndpoint.noHostSelected", + // A restored tab could never hold a valid URL: the backend closes an idle + // tunnel after ten minutes and binds a fresh port on the next open. So + // these tabs are session-only and never saved. + persistent: false, + inLayouts: false, + }); + + // One entry per host, not one per endpoint: with several it opens a picker. + // Gated on enableWebUi alone, since a direct endpoint needs no SSH. + app.registerHostAction({ + id: TAB_TYPE, + titleKey: "hosts.tabWebUi", + icon: Globe, + kind: "open", + order: 80, + when: (host) => endpointsOf(host).length > 0, + label: (host) => { + const endpoints = endpointsOf(host); + return endpoints.length === 1 ? endpoints[0].label : undefined; + }, + items: (host) => + endpointsOf(host).map((endpoint) => ({ + id: endpoint.id, + label: endpoint.label, + run: (target, shell) => openEndpoint(target, endpoint, shell), + })), + }); + + app.registerHostEditorSection({ + id: "web-ui", + group: "ssh", + titleKey: "hosts.tabWebUi", + icon: Globe, + order: 40, + component: WebUiSection, + }); +} diff --git a/plugins/web-endpoint/tests/backend/host-web-endpoint-enumeration.test.ts b/plugins/web-endpoint/tests/backend/host-web-endpoint-enumeration.test.ts index 42aa2d58c..72c86b6fd 100644 --- a/plugins/web-endpoint/tests/backend/host-web-endpoint-enumeration.test.ts +++ b/plugins/web-endpoint/tests/backend/host-web-endpoint-enumeration.test.ts @@ -39,7 +39,7 @@ const ENUMERATION_POINTS = [ "src/ui/sidebar/host-export-payload.ts", "src/ui/sidebar/HostManagerData.ts", "src/ui/sidebar/HostEditorData.ts", - "src/ui/shell/tabUtils.tsx", + "src/ui/lib/host-to-ssh-host.ts", ]; describe("web endpoint column enumeration", () => { diff --git a/src/ui/tests/sidebar/HostEditorWebUiSection.test.tsx b/plugins/web-endpoint/tests/frontend/HostEditorWebUiSection.test.tsx similarity index 98% rename from src/ui/tests/sidebar/HostEditorWebUiSection.test.tsx rename to plugins/web-endpoint/tests/frontend/HostEditorWebUiSection.test.tsx index 233c28c4d..3a1142af2 100644 --- a/src/ui/tests/sidebar/HostEditorWebUiSection.test.tsx +++ b/plugins/web-endpoint/tests/frontend/HostEditorWebUiSection.test.tsx @@ -13,7 +13,7 @@ vi.mock("react-i18next", () => ({ }), })); -import { HostEditorWebUiSection } from "@/sidebar/HostEditorWebUiSection"; +import { HostEditorWebUiSection } from "../../src/frontend/HostEditorWebUiSection"; function endpoint(overrides: Partial = {}): WebEndpoint { return { diff --git a/plugins/web-endpoint/tests/frontend/activate.test.tsx b/plugins/web-endpoint/tests/frontend/activate.test.tsx new file mode 100644 index 000000000..a4b943e74 --- /dev/null +++ b/plugins/web-endpoint/tests/frontend/activate.test.tsx @@ -0,0 +1,126 @@ +import { afterEach, describe, expect, it } from "vitest"; +import { + renderWithApp, + type RenderedPluginApp, +} from "@termix/plugin-sdk/testing"; +import { hostActionsFor, listHostActions } from "@/sidebar/host-contributions"; +import type { Host } from "@/types/ui-types"; +import type { WebEndpoint } from "@/types"; +import type { PluginManifest } from "@termix/plugin-sdk/manifest"; +import * as plugin from "../../src/frontend/index"; +import manifestJson from "../../manifest.json"; + +const manifest = manifestJson as unknown as PluginManifest; + +function endpoint(overrides: Partial = {}): WebEndpoint { + return { + id: "e1", + label: "Proxmox", + scheme: "https", + port: 8006, + path: "/", + access: "direct", + render: "embedded", + ...overrides, + }; +} + +function host(overrides: Partial = {}): Host { + return { + id: "7", + ip: "10.0.0.5", + name: "nas", + enableSsh: false, + enableWebUi: false, + ...overrides, + } as unknown as Host; +} + +let rendered: RenderedPluginApp | null = null; + +async function webAction(target: Host) { + rendered ??= await renderWithApp(plugin, { manifest }); + return hostActionsFor(listHostActions(), target).find( + (action) => action.id === "web-endpoint", + ); +} + +afterEach(async () => { + await rendered?.deactivate(); + rendered = null; +}); + +describe("web-endpoint activate", () => { + it("registers its tab, host action and editor section", async () => { + rendered = await renderWithApp(plugin, { manifest }); + expect(rendered.registered.tabs()).toEqual(["web-endpoint"]); + expect(rendered.registered.hostEditorSections()).toEqual(["web-ui"]); + }); + + it("offers no Web UI entry when the feature is off, even with endpoints", async () => { + expect( + await webAction( + host({ enableWebUi: false, webUiConfig: { endpoints: [endpoint()] } }), + ), + ).toBeUndefined(); + }); + + it("offers no entry when enabled but no endpoints exist", async () => { + expect( + await webAction( + host({ enableWebUi: true, webUiConfig: { endpoints: [] } }), + ), + ).toBeUndefined(); + }); + + it("appears without SSH", async () => { + const action = await webAction( + host({ + enableSsh: false, + enableWebUi: true, + webUiConfig: { endpoints: [endpoint()] }, + }), + ); + expect(action).toBeDefined(); + }); + + it("labels the entry with the endpoint when there is only one", async () => { + const target = host({ + enableWebUi: true, + webUiConfig: { endpoints: [endpoint({ label: "Proxmox" })] }, + }); + const action = await webAction(target); + expect(action?.label?.(target)).toBe("Proxmox"); + expect(action?.items?.(target).map((item) => item.id)).toEqual(["e1"]); + }); + + it("stays one entry with a picker when there are several", async () => { + const endpoints = Array.from({ length: 16 }, (_, i) => + endpoint({ id: `e${i}`, label: `Endpoint ${i}` }), + ); + const target = host({ enableWebUi: true, webUiConfig: { endpoints } }); + const action = await webAction(target); + expect(action?.label?.(target)).toBeUndefined(); + expect(action?.items?.(target)).toHaveLength(16); + }); + + it("opens an embedded endpoint as a tab carrying its id", async () => { + const target = host({ + enableWebUi: true, + webUiConfig: { endpoints: [endpoint()] }, + }); + const action = await webAction(target); + const calls: unknown[][] = []; + const shell = { + openTab: (...args: unknown[]) => calls.push(args), + } as never; + action!.items!(target)[0].run(target, shell); + expect(calls).toEqual([ + [ + target, + "web-endpoint", + { label: "Proxmox", data: { endpointId: "e1" } }, + ], + ]); + }); +}); diff --git a/plugins/workspaces/locales/en.json b/plugins/workspaces/locales/en.json index 0967ef424..0b3ac96ee 100644 --- a/plugins/workspaces/locales/en.json +++ b/plugins/workspaces/locales/en.json @@ -1 +1,55 @@ -{} +{ + "newUi": { + "sidebar": { + "workspaces": { + "title": "Workspaces", + "saveCurrent": "Save Current", + "saveCurrentTitle": "Save Current Workspace", + "saveCurrentDescription": "Save every open tab, split layout, and pane arrangement as a new named workspace.", + "nameLabel": "Name", + "namePlaceholder": "e.g., Prod Debugging", + "nameRequired": "Workspace name is required", + "colorLabel": "Color", + "workspaceCreated": "Workspace saved", + "workspaceUpdated": "Workspace updated", + "workspaceDeleted": "Workspace deleted", + "workspaceDuplicated": "Workspace duplicated", + "saveFailed": "Failed to save workspace", + "updateFailed": "Failed to update workspace", + "deleteFailed": "Failed to delete workspace", + "duplicateFailed": "Failed to duplicate workspace", + "loadFailed": "Failed to load workspaces", + "applyFailed": "Failed to apply workspace", + "deleteWorkspaceTitle": "Delete Workspace", + "deleteWorkspaceDescription": "Are you sure you want to delete \"{{name}}\"? This cannot be undone.", + "noWorkspaces": "No saved workspaces yet. Save your current tab arrangement to get started.", + "tabCount": "{{count}} tab", + "tabCount_other": "{{count}} tabs", + "apply": "Apply", + "applyConfirmTitle": "Apply Workspace", + "applyConfirmDescription": "Applying \"{{name}}\" will close your current tabs and replace them with this workspace's saved arrangement. Unsaved changes to your current layout will be lost.", + "applyConfirmButton": "Apply Workspace", + "updateWithCurrent": "Update with Current", + "updateWithCurrentConfirm": "Overwrite \"{{name}}\" with your current tab arrangement?", + "rename": "Rename", + "duplicate": "Duplicate", + "duplicateNameSuffix": "{{name}} (copy)", + "setDefault": "Set as Default", + "unsetDefault": "Remove as Default", + "defaultBadge": "Default", + "lastSession": "Last Session", + "lastSessionDescription": "Automatically updated with your most recent tab arrangement. Apply it to recover what you had open.", + "lastUsed": "Last used {{time}}", + "neverUsed": "Never applied", + "tabsSkipped": "Workspace applied — {{count}} tab(s) skipped (host no longer exists): {{names}}" + } + } + }, + "nav": { + "workspaces": "Workspaces" + }, + "onboarding": { + "workflow_workspaces": "Workspaces", + "workflow_workspaces_desc": "Save a set of open tabs and reopen the whole layout later." + } +} diff --git a/plugins/workspaces/locales/translated/af_ZA.json b/plugins/workspaces/locales/translated/af_ZA.json new file mode 100644 index 000000000..7f1d8af66 --- /dev/null +++ b/plugins/workspaces/locales/translated/af_ZA.json @@ -0,0 +1,55 @@ +{ + "newUi": { + "sidebar": { + "workspaces": { + "title": "Werkruimtes", + "saveCurrent": "Stoor Huidige", + "saveCurrentTitle": "Stoor huidige werkspasie", + "saveCurrentDescription": "Stoor elke oop oortjie, gesplete uitleg en paneelrangskikking as 'n nuwe benoemde werkruimte.", + "nameLabel": "Naam", + "namePlaceholder": "bv. Produkontfouting", + "nameRequired": "Werkruimtenaam word vereis", + "colorLabel": "Kleur", + "workspaceCreated": "Werkruimte gestoor", + "workspaceUpdated": "Werkruimte opgedateer", + "workspaceDeleted": "Werkruimte uitgevee", + "workspaceDuplicated": "Werkruimte gedupliseer", + "saveFailed": "Kon nie werkspasie stoor nie", + "updateFailed": "Kon nie werkspasie opdateer nie", + "deleteFailed": "Kon nie werkspasie uitvee nie", + "duplicateFailed": "Kon nie werkruimte dupliseer nie", + "loadFailed": "Kon nie werkruimtes laai nie", + "applyFailed": "Kon nie werkspasie toepas nie", + "deleteWorkspaceTitle": "Vee Werkspasie uit", + "deleteWorkspaceDescription": "Is jy seker jy wil \"{{name}}\" verwyder? Dit kan nie ongedaan gemaak word nie.", + "noWorkspaces": "Geen gestoorde werkruimtes nog nie. Stoor jou huidige oortjie-rangskikking om te begin.", + "tabCount": "{{count}} oortjie", + "tabCount_other": "{{count}} oortjies", + "apply": "Dien toe", + "applyConfirmTitle": "Pas Werkruimte toe", + "applyConfirmDescription": "Deur \"{{name}}\" toe te pas, sal jou huidige oortjies toegemaak word en vervang word met hierdie werkspasie se gestoorde rangskikking. Ongestoorde veranderinge aan jou huidige uitleg sal verlore gaan.", + "applyConfirmButton": "Pas Werkruimte toe", + "updateWithCurrent": "Opdateer met Huidige", + "updateWithCurrentConfirm": "Oorskryf \"{{name}}\" met jou huidige tabbladrangskikking?", + "rename": "Hernoem", + "duplicate": "Duplikaat", + "duplicateNameSuffix": "{{name}} (kopieer)", + "setDefault": "Stel as verstek", + "unsetDefault": "Verwyder as verstek", + "defaultBadge": "Standaard", + "lastSession": "Laaste Sessie", + "lastSessionDescription": "Outomaties opgedateer met jou mees onlangse oortjie-rangskikking. Pas dit toe om te herstel wat jy oop gehad het.", + "lastUsed": "Laas gebruik {{time}}", + "neverUsed": "Nooit toegepas nie", + "tabsSkipped": "Werkruimte toegepas — {{count}} oortjie(s) oorgeslaan (gasheer bestaan nie meer nie): {{names}}" + } + } + }, + "nav": { + "workspaces": "Werkruimtes" + }, + "onboarding": { + "workflow_workspaces": "Werkruimtes", + "workflow_workspaces_desc": "Stoor 'n stel oop oortjies en heropen die hele uitleg later." + } +} diff --git a/plugins/workspaces/locales/translated/ar_SA.json b/plugins/workspaces/locales/translated/ar_SA.json new file mode 100644 index 000000000..c6a8a5117 --- /dev/null +++ b/plugins/workspaces/locales/translated/ar_SA.json @@ -0,0 +1,55 @@ +{ + "newUi": { + "sidebar": { + "workspaces": { + "title": "مساحات العمل", + "saveCurrent": "حفظ الوضع الحالي", + "saveCurrentTitle": "حفظ مساحة العمل الحالية", + "saveCurrentDescription": "احفظ كل علامة تبويب مفتوحة، وتخطيط مقسم، وترتيب أجزاء كمساحة عمل جديدة مسماة.", + "nameLabel": "اسم", + "namePlaceholder": "مثال: تصحيح أخطاء الإنتاج", + "nameRequired": "اسم مساحة العمل مطلوب", + "colorLabel": "لون", + "workspaceCreated": "تم حفظ مساحة العمل", + "workspaceUpdated": "تم تحديث مساحة العمل", + "workspaceDeleted": "تم حذف مساحة العمل", + "workspaceDuplicated": "تم تكرار مساحة العمل", + "saveFailed": "فشل حفظ مساحة العمل", + "updateFailed": "فشل تحديث مساحة العمل", + "deleteFailed": "فشل حذف مساحة العمل", + "duplicateFailed": "فشل تكرار مساحة العمل", + "loadFailed": "فشل تحميل مساحات العمل", + "applyFailed": "فشل تطبيق مساحة العمل", + "deleteWorkspaceTitle": "حذف مساحة العمل", + "deleteWorkspaceDescription": "هل أنت متأكد من رغبتك في حذف \"{{name}}\"؟ لا يمكن التراجع عن هذا.", + "noWorkspaces": "لم يتم حفظ أي مساحات عمل حتى الآن. احفظ ترتيب علامات التبويب الحالي للبدء.", + "tabCount": "{{count}} علامة تبويب", + "tabCount_other": "علامات تبويب {{count}}", + "apply": "يتقدم", + "applyConfirmTitle": "تطبيق مساحة العمل", + "applyConfirmDescription": "سيؤدي تطبيق \"{{name}}\" إلى إغلاق علامات التبويب الحالية واستبدالها بالترتيب المحفوظ لمساحة العمل هذه. ستفقد التغييرات غير المحفوظة على تخطيطك الحالي.", + "applyConfirmButton": "تطبيق مساحة العمل", + "updateWithCurrent": "تحديث بالبيانات الحالية", + "updateWithCurrentConfirm": "هل تريد استبدال \"{{name}}\" بترتيب علامات التبويب الحالي؟", + "rename": "إعادة تسمية", + "duplicate": "ينسخ", + "duplicateNameSuffix": "{{name}} (نسخة)", + "setDefault": "تعيين كافتراضي", + "unsetDefault": "إزالة كإعداد افتراضي", + "defaultBadge": "تقصير", + "lastSession": "الجلسة الأخيرة", + "lastSessionDescription": "يتم تحديثها تلقائيًا بأحدث ترتيب لعلامات التبويب لديك. قم بتطبيقها لاستعادة ما كنت قد فتحته.", + "lastUsed": "آخر استخدام {{time}}", + "neverUsed": "لم يتم التقديم مطلقا", + "tabsSkipped": "تم تطبيق مساحة العمل — تم تخطي علامة (علامات) التبويب {{count}} (لم يعد المضيف موجودًا): {{names}}" + } + } + }, + "nav": { + "workspaces": "مساحات العمل" + }, + "onboarding": { + "workflow_workspaces": "مساحات العمل", + "workflow_workspaces_desc": "احفظ مجموعة من علامات التبويب المفتوحة وأعد فتح التخطيط بأكمله لاحقًا." + } +} diff --git a/plugins/workspaces/locales/translated/bg_BG.json b/plugins/workspaces/locales/translated/bg_BG.json new file mode 100644 index 000000000..e63caaebc --- /dev/null +++ b/plugins/workspaces/locales/translated/bg_BG.json @@ -0,0 +1,55 @@ +{ + "newUi": { + "sidebar": { + "workspaces": { + "title": "Работни пространства", + "saveCurrent": "Запазване на текущото", + "saveCurrentTitle": "Запазване на текущото работно пространство", + "saveCurrentDescription": "Запазете всеки отворен раздел, разделено оформление и подредба на панели като ново именувано работно пространство.", + "nameLabel": "Име", + "namePlaceholder": "напр. Отстраняване на грешки в продукта", + "nameRequired": "Името на работното пространство е задължително", + "colorLabel": "Цвят", + "workspaceCreated": "Работното пространство е запазено", + "workspaceUpdated": "Работното пространство е актуализирано", + "workspaceDeleted": "Работното пространство е изтрито", + "workspaceDuplicated": "Работното пространство е дублирано", + "saveFailed": "Запазването на работното пространство не бе успешно", + "updateFailed": "Актуализирането на работното пространство не бе успешно", + "deleteFailed": "Изтриването на работното пространство не бе успешно", + "duplicateFailed": "Дублирането на работното пространство не бе успешно", + "loadFailed": "Зареждането на работните пространства не бе успешно", + "applyFailed": "Прилагането на работното пространство не бе успешно", + "deleteWorkspaceTitle": "Изтриване на работно пространство", + "deleteWorkspaceDescription": "Сигурни ли сте, че искате да изтриете „{{name}}“? Това не може да бъде отменено.", + "noWorkspaces": "Все още няма запазени работни пространства. Запазете текущото си разположение на раздели, за да започнете.", + "tabCount": "раздел {{count}}", + "tabCount_other": "{{count}} раздели", + "apply": "Приложи", + "applyConfirmTitle": "Прилагане на работно пространство", + "applyConfirmDescription": "Прилагането на „{{name}}“ ще затвори текущите ви раздели и ще ги замени със запазената подредба на това работно пространство. Незапазените промени в текущото ви оформление ще бъдат загубени.", + "applyConfirmButton": "Прилагане на работно пространство", + "updateWithCurrent": "Актуализиране с текущото", + "updateWithCurrentConfirm": "Да се презапише ли „{{name}}“ с текущата ви подредба на табулации?", + "rename": "Преименуване", + "duplicate": "Дубликат", + "duplicateNameSuffix": "{{name}} (копие)", + "setDefault": "Задай по подразбиране", + "unsetDefault": "Премахване по подразбиране", + "defaultBadge": "По подразбиране", + "lastSession": "Последна сесия", + "lastSessionDescription": "Автоматично се актуализира с най-скорошната ви подредба на раздели. Приложете я, за да възстановите това, което сте имали отворено.", + "lastUsed": "Последно използвано {{time}}", + "neverUsed": "Никога не е прилагано", + "tabsSkipped": "Приложено е работно пространство — {{count}} пропуснати раздели (хостът вече не съществува): {{names}}" + } + } + }, + "nav": { + "workspaces": "Работни пространства" + }, + "onboarding": { + "workflow_workspaces": "Работни пространства", + "workflow_workspaces_desc": "Запазете набор от отворени раздели и отворете отново цялото оформление по-късно." + } +} diff --git a/plugins/workspaces/locales/translated/bn_BD.json b/plugins/workspaces/locales/translated/bn_BD.json new file mode 100644 index 000000000..b9098554d --- /dev/null +++ b/plugins/workspaces/locales/translated/bn_BD.json @@ -0,0 +1,55 @@ +{ + "newUi": { + "sidebar": { + "workspaces": { + "title": "কর্মক্ষেত্র", + "saveCurrent": "বর্তমান সংরক্ষণ করুন", + "saveCurrentTitle": "বর্তমান ওয়ার্কস্পেস সংরক্ষণ করুন", + "saveCurrentDescription": "প্রতিটি খোলা ট্যাব, স্প্লিট লেআউট এবং পেন বিন্যাসকে একটি নতুন নামযুক্ত ওয়ার্কস্পেস হিসেবে সংরক্ষণ করুন।", + "nameLabel": "নাম", + "namePlaceholder": "যেমন, প্রোডাকশন ডিবাগিং", + "nameRequired": "ওয়ার্কস্পেসের নাম আবশ্যক।", + "colorLabel": "রঙ", + "workspaceCreated": "ওয়ার্কস্পেস সংরক্ষিত", + "workspaceUpdated": "ওয়ার্কস্পেস আপডেট করা হয়েছে", + "workspaceDeleted": "ওয়ার্কস্পেস মুছে ফেলা হয়েছে", + "workspaceDuplicated": "ওয়ার্কস্পেস নকল করা হয়েছে", + "saveFailed": "ওয়ার্কস্পেস সংরক্ষণ করতে ব্যর্থ হয়েছে", + "updateFailed": "ওয়ার্কস্পেস আপডেট করতে ব্যর্থ হয়েছে", + "deleteFailed": "ওয়ার্কস্পেস মুছে ফেলা ব্যর্থ হয়েছে", + "duplicateFailed": "ওয়ার্কস্পেস নকল করতে ব্যর্থ হয়েছে", + "loadFailed": "ওয়ার্কস্পেস লোড করতে ব্যর্থ হয়েছে", + "applyFailed": "ওয়ার্কস্পেস প্রয়োগ করতে ব্যর্থ হয়েছে", + "deleteWorkspaceTitle": "ওয়ার্কস্পেস মুছুন", + "deleteWorkspaceDescription": "আপনি কি \"{{name}}\" মুছে ফেলতে নিশ্চিত? এটি আর পূর্বাবস্থায় ফেরানো যাবে না।", + "noWorkspaces": "এখনো কোনো ওয়ার্কস্পেস সেভ করা হয়নি। কাজ শুরু করার জন্য আপনার বর্তমান ট্যাব বিন্যাসটি সেভ করুন।", + "tabCount": "{{count}} ট্যাব", + "tabCount_other": "{{count}} ট্যাব", + "apply": "আবেদন করুন", + "applyConfirmTitle": "ওয়ার্কস্পেস প্রয়োগ করুন", + "applyConfirmDescription": "\"{{name}}\" প্রয়োগ করলে আপনার বর্তমান ট্যাবগুলি বন্ধ হয়ে যাবে এবং সেগুলির পরিবর্তে এই ওয়ার্কস্পেসের সংরক্ষিত বিন্যাসটি প্রদর্শিত হবে। আপনার বর্তমান লেআউটে করা অসংরক্ষিত পরিবর্তনগুলি হারিয়ে যাবে।", + "applyConfirmButton": "ওয়ার্কস্পেস প্রয়োগ করুন", + "updateWithCurrent": "বর্তমান তথ্য দিয়ে আপডেট করুন", + "updateWithCurrentConfirm": "আপনার বর্তমান ট্যাব বিন্যাস দিয়ে \"{{name}}\" ওভাররাইট করবেন?", + "rename": "পুনঃনামকরণ", + "duplicate": "নকল", + "duplicateNameSuffix": "{{name}} (অনুলিপি)", + "setDefault": "ডিফল্ট হিসাবে সেট করা হয়েছে", + "unsetDefault": "ডিফল্ট হিসেবে অপসারণ করুন", + "defaultBadge": "ডিফল্ট", + "lastSession": "শেষ অধিবেশন", + "lastSessionDescription": "আপনার সর্বশেষ ট্যাব বিন্যাস অনুযায়ী স্বয়ংক্রিয়ভাবে আপডেট হয়। আপনার খোলা ট্যাবগুলো পুনরুদ্ধার করতে এটি প্রয়োগ করুন।", + "lastUsed": "সর্বশেষ ব্যবহৃত {{time}}", + "neverUsed": "কখনো প্রয়োগ করা হয়নি", + "tabsSkipped": "ওয়ার্কস্পেস প্রয়োগ করা হয়েছে — {{count}} টি ট্যাব বাদ দেওয়া হয়েছে (হোস্টটি আর বিদ্যমান নেই): {{names}}" + } + } + }, + "nav": { + "workspaces": "কর্মক্ষেত্র" + }, + "onboarding": { + "workflow_workspaces": "কর্মক্ষেত্র", + "workflow_workspaces_desc": "খোলা ট্যাবগুলো সংরক্ষণ করুন এবং পরে সম্পূর্ণ লেআউটটি আবার খুলুন।" + } +} diff --git a/plugins/workspaces/locales/translated/ca_ES.json b/plugins/workspaces/locales/translated/ca_ES.json new file mode 100644 index 000000000..e9be76f0c --- /dev/null +++ b/plugins/workspaces/locales/translated/ca_ES.json @@ -0,0 +1,55 @@ +{ + "newUi": { + "sidebar": { + "workspaces": { + "title": "Espais de treball", + "saveCurrent": "Desa l'actual", + "saveCurrentTitle": "Desa l'espai de treball actual", + "saveCurrentDescription": "Desa totes les pestanyes obertes, dissenys dividits i disposicions de panells com un espai de treball amb un nom nou.", + "nameLabel": "Nom", + "namePlaceholder": "p. ex., depuració de productes", + "nameRequired": "El nom de l'espai de treball és obligatori", + "colorLabel": "Color", + "workspaceCreated": "L'espai de treball s'ha desat", + "workspaceUpdated": "Espai de treball actualitzat", + "workspaceDeleted": "L'espai de treball s'ha suprimit", + "workspaceDuplicated": "Espai de treball duplicat", + "saveFailed": "No s'ha pogut desar l'espai de treball", + "updateFailed": "No s'ha pogut actualitzar l'espai de treball", + "deleteFailed": "No s'ha pogut suprimir l'espai de treball", + "duplicateFailed": "No s'ha pogut duplicar l'espai de treball", + "loadFailed": "No s'han pogut carregar els espais de treball", + "applyFailed": "No s'ha pogut aplicar l'espai de treball", + "deleteWorkspaceTitle": "Suprimeix l'espai de treball", + "deleteWorkspaceDescription": "Esteu segur que voleu suprimir \"{{name}}\"? Això no es pot desfer.", + "noWorkspaces": "Encara no hi ha espais de treball desats. Deseu la disposició actual de les pestanyes per començar.", + "tabCount": "Pestanya {{count}}", + "tabCount_other": "pestanyes {{count}}", + "apply": "Aplica", + "applyConfirmTitle": "Aplica l'espai de treball", + "applyConfirmDescription": "Si apliqueu \"{{name}}\", es tancaran les pestanyes actuals i les substituiran per la disposició desada d'aquest espai de treball. Els canvis no desats al disseny actual es perdran.", + "applyConfirmButton": "Aplica l'espai de treball", + "updateWithCurrent": "Actualitza amb l'actual", + "updateWithCurrentConfirm": "Voleu sobreescriure \"{{name}}\" amb la disposició actual de les pestanyes?", + "rename": "Canvia el nom", + "duplicate": "Duplicat", + "duplicateNameSuffix": "{{name}} (còpia)", + "setDefault": "Estableix com a predeterminat", + "unsetDefault": "Elimina com a predeterminat", + "defaultBadge": "Per defecte", + "lastSession": "Última sessió", + "lastSessionDescription": "Actualitzat automàticament amb la disposició de pestanyes més recent. Aplica-ho per recuperar el que tenies obert.", + "lastUsed": "Últim ús {{time}}", + "neverUsed": "Mai aplicat", + "tabsSkipped": "Espai de treball aplicat — {{count}} pestanyes omeses (l'amfitrió ja no existeix): {{names}}" + } + } + }, + "nav": { + "workspaces": "Espais de treball" + }, + "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." + } +} diff --git a/plugins/workspaces/locales/translated/cs_CZ.json b/plugins/workspaces/locales/translated/cs_CZ.json new file mode 100644 index 000000000..bf8e6f90b --- /dev/null +++ b/plugins/workspaces/locales/translated/cs_CZ.json @@ -0,0 +1,55 @@ +{ + "newUi": { + "sidebar": { + "workspaces": { + "title": "Pracovní prostory", + "saveCurrent": "Uložit aktuální", + "saveCurrentTitle": "Uložit aktuální pracovní prostor", + "saveCurrentDescription": "Uložte každou otevřenou kartu, rozdělené rozvržení a uspořádání panelů jako nový pojmenovaný pracovní prostor.", + "nameLabel": "Jméno", + "namePlaceholder": "např. ladění produktu", + "nameRequired": "Název pracovního prostoru je povinný", + "colorLabel": "Barva", + "workspaceCreated": "Pracovní prostor uložen", + "workspaceUpdated": "Pracovní prostor aktualizován", + "workspaceDeleted": "Pracovní prostor smazán", + "workspaceDuplicated": "Pracovní prostor byl duplikován", + "saveFailed": "Uložení pracovního prostoru se nezdařilo", + "updateFailed": "Aktualizace pracovního prostoru se nezdařilo", + "deleteFailed": "Nepodařilo se smazat pracovní prostor", + "duplicateFailed": "Nepodařilo se duplikovat pracovní prostor", + "loadFailed": "Nepodařilo se načíst pracovní prostory", + "applyFailed": "Použití pracovního prostoru se nezdařilo", + "deleteWorkspaceTitle": "Smazat pracovní prostor", + "deleteWorkspaceDescription": "Opravdu chcete smazat „{{name}}“? Tuto akci nelze vrátit zpět.", + "noWorkspaces": "Zatím nejsou uložené žádné pracovní prostory. Chcete-li začít, uložte si aktuální uspořádání karet.", + "tabCount": "{{count}} záložka", + "tabCount_other": "{{count}} záložek", + "apply": "Použít", + "applyConfirmTitle": "Použít pracovní prostor", + "applyConfirmDescription": "Použitím „{{name}}“ zavřete aktuální karty a nahradí je uloženým uspořádáním tohoto pracovního prostoru. Neuložené změny aktuálního rozvržení budou ztraceny.", + "applyConfirmButton": "Použít pracovní prostor", + "updateWithCurrent": "Aktualizovat s aktuálním", + "updateWithCurrentConfirm": "Přepsat „{{name}}“ aktuálním uspořádáním tabulací?", + "rename": "Přejmenovat", + "duplicate": "Duplikát", + "duplicateNameSuffix": "{{name}} (kopie)", + "setDefault": "Nastavit jako výchozí", + "unsetDefault": "Odebrat jako výchozí", + "defaultBadge": "Výchozí", + "lastSession": "Poslední sezení", + "lastSessionDescription": "Automaticky aktualizováno s vaším posledním uspořádáním karet. Použijte tuto funkci k obnovení toho, co jste měli otevřené.", + "lastUsed": "Naposledy použité {{time}}", + "neverUsed": "Nikdy nepoužíváno", + "tabsSkipped": "Použitý pracovní prostor — {{count}} přeskočeno (hostitel již neexistuje): {{names}}" + } + } + }, + "nav": { + "workspaces": "Pracovní prostory" + }, + "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." + } +} diff --git a/plugins/workspaces/locales/translated/da_DK.json b/plugins/workspaces/locales/translated/da_DK.json new file mode 100644 index 000000000..71548bca0 --- /dev/null +++ b/plugins/workspaces/locales/translated/da_DK.json @@ -0,0 +1,55 @@ +{ + "newUi": { + "sidebar": { + "workspaces": { + "title": "Arbejdsområder", + "saveCurrent": "Gem nuværende", + "saveCurrentTitle": "Gem nuværende arbejdsområde", + "saveCurrentDescription": "Gem alle åbne faner, opdelte layouts og rudearrangementer som et nyt navngivet arbejdsområde.", + "nameLabel": "Navn", + "namePlaceholder": "f.eks. produktfejlfinding", + "nameRequired": "Arbejdsområdenavn er påkrævet", + "colorLabel": "Farve", + "workspaceCreated": "Arbejdsområdet er gemt", + "workspaceUpdated": "Arbejdsområdet er opdateret", + "workspaceDeleted": "Arbejdsområdet er slettet", + "workspaceDuplicated": "Arbejdsområdet er duplikeret", + "saveFailed": "Kunne ikke gemme arbejdsområdet", + "updateFailed": "Kunne ikke opdatere arbejdsområdet", + "deleteFailed": "Kunne ikke slette arbejdsområdet", + "duplicateFailed": "Kunne ikke duplikere arbejdsområdet", + "loadFailed": "Kunne ikke indlæse arbejdsområder", + "applyFailed": "Kunne ikke anvende arbejdsområdet", + "deleteWorkspaceTitle": "Slet arbejdsområde", + "deleteWorkspaceDescription": "Er du sikker på, at du vil slette \"{{name}}\"? Dette kan ikke fortrydes.", + "noWorkspaces": "Ingen gemte arbejdsområder endnu. Gem din nuværende faneopstilling for at komme i gang.", + "tabCount": "{{count}} faneblad", + "tabCount_other": "{{count}} faner", + "apply": "Anvende", + "applyConfirmTitle": "Anvend arbejdsområde", + "applyConfirmDescription": "Hvis du anvender \"{{name}}\", lukkes dine nuværende faner og erstattes med dette arbejdsområdes gemte arrangement. Ændringer af dit nuværende layout, der ikke er gemt, vil gå tabt.", + "applyConfirmButton": "Anvend arbejdsområde", + "updateWithCurrent": "Opdater med aktuel", + "updateWithCurrentConfirm": "Vil du overskrive \"{{name}}\" med din nuværende tabulatoropstilling?", + "rename": "Omdøb", + "duplicate": "Duplikere", + "duplicateNameSuffix": "{{name}} (kopi)", + "setDefault": "Angiv som standard", + "unsetDefault": "Fjern som standard", + "defaultBadge": "Misligholdelse", + "lastSession": "Sidste session", + "lastSessionDescription": "Opdateres automatisk med din seneste faneopsætning. Anvend den til at gendanne det, du havde åbent.", + "lastUsed": "Sidst brugt {{time}}", + "neverUsed": "Aldrig anvendt", + "tabsSkipped": "Arbejdsområde anvendt — {{count}} faneblad(er) sprunget over (værten findes ikke længere): {{names}}" + } + } + }, + "nav": { + "workspaces": "Arbejdsområder" + }, + "onboarding": { + "workflow_workspaces": "Arbejdsområder", + "workflow_workspaces_desc": "Gem et sæt åbne faner, og åbn hele layoutet igen senere." + } +} diff --git a/plugins/workspaces/locales/translated/de_DE.json b/plugins/workspaces/locales/translated/de_DE.json new file mode 100644 index 000000000..3ac95b444 --- /dev/null +++ b/plugins/workspaces/locales/translated/de_DE.json @@ -0,0 +1,55 @@ +{ + "newUi": { + "sidebar": { + "workspaces": { + "title": "Arbeitsbereiche", + "saveCurrent": "Aktuellen Stand speichern", + "saveCurrentTitle": "Aktuellen Arbeitsbereich speichern", + "saveCurrentDescription": "Alle geöffneten Tabs, geteilten Layouts und Fensteranordnungen werden als neuer, benannter Arbeitsbereich gespeichert.", + "nameLabel": "Name", + "namePlaceholder": "z. B. Produktions-Debugging", + "nameRequired": "Die Angabe eines Arbeitsbereichsnamens ist erforderlich.", + "colorLabel": "Farbe", + "workspaceCreated": "Arbeitsbereich gespeichert", + "workspaceUpdated": "Arbeitsbereich aktualisiert", + "workspaceDeleted": "Arbeitsbereich gelöscht", + "workspaceDuplicated": "Arbeitsbereich dupliziert", + "saveFailed": "Arbeitsbereich konnte nicht gespeichert werden", + "updateFailed": "Aktualisierung des Arbeitsbereichs fehlgeschlagen", + "deleteFailed": "Arbeitsbereich konnte nicht gelöscht werden", + "duplicateFailed": "Arbeitsbereich konnte nicht dupliziert werden", + "loadFailed": "Arbeitsbereiche konnten nicht geladen werden", + "applyFailed": "Arbeitsbereich konnte nicht angewendet werden", + "deleteWorkspaceTitle": "Arbeitsbereich löschen", + "deleteWorkspaceDescription": "Möchten Sie \"{{name}}\" wirklich löschen? Dies kann nicht rückgängig gemacht werden.", + "noWorkspaces": "Es sind noch keine Arbeitsbereiche gespeichert. Speichern Sie Ihre aktuelle Tab-Anordnung, um loszulegen.", + "tabCount": "{{count}} Tab", + "tabCount_other": "{{count}} Tabs", + "apply": "Anwenden", + "applyConfirmTitle": "Arbeitsbereich anwenden", + "applyConfirmDescription": "Durch Anwenden von \"{{name}}\" werden Ihre aktuellen Tabs geschlossen und durch die gespeicherte Anordnung dieses Arbeitsbereichs ersetzt. Nicht gespeicherte Änderungen an Ihrem aktuellen Layout gehen dabei verloren.", + "applyConfirmButton": "Arbeitsbereich anwenden", + "updateWithCurrent": "Aktualisierung mit aktuellem Stand", + "updateWithCurrentConfirm": "Soll \"{{name}}\" mit Ihrer aktuellen Tab-Anordnung überschrieben werden?", + "rename": "Umbenennen", + "duplicate": "Duplikat", + "duplicateNameSuffix": "{{name}} (Kopie)", + "setDefault": "Als Standard festlegen", + "unsetDefault": "Als Standard entfernen", + "defaultBadge": "Standard", + "lastSession": "Letzte Sitzung", + "lastSessionDescription": "Die Tab-Anordnung wird automatisch aktualisiert. Wenden Sie sie an, um Ihre geöffneten Tabs wiederherzustellen.", + "lastUsed": "Zuletzt verwendet {{time}}", + "neverUsed": "Nie angewendet", + "tabsSkipped": "Arbeitsbereich angewendet — {{count}} Registerkarte(n) übersprungen (Host existiert nicht mehr): {{names}}" + } + } + }, + "nav": { + "workspaces": "Arbeitsbereiche" + }, + "onboarding": { + "workflow_workspaces": "Arbeitsbereiche", + "workflow_workspaces_desc": "Speichern Sie einen Satz geöffneter Tabs und öffnen Sie das gesamte Layout später wieder." + } +} diff --git a/plugins/workspaces/locales/translated/el_GR.json b/plugins/workspaces/locales/translated/el_GR.json new file mode 100644 index 000000000..daa108b14 --- /dev/null +++ b/plugins/workspaces/locales/translated/el_GR.json @@ -0,0 +1,55 @@ +{ + "newUi": { + "sidebar": { + "workspaces": { + "title": "Χώροι εργασίας", + "saveCurrent": "Αποθήκευση τρέχοντος", + "saveCurrentTitle": "Αποθήκευση τρέχοντος χώρου εργασίας", + "saveCurrentDescription": "Αποθηκεύστε κάθε ανοιχτή καρτέλα, διαιρεμένη διάταξη και διάταξη παραθύρου ως νέο ονομασμένο χώρο εργασίας.", + "nameLabel": "Ονομα", + "namePlaceholder": "π.χ., εντοπισμός σφαλμάτων προϊόντος", + "nameRequired": "Απαιτείται όνομα χώρου εργασίας", + "colorLabel": "Χρώμα", + "workspaceCreated": "Ο χώρος εργασίας αποθηκεύτηκε", + "workspaceUpdated": "Ο χώρος εργασίας ενημερώθηκε", + "workspaceDeleted": "Ο χώρος εργασίας διαγράφηκε", + "workspaceDuplicated": "Ο χώρος εργασίας αντιγράφηκε", + "saveFailed": "Αποτυχία αποθήκευσης χώρου εργασίας", + "updateFailed": "Η ενημέρωση του χώρου εργασίας απέτυχε", + "deleteFailed": "Η διαγραφή του χώρου εργασίας απέτυχε", + "duplicateFailed": "Αποτυχία αντιγραφής χώρου εργασίας", + "loadFailed": "Αποτυχία φόρτωσης χώρων εργασίας", + "applyFailed": "Αποτυχία εφαρμογής χώρου εργασίας", + "deleteWorkspaceTitle": "Διαγραφή χώρου εργασίας", + "deleteWorkspaceDescription": "Είστε σίγουροι ότι θέλετε να διαγράψετε το \"{{name}}\"; Αυτή η ενέργεια δεν μπορεί να αναιρεθεί.", + "noWorkspaces": "Δεν υπάρχουν ακόμη αποθηκευμένοι χώροι εργασίας. Αποθηκεύστε την τρέχουσα διάταξη καρτελών για να ξεκινήσετε.", + "tabCount": "{{count}} καρτέλα", + "tabCount_other": "{{count}} καρτέλες", + "apply": "Εφαρμόζω", + "applyConfirmTitle": "Εφαρμογή χώρου εργασίας", + "applyConfirmDescription": "Η εφαρμογή της συνάρτησης \"{{name}}\" θα κλείσει τις τρέχουσες καρτέλες σας και θα τις αντικαταστήσει με την αποθηκευμένη διάταξη αυτού του χώρου εργασίας. Οι μη αποθηκευμένες αλλαγές στην τρέχουσα διάταξή σας θα χαθούν.", + "applyConfirmButton": "Εφαρμογή χώρου εργασίας", + "updateWithCurrent": "Ενημέρωση με το Τρέχον", + "updateWithCurrentConfirm": "Αντικατάσταση του \"{{name}}\" με την τρέχουσα διάταξη στηλοθετών;", + "rename": "Μετονομάζω", + "duplicate": "Αντίγραφο", + "duplicateNameSuffix": "{{name}} (αντίγραφο)", + "setDefault": "Ορισμός ως προεπιλογή", + "unsetDefault": "Κατάργηση ως προεπιλογή", + "defaultBadge": "Αθέτηση", + "lastSession": "Τελευταία συνεδρία", + "lastSessionDescription": "Ενημερώνεται αυτόματα με την πιο πρόσφατη διάταξη καρτελών. Εφαρμόστε την για να ανακτήσετε ό,τι είχατε ανοιχτό.", + "lastUsed": "Τελευταία χρήση {{time}}", + "neverUsed": "Δεν εφαρμόστηκε ποτέ", + "tabsSkipped": "Εφαρμόστηκε χώρος εργασίας — {{count}} καρτέλα(ες) παραλείφθηκε(οι υποδοχείς δεν υπάρχουν πλέον): {{names}}" + } + } + }, + "nav": { + "workspaces": "Χώροι εργασίας" + }, + "onboarding": { + "workflow_workspaces": "Χώροι εργασίας", + "workflow_workspaces_desc": "Αποθηκεύστε ένα σύνολο ανοιχτών καρτελών και ανοίξτε ξανά ολόκληρη τη διάταξη αργότερα." + } +} diff --git a/plugins/workspaces/locales/translated/es_ES.json b/plugins/workspaces/locales/translated/es_ES.json new file mode 100644 index 000000000..8952a6444 --- /dev/null +++ b/plugins/workspaces/locales/translated/es_ES.json @@ -0,0 +1,55 @@ +{ + "newUi": { + "sidebar": { + "workspaces": { + "title": "Espacios de trabajo", + "saveCurrent": "Guardar actual", + "saveCurrentTitle": "Guardar espacio de trabajo actual", + "saveCurrentDescription": "Guarda cada pestaña abierta, diseño dividido y disposición de paneles como un nuevo espacio de trabajo con nombre.", + "nameLabel": "Nombre", + "namePlaceholder": "p. ej., depuración de producción", + "nameRequired": "Se requiere el nombre del espacio de trabajo.", + "colorLabel": "Color", + "workspaceCreated": "Espacio de trabajo guardado", + "workspaceUpdated": "Espacio de trabajo actualizado", + "workspaceDeleted": "Espacio de trabajo eliminado", + "workspaceDuplicated": "Espacio de trabajo duplicado", + "saveFailed": "No se pudo guardar el espacio de trabajo", + "updateFailed": "No se pudo actualizar el espacio de trabajo", + "deleteFailed": "No se pudo eliminar el espacio de trabajo", + "duplicateFailed": "Error al duplicar el espacio de trabajo", + "loadFailed": "No se pudieron cargar los espacios de trabajo.", + "applyFailed": "No se pudo aplicar el espacio de trabajo", + "deleteWorkspaceTitle": "Eliminar espacio de trabajo", + "deleteWorkspaceDescription": "¿Estás seguro de que quieres eliminar \"{{name}}\"? Esto no se puede deshacer.", + "noWorkspaces": "Aún no hay espacios de trabajo guardados. Guarda la disposición actual de tus pestañas para empezar.", + "tabCount": "{{count}} pestaña", + "tabCount_other": "{{count}} pestañas", + "apply": "Aplicar", + "applyConfirmTitle": "Aplicar espacio de trabajo", + "applyConfirmDescription": "Al aplicar \"{{name}}\" se cerrarán las pestañas actuales y se reemplazarán con la disposición guardada de este espacio de trabajo. Los cambios no guardados en la disposición actual se perderán.", + "applyConfirmButton": "Aplicar espacio de trabajo", + "updateWithCurrent": "Actualizar con la versión actual", + "updateWithCurrentConfirm": "¿Sobrescribir \"{{name}}\" con tu disposición de tabulación actual?", + "rename": "Rebautizar", + "duplicate": "Duplicado", + "duplicateNameSuffix": "{{name}} (copiar)", + "setDefault": "Establecer como predeterminado", + "unsetDefault": "Eliminar como predeterminado", + "defaultBadge": "Por defecto", + "lastSession": "Última sesión", + "lastSessionDescription": "Se actualiza automáticamente con la última configuración de pestañas. Aplícala para recuperar lo que tenías abierto.", + "lastUsed": "Último uso {{time}}", + "neverUsed": "Nunca se ha aplicado", + "tabsSkipped": "Espacio de trabajo aplicado: {{count}} pestaña(s) omitida(s) (el host ya no existe): {{names}}" + } + } + }, + "nav": { + "workspaces": "Espacios de trabajo" + }, + "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." + } +} diff --git a/plugins/workspaces/locales/translated/fi_FI.json b/plugins/workspaces/locales/translated/fi_FI.json new file mode 100644 index 000000000..018c49297 --- /dev/null +++ b/plugins/workspaces/locales/translated/fi_FI.json @@ -0,0 +1,55 @@ +{ + "newUi": { + "sidebar": { + "workspaces": { + "title": "Työtilat", + "saveCurrent": "Tallenna nykyinen", + "saveCurrentTitle": "Tallenna nykyinen työtila", + "saveCurrentDescription": "Tallenna jokainen avoin välilehti, jaettu asettelu ja ruutujärjestely uutena nimettynä työtilana.", + "nameLabel": "Nimi", + "namePlaceholder": "esim. Tuotantovirheenkorjaus", + "nameRequired": "Työtilan nimi on pakollinen", + "colorLabel": "Väri", + "workspaceCreated": "Työtila tallennettu", + "workspaceUpdated": "Työtila päivitetty", + "workspaceDeleted": "Työtila poistettu", + "workspaceDuplicated": "Työtila kopioitu", + "saveFailed": "Työtilan tallentaminen epäonnistui", + "updateFailed": "Työtilan päivittäminen epäonnistui", + "deleteFailed": "Työtilan poistaminen epäonnistui", + "duplicateFailed": "Työtilan kopiointi epäonnistui", + "loadFailed": "Työtilojen lataaminen epäonnistui", + "applyFailed": "Työtilan käyttöönotto epäonnistui", + "deleteWorkspaceTitle": "Poista työtila", + "deleteWorkspaceDescription": "Oletko varma, että haluat poistaa \"{{name}}\"? Tätä ei voi perua.", + "noWorkspaces": "Ei vielä tallennettuja työtiloja. Tallenna nykyinen välilehtijärjestys aloittaaksesi.", + "tabCount": "{{count}} -välilehti", + "tabCount_other": "{{count}} välilehdet", + "apply": "Käytä", + "applyConfirmTitle": "Käytä työtilaa", + "applyConfirmDescription": "Komentosarjan \"{{name}}\" käyttäminen sulkee nykyiset välilehdet ja korvaa ne tämän työtilan tallennetulla asettelulla. Nykyiseen asetteluun tehdyt tallentamattomat muutokset menetetään.", + "applyConfirmButton": "Käytä työtilaa", + "updateWithCurrent": "Päivitä nykyisellä", + "updateWithCurrentConfirm": "Korvataanko \"{{name}}\" nykyisellä sarkainjärjestykselläsi?", + "rename": "Nimeä uudelleen", + "duplicate": "Kopio", + "duplicateNameSuffix": "{{name}} (kopio)", + "setDefault": "Aseta oletukseksi", + "unsetDefault": "Poista oletusarvoksi", + "defaultBadge": "Oletus", + "lastSession": "Viimeisin istunto", + "lastSessionDescription": "Päivittyy automaattisesti viimeisimmän välilehtijärjestyksen mukaan. Käytä sitä palauttaaksesi avoimena olleen sisällön.", + "lastUsed": "Viimeksi käytetty {{time}}", + "neverUsed": "Ei koskaan sovellettu", + "tabsSkipped": "Työtilaa käytetty — {{count}} välilehteä ohitettu (isäntä ei enää ole olemassa): {{names}}" + } + } + }, + "nav": { + "workspaces": "Työtilat" + }, + "onboarding": { + "workflow_workspaces": "Työtilat", + "workflow_workspaces_desc": "Tallenna joukko avoimia välilehtiä ja avaa koko asettelu uudelleen myöhemmin." + } +} diff --git a/plugins/workspaces/locales/translated/fr_FR.json b/plugins/workspaces/locales/translated/fr_FR.json new file mode 100644 index 000000000..6eab9558a --- /dev/null +++ b/plugins/workspaces/locales/translated/fr_FR.json @@ -0,0 +1,55 @@ +{ + "newUi": { + "sidebar": { + "workspaces": { + "title": "Espaces de travail", + "saveCurrent": "Économisez le courant", + "saveCurrentTitle": "Enregistrer l'espace de travail actuel", + "saveCurrentDescription": "Enregistrez chaque onglet ouvert, chaque disposition fractionnée et chaque agencement de volets comme un nouvel espace de travail nommé.", + "nameLabel": "Nom", + "namePlaceholder": "par exemple, le débogage en production", + "nameRequired": "Le nom de l'espace de travail est requis.", + "colorLabel": "Couleur", + "workspaceCreated": "Espace de travail enregistré", + "workspaceUpdated": "Espace de travail mis à jour", + "workspaceDeleted": "Espace de travail supprimé", + "workspaceDuplicated": "Espace de travail dupliqué", + "saveFailed": "Impossible d'enregistrer l'espace de travail", + "updateFailed": "Échec de la mise à jour de l'espace de travail", + "deleteFailed": "Échec de la suppression de l'espace de travail", + "duplicateFailed": "Échec de la duplication de l'espace de travail", + "loadFailed": "Échec du chargement des espaces de travail", + "applyFailed": "Échec de l'application de l'espace de travail", + "deleteWorkspaceTitle": "Supprimer l'espace de travail", + "deleteWorkspaceDescription": "Êtes-vous sûr de vouloir supprimer «{{name}}» ? Cette action est irréversible.", + "noWorkspaces": "Aucun espace de travail enregistré pour le moment. Enregistrez votre disposition d'onglets actuelle pour commencer.", + "tabCount": "{{count}} onglet", + "tabCount_other": "Onglets {{count}}", + "apply": "Appliquer", + "applyConfirmTitle": "Espace de travail à appliquer", + "applyConfirmDescription": "Appliquer «{{name}}» fermera vos onglets actuels et les remplacera par la disposition enregistrée de cet espace de travail. Les modifications non enregistrées de votre disposition actuelle seront perdues.", + "applyConfirmButton": "Espace de travail à appliquer", + "updateWithCurrent": "Mise à jour avec les données actuelles", + "updateWithCurrentConfirm": "Remplacer «{{name}}» par votre disposition de tabulation actuelle ?", + "rename": "Rebaptiser", + "duplicate": "Double", + "duplicateNameSuffix": "{{name}} (copie)", + "setDefault": "Définir comme valeur par défaut", + "unsetDefault": "Supprimer par défaut", + "defaultBadge": "Défaut", + "lastSession": "Dernière session", + "lastSessionDescription": "Mise à jour automatique avec votre dernière configuration d'onglets. Appliquez-la pour retrouver ce que vous aviez ouvert.", + "lastUsed": "Dernière utilisation {{time}}", + "neverUsed": "Jamais postulé", + "tabsSkipped": "Espace de travail appliqué — {{count}} onglet(s) ignoré(s) (l'hôte n'existe plus) : {{names}}" + } + } + }, + "nav": { + "workspaces": "Espaces de travail" + }, + "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." + } +} diff --git a/plugins/workspaces/locales/translated/he_IL.json b/plugins/workspaces/locales/translated/he_IL.json new file mode 100644 index 000000000..350fcc1c6 --- /dev/null +++ b/plugins/workspaces/locales/translated/he_IL.json @@ -0,0 +1,55 @@ +{ + "newUi": { + "sidebar": { + "workspaces": { + "title": "סביבות עבודה", + "saveCurrent": "שמור את הנוכחי", + "saveCurrentTitle": "שמור סביבת עבודה נוכחית", + "saveCurrentDescription": "שמור כל כרטיסייה פתוחה, פריסה מפוצלת וסידור חלונות כסביבת עבודה חדשה בעלת שם.", + "nameLabel": "שֵׁם", + "namePlaceholder": "לדוגמה, ניפוי באגים בפרודוקציה", + "nameRequired": "נדרש שם סביבת עבודה", + "colorLabel": "צֶבַע", + "workspaceCreated": "סביבת העבודה נשמרה", + "workspaceUpdated": "סביבת העבודה עודכנה", + "workspaceDeleted": "סביבת העבודה נמחקה", + "workspaceDuplicated": "סביבת עבודה משוכפלת", + "saveFailed": "שמירת סביבת העבודה נכשלה", + "updateFailed": "נכשל עדכון סביבת העבודה", + "deleteFailed": "מחיקת סביבת העבודה נכשלה", + "duplicateFailed": "שכפול סביבת העבודה נכשל", + "loadFailed": "טעינת סביבות עבודה נכשלה", + "applyFailed": "נכשל בהחלת סביבת העבודה", + "deleteWorkspaceTitle": "מחיקת סביבת עבודה", + "deleteWorkspaceDescription": "האם אתה בטוח שברצונך למחוק את \"{{name}}\"? לא ניתן לבטל פעולה זו.", + "noWorkspaces": "עדיין לא נשמרו סביבות עבודה. שמור את סידור הכרטיסיות הנוכחי שלך כדי להתחיל.", + "tabCount": "טאב {{count}}", + "tabCount_other": "טאבים {{count}}", + "apply": "לִפְנוֹת", + "applyConfirmTitle": "החלת סביבת עבודה", + "applyConfirmDescription": "החלת \"{{name}}\" תסגור את הכרטיסיות הנוכחיות שלך ותחליף אותן בסידור השמור של סביבת עבודה זו. שינויים שלא נשמרו בפריסה הנוכחית שלך יאבדו.", + "applyConfirmButton": "החלת סביבת עבודה", + "updateWithCurrent": "עדכון עם הנוכחי", + "updateWithCurrentConfirm": "להחליף את \"{{name}}\" עם סידור הטאבים הנוכחי שלך?", + "rename": "שינוי שם", + "duplicate": "לְשַׁכְפֵּל", + "duplicateNameSuffix": "{{name}} (העתק)", + "setDefault": "הגדר כברירת מחדל", + "unsetDefault": "הסר כברירת מחדל", + "defaultBadge": "בְּרִירַת מֶחדָל", + "lastSession": "מושב אחרון", + "lastSessionDescription": "מתעדכן אוטומטית עם סידור הכרטיסיות האחרון שלך. השתמש בו כדי לשחזר את מה שהיה פתוח.", + "lastUsed": "בשימוש אחרון {{time}}", + "neverUsed": "מעולם לא יושם", + "tabsSkipped": "סביבת עבודה הוחלת — דילגו על כרטיסיות {{count}} (המארח כבר לא קיים): {{names}}" + } + } + }, + "nav": { + "workspaces": "סביבות עבודה" + }, + "onboarding": { + "workflow_workspaces": "סביבות עבודה", + "workflow_workspaces_desc": "שמור קבוצת כרטיסיות פתוחות ופתח מחדש את כל הפריסה מאוחר יותר." + } +} diff --git a/plugins/workspaces/locales/translated/hi_IN.json b/plugins/workspaces/locales/translated/hi_IN.json new file mode 100644 index 000000000..72d1f3b46 --- /dev/null +++ b/plugins/workspaces/locales/translated/hi_IN.json @@ -0,0 +1,55 @@ +{ + "newUi": { + "sidebar": { + "workspaces": { + "title": "कार्यस्थानों", + "saveCurrent": "वर्तमान सहेजें", + "saveCurrentTitle": "वर्तमान कार्यक्षेत्र सहेजें", + "saveCurrentDescription": "प्रत्येक खुले टैब, स्प्लिट लेआउट और पेन व्यवस्था को एक नए नाम वाले वर्कस्पेस के रूप में सहेजें।", + "nameLabel": "नाम", + "namePlaceholder": "उदाहरण के लिए, प्रोडक्शन डिबगिंग", + "nameRequired": "कार्यक्षेत्र का नाम आवश्यक है", + "colorLabel": "रंग", + "workspaceCreated": "कार्यक्षेत्र सहेजा गया", + "workspaceUpdated": "कार्यक्षेत्र अपडेट किया गया", + "workspaceDeleted": "कार्यक्षेत्र हटा दिया गया", + "workspaceDuplicated": "कार्यक्षेत्र की प्रतिकृति बनाई गई", + "saveFailed": "कार्यक्षेत्र को सहेजने में विफल", + "updateFailed": "वर्कस्पेस को अपडेट करने में विफल", + "deleteFailed": "वर्कस्पेस को हटाने में विफल", + "duplicateFailed": "वर्कस्पेस को डुप्लिकेट करने में विफल", + "loadFailed": "वर्कस्पेस लोड करने में विफल", + "applyFailed": "कार्यक्षेत्र लागू करने में विफल", + "deleteWorkspaceTitle": "वर्कस्पेस हटाएं", + "deleteWorkspaceDescription": "क्या आप वाकई \"{{name}}\" को हटाना चाहते हैं? इसे पूर्ववत नहीं किया जा सकता।", + "noWorkspaces": "अभी तक कोई वर्कस्पेस सेव नहीं किया गया है। शुरू करने के लिए अपनी वर्तमान टैब व्यवस्था को सेव करें।", + "tabCount": "{{count}} टैब", + "tabCount_other": "{{count}} टैब", + "apply": "आवेदन करना", + "applyConfirmTitle": "वर्कस्पेस लागू करें", + "applyConfirmDescription": "\"{{name}}\" लागू करने से आपके वर्तमान टैब बंद हो जाएंगे और उनकी जगह इस वर्कस्पेस की सहेजी गई व्यवस्था लागू हो जाएगी। आपके वर्तमान लेआउट में किए गए असहयोगी परिवर्तन नष्ट हो जाएंगे।", + "applyConfirmButton": "वर्कस्पेस लागू करें", + "updateWithCurrent": "वर्तमान जानकारी से अपडेट करें", + "updateWithCurrentConfirm": "क्या आप \"{{name}}\" को अपनी वर्तमान टैब व्यवस्था से बदलना चाहेंगे?", + "rename": "नाम बदलें", + "duplicate": "डुप्लिकेट", + "duplicateNameSuffix": "{{name}} (कॉपी)", + "setDefault": "डिफाल्ट के रूप में सेट", + "unsetDefault": "डिफ़ॉल्ट के रूप में हटाएँ", + "defaultBadge": "गलती करना", + "lastSession": "पिछला सत्र", + "lastSessionDescription": "आपके टैब की नवीनतम व्यवस्था के साथ स्वचालित रूप से अपडेट हो जाता है। इसे लागू करके आप अपने खुले हुए टैब को पुनः प्राप्त कर सकते हैं।", + "lastUsed": "अंतिम बार उपयोग किया गया {{time}}", + "neverUsed": "कभी आवेदन नहीं किया", + "tabsSkipped": "कार्यक्षेत्र लागू किया गया — {{count}} टैब छोड़े गए (होस्ट अब मौजूद नहीं है): {{names}}" + } + } + }, + "nav": { + "workspaces": "कार्यस्थानों" + }, + "onboarding": { + "workflow_workspaces": "कार्यस्थानों", + "workflow_workspaces_desc": "खुले हुए टैबों के एक सेट को सेव करें और बाद में पूरे लेआउट को दोबारा खोलें।" + } +} diff --git a/plugins/workspaces/locales/translated/hu_HU.json b/plugins/workspaces/locales/translated/hu_HU.json new file mode 100644 index 000000000..bd1ea068c --- /dev/null +++ b/plugins/workspaces/locales/translated/hu_HU.json @@ -0,0 +1,55 @@ +{ + "newUi": { + "sidebar": { + "workspaces": { + "title": "Munkaterületek", + "saveCurrent": "Aktuális mentése", + "saveCurrentTitle": "Aktuális munkaterület mentése", + "saveCurrentDescription": "Minden megnyitott lapot, osztott elrendezést és panelelrendezést mentsen el új, elnevezett munkaterületként.", + "nameLabel": "Név", + "namePlaceholder": "pl., Prod Debugging", + "nameRequired": "Munkaterület neve kötelező", + "colorLabel": "Szín", + "workspaceCreated": "Munkaterület mentve", + "workspaceUpdated": "Munkaterület frissítve", + "workspaceDeleted": "Munkaterület törölve", + "workspaceDuplicated": "Munkaterület duplikálva", + "saveFailed": "Nem sikerült menteni a munkaterületet", + "updateFailed": "Nem sikerült frissíteni a munkaterületet", + "deleteFailed": "Nem sikerült törölni a munkaterületet", + "duplicateFailed": "Nem sikerült a munkaterületet másolni", + "loadFailed": "Nem sikerült betölteni a munkaterületeket", + "applyFailed": "Nem sikerült alkalmazni a munkaterületet", + "deleteWorkspaceTitle": "Munkaterület törlése", + "deleteWorkspaceDescription": "Biztosan törölni szeretnéd a(z) \"{{name}}\" fájlt? Ez a művelet nem vonható vissza.", + "noWorkspaces": "Még nincsenek mentett munkaterületek. A kezdéshez mentse el az aktuális tabulátorelrendezést.", + "tabCount": "{{count}} fül", + "tabCount_other": "{{count}} fülek", + "apply": "Jelentkezés", + "applyConfirmTitle": "Munkaterület alkalmazása", + "applyConfirmDescription": "A(z) „{{name}}” parancs alkalmazása bezárja az aktuális lapokat, és lecseréli azokat a munkaterület mentett elrendezésére. Az aktuális elrendezés nem mentett módosításai elvesznek.", + "applyConfirmButton": "Munkaterület alkalmazása", + "updateWithCurrent": "Frissítés az aktuális programmal", + "updateWithCurrentConfirm": "Felülírja a(z) \"{{name}}\" szöveget a jelenlegi tabulátorelrendezéssel?", + "rename": "Átnevezés", + "duplicate": "Másolat", + "duplicateNameSuffix": "{{name}} (másolat)", + "setDefault": "Beállítás alapértelmezettként", + "unsetDefault": "Eltávolítás alapértelmezettként", + "defaultBadge": "Alapértelmezett", + "lastSession": "Utolsó munkamenet", + "lastSessionDescription": "Automatikusan frissül a legutóbbi tabulátorelrendezéssel. Alkalmazd, hogy visszaállítsd a megnyitott tabulátorokat.", + "lastUsed": "Utolsó használat {{time}}", + "neverUsed": "Soha nem alkalmazták", + "tabsSkipped": "Munkaterület alkalmazva — {{count}} tabulátor(ok) kihagyva (a gazdagép már nem létezik): {{names}}" + } + } + }, + "nav": { + "workspaces": "Munkaterületek" + }, + "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." + } +} diff --git a/plugins/workspaces/locales/translated/id_ID.json b/plugins/workspaces/locales/translated/id_ID.json new file mode 100644 index 000000000..ab5bfa8e2 --- /dev/null +++ b/plugins/workspaces/locales/translated/id_ID.json @@ -0,0 +1,55 @@ +{ + "newUi": { + "sidebar": { + "workspaces": { + "title": "Ruang kerja", + "saveCurrent": "Simpan Saat Ini", + "saveCurrentTitle": "Simpan Ruang Kerja Saat Ini", + "saveCurrentDescription": "Simpan setiap tab yang terbuka, tata letak terpisah, dan susunan panel sebagai ruang kerja baru yang diberi nama.", + "nameLabel": "Nama", + "namePlaceholder": "misalnya, Debugging Produksi", + "nameRequired": "Nama ruang kerja wajib diisi.", + "colorLabel": "Warna", + "workspaceCreated": "Ruang kerja tersimpan", + "workspaceUpdated": "Ruang kerja diperbarui", + "workspaceDeleted": "Ruang kerja dihapus", + "workspaceDuplicated": "Ruang kerja diduplikasi", + "saveFailed": "Gagal menyimpan ruang kerja", + "updateFailed": "Gagal memperbarui ruang kerja", + "deleteFailed": "Gagal menghapus ruang kerja.", + "duplicateFailed": "Gagal menduplikasi ruang kerja.", + "loadFailed": "Gagal memuat ruang kerja", + "applyFailed": "Gagal menerapkan ruang kerja", + "deleteWorkspaceTitle": "Hapus Ruang Kerja", + "deleteWorkspaceDescription": "Apakah Anda yakin ingin menghapus \"{{name}}\"? Tindakan ini tidak dapat dibatalkan.", + "noWorkspaces": "Belum ada ruang kerja yang tersimpan. Simpan susunan tab Anda saat ini untuk memulai.", + "tabCount": "{{count}} tab", + "tabCount_other": "{{count}} tab", + "apply": "Menerapkan", + "applyConfirmTitle": "Terapkan Ruang Kerja", + "applyConfirmDescription": "Menerapkan \"{{name}}\" akan menutup tab Anda saat ini dan menggantinya dengan susunan yang tersimpan di ruang kerja ini. Perubahan yang belum disimpan pada tata letak Anda saat ini akan hilang.", + "applyConfirmButton": "Terapkan Ruang Kerja", + "updateWithCurrent": "Perbarui dengan yang Terbaru", + "updateWithCurrentConfirm": "Timpa \"{{name}}\" dengan susunan tab Anda saat ini?", + "rename": "Ganti nama", + "duplicate": "Duplikat", + "duplicateNameSuffix": "{{name}} (salinan)", + "setDefault": "Tetapkan sebagai Default", + "unsetDefault": "Hapus sebagai Default", + "defaultBadge": "Bawaan", + "lastSession": "Sesi Terakhir", + "lastSessionDescription": "Diperbarui secara otomatis dengan susunan tab terbaru Anda. Terapkan untuk memulihkan tab yang sebelumnya Anda buka.", + "lastUsed": "Terakhir digunakan {{time}}", + "neverUsed": "Tidak pernah melamar", + "tabsSkipped": "Ruang kerja diterapkan — {{count}} tab dilewati (host tidak lagi ada): {{names}}" + } + } + }, + "nav": { + "workspaces": "Ruang kerja" + }, + "onboarding": { + "workflow_workspaces": "Ruang kerja", + "workflow_workspaces_desc": "Simpan sekumpulan tab yang terbuka dan buka kembali seluruh tata letak nanti." + } +} diff --git a/plugins/workspaces/locales/translated/it_IT.json b/plugins/workspaces/locales/translated/it_IT.json new file mode 100644 index 000000000..0afd00db0 --- /dev/null +++ b/plugins/workspaces/locales/translated/it_IT.json @@ -0,0 +1,55 @@ +{ + "newUi": { + "sidebar": { + "workspaces": { + "title": "Spazi di lavoro", + "saveCurrent": "Salva corrente", + "saveCurrentTitle": "Salva l'area di lavoro corrente", + "saveCurrentDescription": "Salva ogni scheda aperta, layout diviso e disposizione dei riquadri come nuova area di lavoro denominata.", + "nameLabel": "Nome", + "namePlaceholder": "ad esempio, Debugging di produzione", + "nameRequired": "Il nome dell'area di lavoro è obbligatorio", + "colorLabel": "Colore", + "workspaceCreated": "Area di lavoro salvata", + "workspaceUpdated": "Area di lavoro aggiornata", + "workspaceDeleted": "Area di lavoro eliminata", + "workspaceDuplicated": "Area di lavoro duplicata", + "saveFailed": "Impossibile salvare l'area di lavoro", + "updateFailed": "Impossibile aggiornare l'area di lavoro", + "deleteFailed": "Impossibile eliminare l'area di lavoro", + "duplicateFailed": "Impossibile duplicare l'area di lavoro", + "loadFailed": "Impossibile caricare gli spazi di lavoro", + "applyFailed": "Impossibile applicare l'area di lavoro", + "deleteWorkspaceTitle": "Elimina l'area di lavoro", + "deleteWorkspaceDescription": "Sei sicuro di voler eliminare \"{{name}}\"? Questa operazione non può essere annullata.", + "noWorkspaces": "Nessun spazio di lavoro salvato al momento. Salva la disposizione attuale delle schede per iniziare.", + "tabCount": "{{count}} tab", + "tabCount_other": "{{count}} schede", + "apply": "Fare domanda a", + "applyConfirmTitle": "Applica l'area di lavoro", + "applyConfirmDescription": "Applicando \"{{name}}\" chiuderai le schede correnti e le sostituirai con la disposizione salvata di quest'area di lavoro. Le modifiche non salvate al layout corrente andranno perse.", + "applyConfirmButton": "Applica l'area di lavoro", + "updateWithCurrent": "Aggiorna con la versione attuale", + "updateWithCurrentConfirm": "Sovrascrivi \"{{name}}\" con la tua attuale disposizione delle schede?", + "rename": "Rinominare", + "duplicate": "Duplicato", + "duplicateNameSuffix": "{{name}} (copia)", + "setDefault": "Imposta come predefinito", + "unsetDefault": "Rimuovi come predefinito", + "defaultBadge": "Predefinito", + "lastSession": "Ultima sessione", + "lastSessionDescription": "Si aggiorna automaticamente con la disposizione delle schede più recente. Applicala per ripristinare quelle che avevi aperte.", + "lastUsed": "Ultimo utilizzo {{time}}", + "neverUsed": "mai applicato", + "tabsSkipped": "Area di lavoro applicata — {{count}} scheda(e) saltata(e) (l'host non esiste più): {{names}}" + } + } + }, + "nav": { + "workspaces": "Spazi di lavoro" + }, + "onboarding": { + "workflow_workspaces": "Spazi di lavoro", + "workflow_workspaces_desc": "Salva le schede aperte e riapri l'intero layout in seguito." + } +} diff --git a/plugins/workspaces/locales/translated/ja_JP.json b/plugins/workspaces/locales/translated/ja_JP.json new file mode 100644 index 000000000..07b5c310e --- /dev/null +++ b/plugins/workspaces/locales/translated/ja_JP.json @@ -0,0 +1,55 @@ +{ + "newUi": { + "sidebar": { + "workspaces": { + "title": "ワークスペース", + "saveCurrent": "現在の状態を保存", + "saveCurrentTitle": "現在のワークスペースを保存", + "saveCurrentDescription": "開いているすべてのタブ、分割レイアウト、ペイン配置を、新しい名前付きワークスペースとして保存します。", + "nameLabel": "名前", + "namePlaceholder": "例:本番環境のデバッグ", + "nameRequired": "ワークスペース名は必須です。", + "colorLabel": "色", + "workspaceCreated": "ワークスペースが保存されました", + "workspaceUpdated": "ワークスペースが更新されました", + "workspaceDeleted": "ワークスペースが削除されました", + "workspaceDuplicated": "ワークスペースが複製されました", + "saveFailed": "ワークスペースの保存に失敗しました", + "updateFailed": "ワークスペースの更新に失敗しました", + "deleteFailed": "ワークスペースの削除に失敗しました", + "duplicateFailed": "ワークスペースの複製に失敗しました", + "loadFailed": "ワークスペースの読み込みに失敗しました", + "applyFailed": "ワークスペースの適用に失敗しました", + "deleteWorkspaceTitle": "ワークスペースを削除", + "deleteWorkspaceDescription": "「{{name}}」を削除してもよろしいですか?この操作は元に戻せません。", + "noWorkspaces": "まだワークスペースが保存されていません。まずは現在のタブの配置を保存してください。", + "tabCount": "{{count}} タブ", + "tabCount_other": "{{count}} タブ", + "apply": "適用する", + "applyConfirmTitle": "ワークスペースを適用する", + "applyConfirmDescription": "\"{{name}}\" を適用すると、現在のタブが閉じられ、このワークスペースに保存されているレイアウトに置き換えられます。現在のレイアウトに対する未保存の変更は失われます。", + "applyConfirmButton": "ワークスペースを適用する", + "updateWithCurrent": "最新情報に更新", + "updateWithCurrentConfirm": "「{{name}}」を現在のタブ配列で上書きしますか?", + "rename": "名前を変更する", + "duplicate": "重複", + "duplicateNameSuffix": "{{name}} (コピー)", + "setDefault": "デフォルトとして設定", + "unsetDefault": "デフォルトから削除", + "defaultBadge": "デフォルト", + "lastSession": "最終セッション", + "lastSessionDescription": "最新のタブ配置に合わせて自動的に更新されます。適用すると、以前開いていたウィンドウが復元されます。", + "lastUsed": "最後に使用されたのは {{time}} です。", + "neverUsed": "一度も応募したことがない", + "tabsSkipped": "ワークスペースが適用されました — {{count}} タブがスキップされました (ホストが存在しなくなりました): {{names}}" + } + } + }, + "nav": { + "workspaces": "ワークスペース" + }, + "onboarding": { + "workflow_workspaces": "ワークスペース", + "workflow_workspaces_desc": "開いているタブのセットを保存し、後でレイアウト全体を再度開くことができます。" + } +} diff --git a/plugins/workspaces/locales/translated/ko_KR.json b/plugins/workspaces/locales/translated/ko_KR.json new file mode 100644 index 000000000..e065dc564 --- /dev/null +++ b/plugins/workspaces/locales/translated/ko_KR.json @@ -0,0 +1,55 @@ +{ + "newUi": { + "sidebar": { + "workspaces": { + "title": "작업 공간", + "saveCurrent": "현재 저장", + "saveCurrentTitle": "현재 작업 공간 저장", + "saveCurrentDescription": "열려 있는 모든 탭, 분할 레이아웃 및 창 배열을 새 이름의 작업 공간으로 저장합니다.", + "nameLabel": "이름", + "namePlaceholder": "예: 프로덕션 디버깅", + "nameRequired": "워크스페이스 이름은 필수 입력 사항입니다.", + "colorLabel": "색상", + "workspaceCreated": "작업 공간이 저장되었습니다", + "workspaceUpdated": "작업 공간이 업데이트되었습니다.", + "workspaceDeleted": "작업 공간이 삭제되었습니다", + "workspaceDuplicated": "작업 공간이 복제되었습니다", + "saveFailed": "작업 공간 저장에 실패했습니다", + "updateFailed": "워크스페이스 업데이트에 실패했습니다.", + "deleteFailed": "워크스페이스 삭제에 실패했습니다.", + "duplicateFailed": "워크스페이스 복제에 실패했습니다.", + "loadFailed": "워크스페이스를 불러오는 데 실패했습니다.", + "applyFailed": "워크스페이스 적용에 실패했습니다", + "deleteWorkspaceTitle": "작업 공간 삭제", + "deleteWorkspaceDescription": "\"{{name}}\"을 삭제하시겠습니까? 이 작업은 되돌릴 수 없습니다.", + "noWorkspaces": "아직 저장된 작업 공간이 없습니다. 시작하려면 현재 탭 구성을 저장하세요.", + "tabCount": "{{count}} 탭", + "tabCount_other": "{{count}} 탭", + "apply": "적용하다", + "applyConfirmTitle": "작업 공간 적용", + "applyConfirmDescription": "\"{{name}}\"를 입력하면 현재 탭이 닫히고 이 작업 공간에 저장된 레이아웃으로 바뀝니다. 현재 레이아웃에 대한 저장되지 않은 변경 사항은 손실됩니다.", + "applyConfirmButton": "작업 공간 적용", + "updateWithCurrent": "현재 정보로 업데이트", + "updateWithCurrentConfirm": "현재 탭 배열로 \"{{name}}\"를 덮어쓰시겠습니까?", + "rename": "이름 변경", + "duplicate": "복제하다", + "duplicateNameSuffix": "{{name}} (복사)", + "setDefault": "기본값으로 설정", + "unsetDefault": "기본값에서 제거", + "defaultBadge": "기본", + "lastSession": "지난 세션", + "lastSessionDescription": "최근 탭 배열로 자동 업데이트됩니다. 적용하면 이전에 열려 있던 탭을 복구할 수 있습니다.", + "lastUsed": "마지막으로 사용된 값 {{time}}", + "neverUsed": "지원한 적 없음", + "tabsSkipped": "워크스페이스 적용됨 — {{count}} 탭 건너뛰기(호스트가 더 이상 존재하지 않음): {{names}}" + } + } + }, + "nav": { + "workspaces": "작업 공간" + }, + "onboarding": { + "workflow_workspaces": "작업 공간", + "workflow_workspaces_desc": "열려 있는 탭들을 저장해두었다가 나중에 전체 레이아웃을 다시 열어보세요." + } +} diff --git a/plugins/workspaces/locales/translated/nl_NL.json b/plugins/workspaces/locales/translated/nl_NL.json new file mode 100644 index 000000000..1e2791b79 --- /dev/null +++ b/plugins/workspaces/locales/translated/nl_NL.json @@ -0,0 +1,55 @@ +{ + "newUi": { + "sidebar": { + "workspaces": { + "title": "Werkruimtes", + "saveCurrent": "Huidige opslaan", + "saveCurrentTitle": "Huidige werkruimte opslaan", + "saveCurrentDescription": "Sla elk geopend tabblad, elke gesplitste lay-out en elke vensterindeling op als een nieuwe, benoemde werkruimte.", + "nameLabel": "Naam", + "namePlaceholder": "bijvoorbeeld, productiedebugging", + "nameRequired": "De naam van de werkruimte is verplicht.", + "colorLabel": "Kleur", + "workspaceCreated": "Werkruimte opgeslagen", + "workspaceUpdated": "Werkruimte bijgewerkt", + "workspaceDeleted": "Werkruimte verwijderd", + "workspaceDuplicated": "Werkruimte gedupliceerd", + "saveFailed": "Het opslaan van de werkruimte is mislukt.", + "updateFailed": "Het bijwerken van de werkruimte is mislukt.", + "deleteFailed": "Het verwijderen van de werkruimte is mislukt.", + "duplicateFailed": "Het dupliceren van de werkruimte is mislukt.", + "loadFailed": "Het laden van de werkruimtes is mislukt.", + "applyFailed": "Het toepassen van de werkruimte is mislukt.", + "deleteWorkspaceTitle": "Werkruimte verwijderen", + "deleteWorkspaceDescription": "Weet je zeker dat je \"{{name}}\" wilt verwijderen? Dit kan niet ongedaan gemaakt worden.", + "noWorkspaces": "Er zijn nog geen werkruimtes opgeslagen. Sla je huidige tabbladindeling op om te beginnen.", + "tabCount": "{{count}} tab", + "tabCount_other": "{{count}} tabs", + "apply": "Toepassen", + "applyConfirmTitle": "Werkruimte toepassen", + "applyConfirmDescription": "Door \"{{name}}\" toe te passen, worden uw huidige tabbladen gesloten en vervangen door de opgeslagen indeling van deze werkruimte. Niet-opgeslagen wijzigingen in uw huidige lay-out gaan verloren.", + "applyConfirmButton": "Werkruimte toepassen", + "updateWithCurrent": "Update met de huidige", + "updateWithCurrentConfirm": "Wil je \"{{name}}\" overschrijven met je huidige tabindeling?", + "rename": "Naam wijzigen", + "duplicate": "Duplicaat", + "duplicateNameSuffix": "{{name}} (kopiëren)", + "setDefault": "Instellen als standaard", + "unsetDefault": "Verwijderen als standaard", + "defaultBadge": "Standaard", + "lastSession": "Laatste sessie", + "lastSessionDescription": "Wordt automatisch bijgewerkt met uw meest recente tabbladindeling. Gebruik deze instelling om uw geopende tabbladen te herstellen.", + "lastUsed": "Laatst gebruikt {{time}}", + "neverUsed": "Nooit gesolliciteerd", + "tabsSkipped": "Werkruimte toegepast — {{count}} tabblad(en) overgeslagen (host bestaat niet meer): {{names}}" + } + } + }, + "nav": { + "workspaces": "Werkruimtes" + }, + "onboarding": { + "workflow_workspaces": "Werkruimtes", + "workflow_workspaces_desc": "Sla een set geopende tabbladen op en open de volledige lay-out later opnieuw." + } +} diff --git a/plugins/workspaces/locales/translated/no_NO.json b/plugins/workspaces/locales/translated/no_NO.json new file mode 100644 index 000000000..a5e708455 --- /dev/null +++ b/plugins/workspaces/locales/translated/no_NO.json @@ -0,0 +1,55 @@ +{ + "newUi": { + "sidebar": { + "workspaces": { + "title": "Arbeidsområder", + "saveCurrent": "Lagre gjeldende", + "saveCurrentTitle": "Lagre gjeldende arbeidsområde", + "saveCurrentDescription": "Lagre alle åpne faner, delte oppsett og ruteoppsett som et nytt navngitt arbeidsområde.", + "nameLabel": "Navn", + "namePlaceholder": "f.eks. produktfeilsøking", + "nameRequired": "Arbeidsområdenavn er obligatorisk", + "colorLabel": "Farge", + "workspaceCreated": "Arbeidsområdet er lagret", + "workspaceUpdated": "Arbeidsområdet er oppdatert", + "workspaceDeleted": "Arbeidsområdet er slettet", + "workspaceDuplicated": "Arbeidsområdet er duplisert", + "saveFailed": "Kunne ikke lagre arbeidsområdet", + "updateFailed": "Kunne ikke oppdatere arbeidsområdet", + "deleteFailed": "Kunne ikke slette arbeidsområdet", + "duplicateFailed": "Kunne ikke duplisere arbeidsområdet", + "loadFailed": "Kunne ikke laste inn arbeidsområder", + "applyFailed": "Kunne ikke bruke arbeidsområdet", + "deleteWorkspaceTitle": "Slett arbeidsområde", + "deleteWorkspaceDescription": "Er du sikker på at du vil slette «{{name}}»? Dette kan ikke angres.", + "noWorkspaces": "Ingen lagrede arbeidsområder ennå. Lagre den nåværende faneoppsettet for å komme i gang.", + "tabCount": "{{count}} fane", + "tabCount_other": "{{count}} faner", + "apply": "Søke", + "applyConfirmTitle": "Bruk arbeidsområde", + "applyConfirmDescription": "Hvis du bruker «{{name}}», lukkes de nåværende fanene dine og erstattes med den lagrede plasseringen i dette arbeidsområdet. Ulagrede endringer i den nåværende layouten vil gå tapt.", + "applyConfirmButton": "Bruk arbeidsområde", + "updateWithCurrent": "Oppdater med gjeldende", + "updateWithCurrentConfirm": "Vil du overskrive «{{name}}» med din nåværende tabulatorordning?", + "rename": "Gi nytt navn", + "duplicate": "Kopiere", + "duplicateNameSuffix": "{{name}} (kopi)", + "setDefault": "Angi som standard", + "unsetDefault": "Fjern som standard", + "defaultBadge": "Misligholde", + "lastSession": "Siste økt", + "lastSessionDescription": "Oppdateres automatisk med den nyeste faneoppsettet ditt. Bruk det for å gjenopprette det du hadde åpent.", + "lastUsed": "Sist brukt {{time}}", + "neverUsed": "Aldri brukt", + "tabsSkipped": "Arbeidsområde brukt — {{count}} fane(r) hoppet over (verten finnes ikke lenger): {{names}}" + } + } + }, + "nav": { + "workspaces": "Arbeidsområder" + }, + "onboarding": { + "workflow_workspaces": "Arbeidsområder", + "workflow_workspaces_desc": "Lagre et sett med åpne faner og åpne hele layouten på nytt senere." + } +} diff --git a/plugins/workspaces/locales/translated/pl_PL.json b/plugins/workspaces/locales/translated/pl_PL.json new file mode 100644 index 000000000..a6a63bb2c --- /dev/null +++ b/plugins/workspaces/locales/translated/pl_PL.json @@ -0,0 +1,55 @@ +{ + "newUi": { + "sidebar": { + "workspaces": { + "title": "Obszary robocze", + "saveCurrent": "Zapisz bieżące", + "saveCurrentTitle": "Zapisz bieżący obszar roboczy", + "saveCurrentDescription": "Zapisz każdą otwartą kartę, podzielony układ i rozmieszczenie paneli jako nowy nazwany obszar roboczy.", + "nameLabel": "Nazwa", + "namePlaceholder": "np. Debugowanie produkcji", + "nameRequired": "Nazwa obszaru roboczego jest wymagana", + "colorLabel": "Kolor", + "workspaceCreated": "Zapisano obszar roboczy", + "workspaceUpdated": "Zaktualizowano obszar roboczy", + "workspaceDeleted": "Usunięto obszar roboczy", + "workspaceDuplicated": "Zduplikowano obszar roboczy", + "saveFailed": "Nie udało się zapisać obszaru roboczego", + "updateFailed": "Nie udało się zaktualizować obszaru roboczego", + "deleteFailed": "Nie udało się usunąć obszaru roboczego", + "duplicateFailed": "Nie udało się zduplikować obszaru roboczego", + "loadFailed": "Nie udało się załadować obszarów roboczych", + "applyFailed": "Nie udało się zastosować obszaru roboczego", + "deleteWorkspaceTitle": "Usuń obszar roboczy", + "deleteWorkspaceDescription": "Czy na pewno chcesz usunąć „{{name}}”? Tego nie można cofnąć.", + "noWorkspaces": "Brak zapisanych obszarów roboczych. Zapisz aktualny układ kart, aby rozpocząć.", + "tabCount": "{{count}} karta", + "tabCount_other": "{{count}} karty", + "apply": "Zastosuj", + "applyConfirmTitle": "Zastosuj obszar roboczy", + "applyConfirmDescription": "Zastosowanie „{{name}}” zamknie bieżące karty i zastąpi je układem zapisanym w tym obszarze roboczym. Niezapisane zmiany bieżącego układu zostaną utracone.", + "applyConfirmButton": "Zastosuj obszar roboczy", + "updateWithCurrent": "Zaktualizuj bieżącym", + "updateWithCurrentConfirm": "Nadpisać „{{name}}” obecnym układem kart?", + "rename": "Zmień nazwę", + "duplicate": "Duplikuj", + "duplicateNameSuffix": "{{name}} (kopia)", + "setDefault": "Ustaw jako domyślne", + "unsetDefault": "Usuń jako domyślne", + "defaultBadge": "Domyślny", + "lastSession": "Ostatnia sesja", + "lastSessionDescription": "Automatycznie aktualizowany o najnowszy układ kart. Zastosuj go, aby przywrócić to, co było otwarte.", + "lastUsed": "Ostatnio użyte {{time}}", + "neverUsed": "Nigdy nie zastosowano", + "tabsSkipped": "Zastosowano obszar roboczy, pominięto {{count}} kart (host już nie istnieje): {{names}}" + } + } + }, + "nav": { + "workspaces": "Obszary robocze" + }, + "onboarding": { + "workflow_workspaces": "Obszary robocze", + "workflow_workspaces_desc": "Zapisz zestaw otwartych kart i otwórz cały układ później." + } +} diff --git a/plugins/workspaces/locales/translated/pt_BR.json b/plugins/workspaces/locales/translated/pt_BR.json new file mode 100644 index 000000000..fef7aaa8b --- /dev/null +++ b/plugins/workspaces/locales/translated/pt_BR.json @@ -0,0 +1,55 @@ +{ + "newUi": { + "sidebar": { + "workspaces": { + "title": "Espaços de trabalho", + "saveCurrent": "Salvar atual", + "saveCurrentTitle": "Salvar espaço de trabalho atual", + "saveCurrentDescription": "Salve cada aba aberta, layout dividido e disposição de painéis como um novo espaço de trabalho nomeado.", + "nameLabel": "Nome", + "namePlaceholder": "Exemplo: Depuração de Produção", + "nameRequired": "É obrigatório dar um nome ao espaço de trabalho.", + "colorLabel": "Cor", + "workspaceCreated": "Espaço de trabalho salvo", + "workspaceUpdated": "Espaço de trabalho atualizado", + "workspaceDeleted": "Espaço de trabalho excluído", + "workspaceDuplicated": "Espaço de trabalho duplicado", + "saveFailed": "Falha ao salvar o espaço de trabalho", + "updateFailed": "Falha ao atualizar o espaço de trabalho", + "deleteFailed": "Falha ao excluir o espaço de trabalho", + "duplicateFailed": "Falha ao duplicar o espaço de trabalho", + "loadFailed": "Falha ao carregar os espaços de trabalho.", + "applyFailed": "Falha ao aplicar o espaço de trabalho", + "deleteWorkspaceTitle": "Excluir espaço de trabalho", + "deleteWorkspaceDescription": "Tem certeza de que deseja excluir \"{{name}}\"? Esta ação não pode ser desfeita.", + "noWorkspaces": "Ainda não há espaços de trabalho salvos. Salve sua configuração atual de abas para começar.", + "tabCount": "{{count}} aba", + "tabCount_other": "{{count}} abas", + "apply": "Aplicar", + "applyConfirmTitle": "Aplicar Espaço de Trabalho", + "applyConfirmDescription": "Aplicar \"{{name}}\" fechará suas abas atuais e as substituirá pela configuração salva deste espaço de trabalho. Alterações não salvas no seu layout atual serão perdidas.", + "applyConfirmButton": "Aplicar Espaço de Trabalho", + "updateWithCurrent": "Atualizar com as informações atuais", + "updateWithCurrentConfirm": "Substituir \"{{name}}\" pela sua configuração de tabulação atual?", + "rename": "Renomear", + "duplicate": "Duplicado", + "duplicateNameSuffix": "{{name}} (copiar)", + "setDefault": "Definir como padrão", + "unsetDefault": "Remover como padrão", + "defaultBadge": "Padrão", + "lastSession": "Última sessão", + "lastSessionDescription": "Atualizado automaticamente com a sua última configuração de abas. Aplique para recuperar o que estava aberto.", + "lastUsed": "Última utilização {{time}}", + "neverUsed": "Nunca aplicado", + "tabsSkipped": "Espaço de trabalho aplicado — {{count}} guia(s) ignorada(s) (o host não existe mais): {{names}}" + } + } + }, + "nav": { + "workspaces": "Espaços de trabalho" + }, + "onboarding": { + "workflow_workspaces": "Espaços de trabalho", + "workflow_workspaces_desc": "Salve um conjunto de abas abertas e reabra todo o layout mais tarde." + } +} diff --git a/plugins/workspaces/locales/translated/pt_PT.json b/plugins/workspaces/locales/translated/pt_PT.json new file mode 100644 index 000000000..611f791ba --- /dev/null +++ b/plugins/workspaces/locales/translated/pt_PT.json @@ -0,0 +1,55 @@ +{ + "newUi": { + "sidebar": { + "workspaces": { + "title": "Espaços de trabalho", + "saveCurrent": "Guardar atual", + "saveCurrentTitle": "Guardar espaço de trabalho atual", + "saveCurrentDescription": "Guarde cada separador aberto, layout dividido e disposição de painéis como um novo espaço de trabalho nomeado.", + "nameLabel": "Nome", + "namePlaceholder": "Exemplo: Depuração de Produção", + "nameRequired": "É obrigatório dar um nome ao espaço de trabalho.", + "colorLabel": "Cor", + "workspaceCreated": "Espaço de trabalho guardado", + "workspaceUpdated": "Espaço de trabalho atualizado", + "workspaceDeleted": "Espaço de trabalho excluído", + "workspaceDuplicated": "Espaço de trabalho duplicado", + "saveFailed": "Falha ao guardar o espaço de trabalho", + "updateFailed": "Falha ao atualizar o espaço de trabalho", + "deleteFailed": "Falha ao eliminar o espaço de trabalho", + "duplicateFailed": "Falha ao duplicar o espaço de trabalho", + "loadFailed": "Falha ao carregar os espaços de trabalho.", + "applyFailed": "Falha ao aplicar o espaço de trabalho", + "deleteWorkspaceTitle": "Apagar espaço de trabalho", + "deleteWorkspaceDescription": "Tem a certeza que pretende eliminar \"{{name}}\"? Esta ação não pode ser anulada.", + "noWorkspaces": "Ainda não há espaços de trabalho guardados. Guarde a sua configuração atual de separadores para começar.", + "tabCount": "{{count}} separador", + "tabCount_other": "{{count}} separadores", + "apply": "Candidatar-se", + "applyConfirmTitle": "Aplicar Espaço de Trabalho", + "applyConfirmDescription": "Aplicar \"{{name}}\" fechará os seus separadores atuais e substituí-los-á pela configuração guardada deste espaço de trabalho. As alterações não guardadas no seu layout atual serão perdidas.", + "applyConfirmButton": "Aplicar Espaço de Trabalho", + "updateWithCurrent": "Atualizar com as informações atuais", + "updateWithCurrentConfirm": "Substituir \"{{name}}\" pela sua configuração de tabulação atual?", + "rename": "Renomear", + "duplicate": "Duplicado", + "duplicateNameSuffix": "{{name}} (copiar)", + "setDefault": "Definir como padrão", + "unsetDefault": "Remover como padrão", + "defaultBadge": "Predefinição", + "lastSession": "Última sessão", + "lastSessionDescription": "Atualizado automaticamente com a sua última configuração de separadores. Aplique para recuperar o que estava aberto.", + "lastUsed": "Última utilização {{time}}", + "neverUsed": "Nunca aplicado", + "tabsSkipped": "Espaço de trabalho aplicado — {{count}} separador(es) ignorado(s) (o host já não existe): {{names}}" + } + } + }, + "nav": { + "workspaces": "Espaços de trabalho" + }, + "onboarding": { + "workflow_workspaces": "Espaços de trabalho", + "workflow_workspaces_desc": "Guarde um conjunto de separadores abertos e reabra todo o layout mais tarde." + } +} diff --git a/plugins/workspaces/locales/translated/ro_RO.json b/plugins/workspaces/locales/translated/ro_RO.json new file mode 100644 index 000000000..d6e5207ea --- /dev/null +++ b/plugins/workspaces/locales/translated/ro_RO.json @@ -0,0 +1,55 @@ +{ + "newUi": { + "sidebar": { + "workspaces": { + "title": "Spații de lucru", + "saveCurrent": "Salvați curentul", + "saveCurrentTitle": "Salvați spațiul de lucru curent", + "saveCurrentDescription": "Salvați fiecare filă deschisă, aspect divizat și aranjament de panouri ca un spațiu de lucru nou denumit.", + "nameLabel": "Nume", + "namePlaceholder": "de exemplu, Depanare produs", + "nameRequired": "Numele spațiului de lucru este obligatoriu", + "colorLabel": "Culoare", + "workspaceCreated": "Spațiul de lucru a fost salvat", + "workspaceUpdated": "Spațiul de lucru a fost actualizat", + "workspaceDeleted": "Spațiul de lucru a fost șters", + "workspaceDuplicated": "Spațiul de lucru a fost duplicat", + "saveFailed": "Spațiul de lucru nu a putut fi salvat", + "updateFailed": "Spațiul de lucru nu a putut fi actualizat", + "deleteFailed": "Nu s-a putut șterge spațiul de lucru", + "duplicateFailed": "Spațiul de lucru nu a putut fi duplicat", + "loadFailed": "Nu s-au putut încărca spațiile de lucru", + "applyFailed": "Nu s-a putut aplica spațiul de lucru", + "deleteWorkspaceTitle": "Ștergeți spațiul de lucru", + "deleteWorkspaceDescription": "Sigur vrei să ștergi „{{name}}”? Această acțiune nu poate fi anulată.", + "noWorkspaces": "Încă nu există spații de lucru salvate. Salvați aranjamentul actual al filelor pentru a începe.", + "tabCount": "fila {{count}}", + "tabCount_other": "{{count}} tab-uri", + "apply": "Aplică", + "applyConfirmTitle": "Aplicați spațiul de lucru", + "applyConfirmDescription": "Aplicarea comenzii „{{name}}” va închide filele curente și le va înlocui cu aranjamentul salvat al acestui spațiu de lucru. Modificările nesalvate ale aspectului curent se vor pierde.", + "applyConfirmButton": "Aplicați spațiul de lucru", + "updateWithCurrent": "Actualizare cu curent", + "updateWithCurrentConfirm": "Suprascrieți „{{name}}” cu aranjamentul actual al tabulatorilor?", + "rename": "Redenumire", + "duplicate": "Duplicat", + "duplicateNameSuffix": "{{name}} (copie)", + "setDefault": "Setare ca implicită", + "unsetDefault": "Eliminare ca implicită", + "defaultBadge": "Implicit", + "lastSession": "Ultima sesiune", + "lastSessionDescription": "Actualizat automat cu cea mai recentă aranjare a filelor. Aplică-l pentru a recupera ce aveai deschis.", + "lastUsed": "Ultima utilizare {{time}}", + "neverUsed": "Niciodată aplicat", + "tabsSkipped": "Spațiu de lucru aplicat — {{count}} filă(e) omisă (gazda nu mai există): {{names}}" + } + } + }, + "nav": { + "workspaces": "Spații de lucru" + }, + "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." + } +} diff --git a/plugins/workspaces/locales/translated/ru_RU.json b/plugins/workspaces/locales/translated/ru_RU.json new file mode 100644 index 000000000..fad81d601 --- /dev/null +++ b/plugins/workspaces/locales/translated/ru_RU.json @@ -0,0 +1,55 @@ +{ + "newUi": { + "sidebar": { + "workspaces": { + "title": "Рабочие места", + "saveCurrent": "Сохранить текущий", + "saveCurrentTitle": "Сохранить текущее рабочее пространство", + "saveCurrentDescription": "Сохраните все открытые вкладки, разделенные окна и расположение панелей в виде новых именованных рабочих областей.", + "nameLabel": "Имя", + "namePlaceholder": "например, отладка в рабочей среде.", + "nameRequired": "Название рабочей области обязательно для ввода.", + "colorLabel": "Цвет", + "workspaceCreated": "Рабочее пространство сохранено", + "workspaceUpdated": "Рабочее пространство обновлено", + "workspaceDeleted": "Рабочее пространство удалено", + "workspaceDuplicated": "Рабочее пространство дублировано", + "saveFailed": "Не удалось сохранить рабочее пространство.", + "updateFailed": "Не удалось обновить рабочее пространство.", + "deleteFailed": "Не удалось удалить рабочее пространство.", + "duplicateFailed": "Не удалось создать дубликат рабочего пространства.", + "loadFailed": "Не удалось загрузить рабочие пространства.", + "applyFailed": "Не удалось применить рабочее пространство", + "deleteWorkspaceTitle": "Удалить рабочее пространство", + "deleteWorkspaceDescription": "Вы уверены, что хотите удалить \"{{name}}\"? Это действие необратимо.", + "noWorkspaces": "Пока нет сохраненных рабочих пространств. Сохраните текущее расположение вкладок, чтобы начать работу.", + "tabCount": "{{count}} вкладка", + "tabCount_other": "{{count}} вкладки", + "apply": "Применять", + "applyConfirmTitle": "Применить рабочее пространство", + "applyConfirmDescription": "Применение \"{{name}}\" закроет текущие вкладки и заменит их сохраненным расположением элементов в этом рабочем пространстве. Несохраненные изменения текущего расположения будут потеряны.", + "applyConfirmButton": "Применить рабочее пространство", + "updateWithCurrent": "Обновить с учетом текущих изменений", + "updateWithCurrentConfirm": "Заменить \"{{name}}\" на текущую компоновку вкладок?", + "rename": "Переименовать", + "duplicate": "Дубликат", + "duplicateNameSuffix": "{{name}} (копия)", + "setDefault": "Установить как значение по умолчанию", + "unsetDefault": "Удалить как значение по умолчанию", + "defaultBadge": "По умолчанию", + "lastSession": "Последняя сессия", + "lastSessionDescription": "Автоматическое обновление с учетом вашего последнего расположения вкладок. Примените изменения, чтобы восстановить открытые ранее вкладки.", + "lastUsed": "Последнее использование {{time}}", + "neverUsed": "Никогда не подавал заявку", + "tabsSkipped": "Рабочая область применена — {{count}} вкладки пропущены (хост больше не существует): {{names}}" + } + } + }, + "nav": { + "workspaces": "Рабочие места" + }, + "onboarding": { + "workflow_workspaces": "Рабочие места", + "workflow_workspaces_desc": "Сохраните набор открытых вкладок и откройте весь интерфейс позже." + } +} diff --git a/plugins/workspaces/locales/translated/sr_SP.json b/plugins/workspaces/locales/translated/sr_SP.json new file mode 100644 index 000000000..0ade9cb61 --- /dev/null +++ b/plugins/workspaces/locales/translated/sr_SP.json @@ -0,0 +1,55 @@ +{ + "newUi": { + "sidebar": { + "workspaces": { + "title": "Радни простори", + "saveCurrent": "Сачувај тренутно", + "saveCurrentTitle": "Сачувај тренутни радни простор", + "saveCurrentDescription": "Сачувајте сваку отворену картицу, подељени распоред и распоред окна као нови именовани радни простор.", + "nameLabel": "Име", + "namePlaceholder": "нпр. Отклањање грешака у производном систему", + "nameRequired": "Назив радног простора је обавезан", + "colorLabel": "Боја", + "workspaceCreated": "Радни простор сачуван", + "workspaceUpdated": "Радни простор је ажуриран", + "workspaceDeleted": "Радни простор је обрисан", + "workspaceDuplicated": "Радни простор је дуплиран", + "saveFailed": "Чување радног простора није успело", + "updateFailed": "Ажурирање радног простора није успело", + "deleteFailed": "Брисање радног простора није успело", + "duplicateFailed": "Дуплирање радног простора није успело", + "loadFailed": "Учитавање радних простора није успело", + "applyFailed": "Примена радног простора није успела", + "deleteWorkspaceTitle": "Обриши радни простор", + "deleteWorkspaceDescription": "Да ли сте сигурни да желите да обришете „{{name}}“? Ова радња се не може поништити.", + "noWorkspaces": "Још увек нема сачуваних радних простора. Сачувајте тренутни распоред картица да бисте започели.", + "tabCount": "{{count}} картица", + "tabCount_other": "{{count}} картице", + "apply": "Примени", + "applyConfirmTitle": "Примени радни простор", + "applyConfirmDescription": "Применом „{{name}}“ затворићете тренутне картице и заменити их сачуваним распоредом овог радног простора. Несачуване измене тренутног распореда биће изгубљене.", + "applyConfirmButton": "Примени радни простор", + "updateWithCurrent": "Ажурирај са Тренутним", + "updateWithCurrentConfirm": "Преписати „{{name}}“ тренутним распоредом табулатора?", + "rename": "Преименуј", + "duplicate": "Дупликат", + "duplicateNameSuffix": "{{name}} (копија)", + "setDefault": "Постави као подразумевано", + "unsetDefault": "Уклони као подразумевано", + "defaultBadge": "Подразумевано", + "lastSession": "Последња сесија", + "lastSessionDescription": "Аутоматски се ажурира са вашим најновијим распоредом картица. Примените га да бисте вратили оно што сте имали отворено.", + "lastUsed": "Последња употреба {{time}}", + "neverUsed": "Никада примењено", + "tabsSkipped": "Примењен радни простор — {{count}} прескочених картица (хост више не постоји): {{names}}" + } + } + }, + "nav": { + "workspaces": "Радни простори" + }, + "onboarding": { + "workflow_workspaces": "Радни простори", + "workflow_workspaces_desc": "Сачувајте скуп отворених картица и поново отворите цео распоред касније." + } +} diff --git a/plugins/workspaces/locales/translated/sv_SE.json b/plugins/workspaces/locales/translated/sv_SE.json new file mode 100644 index 000000000..4a3ef9b57 --- /dev/null +++ b/plugins/workspaces/locales/translated/sv_SE.json @@ -0,0 +1,55 @@ +{ + "newUi": { + "sidebar": { + "workspaces": { + "title": "Arbetsytor", + "saveCurrent": "Spara aktuell", + "saveCurrentTitle": "Spara aktuell arbetsyta", + "saveCurrentDescription": "Spara alla öppna flikar, delade layouter och rutorrangemang som en ny namngiven arbetsyta.", + "nameLabel": "Namn", + "namePlaceholder": "t.ex. produktfelsökning", + "nameRequired": "Arbetsytans namn krävs", + "colorLabel": "Färg", + "workspaceCreated": "Arbetsytan sparad", + "workspaceUpdated": "Arbetsytan uppdaterad", + "workspaceDeleted": "Arbetsytan raderad", + "workspaceDuplicated": "Arbetsyta duplicerad", + "saveFailed": "Kunde inte spara arbetsytan", + "updateFailed": "Misslyckades med att uppdatera arbetsytan", + "deleteFailed": "Misslyckades med att ta bort arbetsytan", + "duplicateFailed": "Misslyckades med att duplicera arbetsytan", + "loadFailed": "Misslyckades med att läsa in arbetsytor", + "applyFailed": "Kunde inte tillämpa arbetsytan", + "deleteWorkspaceTitle": "Ta bort arbetsyta", + "deleteWorkspaceDescription": "Är du säker på att du vill ta bort \"{{name}}\"? Detta kan inte ångras.", + "noWorkspaces": "Inga sparade arbetsytor ännu. Spara din nuvarande flikstruktur för att komma igång.", + "tabCount": "{{count}} flik", + "tabCount_other": "{{count}} flikar", + "apply": "Tillämpas", + "applyConfirmTitle": "Använd arbetsyta", + "applyConfirmDescription": "Om du använder \"{{name}}\" stängs dina nuvarande flikar och ersätts med den här arbetsytans sparade layout. Osparade ändringar i din nuvarande layout kommer att gå förlorade.", + "applyConfirmButton": "Använd arbetsyta", + "updateWithCurrent": "Uppdatera med aktuellt", + "updateWithCurrentConfirm": "Skriv över \"{{name}}\" med din nuvarande tabulering?", + "rename": "Döpa om", + "duplicate": "Duplicera", + "duplicateNameSuffix": "{{name}} (kopiera)", + "setDefault": "Ange som standard", + "unsetDefault": "Ta bort som standard", + "defaultBadge": "Standard", + "lastSession": "Senaste sessionen", + "lastSessionDescription": "Uppdateras automatiskt med din senaste flikstruktur. Använd den för att återställa det du hade öppet.", + "lastUsed": "Senast använd {{time}}", + "neverUsed": "Aldrig tillämpad", + "tabsSkipped": "Arbetsyta tillämpad — {{count}} flik(kar) hoppade över (värden finns inte längre): {{names}}" + } + } + }, + "nav": { + "workspaces": "Arbetsytor" + }, + "onboarding": { + "workflow_workspaces": "Arbetsytor", + "workflow_workspaces_desc": "Spara en uppsättning öppna flikar och öppna hela layouten igen senare." + } +} diff --git a/plugins/workspaces/locales/translated/th_TH.json b/plugins/workspaces/locales/translated/th_TH.json new file mode 100644 index 000000000..6721d34fa --- /dev/null +++ b/plugins/workspaces/locales/translated/th_TH.json @@ -0,0 +1,55 @@ +{ + "newUi": { + "sidebar": { + "workspaces": { + "title": "พื้นที่ทำงาน", + "saveCurrent": "บันทึกปัจจุบัน", + "saveCurrentTitle": "บันทึกพื้นที่ทำงานปัจจุบัน", + "saveCurrentDescription": "บันทึกแท็บที่เปิดอยู่ทั้งหมด รูปแบบการแบ่งหน้าจอ และการจัดเรียงบานหน้าต่างทั้งหมดเป็นพื้นที่ทำงานใหม่ที่มีชื่อ", + "nameLabel": "ชื่อ", + "namePlaceholder": "เช่น การดีบักผลิตภัณฑ์", + "nameRequired": "จำเป็นต้องระบุชื่อพื้นที่ทำงาน", + "colorLabel": "สี", + "workspaceCreated": "พื้นที่ทำงานได้รับการบันทึกแล้ว", + "workspaceUpdated": "พื้นที่ทำงานได้รับการอัปเดตแล้ว", + "workspaceDeleted": "พื้นที่ทำงานถูกลบแล้ว", + "workspaceDuplicated": "พื้นที่ทำงานถูกทำซ้ำ", + "saveFailed": "ไม่สามารถบันทึกพื้นที่ทำงานได้", + "updateFailed": "ไม่สามารถอัปเดตพื้นที่ทำงานได้", + "deleteFailed": "ไม่สามารถลบพื้นที่ทำงานได้", + "duplicateFailed": "ไม่สามารถคัดลอกพื้นที่ทำงานได้", + "loadFailed": "ไม่สามารถโหลดพื้นที่ทำงานได้", + "applyFailed": "ไม่สามารถใช้งานพื้นที่ทำงานได้", + "deleteWorkspaceTitle": "ลบพื้นที่ทำงาน", + "deleteWorkspaceDescription": "คุณแน่ใจหรือไม่ว่าต้องการลบ \"{{name}}\"? การดำเนินการนี้ไม่สามารถย้อนกลับได้", + "noWorkspaces": "ยังไม่ได้บันทึกพื้นที่ทำงานใดๆ บันทึกการจัดเรียงแท็บปัจจุบันของคุณเพื่อเริ่มต้นใช้งาน", + "tabCount": "{{count}} แท็บ", + "tabCount_other": "{{count}} แท็บ", + "apply": "นำมาใช้", + "applyConfirmTitle": "ใช้พื้นที่ทำงาน", + "applyConfirmDescription": "การใช้ \"{{name}}\" จะปิดแท็บปัจจุบันของคุณและแทนที่ด้วยการจัดเรียงที่บันทึกไว้ของพื้นที่ทำงานนี้ การเปลี่ยนแปลงที่ยังไม่ได้บันทึกในเค้าโครงปัจจุบันของคุณจะหายไป", + "applyConfirmButton": "ใช้พื้นที่ทำงาน", + "updateWithCurrent": "อัปเดตด้วยข้อมูลปัจจุบัน", + "updateWithCurrentConfirm": "เขียนทับ \"{{name}}\" ด้วยการจัดเรียงแท็บปัจจุบันของคุณหรือไม่?", + "rename": "เปลี่ยนชื่อ", + "duplicate": "ทำซ้ำ", + "duplicateNameSuffix": "{{name}} (คัดลอก)", + "setDefault": "ตั้งเป็นค่าเริ่มต้น", + "unsetDefault": "ลบออกเป็นค่าเริ่มต้น", + "defaultBadge": "ค่าเริ่มต้น", + "lastSession": "เซสชั่นสุดท้าย", + "lastSessionDescription": "ระบบจะอัปเดตการจัดเรียงแท็บล่าสุดของคุณโดยอัตโนมัติ ใช้เพื่อกู้คืนแท็บที่คุณเปิดไว้ก่อนหน้านี้", + "lastUsed": "ใช้งานครั้งล่าสุด {{time}}", + "neverUsed": "ไม่เคยสมัคร", + "tabsSkipped": "พื้นที่ทำงานถูกใช้งานแล้ว — ข้ามแท็บ {{count}} แท็บ (โฮสต์ไม่มีอยู่แล้ว): {{names}}" + } + } + }, + "nav": { + "workspaces": "พื้นที่ทำงาน" + }, + "onboarding": { + "workflow_workspaces": "พื้นที่ทำงาน", + "workflow_workspaces_desc": "บันทึกชุดแท็บที่เปิดอยู่ แล้วเปิดเค้าโครงทั้งหมดอีกครั้งในภายหลัง" + } +} diff --git a/plugins/workspaces/locales/translated/tr_TR.json b/plugins/workspaces/locales/translated/tr_TR.json new file mode 100644 index 000000000..252c1d2dc --- /dev/null +++ b/plugins/workspaces/locales/translated/tr_TR.json @@ -0,0 +1,55 @@ +{ + "newUi": { + "sidebar": { + "workspaces": { + "title": "Çalışma Alanları", + "saveCurrent": "Mevcut Olanı Kaydet", + "saveCurrentTitle": "Geçerli Çalışma Alanını Kaydet", + "saveCurrentDescription": "Açık olan her sekmeyi, bölünmüş düzeni ve bölme düzenini yeni bir adlandırılmış çalışma alanı olarak kaydedin.", + "nameLabel": "İsim", + "namePlaceholder": "Örneğin, Üretim Hata Ayıklaması", + "nameRequired": "Çalışma alanı adı zorunludur.", + "colorLabel": "Renk", + "workspaceCreated": "Çalışma alanı kaydedildi.", + "workspaceUpdated": "Çalışma alanı güncellendi.", + "workspaceDeleted": "Çalışma alanı silindi", + "workspaceDuplicated": "Çalışma alanı kopyalandı", + "saveFailed": "Çalışma alanını kaydetme başarısız oldu.", + "updateFailed": "Çalışma alanını güncelleme başarısız oldu.", + "deleteFailed": "Çalışma alanını silme işlemi başarısız oldu.", + "duplicateFailed": "Çalışma alanını çoğaltma başarısız oldu.", + "loadFailed": "Çalışma alanları yüklenemedi.", + "applyFailed": "Çalışma alanı uygulanamadı.", + "deleteWorkspaceTitle": "Çalışma Alanını Sil", + "deleteWorkspaceDescription": "\"{{name}}\" öğesini silmek istediğinizden emin misiniz? Bu işlem geri alınamaz.", + "noWorkspaces": "Henüz kaydedilmiş çalışma alanı yok. Başlamak için mevcut sekme düzeninizi kaydedin.", + "tabCount": "{{count}} sekmesi", + "tabCount_other": "{{count}} sekmeler", + "apply": "Uygula", + "applyConfirmTitle": "Çalışma Alanına Başvur", + "applyConfirmDescription": "\"{{name}}\" komutunu uygulamak, mevcut sekmelerinizi kapatacak ve bunların yerine bu çalışma alanının kaydedilmiş düzenini getirecektir. Mevcut düzeninizde yapılan kaydedilmemiş değişiklikler kaybolacaktır.", + "applyConfirmButton": "Çalışma Alanına Başvur", + "updateWithCurrent": "Güncel bilgilerle güncelleyin", + "updateWithCurrentConfirm": "\"{{name}}\" ifadesini mevcut sekme düzeninizle değiştirin mi?", + "rename": "Yeniden isimlendirmek", + "duplicate": "Kopyalamak", + "duplicateNameSuffix": "{{name}} (kopyala)", + "setDefault": "Varsayılan olarak ayarla", + "unsetDefault": "Varsayılan ayarı kaldır", + "defaultBadge": "Varsayılan", + "lastSession": "Son Oturum", + "lastSessionDescription": "En son sekme düzeninize göre otomatik olarak güncellenir. Açık olan uygulamalarınızı geri yüklemek için uygulayın.", + "lastUsed": "Son kullanım {{time}}", + "neverUsed": "Hiç başvurmadım", + "tabsSkipped": "Çalışma alanı uygulandı — {{count}} sekme atlandı (ana bilgisayar artık mevcut değil): {{names}}" + } + } + }, + "nav": { + "workspaces": "Çalışma Alanları" + }, + "onboarding": { + "workflow_workspaces": "Çalışma Alanları", + "workflow_workspaces_desc": "Açık sekmeleri kaydedin ve daha sonra tüm düzeni yeniden açın." + } +} diff --git a/plugins/workspaces/locales/translated/uk_UA.json b/plugins/workspaces/locales/translated/uk_UA.json new file mode 100644 index 000000000..c4cb5d017 --- /dev/null +++ b/plugins/workspaces/locales/translated/uk_UA.json @@ -0,0 +1,55 @@ +{ + "newUi": { + "sidebar": { + "workspaces": { + "title": "Робочі простори", + "saveCurrent": "Зберегти поточний", + "saveCurrentTitle": "Зберегти поточну робочу область", + "saveCurrentDescription": "Збережіть кожну відкриту вкладку, розділений макет та розташування панелей як нове іменоване робоче середовище.", + "nameLabel": "Ім'я", + "namePlaceholder": "наприклад, налагодження продукту", + "nameRequired": "Потрібно вказати назву робочої області", + "colorLabel": "Колір", + "workspaceCreated": "Робочу область збережено", + "workspaceUpdated": "Робочу область оновлено", + "workspaceDeleted": "Робочу область видалено", + "workspaceDuplicated": "Робочу область продубльовано", + "saveFailed": "Не вдалося зберегти робочу область", + "updateFailed": "Не вдалося оновити робочу область", + "deleteFailed": "Не вдалося видалити робочу область", + "duplicateFailed": "Не вдалося дублювати робочу область", + "loadFailed": "Не вдалося завантажити робочі області", + "applyFailed": "Не вдалося застосувати робочу область", + "deleteWorkspaceTitle": "Видалити робочу область", + "deleteWorkspaceDescription": "Ви впевнені, що хочете видалити \"{{name}}\"? Цю дію неможливо скасувати.", + "noWorkspaces": "Поки що немає збережених робочих областей. Збережіть поточне розташування вкладок, щоб розпочати.", + "tabCount": "вкладка {{count}}", + "tabCount_other": "{{count}} вкладок", + "apply": "Застосувати", + "applyConfirmTitle": "Застосувати робочу область", + "applyConfirmDescription": "Застосування \"{{name}}\" закриє ваші поточні вкладки та замінить їх збереженим розташуванням цього робочого простору. Незбережені зміни до вашого поточного макета будуть втрачені.", + "applyConfirmButton": "Застосувати робочу область", + "updateWithCurrent": "Оновити за допомогою поточного", + "updateWithCurrentConfirm": "Перезаписати \"{{name}}\" поточним розташуванням табуляцій?", + "rename": "Перейменувати", + "duplicate": "Дублікат", + "duplicateNameSuffix": "{{name}} (копія)", + "setDefault": "Встановити за замовчуванням", + "unsetDefault": "Видалити як за замовчуванням", + "defaultBadge": "За замовчуванням", + "lastSession": "Остання сесія", + "lastSessionDescription": "Автоматично оновлюється з урахуванням останнього розташування вкладок. Застосуйте це, щоб відновити те, що було відкрито.", + "lastUsed": "Востаннє використовувалося {{time}}", + "neverUsed": "Ніколи не застосовувався", + "tabsSkipped": "Робочий простір застосовано — пропущено {{count}} вкладок (хост більше не існує): {{names}}" + } + } + }, + "nav": { + "workspaces": "Робочі простори" + }, + "onboarding": { + "workflow_workspaces": "Робочі простори", + "workflow_workspaces_desc": "Збережіть набір відкритих вкладок і знову відкрийте весь макет пізніше." + } +} diff --git a/plugins/workspaces/locales/translated/vi_VN.json b/plugins/workspaces/locales/translated/vi_VN.json new file mode 100644 index 000000000..2de78abb4 --- /dev/null +++ b/plugins/workspaces/locales/translated/vi_VN.json @@ -0,0 +1,55 @@ +{ + "newUi": { + "sidebar": { + "workspaces": { + "title": "Không gian làm việc", + "saveCurrent": "Lưu hiện tại", + "saveCurrentTitle": "Lưu không gian làm việc hiện tại", + "saveCurrentDescription": "Lưu tất cả các tab đang mở, bố cục chia màn hình và cách sắp xếp khung cửa sổ dưới dạng một không gian làm việc mới có tên.", + "nameLabel": "Tên", + "namePlaceholder": "Ví dụ: Gỡ lỗi sản phẩm", + "nameRequired": "Tên không gian làm việc là bắt buộc", + "colorLabel": "Màu sắc", + "workspaceCreated": "Không gian làm việc đã được lưu", + "workspaceUpdated": "Không gian làm việc đã được cập nhật", + "workspaceDeleted": "Không gian làm việc đã bị xóa", + "workspaceDuplicated": "Không gian làm việc được sao chép", + "saveFailed": "Không thể lưu không gian làm việc", + "updateFailed": "Không thể cập nhật không gian làm việc", + "deleteFailed": "Không thể xóa không gian làm việc", + "duplicateFailed": "Không thể sao chép không gian làm việc", + "loadFailed": "Không thể tải không gian làm việc", + "applyFailed": "Không thể áp dụng không gian làm việc", + "deleteWorkspaceTitle": "Xóa không gian làm việc", + "deleteWorkspaceDescription": "Bạn có chắc chắn muốn xóa \"{{name}}\" không? Thao tác này không thể hoàn tác.", + "noWorkspaces": "Chưa có không gian làm việc nào được lưu. Hãy lưu cách bố trí tab hiện tại của bạn để bắt đầu.", + "tabCount": "{{count}} tab", + "tabCount_other": "{{count}} tab", + "apply": "Áp dụng", + "applyConfirmTitle": "Áp dụng Không gian làm việc", + "applyConfirmDescription": "Áp dụng \"{{name}}\" sẽ đóng các tab hiện tại của bạn và thay thế chúng bằng bố cục đã lưu của không gian làm việc này. Các thay đổi chưa được lưu đối với bố cục hiện tại của bạn sẽ bị mất.", + "applyConfirmButton": "Áp dụng Không gian làm việc", + "updateWithCurrent": "Cập nhật với thông tin hiện tại", + "updateWithCurrentConfirm": "Bạn có muốn ghi đè \"{{name}}\" bằng cách sắp xếp tab hiện tại của mình không?", + "rename": "Đổi tên", + "duplicate": "Nhân bản", + "duplicateNameSuffix": "{{name}} (copy)", + "setDefault": "Đặt làm mặc định", + "unsetDefault": "Xóa khỏi danh sách mặc định", + "defaultBadge": "Mặc định", + "lastSession": "Phiên cuối cùng", + "lastSessionDescription": "Tự động cập nhật với cách sắp xếp tab gần đây nhất của bạn. Áp dụng để khôi phục các tab bạn đã mở trước đó.", + "lastUsed": "Lần sử dụng cuối cùng {{time}}", + "neverUsed": "Chưa từng ứng tuyển", + "tabsSkipped": "Không gian làm việc đã được áp dụng — {{count}} tab đã bị bỏ qua (máy chủ không còn tồn tại): {{names}}" + } + } + }, + "nav": { + "workspaces": "Không gian làm việc" + }, + "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." + } +} diff --git a/plugins/workspaces/locales/translated/zh_CN.json b/plugins/workspaces/locales/translated/zh_CN.json new file mode 100644 index 000000000..47c6d90c8 --- /dev/null +++ b/plugins/workspaces/locales/translated/zh_CN.json @@ -0,0 +1,55 @@ +{ + "newUi": { + "sidebar": { + "workspaces": { + "title": "工作区", + "saveCurrent": "保存当前", + "saveCurrentTitle": "保存当前工作区", + "saveCurrentDescription": "将所有打开的标签页、拆分布局和窗格排列保存为一个新的命名工作区。", + "nameLabel": "名称", + "namePlaceholder": "例如,生产环境调试", + "nameRequired": "工作区名称为必填项", + "colorLabel": "颜色", + "workspaceCreated": "工作区已保存", + "workspaceUpdated": "工作区已更新", + "workspaceDeleted": "工作区已删除", + "workspaceDuplicated": "工作区已复制", + "saveFailed": "保存工作区失败", + "updateFailed": "工作区更新失败", + "deleteFailed": "删除工作区失败", + "duplicateFailed": "复制工作区失败", + "loadFailed": "加载工作区失败", + "applyFailed": "应用工作区失败", + "deleteWorkspaceTitle": "删除工作区", + "deleteWorkspaceDescription": "您确定要删除“{{name}}”吗?此操作无法撤销。", + "noWorkspaces": "尚未保存任何工作区。请保存您当前的标签页排列方式以开始使用。", + "tabCount": "{{count}} 个标签页", + "tabCount_other": "{{count}} 个标签页", + "apply": "应用", + "applyConfirmTitle": "应用工作区", + "applyConfirmDescription": "应用“{{name}}”将关闭您当前的标签页,并将其替换为此工作区已保存的布局。您对当前布局的未保存更改将会丢失。", + "applyConfirmButton": "应用工作区", + "updateWithCurrent": "更新至当前版本", + "updateWithCurrentConfirm": "用您当前的标签页排列覆盖“{{name}}”?", + "rename": "重命名", + "duplicate": "复制", + "duplicateNameSuffix": "{{name}}(副本)", + "setDefault": "设置为默认值", + "unsetDefault": "移除默认设置", + "defaultBadge": "默认", + "lastSession": "上次会话", + "lastSessionDescription": "自动更新至您最近的标签页排列方式。应用此操作即可恢复您之前打开的标签页。", + "lastUsed": "上次使用 {{time}}", + "neverUsed": "从未应用过", + "tabsSkipped": "已应用工作区 — 跳过 {{count}} 个标签页(主机已不存在): {{names}}" + } + } + }, + "nav": { + "workspaces": "工作区" + }, + "onboarding": { + "workflow_workspaces": "工作区", + "workflow_workspaces_desc": "保存当前打开的标签页组合,方便之后一键恢复整个布局。" + } +} diff --git a/plugins/workspaces/locales/translated/zh_TW.json b/plugins/workspaces/locales/translated/zh_TW.json new file mode 100644 index 000000000..7eaa71f46 --- /dev/null +++ b/plugins/workspaces/locales/translated/zh_TW.json @@ -0,0 +1,55 @@ +{ + "newUi": { + "sidebar": { + "workspaces": { + "title": "工作區", + "saveCurrent": "儲存目前", + "saveCurrentTitle": "儲存目前工作區", + "saveCurrentDescription": "將所有開啟的標籤頁、分割版面配置和窗格排列儲存為一個新的命名工作區。", + "nameLabel": "姓名", + "namePlaceholder": "例如,生產環境調試", + "nameRequired": "工作區名稱為必填項", + "colorLabel": "顏色", + "workspaceCreated": "工作區已儲存", + "workspaceUpdated": "工作區已更新", + "workspaceDeleted": "工作區已刪除", + "workspaceDuplicated": "工作區已複製", + "saveFailed": "保存工作區失敗", + "updateFailed": "工作區更新失敗", + "deleteFailed": "刪除工作區失敗", + "duplicateFailed": "複製工作區失敗", + "loadFailed": "載入工作區失敗", + "applyFailed": "應用工作區失敗", + "deleteWorkspaceTitle": "刪除工作區", + "deleteWorkspaceDescription": "您確定要刪除「{{name}}」嗎?此操作無法撤銷。", + "noWorkspaces": "尚未保存任何工作區。請儲存您目前的標籤頁排列方式以開始使用。", + "tabCount": "{{count}} 選項卡", + "tabCount_other": "{{count}} 標籤", + "apply": "申請", + "applyConfirmTitle": "應用工作區", + "applyConfirmDescription": "應用「{{name}}」將關閉您目前的標籤頁,並將其替換為此工作區已儲存的佈局。您對目前佈局的未儲存變更將會遺失。", + "applyConfirmButton": "應用工作區", + "updateWithCurrent": "更新至目前版本", + "updateWithCurrentConfirm": "用您目前的製表符排列覆蓋“{{name}}”?", + "rename": "重新命名", + "duplicate": "複製", + "duplicateNameSuffix": "{{name}} (複製)", + "setDefault": "設定為預設值", + "unsetDefault": "移除預設設定", + "defaultBadge": "預設", + "lastSession": "上次會議", + "lastSessionDescription": "自動更新至您最近的標籤頁排列方式。應用此操作即可恢復您先前開啟的標籤頁。", + "lastUsed": "上次使用 {{time}}", + "neverUsed": "從未申請過", + "tabsSkipped": "已應用工作區 — 跳過 {{count}} 個標籤頁(主機已不存在): {{names}}" + } + } + }, + "nav": { + "workspaces": "工作區" + }, + "onboarding": { + "workflow_workspaces": "工作區", + "workflow_workspaces_desc": "儲存一組開啟的標籤頁,稍後重新開啟整個佈局。" + } +} diff --git a/plugins/workspaces/manifest.json b/plugins/workspaces/manifest.json index b46e79162..642354dbf 100644 --- a/plugins/workspaces/manifest.json +++ b/plugins/workspaces/manifest.json @@ -16,5 +16,14 @@ }, "capabilities": ["db:own", "network:serve", "ui:surface"], "locales": "locales", - "platforms": ["linux", "win32", "darwin"] + "platforms": ["linux", "win32", "darwin"], + "contributes": { + "panels": [ + { + "id": "workspaces", + "titleKey": "nav.workspaces", + "icon": "LayoutTemplate" + } + ] + } } diff --git a/plugins/workspaces/src/frontend/WorkspacesPanel.tsx b/plugins/workspaces/src/frontend/WorkspacesPanel.tsx index 435152877..ed4acbc43 100644 --- a/plugins/workspaces/src/frontend/WorkspacesPanel.tsx +++ b/plugins/workspaces/src/frontend/WorkspacesPanel.tsx @@ -1,6 +1,6 @@ import { getErrorMessage } from "@/lib/error-message.js"; import { useState, useEffect, useCallback, useRef } from "react"; -import { useTranslation } from "react-i18next"; +import { useTranslation } from "@termix/plugin-sdk/frontend"; import { toast } from "sonner"; import { LayoutTemplate, diff --git a/plugins/workspaces/src/frontend/index.mjs b/plugins/workspaces/src/frontend/index.mjs deleted file mode 100644 index 7bc89d5a4..000000000 --- a/plugins/workspaces/src/frontend/index.mjs +++ /dev/null @@ -1,34 +0,0 @@ -/** - * Frontend half of the workspaces plugin. - * - * WorkspacesPanel is a left-sidebar railView panel (opened from the rail, - * not a Tab), the same shape as FleetsPanel/HostsPanel/CredentialsPanel. - * None of those go through registerRailItem/registerTabComponent either -- - * per src/ui/shell/pluginLoader.ts's own comment, a rail-view panel like - * this is rendered directly by AppShell.tsx rather than registered at - * runtime. WorkspacesPanel is reached today through a direct relative - * import in AppShell.tsx (../../plugins/workspaces/frontend/WorkspacesPanel), - * not through register() below. - * - * register()/unregister() still follow the same shape every other plugin's - * frontend entry does, so this is ready the moment a real frontend plugin - * loader exists -- see plugins/ssh-terminal/frontend/index.mjs and - * src/ui/tests/sidebar/plugin-extension-seam.test.tsx, which says outright - * "there is no plugin loader yet". - */ - -export const id = "workspaces"; -export const railViewId = "workspaces"; - -export async function register({ registerRailItem, icons }) { - registerRailItem?.({ - id: railViewId, - icon: icons.LayoutTemplate, - labelKey: "nav.workspaces", - separatorAfter: true, - }); -} - -export async function unregister({ unregisterRailItem }) { - unregisterRailItem?.(railViewId); -} diff --git a/plugins/workspaces/src/frontend/index.tsx b/plugins/workspaces/src/frontend/index.tsx new file mode 100644 index 000000000..e8a26da21 --- /dev/null +++ b/plugins/workspaces/src/frontend/index.tsx @@ -0,0 +1,95 @@ +import { LayoutTemplate } from "lucide-react"; +import i18next from "i18next"; +import { toast } from "sonner"; +import type { PanelProps, TermixApp } from "@termix/plugin-sdk/frontend"; +import type { Workspace, WorkspacePayload } from "@/types/ui-types"; +import { WorkspacesPanel } from "./WorkspacesPanel"; +import { + applyWorkspaceServer, + listWorkspaces, + saveLastSessionWorkspace, +} from "./workspaces-api"; + +const LAST_SESSION_DELAY_MS = 2000; + +export function activate(app: TermixApp): void { + const applyWorkspace = async (workspace: Workspace) => { + const { skipped } = await app.tabs.applyLayout( + workspace.payload as unknown as Parameters< + typeof app.tabs.applyLayout + >[0], + { name: workspace.name }, + ); + if (skipped.length > 0) { + toast.warning( + i18next.t("workspaces:newUi.sidebar.workspaces.tabsSkipped", { + count: skipped.length, + names: skipped.join(", "), + }), + ); + } + applyWorkspaceServer(workspace.id).catch(() => {}); + }; + + function Panel({ active }: PanelProps) { + return ( +
+ + app.tabs.getLayout() as unknown as WorkspacePayload + } + onApplyWorkspace={(workspace) => void applyWorkspace(workspace)} + /> +
+ ); + } + + app.registerRailItem({ + id: "workspaces", + icon: LayoutTemplate, + titleKey: "nav.workspaces", + after: "split-screen", + }); + app.registerPanel("workspaces", Panel); + + // After login, a default workspace applies unless the session already + // brought tabs back, which is the more precise restore. + app.tabs.onReady(() => { + const layout = app.tabs.getLayout() as unknown as WorkspacePayload | null; + if (layout && layout.tabs.length > 0) return; + listWorkspaces() + .then((workspaces) => { + const preferred = workspaces.find( + (workspace) => workspace.kind === "manual" && workspace.isDefault, + ); + if (preferred) void applyWorkspace(preferred); + }) + .catch(() => {}); + }); + + // Keeps an implicit "last session" snapshot current, so an arrangement can + // always be recovered even if it was never saved. + let timer: ReturnType | null = null; + app.tabs.onChange(() => { + if (timer) clearTimeout(timer); + timer = setTimeout(() => { + const layout = app.tabs.getLayout(); + if (layout) { + saveLastSessionWorkspace(layout as unknown as WorkspacePayload).catch( + () => {}, + ); + } + }, LAST_SESSION_DELAY_MS); + }); + app.onDispose(() => { + if (timer) clearTimeout(timer); + }); + + app.registerSlotContribution("onboarding.workflow", { + actionId: "workspaces.tip", + titleKey: "onboarding.workflow_workspaces", + descriptionKey: "onboarding.workflow_workspaces_desc", + icon: LayoutTemplate, + }); +} diff --git a/plugins/workspaces/src/frontend/workspaceUtils.ts b/plugins/workspaces/src/frontend/workspaceUtils.ts deleted file mode 100644 index 8fa7d07a1..000000000 --- a/plugins/workspaces/src/frontend/workspaceUtils.ts +++ /dev/null @@ -1,163 +0,0 @@ -import type { - Host, - Tab, - TabType, - WorkspacePayload, - WorkspaceTabSnapshot, -} from "@/types/ui-types"; - -// "dashboard" is deliberately excluded: AppShell always keeps a dashboard -// tab alive as the fallback when every other tab closes, so it isn't a -// meaningful part of a saved arrangement and shouldn't count toward -// tabCount or be reopened on apply. -export const WORKSPACE_CAPTURABLE_TYPES: TabType[] = [ - "terminal", - "rdp", - "vnc", - "telnet", - "host-metrics", - "proxmox-stats", - "files", - "docker", - "tunnel", - "network_graph", - "tmux_monitor", - "serial", - "homepage", - "fleet-inventory", - "termix-id", - "session-logs", - "snippets", - "macros", - "history", - "ssh-tools", - "automations", - "ai", -]; - -export const HOSTLESS_WORKSPACE_TAB_TYPES: TabType[] = [ - "tunnel", - "network_graph", - "tmux_monitor", - "homepage", - "fleet-inventory", - "docker", - "termix-id", - "session-logs", - "snippets", - "macros", - "history", - "ssh-tools", - "automations", - "ai", -]; - -function createWorkspaceSlotId(): string { - if (typeof globalThis.crypto?.randomUUID === "function") { - return globalThis.crypto.randomUUID(); - } - return `${Date.now().toString(36)}-${Math.random().toString(36).slice(2)}-${Math.random().toString(36).slice(2)}`; -} - -/** - * Maps live tabs to WorkspaceTabSnapshots, generating a fresh slotId per tab. - * slotId is a stable key within the saved payload, distinct from Tab.id - * (which is regenerated every time a tab is opened). - */ -export function buildWorkspaceTabSnapshots( - tabs: Tab[], - genSlotId: () => string = createWorkspaceSlotId, -): { snapshots: WorkspaceTabSnapshot[]; slotIdByTabId: Map } { - const capturable = tabs.filter((t) => - WORKSPACE_CAPTURABLE_TYPES.includes(t.type), - ); - const slotIdByTabId = new Map(capturable.map((t) => [t.id, genSlotId()])); - - const snapshots: WorkspaceTabSnapshot[] = capturable.map((t) => ({ - slotId: slotIdByTabId.get(t.id)!, - type: t.type, - hostSyncId: t.type === "serial" ? null : (t.host?.syncId ?? null), - hostNameSnapshot: t.host?.name ?? null, - label: t.label, - customLabel: t.customLabel, - initialFilePath: t.initialFilePath, - initialPath: t.initialPath, - fleetId: t.fleetId, - serialConfig: t.type === "serial" ? t.serialConfig : undefined, - })); - - return { snapshots, slotIdByTabId }; -} - -/** Remaps a slotId-keyed array (paneTabIds shape) to live tab ids via a slotId->tabId map. */ -export function remapSlotIds( - slotIds: (string | null)[], - slotIdToTabId: Map, -): (string | null)[] { - return slotIds.map((slotId) => - slotId != null ? (slotIdToTabId.get(slotId) ?? null) : null, - ); -} - -/** - * Resolves how to (re)open a single workspace-payload tab on apply. - * - * "singleton" covers every rail-singleton tab type (dashboard/tunnel/docker/ - * etc.) whether or not a host was resolved for it - these always go through - * openSingletonTab, which accepts an optional preselected host. "host" is - * for genuinely per-host tab types (terminal/rdp/files/...), which always - * need a resolved host to open at all. - */ -export function resolveWorkspaceTabTarget( - snapshot: WorkspaceTabSnapshot, - allHosts: Host[], -): - | { kind: "serial" } - | { kind: "singleton"; host?: Host } - | { kind: "host"; host: Host } - | { kind: "skip" } { - if (snapshot.type === "serial") { - return snapshot.serialConfig ? { kind: "serial" } : { kind: "skip" }; - } - - let host: Host | undefined; - if (snapshot.hostSyncId) { - host = allHosts.find((h) => h.syncId === snapshot.hostSyncId); - if (!host) return { kind: "skip" }; - } - - if (HOSTLESS_WORKSPACE_TAB_TYPES.includes(snapshot.type)) { - return { kind: "singleton", host }; - } - - return host ? { kind: "host", host } : { kind: "skip" }; -} - -export function buildWorkspacePayload(input: { - tabs: Tab[]; - activeTabId: string; - splitMode: WorkspacePayload["splitMode"]; - paneTabIds: (string | null)[]; - rowSizes: number[]; - rowColSizes: number[][]; - genSlotId?: () => string; - sidebar?: WorkspacePayload["sidebar"]; -}): WorkspacePayload { - const { snapshots, slotIdByTabId } = buildWorkspaceTabSnapshots( - input.tabs, - input.genSlotId, - ); - - return { - version: 1, - tabs: snapshots, - activeSlotId: slotIdByTabId.get(input.activeTabId) ?? null, - splitMode: input.splitMode, - paneTabIds: input.paneTabIds.map((tabId) => - tabId != null ? (slotIdByTabId.get(tabId) ?? null) : null, - ), - rowSizes: input.rowSizes, - rowColSizes: input.rowColSizes, - ...(input.sidebar ? { sidebar: input.sidebar } : {}), - }; -} diff --git a/plugins/workspaces/tests/frontend/activate.test.tsx b/plugins/workspaces/tests/frontend/activate.test.tsx new file mode 100644 index 000000000..814097280 --- /dev/null +++ b/plugins/workspaces/tests/frontend/activate.test.tsx @@ -0,0 +1,53 @@ +import { afterEach, describe, expect, it } from "vitest"; +import { + renderWithApp, + type RenderedPluginApp, +} from "@termix/plugin-sdk/testing"; +import type { PluginManifest } from "@termix/plugin-sdk/manifest"; +import * as plugin from "../../src/frontend/index"; +import manifestJson from "../../manifest.json"; +import locales from "../../locales/en.json"; + +const manifest = manifestJson as unknown as PluginManifest; + +const declared = (views?: Array<{ id: string }>) => + (views ?? []).map((view) => view.id).sort(); + +let rendered: RenderedPluginApp | null = null; + +afterEach(async () => { + await rendered?.deactivate(); + rendered = null; +}); + +describe(`${manifest.id} activate`, () => { + it("activates and registers only views its manifest declares", async () => { + rendered = await renderWithApp(plugin, { manifest, locales }); + const contributes = manifest.contributes as unknown as Record< + string, + Array<{ id: string }> | undefined + >; + const tabs = declared(contributes.tabs); + // A rail panel may reuse one of the plugin's tab ids. + const panels = [...declared(contributes.panels), ...tabs]; + const cards = declared(contributes.dashboardCards); + for (const id of rendered.registered.tabs()) expect(tabs).toContain(id); + for (const id of rendered.registered.panels()) expect(panels).toContain(id); + for (const id of rendered.registered.dashboardCards()) { + expect(cards).toContain(id); + } + }); + + it("removes everything it registered on deactivate", async () => { + const app = await renderWithApp(plugin, { manifest, locales }); + await app.deactivate(); + expect(app.registered.tabs()).toEqual([]); + expect(app.registered.panels()).toEqual([]); + expect(app.registered.railItems()).toEqual([]); + expect(app.registered.hostActions()).toEqual([]); + expect(app.registered.hostEditorSections()).toEqual([]); + expect(app.registered.dashboardCards()).toEqual([]); + expect(app.registered.settingsComponents()).toEqual([]); + expect(app.registered.actions()).toEqual([]); + }); +}); diff --git a/scripts/check-importmap-csp.cjs b/scripts/check-importmap-csp.cjs new file mode 100644 index 000000000..9a3721ffa --- /dev/null +++ b/scripts/check-importmap-csp.cjs @@ -0,0 +1,67 @@ +#!/usr/bin/env node +/** + * Keeps the nginx CSP in step with the plugin import map. + * + * index.html carries an inline