From 2cee2da21d25ace58aff71b4c2ff402328350b3c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=BA=8C=E4=B8=AB=E8=AE=B2=E6=A2=B5?= Date: Thu, 10 Sep 2026 12:43:46 +0800 Subject: [PATCH] feat(consul): improve deregister flow and agent write hints --- .../src/components/consul/ConsulServices.vue | 78 ++- .../ConsulServicesInteraction.spec.ts | 9 +- .../consul/__tests__/ConsulWatchViews.spec.ts | 16 +- apps/desktop/src/i18n/locales/az.ts | 6 +- apps/desktop/src/i18n/locales/consulAz.ts | 472 ++++++++++++++++++ apps/desktop/src/i18n/locales/consulEs.ts | 472 ++++++++++++++++++ apps/desktop/src/i18n/locales/consulIt.ts | 472 ++++++++++++++++++ apps/desktop/src/i18n/locales/consulJa.ts | 471 +++++++++++++++++ apps/desktop/src/i18n/locales/consulKo.ts | 471 +++++++++++++++++ apps/desktop/src/i18n/locales/consulPtBR.ts | 472 ++++++++++++++++++ apps/desktop/src/i18n/locales/consulTr.ts | 471 +++++++++++++++++ apps/desktop/src/i18n/locales/consulUi.ts | 26 +- apps/desktop/src/i18n/locales/consulZhCN.ts | 29 +- apps/desktop/src/i18n/locales/consulZhTW.ts | 471 +++++++++++++++++ apps/desktop/src/i18n/locales/es.ts | 128 ++--- apps/desktop/src/i18n/locales/it.ts | 136 ++--- apps/desktop/src/i18n/locales/ja.ts | 132 ++--- apps/desktop/src/i18n/locales/ko.ts | 142 +++--- apps/desktop/src/i18n/locales/pt-BR.ts | 128 ++--- apps/desktop/src/i18n/locales/tr.ts | 24 +- apps/desktop/src/i18n/locales/zh-TW.ts | 32 +- apps/desktop/src/lib/consul/agentTarget.ts | 27 +- 22 files changed, 4285 insertions(+), 400 deletions(-) create mode 100644 apps/desktop/src/i18n/locales/consulAz.ts create mode 100644 apps/desktop/src/i18n/locales/consulEs.ts create mode 100644 apps/desktop/src/i18n/locales/consulIt.ts create mode 100644 apps/desktop/src/i18n/locales/consulJa.ts create mode 100644 apps/desktop/src/i18n/locales/consulKo.ts create mode 100644 apps/desktop/src/i18n/locales/consulPtBR.ts create mode 100644 apps/desktop/src/i18n/locales/consulTr.ts create mode 100644 apps/desktop/src/i18n/locales/consulZhTW.ts diff --git a/apps/desktop/src/components/consul/ConsulServices.vue b/apps/desktop/src/components/consul/ConsulServices.vue index 48afa089fb..448d55a41e 100644 --- a/apps/desktop/src/components/consul/ConsulServices.vue +++ b/apps/desktop/src/components/consul/ConsulServices.vue @@ -10,7 +10,7 @@ import * as api from "@/lib/backend/api"; import { useConnectionStore } from "@/stores/connectionStore"; import { useConsulStore } from "@/stores/consulStore"; import { nextWatchIndex } from "@/lib/consul/watchState"; -import { consulAgentWriteTargetSafe } from "@/lib/consul/agentTarget"; +import { consulAgentWriteBlockedReason } from "@/lib/consul/agentTarget"; import { clampConsulPage, CONSUL_LIST_PAGE_SIZE, paginateConsulItems } from "@/lib/consul/pagination"; import { useI18n } from "vue-i18n"; import type { ConsulAgentIdentity, ConsulAgentService, ConsulAgentServiceRegistration, ConsulCatalogNode, ConsulCatalogServiceNode, ConsulDomainWatchResponse, ConsulHealthCheck, ConsulNodeServices, ConsulScope } from "@/types/consul"; @@ -35,7 +35,13 @@ const agentTarget = computed(() => { const address = String(target.address || "").trim(); return node && address ? { node, address } : null; }); -const canAgentWrite = computed(() => consulAgentWriteTargetSafe(store.getConfig(props.connectionId), identity.value?.node)); +const agentWriteBlockedReason = computed(() => consulAgentWriteBlockedReason(store.getConfig(props.connectionId), identity.value?.node)); +const canAgentWrite = computed(() => agentWriteBlockedReason.value === null); +const agentWriteDisabledMessage = computed(() => { + if (agentLoading.value && !identity.value) return t("consul.ui.agentTargetVerifying"); + const reason = agentWriteBlockedReason.value; + return reason ? t(`consul.ui.agentWriteBlocked.${reason}`) : ""; +}); const agentTargetStatus = computed<"verifying" | "writable" | "readonly">(() => { if (agentLoading.value && !identity.value) return "verifying"; return canAgentWrite.value ? "writable" : "readonly"; @@ -59,6 +65,8 @@ const agentLoading = ref(true); const saving = ref(false); const editorOpen = ref(false); const maintenancePendingId = ref(""); +const deregisterPendingId = ref(""); +const deregisterSuccess = ref(""); const form = ref({ id: "", name: "", tags: "", address: "", port: 0 }); let sequence = 0; const watchEnabled = ref(false); @@ -361,11 +369,12 @@ async function load() { if (browseMode.value === "service") await loadInstances(); else await loadNodeServices(); } - void loadAgentData(current); + if (current === sequence) await loadAgentData(current); } async function loadAgentData(current = sequence) { agentLoading.value = true; + identity.value = null; await Promise.all([ independent(t("consul.ui.agent"), async () => { const result = await withTimeout(api.consulAgentSelf(props.connectionId), 8_000, t("consul.ui.agentIdentityRequestTimedOut")); @@ -498,15 +507,41 @@ async function registerService() { } async function deregister(id: string) { - if (!canAgentWrite.value || !window.confirm(t("consul.ui.deregisterService", { id, node: agentTarget.value?.node || t("consul.ui.targetAgent") }))) return; - await independent(t("consul.ui.writeOperation"), async () => { - await api.consulAgentDeregisterService(props.connectionId, id); + if (!canAgentWrite.value || deregisterPendingId.value || maintenancePendingId.value) return; + const node = agentTarget.value?.node; + if (!node) return; + if (!window.confirm(`${t("consul.ui.deregisterService", { id, node })}\n\n${t("consul.ui.deregisterServiceHint")}`)) return; + const connectionId = props.connectionId; + const generation = consulStore.generation; + const isCurrent = () => connectionId === props.connectionId && generation === consulStore.generation; + deregisterPendingId.value = id; + deregisterSuccess.value = ""; + const writeErrorKey = t("consul.ui.writeOperation"); + const remainingErrors = { ...errors.value }; + delete remainingErrors[writeErrorKey]; + errors.value = remainingErrors; + try { + await api.consulAgentDeregisterService(connectionId, id); + } catch (error) { + if (isCurrent()) errors.value = { ...errors.value, [writeErrorKey]: errorMessage(error) }; + deregisterPendingId.value = ""; + return; + } + try { + if (!isCurrent()) return; + deregisterSuccess.value = t("consul.ui.deregisterServiceSucceeded", { id, node }); + if (selectedLocalService.value?.ID === id) selectedLocalService.value = null; + // The write has succeeded; subsequent read failures must not be reported as a failed deregistration. await load(); - }); + } catch (error) { + if (isCurrent()) errors.value = { ...errors.value, [t("consul.ui.deregisterRefreshFailed")]: errorMessage(error) }; + } finally { + deregisterPendingId.value = ""; + } } async function maintenance(id: string, enable: boolean) { - if (!canAgentWrite.value) return; + if (!canAgentWrite.value || deregisterPendingId.value || maintenancePendingId.value) return; maintenancePendingId.value = id; try { await independent(t("consul.ui.writeOperation"), async () => { @@ -540,9 +575,16 @@ watch(nodeServiceItems, (items) => { watch(filteredLocalServiceItems, (items) => { localServicePage.value = clampConsulPage(localServicePage.value, items.length); }); +watch( + () => consulStore.generation, + () => { + deregisterSuccess.value = ""; + }, +); watch( () => props.connectionId, async () => { + deregisterSuccess.value = ""; await stopWatches(); watchEnabled.value = false; watchPaused.value = false; @@ -873,8 +915,9 @@ defineExpose({ refresh: () => (void load(), true) });
- {{ t("consul.ui.agentWriteDisabledHint", { target: identity ? `${identity.node} (${identity.address})` : t("consul.ui.unknownWritesDisabled") }) }} + {{ agentWriteDisabledMessage }}
+
{{ deregisterSuccess }}
-
- + >
diff --git a/apps/desktop/src/components/consul/__tests__/ConsulServicesInteraction.spec.ts b/apps/desktop/src/components/consul/__tests__/ConsulServicesInteraction.spec.ts index 9ea28e6589..b4b815035a 100644 --- a/apps/desktop/src/components/consul/__tests__/ConsulServicesInteraction.spec.ts +++ b/apps/desktop/src/components/consul/__tests__/ConsulServicesInteraction.spec.ts @@ -198,7 +198,7 @@ describe("ConsulServices interactions", () => { expect(catalogRow!.getAttribute("aria-expanded")).toBe("false"); }); - it("keeps local service cards interactive while explaining read-only Agent actions", async () => { + it("keeps local service cards interactive and deregistration disabled when the Agent target is missing", async () => { const host = document.createElement("div"); document.body.appendChild(host); const app = createApp(ConsulServices, { connectionId: "connection-1" }); @@ -207,9 +207,14 @@ describe("ConsulServices interactions", () => { await settle(); expect(host.textContent).toContain("consul.ui.agentReadOnly"); - expect(host.textContent).toContain("consul.ui.agentWriteDisabledHint"); + expect(host.textContent).toContain("consul.ui.agentWriteBlocked.targetRequired"); expect(host.textContent).not.toContain("consul.ui.enableMaintenance"); + const deregisterButton = Array.from(host.querySelectorAll("button")).find((button) => button.textContent?.trim() === "consul.ui.deregister"); + expect(deregisterButton).toBeTruthy(); + expect(deregisterButton!.disabled).toBe(true); + expect(deregisterButton!.title).toBe("consul.ui.agentWriteBlocked.targetRequired"); + const localServiceButton = Array.from(host.querySelectorAll("button")).find((button) => button.textContent?.includes("dbx-demo-api-1")); expect(localServiceButton).toBeTruthy(); expect(localServiceButton!.hasAttribute("disabled")).toBe(false); diff --git a/apps/desktop/src/components/consul/__tests__/ConsulWatchViews.spec.ts b/apps/desktop/src/components/consul/__tests__/ConsulWatchViews.spec.ts index 14aed97166..897309ac7c 100644 --- a/apps/desktop/src/components/consul/__tests__/ConsulWatchViews.spec.ts +++ b/apps/desktop/src/components/consul/__tests__/ConsulWatchViews.spec.ts @@ -87,8 +87,10 @@ describe("Consul Catalog and Health watch views", () => { expect(services).toContain("maintenance(service.ID, false)"); expect(services).toContain('t("consul.ui.enableMaintenance")'); expect(services).toContain('t("consul.ui.disableMaintenance")'); - expect(services).toContain('v-if="canAgentWrite"'); - expect(services).toContain('t("consul.ui.agentWriteDisabledHint"'); + expect(services).toContain('v-if="canAgentWrite && !isServiceInMaintenance(service.ID)"'); + expect(services).toContain('v-else-if="canAgentWrite"'); + expect(services).toContain("t(`consul.ui.agentWriteBlocked.${reason}`)"); + expect(services).toContain("{{ agentWriteDisabledMessage }}"); }); it("keeps Catalog browsing searchable and separates readable Catalog data from Agent actions", () => { @@ -104,7 +106,11 @@ describe("Consul Catalog and Health watch views", () => { expect(services).toContain('@click="selectService(name)"'); expect(services).toContain('@click="selectNode(name)"'); expect(services).toContain("Catalog browsing must remain responsive even when an Agent endpoint is slow or unavailable."); - expect(services).toContain("void loadAgentData(current);"); + const loadSource = services.slice(services.indexOf("async function load() {"), services.indexOf("async function loadAgentData(")); + const catalogReady = loadSource.indexOf("loading.value = false;"); + const agentLoad = loadSource.indexOf("if (current === sequence) await loadAgentData(current);"); + expect(catalogReady).toBeGreaterThanOrEqual(0); + expect(agentLoad).toBeGreaterThan(catalogReady); expect(services).toContain("t('consul.ui.searchAllServices')"); expect(services).toContain("t('consul.ui.searchLocalServices')"); }); @@ -138,9 +144,11 @@ describe("Consul Catalog and Health watch views", () => { it("gates Agent writes on an explicit target that matches the Agent node", () => { for (const source of [services, health]) { expect(source).toContain("config.agentTarget || config.agent_target"); - expect(source).toContain("consulAgentWriteTargetSafe(store.getConfig(props.connectionId), identity.value?.node)"); expect(source).toContain(':disabled="!canAgentWrite"'); } + expect(services).toContain("consulAgentWriteBlockedReason(store.getConfig(props.connectionId), identity.value?.node)"); + expect(services).toContain("const canAgentWrite = computed(() => agentWriteBlockedReason.value === null);"); + expect(health).toContain("consulAgentWriteTargetSafe(store.getConfig(props.connectionId), identity.value?.node)"); }); it("supports exact-Key and prefix KV watches and exposes batch atomicity", () => { diff --git a/apps/desktop/src/i18n/locales/az.ts b/apps/desktop/src/i18n/locales/az.ts index 603d0df355..87a26d0862 100644 --- a/apps/desktop/src/i18n/locales/az.ts +++ b/apps/desktop/src/i18n/locales/az.ts @@ -1,11 +1,11 @@ import { withEnglishFallback } from "./fallback"; import docs from "./docs/az"; -import { consulUiMessages } from "./consulUi"; +import { consulAzMessages } from "./consulAz"; import { sqlServerTraceMessages as sqlServerTrace } from "./sqlServerTraceMessages"; import { meilisearchManagementAz } from "./meilisearchManagement"; const consul = { - ...consulUiMessages, + ...consulAzMessages, prefixPlaceholder: "Açar prefiksi, məsələn, app/ və ya services/", newKey: "Yeni açar", loadingKeys: "Açarlar yüklənir...", @@ -696,7 +696,7 @@ export default withEnglishFallback({ consulAgentTargetHint: "Agentin yazma əməliyyatları üçün tələb olunur. DNS/yük tarazlaşdırıcılı və nəqliyyat qatı son nöqtələri yalnız oxuma üçün qalır.", consulMeshFeatures: "Xidmət şəbəkəsi", consulMeshVisible: "Təkmil xidmət şəbəkəsi iş sahəsini göstər", - consulMeshVisibleHint: "Yalnız Connect, niyyətlər və ya həmyaşıd əlaqələrini idarə etmək üçün aktiv edin. Deaktiv olduqda iş sahəsi gizli qalır.", + consulMeshVisibleHint: "Yalnız Connect, giriş qaydaları və ya həmkar bağlantılarını idarə etmək üçün aktiv edin. Deaktiv olduqda iş sahəsi gizli qalır.", consulOperatorWrites: "Operator yazma əməliyyatları", consulOperatorVisible: "Təcrübi Operator iş sahəsini göstər", consulOperatorSnapshotRestore: "Ani görüntüdən bərpanı aktiv et", diff --git a/apps/desktop/src/i18n/locales/consulAz.ts b/apps/desktop/src/i18n/locales/consulAz.ts new file mode 100644 index 0000000000..d1ded06fb5 --- /dev/null +++ b/apps/desktop/src/i18n/locales/consulAz.ts @@ -0,0 +1,472 @@ +import type { ConsulMessages } from "./consulUi"; + +export const consulAzMessages = { + ui: { + unknown: "Naməlum", + peeringPending: "Gözləyir", + peeringEstablishing: "Qurulur", + peeringActive: "Aktiv", + peeringFailing: "Uğursuz olur", + peeringDeleting: "Silinir", + peeringTerminated: "Sonlandırılıb", + refresh: "Yenilə", + cancel: "Ləğv et", + create: "Yarat", + update: "Yenilə", + save: "Yadda saxla", + delete: "Sil", + edit: "Redaktə et", + apply: "Tətbiq et", + close: "Bağla", + hide: "Gizlət", + reveal: "Göstər", + copy: "Kopyala", + copied: "Kopyalandı", + copyFailed: "Kopyalama alınmadı", + copyOnce: "Bir dəfə kopyala", + pause: "Fasilə ver", + watchAction: "İzlə", + watchPrefix: "Prefiksi izlə", + watchModePrefix: "Prefiks", + watchModeKey: "Dəqiq açar", + sessionProtected: "Sessiya tərəfindən qorunur", + sessionProtectedHint: "Bu paylanmış kilidi qorumaq üçün redaktə və silmə deaktiv edilib.", + atomicTransaction: "Atomik tranzaksiya", + nonAtomicBatches: "{count} toplu əməliyyat arasında atomik deyil", + batchOperation: "Toplu əməliyyat {batch} · OpIndex {op}", + operationTotals: "Uğurlu {succeeded} · Ziddiyyətli {conflicted} · Buraxılmış {skipped} · Uğursuz {failed}", + deleteOperationTotals: "Uğurlu {succeeded} · Ziddiyyətli {conflicted} · Uğursuz {failed}", + clientSideMigration: "DBX mənbədən oxuyur və hədəfə yazır. Bu, Consul-un daxili məlumat mərkəzləri arası replikasiyası deyil.", + bundleFileType: "DBX Consul KV paketi", + sourceKeyMissingModifyIndex: "Mənbə açarın ModifyIndex dəyəri yoxdur", + transactionRejected: "Consul tranzaksiyanı rədd etdi", + overview: "Klasterə ümumi baxış", + capabilities: "İmkanlar", + probeLoading: "Yüklənir", + probeReady: "Hazır", + probeForbidden: "Giriş qadağandır", + probeUnsupported: "Dəstəklənmir", + probeError: "Xəta", + autopilotHealth: "Autopilot işlək vəziyyəti", + datacenter: "Məlumat mərkəzi", + agentNode: "Agent qovşağı", + agentAddress: "Agent ünvanı", + version: "Versiya", + mode: "Rejim", + server: "Server", + client: "Müştəri", + leader: "Lider", + raftPeers: "Raft üzvləri", + membersAlive: "Aktiv üzvlər", + members: "Üzvlər", + node: "Qovşaq", + address: "Ünvan", + status: "Status", + alive: "aktiv", + leaving: "ayrılır", + failed: "Uğursuz", + previousPage: "Əvvəlki səhifə", + nextPage: "Növbəti səhifə", + pageStatus: "{page} / {pages} · cəmi {total}", + searchAllServices: "Bütün xidmətlərdə axtar", + searchAllNodes: "Bütün qovşaqlarda axtar", + searchLocalServices: "Yerli Agent xidmətlərində axtar", + query: "Sorğu", + searchHealthChecks: "Yoxlama adı, ID, qovşaq, xidmət, çıxış və ya qeydlərdə axtar", + allCheckTypes: "Bütün yoxlama növləri", + clearFilters: "Filtrləri təmizlə", + healthResultCount: "{total} yoxlamadan {filtered}-i", + services: "Xidmətlər", + nodes: "Qovşaqlar", + service: "Xidmət", + catalogServices: "Kataloq xidmətləri", + catalogNodes: "Kataloq qovşaqları", + noVisibleServices: "Görünən xidmət yoxdur", + noVisibleNodes: "Görünən qovşaq yoxdur", + noMatchingServices: "Uyğun xidmət yoxdur", + noMatchingNodes: "Uyğun qovşaq yoxdur", + agentTarget: "Agent hədəfi: {target}", + agentTargetVerifying: "Agent hədəfi yoxlanılır", + unknownWritesDisabled: "naməlum - yazma deaktivdir", + targetAgent: "hədəf Agent", + agentWriteReady: "Yazıla bilər", + agentReadOnly: "Yalnız oxuma", + agentWriteDisabledHint: "Uyğun Agent hədəfi konfiqurasiya edilmədiyindən texniki xidmət və qeydiyyatdan çıxarma deaktivdir. Aşkarlanan Agent: {target}.", + agentWriteBlocked: { + connectionUnavailable: "Bağlantı konfiqurasiyası əlçatan deyil. Yazmadan əvvəl yenidən qoşulun.", + readOnly: "Bu bağlantı yalnız oxuma üçündür. Xidmətin qeydiyyatdan çıxarılması deaktivdir.", + transport: "Nəqliyyat qatları vasitəsilə Agent-ə yazmaq mümkün deyil. Hədəf Agent-ə birbaşa qoşulun.", + targetRequired: "Bağlantını redaktə edərək Agent hədəf qovşağını və ünvanını konfiqurasiya edin. Qovşaq cari Agent ilə, ünvan isə bağlantının son nöqtəsi ilə uyğun gəlməlidir.", + identityUnavailable: "Agent kimliyi oxuna bilmir. Yazma deaktivdir. Bağlantını və Agent oxuma icazələrini yoxlayıb yeniləyin.", + nodeMismatch: "Konfiqurasiya edilmiş hədəf qovşaq cari Agent ilə uyğun gəlmir. Bağlantı parametrlərini yoxlayın.", + directAddressRequired: "Agent-ə yazmaq üçün birbaşa IP və ya localhost son nöqtəsi tələb olunur. DNS və yük balanslaşdırılan ünvanlar dəstəklənmir.", + addressMismatch: "Agent hədəf ünvanı bağlantının son nöqtəsi ilə uyğun gəlmir. Bağlantı parametrlərini yoxlayın.", + invalidAddress: "Consul bağlantı ünvanı etibarsızdır. Bağlantı parametrlərini yoxlayın.", + }, + register: "Qeydiyyata al", + registrationHint: "HTTP Agent qeydiyyatları hədəf Agent-in icra mühitinə aiddir və onun daimi konfiqurasiya fayllarını dəyişmir.", + name: "Ad", + id: "ID", + port: "Port", + tags: "Teqlər (vergüllə ayrılmış)", + registerOn: "{node} üzərində qeydiyyata al", + catalogInstances: "Kataloq instansiyaları", + nodeServices: "Qovşaq xidmətləri", + serviceId: "Xidmət ID-si", + localAgentServices: "Yerli Agent xidmətləri", + enableMaintenance: "Texniki xidmət rejimini aktiv et", + disableMaintenance: "Texniki xidmət rejimini deaktiv et", + deregister: "Qeydiyyatdan çıxar", + deregisterService: "{node} üzərindəki {id} yerli xidməti qeydiyyatdan çıxarılsın?", + deregistering: "Qeydiyyatdan çıxarılır", + deregisterServiceHint: "Bu əməliyyat xidmət qeydiyyatını və əlaqəli yoxlamaları silir. Kataloq daha sonra sinxronlaşdırılır. Xidmət prosesi işləməyə davam edir və özünü yenidən qeydiyyata ala bilər.", + deregisterServiceSucceeded: "{node} üzərindəki {id} xidməti qeydiyyatdan çıxarıldı. Kataloqun sinxronlaşdırılması bir qədər vaxt ala bilər; tətbiq xidməti yenidən qeydiyyata alsa, xidmət yenidən görünə bilər.", + deregisterRefreshFailed: "Xidmət qeydiyyatdan çıxarıldı, lakin yeniləmə alınmadı. Əl ilə yeniləyin", + maintenanceReason: "DBX istifadəçi sorğusu", + serviceDetails: "{service} təfərrüatları", + kind: "Növ", + serviceKind: "ServiceKind", + standard: "standart", + metadata: "Metaverilənlər", + nodeMeta: "Qovşaq metaverilənləri", + serviceMeta: "Xidmət metaverilənləri", + nodeId: "Qovşaq ID-si", + serviceWeights: "Uğurlu / Xəbərdarlıq", + taggedAddresses: "TaggedAddresses", + enableTagOverride: "EnableTagOverride", + agent: "Agent", + watch: "İzləmə", + writeOperation: "Yazma əməliyyatı", + localServiceDetails: "Yerli xidmət təfərrüatları", + agentIdentityRequestTimedOut: "Agent kimliyinin yüklənməsi üçün vaxt bitdi.", + localServicesRequestTimedOut: "Yerli Agent xidmətlərinin yüklənməsi üçün vaxt bitdi.", + localChecksRequestTimedOut: "Yerli Agent yoxlamalarının yüklənməsi üçün vaxt bitdi.", + healthChecks: "İşlək vəziyyət yoxlamaları", + state: "Vəziyyət", + nodeName: "Qovşaq adı", + allStates: "Bütün vəziyyətlər", + passing: "Uğurlu", + warning: "Xəbərdarlıq", + critical: "Kritik", + watchPaused: "İzləməyə fasilə verilib", + watchingIndex: "{index} indeksi izlənir", + pauseWatch: "İzləməyə fasilə ver", + startWatch: "İzləməni başlat", + checkRegistrationHint: "Agent yoxlamaları {node} üzərində icra zamanı qeydiyyatlarıdır və Agent konfiqurasiya fayllarında daimi saxlanılmır.", + type: "Növ", + ttl: "TTL", + http: "HTTP", + tcp: "TCP", + grpc: "gRPC", + docker: "Docker", + script: "Skript", + arguments: "Arqumentlər", + containerId: "Konteyner ID-si", + endpoint: "Son nöqtə", + interval: "İnterval", + timeout: "Vaxt limiti", + commandArguments: "Əmr arqumentləri", + clusterHealth: "Klasterin işlək vəziyyəti", + nodeHealth: "Qovşağın işlək vəziyyəti: {node}", + serviceHealth: "Xidmətin işlək vəziyyəti: {service}", + noMatchingHealthChecks: "Uyğun işlək vəziyyət yoxlaması yoxdur", + serviceInstances: "Xidmət instansiyaları", + localAgentChecks: "Yerli Agent yoxlamaları", + maintenance: "texniki xidmət", + ttlPass: "TTL uğurlu", + ttlWarn: "TTL xəbərdarlığı", + ttlFail: "TTL uğursuz", + deregisterCheck: "{node} üzərindəki {id} yoxlaması qeydiyyatdan çıxarılsın?", + checkDetails: "{check} təfərrüatları", + checkId: "Yoxlama ID-si", + notes: "Qeydlər", + output: "Çıxış", + definition: "Tərif", + indexes: "CreateIndex / ModifyIndex", + sessionsAndLocks: "Sessiyalar və kilidlər", + sessions: "Sessiyalar", + sessionDescription: "Sessiya Consul KV kilidlərinin istifadə etdiyi icarəyə bənzər müqavilədir. TTL sessiyalarının müddəti yenilənməlidir; TTL-siz sessiyalar açıq şəkildə məhv edilənədək və ya yoxlamaları tərəfindən etibarsız edilənədək qalır.", + createSession: "Sessiya yarat", + searchSessions: "Sessiya adı, ID, qovşaq və ya yoxlamada axtar", + sessionResultCount: "{total} sessiyadan {filtered}-i göstərilir", + noMatchingSessions: "Uyğun sessiya yoxdur", + allSessionTypes: "Bütün sessiya növləri", + ttlSessions: "TTL sessiyaları", + persistentSessions: "TTL-siz sessiyalar", + allBehaviors: "Bütün davranışlar", + aclFilteredSessions: "Sessiya siyahısı ACL-lər tərəfindən filtrlənib", + sessionRequestTimedOut: "Sessiyaların yüklənməsi üçün vaxt bitdi. Consul bağlantısını yoxlayıb yenidən cəhd edin.", + complete: "Tamamlandı", + lock: "Kilid", + lockManagement: "KV kilid idarəetməsi", + lockIndex: "LockIndex {index}", + lockDelay: "Kilid gecikməsi", + lockDelayHint: "0s–60s; etibarsız edilmədən sonra kilidin yenidən alınmasını gecikdirir.", + nodeOptional: "Qovşaq (istəyə bağlı)", + behavior: "Davranış", + behaviorRelease: "azad et (release)", + behaviorDelete: "sil (delete)", + behaviorHint: "release tutulan açarları saxlayır; delete sessiyanın müddəti bitdikdə onları silir.", + releaseLocks: "Kilidləri azad et", + deleteKeys: "Açarları sil", + deleteBehaviorWarning: "Behavior=delete bu sessiya etibarsız edildikdə onun tutduğu bütün açarları silir. Davam edilsin?", + checks: "Yoxlamalar", + nodeChecks: "Qovşaq yoxlamaları", + serviceChecks: "Xidmət yoxlamaları", + nodeCheckShort: "Qovşaq", + serviceCheckShort: "Xidmət", + serviceChecksPlaceholder: "service:api:health{'@'}namespace-a", + serviceChecksHint: "Vergüllə ayrılmış yoxlama ID-ləri; əhatə dairəsi müəyyən edilmiş yoxlama üçün ID{'@'}namespace istifadə edin.", + lockHint: "Açarı yoxlayın, sessiya seçin, sonra məsləhət xarakterli kilidi alın və ya azad edin.", + key: "Açar", + inspectKey: "Açarı yoxla", + keyExists: "Açar mövcuddur", + keyNotFound: "Açar mövcud deyil", + keyUnlocked: "Açar hazırda tutulmur", + keyHeldBy: "{session} sessiyası tərəfindən tutulur", + sessionValue: "Sessiya {id}", + modifyIndexValue: "ModifyIndex {index}", + createIndex: "CreateIndex", + modifyIndexLabel: "ModifyIndex", + selectSession: "Sessiya seçin", + sessionId: "Sessiya ID-si", + expectedModifyIndex: "Gözlənilən ModifyIndex (yeni açar üçün 0)", + value: "Dəyər", + releaseMatchingSession: "Azad et", + acquire: "Al", + unnamedSession: "Adsız sessiya", + heldKeys: "Tutulan açarlar", + heldKeysIncomplete: "Nəticələr natamamdır və ya ACL ilə filtrlənib", + stop: "Dayandır", + renewNow: "İndi yenilə", + autoRenew: "Avtomatik yenilə", + autoRenewPageHint: "Avtomatik yeniləmə yalnız bu bağlantı və səhifə aktiv qaldıqda işləyir.", + noRenewRequired: "Yeniləmə tələb olunmur", + noTtl: "TTL yoxdur", + ttlOptional: "TTL (istəyə bağlı)", + ttlRangeHint: "Daimi sessiya üçün boş saxlayın və ya 10s–24h istifadə edin.", + invalidSessionTtl: "TTL boş və ya 10s ilə 24h arasında etibarlı müddət olmalıdır.", + invalidLockDelay: "Kilid gecikməsi 0s ilə 60s arasında etibarlı müddət olmalıdır.", + destroy: "Məhv et", + noHeldKeys: "Tutulan açar yoxdur", + noVisibleSessions: "Görünən sessiya yoxdur", + destroySession: "{id} sessiyası məhv edilsin? Bu sessiyadan istifadə edən kilidlər onun davranışına görə azad edilə və ya silinə bilər.", + destroySessionImpact: "{id} sessiyası məhv edilsin? Davranış: {behavior}. Tutulan açarlar ({count}): {keys}", + sessionImpactIncomplete: "Sessiyanın təsiri natamamdır və ya ACL ilə filtrlənib. Məhv etmə bloklanıb.", + sessionDetails: "TTL {ttl} · {behavior} · yoxlamalar {checks}", + tokens: "Tokenlər", + policies: "Siyasətlər", + roles: "Rollar", + authMethods: "Autentifikasiya üsulları", + bindingRules: "Bağlama qaydaları", + templatedPolicies: "Şablonlu siyasətlər", + capability: "İmkan: {status}", + capabilitySupported: "Dəstəklənir", + capabilityUnsupported: "Dəstəklənmir", + capabilityDisabled: "Deaktiv", + capabilityForbidden: "İcazə yoxdur", + capabilityUnknown: "Naməlum", + loading: "Yüklənir...", + viewOrEdit: "Bax və ya redaktə et", + cloneToken: "Tokeni klonla", + deleteAndInspectReferences: "Sil və istinadları yoxla", + noResources: "Resurs yoxdur", + editResource: "{kind} redaktə et", + createResource: "{kind} yarat", + knownImpact: "Məlum təsir: {tokens} token, {roles} rol, {bindingRules} bağlama qaydası", + incomplete: "(natamam)", + reviewAclChanges: "ACL dəyişikliklərini nəzərdən keçir", + deleteResource: "{label} sil", + tokenReferences: "Token istinadları: {tokens} · Rol istinadları: {roles} · Bağlama qaydası istinadları: {bindingRules}", + impactBlocked: "Təsir natamamdır və ya ACL ilə filtrlənib. Silmə bloklanıb.", + cloneTokenDescription: "Klonlanmış tokenin təsviri", + scope: "Consul əhatə dairəsi", + adminPartition: "İnzibati bölmə", + namespace: "Ad fəzası", + default: "standart", + applyScope: "Əhatə dairəsini tətbiq et", + enterpriseCapability: "Korporativ imkan: {status}. Həyat dövrü əməliyyatları əlçatan deyil.", + namespaces: "Ad fəzaları", + lifecycleImpact: "Əhatə dairəsindəki resurslara təsir", + inspectImpactAndDelete: "Təsiri yoxla və sil", + impactAclFiltered: "Consul ACL ilə filtrlənmiş nəticələr bildirir; silmə bloklanıb.", + impactUnavailable: "Sadalanmadı: {resources}", + impactResource: { + services: "Xidmətlər", + nodes: "Qovşaqlar", + kvKeys: "KV açarları", + healthChecks: "İşlək vəziyyət yoxlamaları", + sessions: "Sessiyalar", + configEntries: "Konfiqurasiya qeydləri", + intentions: "Giriş qaydaları", + peerings: "Həmkar bağlantıları", + namespaces: "Ad fəzaları", + aclTokens: "ACL tokenləri", + aclPolicies: "ACL siyasətləri", + aclRoles: "ACL rolları", + aclAuthMethods: "ACL autentifikasiya üsulları", + aclBindingRules: "ACL bağlama qaydaları", + }, + configEntries: "Konfiqurasiya qeydləri", + intentions: "Giriş qaydaları", + discoveryChain: "Kəşf zənciri", + peering: "Həmkar bağlantısı", + exportedServices: "İxrac edilmiş xidmətlər", + configEntryKind: "Konfiqurasiya qeydinin növü", + loadKind: "Növü yüklə", + newJson: "Yeni JSON", + modifyIndex: "ModifyIndex {index}", + rawJson: "Xam JSON", + newIntention: "Yeni giriş qaydası", + sourceService: "Mənbə xidmət", + destinationService: "Təyinat xidməti", + check: "Yoxla", + matchSource: "Mənbəni uyğunlaşdır", + matchDestination: "Təyinatı uyğunlaşdır", + allowed: "İcazə verilib", + denied: "Rədd edilib", + matchedIntentions: "{count} giriş qaydası uyğun gəldi", + details: "Təfərrüatlar", + serviceName: "Xidmət adı", + compile: "Kompilyasiya et", + defaultProtocol: "standart protokol", + configuredDatacenter: "konfiqurasiya edilmiş məlumat mərkəzi", + start: "Başlat", + next: "Növbəti: {nodes}", + terminalTarget: "Son / hədəf", + upstreamTargets: "Yuxarı axın hədəfləri ({count})", + peerName: "Həmkar adı", + peeringToken: "Bağlantı qurmaq üçün həmkar tokeni", + generateToken: "Token yarat", + establish: "Qur", + editExportedServices: "exported-services qeydini redaktə et", + serviceMeshConfigEntry: "Xidmət şəbəkəsi konfiqurasiya qeydi", + applyWithCas: "CAS ilə tətbiq et", + reviewMeshChanges: "Xidmət şəbəkəsi dəyişikliklərini nəzərdən keçir", + deleteConfig: "{kind}/{name} silinsin?", + deleteIntention: "{id} giriş qaydası silinsin?", + deleteIntentionExact: "{source} -> {destination} giriş qaydası silinsin?", + deletePeering: "{name} həmkar bağlantısı silinsin?", + permissions: "{count} icazə", + actionRule: "əməliyyat qaydası", + tools: "Consul alətləri", + preparedQueries: "Hazırlanmış sorğular", + events: "Hadisələr", + coordinates: "Şəbəkə koordinatları", + queryName: "Sorğu adı", + targetService: "Hədəf xidmət", + targetServiceValue: "Hədəf xidmət: {service}", + cancelEdit: "Redaktəni ləğv et", + execute: "İcra et", + explain: "İzah et", + eventName: "Hadisə adı", + payload: "Yük", + fire: "Göndər", + deletePreparedQuery: "{id} hazırlanmış sorğusu silinsin?", + nodesDatacenter: "{count} qovşaq · {datacenter}", + coordinateError: "{segment} · xəta {error}", + preparedQueriesDescription: + "Consul-da saxlanılan təkrar istifadə edilə bilən xidmət kəşf sorğuları. İcra et uyğun və işlək xidmət instansiyalarını tapır; İzah et qüvvədə olan sorğunu göstərir. Sadə redaktor yalnız adı və hədəf xidməti dəyişir, Consul-da artıq saxlanılan genişləndirilmiş sahələri qoruyur.", + eventsDescription: "Consul gossip vasitəsilə yayılan, çatdırılmasına zəmanət verilməyən yüngül mesajlar. Hadisələr müvəqqəti diaqnostika və ya bildirişlərdir, daimi mesaj növbəsi deyil.", + coordinatesDescription: "Şəbəkə yaxınlığını müqayisə etmək üçün Consul tərəfindən təxmin edilən, yalnız oxunan şəbəkə koordinatları. Bunlar coğrafi mövqelər deyil.", + noPreparedQueries: "Hazırlanmış sorğu yoxdur", + noEvents: "Son hadisə yoxdur", + noCoordinates: "Şəbəkə koordinatları yoxdur", + queryExecutionResult: "İcra nəticəsi · {count} instansiya · {datacenter}", + noQueryNodes: "Bu sorğuya uyğun xidmət instansiyası yoxdur", + queryExplanation: "Qüvvədə olan sorğu", + eventNodeFilter: "Qovşaq müntəzəm ifadəsi (istəyə bağlı)", + eventServiceFilter: "Xidmət müntəzəm ifadəsi (istəyə bağlı)", + eventTagFilter: "Teq müntəzəm ifadəsi (istəyə bağlı)", + eventPayloadBytes: "Yük {count} / 100 bayt", + segment: "Seqment", + error: "Xəta", + adjustment: "Düzəliş", + height: "Hündürlük", + operatorReadOnly: "Operator (yalnız oxuma)", + snapshot: "Ani görüntü", + snapshotRestore: "Ani görüntünün bərpası", + targetDatacenter: "Hədəf məlumat mərkəzi", + restoreSnapshot: "Ani görüntünü bərpa et", + restoreSnapshotConfirmation: "RESTORE SNAPSHOT {datacenter}", + autopilotUpdate: "Autopilot yeniləməsi", + cleanupDeadServers: "İşləməyən serverləri təmizlə", + updateAutopilot: "Autopilot-u yenilə", + updateAutopilotConfirmation: "UPDATE AUTOPILOT", + raftOperations: "Raft əməliyyatları", + serverId: "Server ID-si", + peerAddress: "Həmkar ünvanı (yalnız silmə)", + reenterIdAddress: "ID və ya ünvanı yenidən daxil edin", + transferLeader: "Liderliyi ötür", + removePeer: "Həmkarı sil", + gossipKeyring: "Gossip açar dəsti", + operation: "Əməliyyat", + install: "Quraşdır", + use: "İstifadə et", + remove: "Sil", + gossipKey: "Gossip açarı", + changeKeyring: "Açar dəstini dəyiş", + changeKeyringConfirmation: "CHANGE KEYRING", + licenseUpdate: "Lisenziya yeniləməsi", + license: "Lisenziya", + updateLicense: "Lisenziyanı yenilə", + updateLicenseConfirmation: "UPDATE LICENSE", + }, + tools: { + search: "Axtar", + searchTitle: "Consul KV-də axtar", + searchQuery: "Axtarılacaq mətn", + prefixOptional: "Prefiks (istəyə bağlı)", + searchAll: "Açarlar və dəyərlər", + searchKeys: "Yalnız açarlar", + searchValues: "Yalnız dəyərlər", + caseSensitive: "Böyük/kiçik hərfə həssas", + scanned: "{count} açar skan edildi", + searchLimited: "Bağlantını qorumaq üçün nəticələr məhdudlaşdırılıb.", + noSearchResults: "Uyğun açar yoxdur", + searchSummary: "Skan edilmiş {scanned} açarda {matched} uyğunluq", + exportSearchResults: "Nəticələri ixrac et", + searchResultsFileType: "Consul KV axtarış nəticələri", + searchResultsExported: "{count} axtarış nəticəsi ixrac edildi", + exportPrefix: "Prefiksi ixrac et", + prefix: "Prefiks", + emptyPrefixAll: "Əlçatan bütün açarlar üçün boş saxlayın", + exportLimitHint: "İxraclar cari əhatə dairəsini ehtiva edir və təhlükəsiz idxal üçün lazım olan açar metaverilənlərini qoruyur.", + exported: "{count} açar ixrac edildi", + import: "İdxal et", + importTitle: "Consul KV paketini idxal et", + invalidBundle: "Bu fayl etibarlı DBX Consul KV paketi deyil", + importApplied: "{count} açar idxal edildi", + migrate: "Köçür", + migrateTitle: "Consul KV-ni köçür", + sourcePrefix: "Mənbə prefiksi", + targetConnection: "Hədəf bağlantı", + selectTarget: "Hədəf bağlantı seçin", + targetReadOnly: "Hədəf bağlantı yalnız oxuma üçündür.", + conflictPolicy: "Ziddiyyət siyasəti", + policyAbort: "Ziddiyyət olduqda dayandır", + policySkip: "Ziddiyyətləri burax", + policyCas: "CAS istifadə et", + bundleSummary: "{count} açar · Məlumat mərkəzi {dc} · Ad fəzası {ns} · Bölmə {partition}", + creates: "Yarat {count}", + updates: "Yenilə {count}", + unchanged: "Dəyişməyib {count}", + skipped: "Buraxılıb {count}", + conflicts: "Ziddiyyətlər {count}", + loadPreview: "Önbaxışı yüklə", + loadingPreview: "Önbaxış yüklənir...", + apply: "Tətbiq et", + preview: "Önbaxış", + deletePrefix: "Prefiksi sil", + deletePrefixTitle: "Consul KV prefiksini sil", + deletePrefixPlaceholder: "Silinəcək prefiks", + deletePrefixWarning: "Bu əməliyyat prefiks altındakı bütün görünən açarları silir. Təsdiqləməzdən əvvəl önbaxışı nəzərdən keçirin.", + candidates: "Namizədlər {count}", + lockedCount: "Kilidli {count}", + filtered: "filtrlənib", + complete: "Tam", + confirmDeletePrefix: "Təsdiqlənmiş açarları sil", + prefixDeleted: "{count} açar silindi", + operation: { create: "Yarat", update: "Yenilə", unchanged: "Dəyişməyib", skipped: "Buraxılıb", conflict: "Ziddiyyət", locked: "Kilidli", succeeded: "Uğurlu", conflicted: "Ziddiyyət yarandı", failed: "Uğursuz" }, + }, +} satisfies ConsulMessages; diff --git a/apps/desktop/src/i18n/locales/consulEs.ts b/apps/desktop/src/i18n/locales/consulEs.ts new file mode 100644 index 0000000000..076438e77e --- /dev/null +++ b/apps/desktop/src/i18n/locales/consulEs.ts @@ -0,0 +1,472 @@ +import type { ConsulMessages } from "./consulUi"; + +export const consulEsMessages = { + ui: { + unknown: "Desconocido", + peeringPending: "Pendiente", + peeringEstablishing: "Estableciendo", + peeringActive: "Activo", + peeringFailing: "Con errores", + peeringDeleting: "Eliminando", + peeringTerminated: "Finalizado", + refresh: "Actualizar", + cancel: "Cancelar", + create: "Crear", + update: "Actualizar", + save: "Guardar", + delete: "Eliminar", + edit: "Editar", + apply: "Aplicar", + close: "Cerrar", + hide: "Ocultar", + reveal: "Mostrar", + copy: "Copiar", + copied: "Copiado", + copyFailed: "Error al copiar", + copyOnce: "Copiar una vez", + pause: "Pausar", + watchAction: "Vigilar", + watchPrefix: "Vigilar prefijo", + watchModePrefix: "Prefijo", + watchModeKey: "Clave exacta", + sessionProtected: "Protegido por una sesión", + sessionProtectedHint: "La edición y la eliminación están deshabilitadas para proteger este bloqueo distribuido.", + atomicTransaction: "Transacción atómica", + nonAtomicBatches: "Sin atomicidad entre los {count} lotes", + batchOperation: "Lote {batch} · OpIndex {op}", + operationTotals: "Correctas {succeeded} · En conflicto {conflicted} · Omitidas {skipped} · Fallidas {failed}", + deleteOperationTotals: "Correctas {succeeded} · En conflicto {conflicted} · Fallidas {failed}", + clientSideMigration: "DBX lee del origen y escribe en el destino. No es una replicación nativa de Consul entre centros de datos.", + bundleFileType: "Paquete KV de Consul de DBX", + sourceKeyMissingModifyIndex: "La clave de origen no tiene ModifyIndex", + transactionRejected: "Consul rechazó la transacción", + overview: "Resumen del clúster", + capabilities: "Capacidades", + probeLoading: "Cargando", + probeReady: "Listo", + probeForbidden: "Sin permiso", + probeUnsupported: "No compatible", + probeError: "Error", + autopilotHealth: "Estado de Autopilot", + datacenter: "Centro de datos", + agentNode: "Nodo del agente", + agentAddress: "Dirección del agente", + version: "Versión", + mode: "Modo", + server: "Servidor", + client: "Cliente", + leader: "Líder", + raftPeers: "Miembros de Raft", + membersAlive: "Miembros activos", + members: "Miembros", + node: "Nodo", + address: "Dirección", + status: "Estado", + alive: "activo", + leaving: "saliendo", + failed: "fallido", + previousPage: "Página anterior", + nextPage: "Página siguiente", + pageStatus: "{page} / {pages} · {total} en total", + searchAllServices: "Buscar en todos los servicios", + searchAllNodes: "Buscar en todos los nodos", + searchLocalServices: "Buscar servicios del agente local", + query: "Consultar", + searchHealthChecks: "Buscar por nombre de comprobación, ID, nodo, servicio, salida o notas", + allCheckTypes: "Todos los tipos de comprobación", + clearFilters: "Borrar filtros", + healthResultCount: "{filtered} de {total} comprobaciones", + services: "Servicios", + nodes: "Nodos", + service: "Servicio", + catalogServices: "Servicios del catálogo", + catalogNodes: "Nodos del catálogo", + noVisibleServices: "No hay servicios visibles", + noVisibleNodes: "No hay nodos visibles", + noMatchingServices: "No hay servicios coincidentes", + noMatchingNodes: "No hay nodos coincidentes", + agentTarget: "Agente de destino: {target}", + agentTargetVerifying: "Verificando el agente de destino", + unknownWritesDisabled: "desconocido; escrituras deshabilitadas", + targetAgent: "el agente de destino", + agentWriteReady: "Escritura habilitada", + agentReadOnly: "Solo lectura", + agentWriteDisabledHint: "No se ha configurado un agente de destino coincidente, por lo que el mantenimiento y la baja están deshabilitados. Agente detectado: {target}.", + agentWriteBlocked: { + connectionUnavailable: "La configuración de la conexión no está disponible. Vuelva a conectarse antes de escribir.", + readOnly: "Esta conexión es de solo lectura. La baja de servicios está deshabilitada.", + transport: "No se puede escribir en el agente mediante capas de transporte. Conéctese directamente al agente de destino.", + targetRequired: "Edite la conexión y configure el nodo y la dirección del agente de destino. El nodo debe coincidir con el agente actual y la dirección con el extremo de conexión.", + identityUnavailable: "No se pudo leer la identidad del agente. Las escrituras están deshabilitadas. Compruebe la conexión y los permisos de lectura del agente y actualice.", + nodeMismatch: "El nodo de destino configurado no coincide con el agente actual. Revise la configuración de la conexión.", + directAddressRequired: "Las escrituras en el agente requieren una IP directa o localhost. No se admiten direcciones DNS ni con balanceo de carga.", + addressMismatch: "La dirección del agente de destino no coincide con el extremo de conexión. Revise la configuración de la conexión.", + invalidAddress: "La dirección de conexión de Consul no es válida. Revise la configuración de la conexión.", + }, + register: "Registrar", + registrationHint: "Los registros mediante HTTP pertenecen al estado de ejecución del agente de destino y no modifican sus archivos de configuración persistentes.", + name: "Nombre", + id: "ID", + port: "Puerto", + tags: "Etiquetas (separadas por comas)", + registerOn: "Registrar en {node}", + catalogInstances: "Instancias del catálogo", + nodeServices: "Servicios del nodo", + serviceId: "ID del servicio", + localAgentServices: "Servicios del agente local", + enableMaintenance: "Habilitar mantenimiento", + disableMaintenance: "Deshabilitar mantenimiento", + deregister: "Dar de baja", + deregisterService: "¿Dar de baja el servicio local {id} de {node}?", + deregistering: "Dando de baja", + deregisterServiceHint: "Esto elimina el registro del servicio y las comprobaciones asociadas. El catálogo se sincronizará después. El proceso del servicio seguirá ejecutándose y podría registrarse de nuevo.", + deregisterServiceSucceeded: "El servicio {id} se dio de baja de {node}. La sincronización del catálogo puede tardar un momento; el servicio podría reaparecer si la aplicación vuelve a registrarlo.", + deregisterRefreshFailed: "El servicio se dio de baja, pero la actualización falló. Actualice manualmente", + maintenanceReason: "Solicitud del usuario de DBX", + serviceDetails: "Detalles de {service}", + kind: "Clase", + serviceKind: "ServiceKind", + standard: "estándar", + metadata: "Metadatos", + nodeMeta: "Metadatos del nodo", + serviceMeta: "Metadatos del servicio", + nodeId: "ID del nodo", + serviceWeights: "Correcto / Advertencia", + taggedAddresses: "TaggedAddresses", + enableTagOverride: "EnableTagOverride", + agent: "Agente", + watch: "Vigilancia", + writeOperation: "Operación de escritura", + localServiceDetails: "Detalles del servicio local", + agentIdentityRequestTimedOut: "Se agotó el tiempo de carga de la identidad del agente.", + localServicesRequestTimedOut: "Se agotó el tiempo de carga de los servicios del agente local.", + localChecksRequestTimedOut: "Se agotó el tiempo de carga de las comprobaciones del agente local.", + healthChecks: "Comprobaciones de estado", + state: "Estado", + nodeName: "Nombre del nodo", + allStates: "Todos los estados", + passing: "Correcto", + warning: "Advertencia", + critical: "Crítico", + watchPaused: "Vigilancia pausada", + watchingIndex: "Vigilando el índice {index}", + pauseWatch: "Pausar vigilancia", + startWatch: "Iniciar vigilancia", + checkRegistrationHint: "Las comprobaciones del agente son registros en ejecución en {node} y no se guardan en los archivos de configuración del agente.", + type: "Tipo", + ttl: "TTL", + http: "HTTP", + tcp: "TCP", + grpc: "gRPC", + docker: "Docker", + script: "Script", + arguments: "Argumentos", + containerId: "ID del contenedor", + endpoint: "Extremo", + interval: "Intervalo", + timeout: "Tiempo de espera", + commandArguments: "Argumentos del comando", + clusterHealth: "Estado del clúster", + nodeHealth: "Estado del nodo: {node}", + serviceHealth: "Estado del servicio: {service}", + noMatchingHealthChecks: "No hay comprobaciones de estado coincidentes", + serviceInstances: "Instancias del servicio", + localAgentChecks: "Comprobaciones del agente local", + maintenance: "mantenimiento", + ttlPass: "TTL correcto", + ttlWarn: "Advertencia TTL", + ttlFail: "Fallo TTL", + deregisterCheck: "¿Dar de baja la comprobación {id} de {node}?", + checkDetails: "Detalles de {check}", + checkId: "ID de la comprobación", + notes: "Notas", + output: "Salida", + definition: "Definición", + indexes: "CreateIndex / ModifyIndex", + sessionsAndLocks: "Sesiones y bloqueos", + sessions: "Sesiones", + sessionDescription: "Una sesión es un contrato similar a un arrendamiento que utilizan los bloqueos KV de Consul. Las sesiones con TTL requieren renovación; las sesiones sin TTL permanecen hasta que se destruyen explícitamente o sus comprobaciones las invalidan.", + createSession: "Crear sesión", + searchSessions: "Buscar por nombre de sesión, ID, nodo o comprobación", + sessionResultCount: "Mostrando {filtered} de {total} sesiones", + noMatchingSessions: "No hay sesiones coincidentes", + allSessionTypes: "Todos los tipos de sesión", + ttlSessions: "Sesiones con TTL", + persistentSessions: "Sesiones sin TTL", + allBehaviors: "Todos los comportamientos", + aclFilteredSessions: "La lista de sesiones se filtró mediante ACL", + sessionRequestTimedOut: "Se agotó el tiempo de carga de las sesiones. Compruebe la conexión de Consul e inténtelo de nuevo.", + complete: "Completo", + lock: "Bloqueo", + lockManagement: "Gestión de bloqueos KV", + lockIndex: "LockIndex {index}", + lockDelay: "Retardo del bloqueo", + lockDelayHint: "0s–60s; retrasa la readquisición tras la invalidación.", + nodeOptional: "Nodo (opcional)", + behavior: "Comportamiento", + behaviorRelease: "liberar", + behaviorDelete: "eliminar", + behaviorHint: "release conserva las claves retenidas; delete las elimina cuando caduca la sesión.", + releaseLocks: "Liberar bloqueos", + deleteKeys: "Eliminar claves", + deleteBehaviorWarning: "Behavior=delete elimina todas las claves retenidas por esta sesión cuando se invalida. ¿Continuar?", + checks: "Comprobaciones", + nodeChecks: "Comprobaciones del nodo", + serviceChecks: "Comprobaciones del servicio", + nodeCheckShort: "Nodo", + serviceCheckShort: "Servicio", + serviceChecksPlaceholder: "service:api:health{'@'}namespace-a", + serviceChecksHint: "ID de comprobación separados por comas; use ID{'@'}namespace para una comprobación con ámbito.", + lockHint: "Inspeccione la clave, seleccione una sesión y adquiera o libere el bloqueo cooperativo.", + key: "Clave", + inspectKey: "Inspeccionar clave", + keyExists: "La clave existe", + keyNotFound: "La clave no existe", + keyUnlocked: "La clave no está retenida actualmente", + keyHeldBy: "Retenida por la sesión {session}", + sessionValue: "Sesión {id}", + modifyIndexValue: "ModifyIndex {index}", + createIndex: "CreateIndex", + modifyIndexLabel: "ModifyIndex", + selectSession: "Seleccionar una sesión", + sessionId: "ID de la sesión", + expectedModifyIndex: "ModifyIndex esperado (0 para una clave nueva)", + value: "Valor", + releaseMatchingSession: "Liberar", + acquire: "Adquirir", + unnamedSession: "Sesión sin nombre", + heldKeys: "Claves retenidas", + heldKeysIncomplete: "Los resultados están incompletos o filtrados por ACL", + stop: "Detener", + renewNow: "Renovar ahora", + autoRenew: "Renovación automática", + autoRenewPageHint: "La renovación automática solo funciona mientras esta conexión y esta página permanezcan activas.", + noRenewRequired: "No requiere renovación", + noTtl: "Sin TTL", + ttlOptional: "TTL (opcional)", + ttlRangeHint: "Déjelo vacío para una sesión persistente o use un valor entre 10s y 24h.", + invalidSessionTtl: "El TTL debe estar vacío o ser una duración válida entre 10s y 24h.", + invalidLockDelay: "El retardo del bloqueo debe ser una duración válida entre 0s y 60s.", + destroy: "Destruir", + noHeldKeys: "No hay claves retenidas", + noVisibleSessions: "No hay sesiones visibles", + destroySession: "¿Destruir la sesión {id}? Los bloqueos que la utilizan podrían liberarse o eliminarse según su comportamiento.", + destroySessionImpact: "¿Destruir la sesión {id}? Comportamiento: {behavior}. Claves retenidas ({count}): {keys}", + sessionImpactIncomplete: "El impacto de la sesión está incompleto o filtrado por ACL. La destrucción está bloqueada.", + sessionDetails: "TTL {ttl} · {behavior} · comprobaciones {checks}", + tokens: "Tokens", + policies: "Políticas", + roles: "Roles", + authMethods: "Métodos de autenticación", + bindingRules: "Reglas de vinculación", + templatedPolicies: "Políticas con plantilla", + capability: "Capacidad: {status}", + capabilitySupported: "Compatible", + capabilityUnsupported: "No compatible", + capabilityDisabled: "Deshabilitada", + capabilityForbidden: "Sin permiso", + capabilityUnknown: "Desconocida", + loading: "Cargando...", + viewOrEdit: "Ver o editar", + cloneToken: "Clonar token", + deleteAndInspectReferences: "Eliminar e inspeccionar referencias", + noResources: "No hay recursos", + editResource: "Editar {kind}", + createResource: "Crear {kind}", + knownImpact: "Impacto conocido: {tokens} tokens, {roles} roles, {bindingRules} reglas de vinculación", + incomplete: "(incompleto)", + reviewAclChanges: "Revisar cambios de ACL", + deleteResource: "Eliminar {label}", + tokenReferences: "Referencias de tokens: {tokens} · Referencias de roles: {roles} · Referencias de reglas de vinculación: {bindingRules}", + impactBlocked: "El impacto está incompleto o filtrado por ACL. La eliminación está bloqueada.", + cloneTokenDescription: "Descripción del token clonado", + scope: "Ámbito de Consul", + adminPartition: "Partición administrativa", + namespace: "Espacio de nombres", + default: "predeterminado", + applyScope: "Aplicar ámbito", + enterpriseCapability: "Capacidad Enterprise: {status}. Las acciones del ciclo de vida no están disponibles.", + namespaces: "Espacios de nombres", + lifecycleImpact: "Impacto en los recursos del ámbito", + inspectImpactAndDelete: "Inspeccionar impacto y eliminar", + impactAclFiltered: "Consul indica que los resultados están filtrados por ACL; la eliminación está bloqueada.", + impactUnavailable: "No se pudo enumerar: {resources}", + impactResource: { + services: "Servicios", + nodes: "Nodos", + kvKeys: "Claves KV", + healthChecks: "Comprobaciones de estado", + sessions: "Sesiones", + configEntries: "Entradas de configuración", + intentions: "Intenciones", + peerings: "Emparejamientos", + namespaces: "Espacios de nombres", + aclTokens: "Tokens ACL", + aclPolicies: "Políticas ACL", + aclRoles: "Roles ACL", + aclAuthMethods: "Métodos de autenticación ACL", + aclBindingRules: "Reglas de vinculación ACL", + }, + configEntries: "Entradas de configuración", + intentions: "Intenciones", + discoveryChain: "Cadena de descubrimiento", + peering: "Emparejamiento", + exportedServices: "Servicios exportados", + configEntryKind: "Tipo de entrada de configuración", + loadKind: "Cargar tipo", + newJson: "Nuevo JSON", + modifyIndex: "ModifyIndex {index}", + rawJson: "JSON sin procesar", + newIntention: "Nueva intención", + sourceService: "Servicio de origen", + destinationService: "Servicio de destino", + check: "Comprobar", + matchSource: "Origen de coincidencia", + matchDestination: "Destino de coincidencia", + allowed: "Permitido", + denied: "Denegado", + matchedIntentions: "{count} intenciones coincidentes", + details: "Detalles", + serviceName: "Nombre del servicio", + compile: "Compilar", + defaultProtocol: "protocolo predeterminado", + configuredDatacenter: "centro de datos configurado", + start: "Iniciar", + next: "Siguiente: {nodes}", + terminalTarget: "Terminal / destino", + upstreamTargets: "Destinos ascendentes ({count})", + peerName: "Nombre del par", + peeringToken: "Token para establecer el emparejamiento", + generateToken: "Generar token", + establish: "Establecer", + editExportedServices: "Editar entrada exported-services", + serviceMeshConfigEntry: "Entrada de configuración de la malla de servicios", + applyWithCas: "Aplicar con CAS", + reviewMeshChanges: "Revisar cambios de la malla de servicios", + deleteConfig: "¿Eliminar {kind}/{name}?", + deleteIntention: "¿Eliminar la intención {id}?", + deleteIntentionExact: "¿Eliminar la intención {source} -> {destination}?", + deletePeering: "¿Eliminar el emparejamiento {name}?", + permissions: "{count} permisos", + actionRule: "regla de acción", + tools: "Herramientas de Consul", + preparedQueries: "Consultas preparadas", + events: "Eventos", + coordinates: "Coordenadas de red", + queryName: "Nombre de la consulta", + targetService: "Servicio de destino", + targetServiceValue: "Servicio de destino: {service}", + cancelEdit: "Cancelar edición", + execute: "Ejecutar", + explain: "Explicar", + eventName: "Nombre del evento", + payload: "Contenido", + fire: "Emitir", + deletePreparedQuery: "¿Eliminar la consulta preparada {id}?", + nodesDatacenter: "{count} nodos · {datacenter}", + coordinateError: "{segment} · error {error}", + preparedQueriesDescription: + "Consultas reutilizables de descubrimiento de servicios almacenadas en Consul. Ejecutar resuelve las instancias sanas coincidentes; Explicar muestra la consulta efectiva. El editor sencillo solo cambia el nombre y el servicio de destino, conservando los campos avanzados almacenados en Consul.", + eventsDescription: "Mensajes ligeros distribuidos mediante gossip de Consul sin garantía de entrega. Los eventos son diagnósticos o notificaciones transitorios, no una cola de mensajes persistente.", + coordinatesDescription: "Coordenadas de red de solo lectura estimadas por Consul para comparar la proximidad de red. No son ubicaciones geográficas.", + noPreparedQueries: "No hay consultas preparadas", + noEvents: "No hay eventos recientes", + noCoordinates: "No hay coordenadas de red", + queryExecutionResult: "Resultado de ejecución · {count} instancias · {datacenter}", + noQueryNodes: "Ninguna instancia de servicio coincide con esta consulta", + queryExplanation: "Consulta efectiva", + eventNodeFilter: "Expresión regular del nodo (opcional)", + eventServiceFilter: "Expresión regular del servicio (opcional)", + eventTagFilter: "Expresión regular de la etiqueta (opcional)", + eventPayloadBytes: "Contenido {count} / 100 bytes", + segment: "Segmento", + error: "Error", + adjustment: "Ajuste", + height: "Altura", + operatorReadOnly: "Operaciones (solo lectura)", + snapshot: "Instantánea", + snapshotRestore: "Restauración de instantánea", + targetDatacenter: "Centro de datos de destino", + restoreSnapshot: "Restaurar instantánea", + restoreSnapshotConfirmation: "RESTORE SNAPSHOT {datacenter}", + autopilotUpdate: "Actualización de Autopilot", + cleanupDeadServers: "Limpiar servidores inactivos", + updateAutopilot: "Actualizar Autopilot", + updateAutopilotConfirmation: "UPDATE AUTOPILOT", + raftOperations: "Operaciones de Raft", + serverId: "ID del servidor", + peerAddress: "Dirección del miembro (solo para eliminar)", + reenterIdAddress: "Vuelva a introducir el ID o la dirección", + transferLeader: "Transferir liderazgo", + removePeer: "Eliminar miembro", + gossipKeyring: "Llavero de gossip", + operation: "Operación", + install: "Instalar", + use: "Usar", + remove: "Eliminar", + gossipKey: "Clave de gossip", + changeKeyring: "Cambiar llavero", + changeKeyringConfirmation: "CHANGE KEYRING", + licenseUpdate: "Actualización de licencia", + license: "Licencia", + updateLicense: "Actualizar licencia", + updateLicenseConfirmation: "UPDATE LICENSE", + }, + tools: { + search: "Buscar", + searchTitle: "Buscar en KV de Consul", + searchQuery: "Texto que buscar", + prefixOptional: "Prefijo (opcional)", + searchAll: "Claves y valores", + searchKeys: "Solo claves", + searchValues: "Solo valores", + caseSensitive: "Distinguir mayúsculas de minúsculas", + scanned: "{count} claves examinadas", + searchLimited: "Los resultados están limitados para proteger la conexión.", + noSearchResults: "No hay claves coincidentes", + searchSummary: "{matched} coincidencias en {scanned} claves examinadas", + exportSearchResults: "Exportar resultados", + searchResultsFileType: "Resultados de búsqueda KV de Consul", + searchResultsExported: "{count} resultados de búsqueda exportados", + exportPrefix: "Exportar prefijo", + prefix: "Prefijo", + emptyPrefixAll: "Déjelo vacío para incluir todas las claves accesibles", + exportLimitHint: "Las exportaciones incluyen el ámbito actual y conservan los metadatos de las claves necesarios para una importación segura.", + exported: "{count} claves exportadas", + import: "Importar", + importTitle: "Importar paquete KV de Consul", + invalidBundle: "Este archivo no es un paquete KV de Consul de DBX válido", + importApplied: "{count} claves importadas", + migrate: "Migrar", + migrateTitle: "Migrar KV de Consul", + sourcePrefix: "Prefijo de origen", + targetConnection: "Conexión de destino", + selectTarget: "Seleccionar una conexión de destino", + targetReadOnly: "La conexión de destino es de solo lectura.", + conflictPolicy: "Política de conflictos", + policyAbort: "Abortar si hay conflictos", + policySkip: "Omitir conflictos", + policyCas: "Usar CAS", + bundleSummary: "{count} claves · Centro de datos {dc} · Espacio de nombres {ns} · Partición {partition}", + creates: "Crear {count}", + updates: "Actualizar {count}", + unchanged: "Sin cambios {count}", + skipped: "Omitidas {count}", + conflicts: "Conflictos {count}", + loadPreview: "Cargar vista previa", + loadingPreview: "Cargando vista previa...", + apply: "Aplicar", + preview: "Vista previa", + deletePrefix: "Eliminar prefijo", + deletePrefixTitle: "Eliminar prefijo KV de Consul", + deletePrefixPlaceholder: "Prefijo que eliminar", + deletePrefixWarning: "Esta operación elimina todas las claves visibles bajo el prefijo. Revise la vista previa antes de confirmar.", + candidates: "Candidatas {count}", + lockedCount: "Bloqueadas {count}", + filtered: "filtrado", + complete: "completo", + confirmDeletePrefix: "Eliminar claves confirmadas", + prefixDeleted: "{count} claves eliminadas", + operation: { create: "Crear", update: "Actualizar", unchanged: "Sin cambios", skipped: "Omitida", conflict: "Conflicto", locked: "Bloqueada", succeeded: "Correcta", conflicted: "En conflicto", failed: "Fallida" }, + }, +} satisfies ConsulMessages; diff --git a/apps/desktop/src/i18n/locales/consulIt.ts b/apps/desktop/src/i18n/locales/consulIt.ts new file mode 100644 index 0000000000..7c40fc8d4e --- /dev/null +++ b/apps/desktop/src/i18n/locales/consulIt.ts @@ -0,0 +1,472 @@ +import type { ConsulMessages } from "./consulUi"; + +export const consulItMessages = { + ui: { + unknown: "Sconosciuto", + peeringPending: "In attesa", + peeringEstablishing: "Connessione in corso", + peeringActive: "Attivo", + peeringFailing: "In errore", + peeringDeleting: "Eliminazione in corso", + peeringTerminated: "Terminato", + refresh: "Aggiorna", + cancel: "Annulla", + create: "Crea", + update: "Aggiorna", + save: "Salva", + delete: "Elimina", + edit: "Modifica", + apply: "Applica", + close: "Chiudi", + hide: "Nascondi", + reveal: "Mostra", + copy: "Copia", + copied: "Copiato", + copyFailed: "Copia non riuscita", + copyOnce: "Copia una volta", + pause: "Pausa", + watchAction: "Monitora", + watchPrefix: "Monitora prefisso", + watchModePrefix: "Prefisso", + watchModeKey: "Chiave esatta", + sessionProtected: "Protetto da una sessione", + sessionProtectedHint: "Modifica ed eliminazione disabilitate per proteggere questo blocco distribuito.", + atomicTransaction: "Transazione atomica", + nonAtomicBatches: "Non atomica tra {count} lotti", + batchOperation: "Lotto {batch} · OpIndex {op}", + operationTotals: "Riuscite {succeeded} · In conflitto {conflicted} · Ignorate {skipped} · Non riuscite {failed}", + deleteOperationTotals: "Riuscite {succeeded} · In conflitto {conflicted} · Non riuscite {failed}", + clientSideMigration: "DBX legge dall'origine e scrive nella destinazione. Non si tratta della replica nativa Consul tra datacenter.", + bundleFileType: "Pacchetto DBX Consul KV", + sourceKeyMissingModifyIndex: "La chiave di origine non ha ModifyIndex", + transactionRejected: "Consul ha rifiutato la transazione", + overview: "Panoramica del cluster", + capabilities: "Capacità", + probeLoading: "Caricamento", + probeReady: "Pronto", + probeForbidden: "Accesso negato", + probeUnsupported: "Non supportato", + probeError: "Errore", + autopilotHealth: "Stato di Autopilot", + datacenter: "Datacenter", + agentNode: "Nodo dell'agente", + agentAddress: "Indirizzo dell'agente", + version: "Versione", + mode: "Modalità", + server: "Server", + client: "Client", + leader: "Leader", + raftPeers: "Peer Raft", + membersAlive: "Membri attivi", + members: "Membri", + node: "Nodo", + address: "Indirizzo", + status: "Stato", + alive: "attivo", + leaving: "in uscita", + failed: "Non riuscito", + previousPage: "Pagina precedente", + nextPage: "Pagina successiva", + pageStatus: "{page} / {pages} · {total} totali", + searchAllServices: "Cerca in tutti i servizi", + searchAllNodes: "Cerca in tutti i nodi", + searchLocalServices: "Cerca servizi dell'agente locale", + query: "Query", + searchHealthChecks: "Cerca nome del controllo, ID, nodo, servizio, output o note", + allCheckTypes: "Tutti i tipi di controllo", + clearFilters: "Rimuovi filtri", + healthResultCount: "{filtered} di {total} controlli", + services: "Servizi", + nodes: "Nodi", + service: "Servizio", + catalogServices: "Servizi del catalogo", + catalogNodes: "Nodi del catalogo", + noVisibleServices: "Nessun servizio visibile", + noVisibleNodes: "Nessun nodo visibile", + noMatchingServices: "Nessun servizio corrispondente", + noMatchingNodes: "Nessun nodo corrispondente", + agentTarget: "Agente di destinazione: {target}", + agentTargetVerifying: "Verifica dell'agente di destinazione", + unknownWritesDisabled: "sconosciuto - scritture disabilitate", + targetAgent: "l'agente di destinazione", + agentWriteReady: "Scrittura consentita", + agentReadOnly: "Sola lettura", + agentWriteDisabledHint: "Nessun agente di destinazione corrispondente configurato: manutenzione e deregistrazione disabilitate. Agente rilevato: {target}.", + agentWriteBlocked: { + connectionUnavailable: "Configurazione della connessione non disponibile. Riconnettiti prima di scrivere.", + readOnly: "Questa connessione è di sola lettura. La deregistrazione dei servizi è disabilitata.", + transport: "Le scritture sull'agente non sono disponibili tramite i livelli di trasporto. Connettiti direttamente all'agente di destinazione.", + targetRequired: "Modifica la connessione e configura nodo e indirizzo dell'agente di destinazione. Il nodo deve corrispondere all'agente attuale e l'indirizzo all'endpoint della connessione.", + identityUnavailable: "Impossibile leggere l'identità dell'agente. Scritture disabilitate. Controlla connessione e permessi di lettura dell'agente, quindi aggiorna.", + nodeMismatch: "Il nodo di destinazione configurato non corrisponde all'agente attuale. Controlla le impostazioni della connessione.", + directAddressRequired: "Le scritture sull'agente richiedono un endpoint IP diretto o localhost. DNS e indirizzi con bilanciamento del carico non sono supportati.", + addressMismatch: "L'indirizzo dell'agente di destinazione non corrisponde all'endpoint della connessione. Controlla le impostazioni della connessione.", + invalidAddress: "L'indirizzo della connessione Consul non è valido. Controlla le impostazioni della connessione.", + }, + register: "Registra", + registrationHint: "Le registrazioni HTTP dell'agente appartengono al runtime dell'agente di destinazione e non modificano i suoi file di configurazione persistenti.", + name: "Nome", + id: "ID", + port: "Porta", + tags: "Tag (separati da virgole)", + registerOn: "Registra su {node}", + catalogInstances: "Istanze del catalogo", + nodeServices: "Servizi del nodo", + serviceId: "ID servizio", + localAgentServices: "Servizi dell'agente locale", + enableMaintenance: "Abilita manutenzione", + disableMaintenance: "Disabilita manutenzione", + deregister: "Deregistra", + deregisterService: "Deregistrare il servizio locale {id} da {node}?", + deregistering: "Deregistrazione in corso", + deregisterServiceHint: "Rimuove la registrazione del servizio e i controlli associati. Il catalogo verrà sincronizzato in seguito. Il processo del servizio continua a funzionare e potrebbe registrarsi nuovamente.", + deregisterServiceSucceeded: "Il servizio {id} è stato deregistrato da {node}. La sincronizzazione del catalogo potrebbe richiedere qualche istante; il servizio potrebbe ricomparire se l'applicazione lo registra nuovamente.", + deregisterRefreshFailed: "Servizio deregistrato, ma aggiornamento non riuscito. Aggiorna manualmente", + maintenanceReason: "Richiesta dell'utente DBX", + serviceDetails: "Dettagli di {service}", + kind: "Categoria", + serviceKind: "ServiceKind", + standard: "standard", + metadata: "Metadati", + nodeMeta: "Metadati del nodo", + serviceMeta: "Metadati del servizio", + nodeId: "ID nodo", + serviceWeights: "Regolare / Avviso", + taggedAddresses: "TaggedAddresses", + enableTagOverride: "EnableTagOverride", + agent: "Agente", + watch: "Monitoraggio", + writeOperation: "Operazione di scrittura", + localServiceDetails: "Dettagli del servizio locale", + agentIdentityRequestTimedOut: "Tempo scaduto per il caricamento dell'identità dell'agente.", + localServicesRequestTimedOut: "Tempo scaduto per il caricamento dei servizi dell'agente locale.", + localChecksRequestTimedOut: "Tempo scaduto per il caricamento dei controlli dell'agente locale.", + healthChecks: "Controlli di integrità", + state: "Stato", + nodeName: "Nome nodo", + allStates: "Tutti gli stati", + passing: "Regolare", + warning: "Avviso", + critical: "Critico", + watchPaused: "Monitoraggio in pausa", + watchingIndex: "Monitoraggio dell'indice {index}", + pauseWatch: "Sospendi monitoraggio", + startWatch: "Avvia monitoraggio", + checkRegistrationHint: "I controlli dell'agente sono registrazioni di runtime su {node} e non vengono salvati nei file di configurazione dell'agente.", + type: "Tipo", + ttl: "TTL", + http: "HTTP", + tcp: "TCP", + grpc: "gRPC", + docker: "Docker", + script: "Script", + arguments: "Argomenti", + containerId: "ID container", + endpoint: "Endpoint", + interval: "Intervallo", + timeout: "Timeout", + commandArguments: "Argomenti del comando", + clusterHealth: "Integrità del cluster", + nodeHealth: "Integrità del nodo: {node}", + serviceHealth: "Integrità del servizio: {service}", + noMatchingHealthChecks: "Nessun controllo di integrità corrispondente", + serviceInstances: "Istanze del servizio", + localAgentChecks: "Controlli dell'agente locale", + maintenance: "manutenzione", + ttlPass: "TTL regolare", + ttlWarn: "TTL in avviso", + ttlFail: "TTL critico", + deregisterCheck: "Deregistrare il controllo {id} da {node}?", + checkDetails: "Dettagli di {check}", + checkId: "ID controllo", + notes: "Note", + output: "Output", + definition: "Definizione", + indexes: "CreateIndex / ModifyIndex", + sessionsAndLocks: "Sessioni e blocchi", + sessions: "Sessioni", + sessionDescription: "Una sessione è un contratto simile a un lease usato dai blocchi Consul KV. Le sessioni TTL richiedono il rinnovo; quelle senza TTL restano attive finché non vengono distrutte esplicitamente o invalidate dai propri controlli.", + createSession: "Crea sessione", + searchSessions: "Cerca nome della sessione, ID, nodo o controllo", + sessionResultCount: "Visualizzate {filtered} di {total} sessioni", + noMatchingSessions: "Nessuna sessione corrispondente", + allSessionTypes: "Tutti i tipi di sessione", + ttlSessions: "Sessioni TTL", + persistentSessions: "Sessioni senza TTL", + allBehaviors: "Tutti i comportamenti", + aclFilteredSessions: "L'elenco delle sessioni è stato filtrato dalle ACL", + sessionRequestTimedOut: "Tempo scaduto per il caricamento delle sessioni. Controlla la connessione Consul e riprova.", + complete: "Completo", + lock: "Blocco", + lockManagement: "Gestione blocchi KV", + lockIndex: "LockIndex {index}", + lockDelay: "Ritardo del blocco", + lockDelayHint: "0s–60s; ritarda la riacquisizione dopo l'invalidazione.", + nodeOptional: "Nodo (facoltativo)", + behavior: "Comportamento", + behaviorRelease: "Rilascia (release)", + behaviorDelete: "Elimina (delete)", + behaviorHint: "release mantiene le chiavi bloccate; delete le rimuove alla scadenza della sessione.", + releaseLocks: "Rilascia blocchi", + deleteKeys: "Elimina chiavi", + deleteBehaviorWarning: "Behavior=delete rimuove tutte le chiavi bloccate da questa sessione quando viene invalidata. Continuare?", + checks: "Controlli", + nodeChecks: "Controlli del nodo", + serviceChecks: "Controlli del servizio", + nodeCheckShort: "Nodo", + serviceCheckShort: "Servizio", + serviceChecksPlaceholder: "service:api:health{'@'}namespace-a", + serviceChecksHint: "ID dei controlli separati da virgole; usa ID{'@'}namespace per un controllo con ambito.", + lockHint: "Ispeziona la chiave, seleziona una sessione, quindi acquisisci o rilascia il blocco consultivo.", + key: "Chiave", + inspectKey: "Ispeziona chiave", + keyExists: "La chiave esiste", + keyNotFound: "La chiave non esiste", + keyUnlocked: "La chiave non è attualmente bloccata", + keyHeldBy: "Bloccata dalla sessione {session}", + sessionValue: "Sessione {id}", + modifyIndexValue: "ModifyIndex {index}", + createIndex: "CreateIndex", + modifyIndexLabel: "ModifyIndex", + selectSession: "Seleziona una sessione", + sessionId: "ID sessione", + expectedModifyIndex: "ModifyIndex previsto (0 per una nuova chiave)", + value: "Valore", + releaseMatchingSession: "Rilascia", + acquire: "Acquisisci", + unnamedSession: "Sessione senza nome", + heldKeys: "Chiavi bloccate", + heldKeysIncomplete: "Risultati incompleti o filtrati dalle ACL", + stop: "Interrompi", + renewNow: "Rinnova ora", + autoRenew: "Rinnovo automatico", + autoRenewPageHint: "Il rinnovo automatico funziona solo mentre questa connessione e questa pagina restano attive.", + noRenewRequired: "Nessun rinnovo necessario", + noTtl: "Senza TTL", + ttlOptional: "TTL (facoltativo)", + ttlRangeHint: "Lascia vuoto per una sessione persistente oppure usa 10s–24h.", + invalidSessionTtl: "TTL deve essere vuoto o una durata valida tra 10s e 24h.", + invalidLockDelay: "Il ritardo del blocco deve essere una durata valida tra 0s e 60s.", + destroy: "Distruggi", + noHeldKeys: "Nessuna chiave bloccata", + noVisibleSessions: "Nessuna sessione visibile", + destroySession: "Distruggere la sessione {id}? I blocchi che la utilizzano potrebbero essere rilasciati o eliminati secondo il suo comportamento.", + destroySessionImpact: "Distruggere la sessione {id}? Comportamento: {behavior}. Chiavi bloccate ({count}): {keys}", + sessionImpactIncomplete: "L'impatto della sessione è incompleto o filtrato dalle ACL. Distruzione bloccata.", + sessionDetails: "TTL {ttl} · {behavior} · controlli {checks}", + tokens: "Token", + policies: "Policy", + roles: "Ruoli", + authMethods: "Metodi di autenticazione", + bindingRules: "Regole di associazione", + templatedPolicies: "Policy da modello", + capability: "Capacità: {status}", + capabilitySupported: "Supportato", + capabilityUnsupported: "Non supportato", + capabilityDisabled: "Disabilitato", + capabilityForbidden: "Nessun permesso", + capabilityUnknown: "Sconosciuto", + loading: "Caricamento...", + viewOrEdit: "Visualizza o modifica", + cloneToken: "Clona token", + deleteAndInspectReferences: "Elimina e ispeziona riferimenti", + noResources: "Nessuna risorsa", + editResource: "Modifica {kind}", + createResource: "Crea {kind}", + knownImpact: "Impatto noto: {tokens} token, {roles} ruoli, {bindingRules} regole di associazione", + incomplete: "(incompleto)", + reviewAclChanges: "Rivedi modifiche ACL", + deleteResource: "Elimina {label}", + tokenReferences: "Riferimenti ai token: {tokens} · Ai ruoli: {roles} · Alle regole di associazione: {bindingRules}", + impactBlocked: "Impatto incompleto o filtrato dalle ACL. Eliminazione bloccata.", + cloneTokenDescription: "Descrizione del token clonato", + scope: "Ambito Consul", + adminPartition: "Partizione amministrativa", + namespace: "Namespace", + default: "predefinito", + applyScope: "Applica ambito", + enterpriseCapability: "Capacità Enterprise: {status}. Azioni del ciclo di vita non disponibili.", + namespaces: "Namespace", + lifecycleImpact: "Impatto sulle risorse nell'ambito", + inspectImpactAndDelete: "Ispeziona impatto ed elimina", + impactAclFiltered: "Consul segnala risultati filtrati dalle ACL; eliminazione bloccata.", + impactUnavailable: "Impossibile elencare: {resources}", + impactResource: { + services: "Servizi", + nodes: "Nodi", + kvKeys: "Chiavi KV", + healthChecks: "Controlli di integrità", + sessions: "Sessioni", + configEntries: "Voci di configurazione", + intentions: "Intenzioni", + peerings: "Peering", + namespaces: "Namespace", + aclTokens: "Token ACL", + aclPolicies: "Policy ACL", + aclRoles: "Ruoli ACL", + aclAuthMethods: "Metodi di autenticazione ACL", + aclBindingRules: "Regole di associazione ACL", + }, + configEntries: "Voci di configurazione", + intentions: "Intenzioni", + discoveryChain: "Catena di individuazione", + peering: "Peering", + exportedServices: "Servizi esportati", + configEntryKind: "Tipo di voce di configurazione", + loadKind: "Carica tipo", + newJson: "Nuovo JSON", + modifyIndex: "ModifyIndex {index}", + rawJson: "JSON originale", + newIntention: "Nuova intenzione", + sourceService: "Servizio di origine", + destinationService: "Servizio di destinazione", + check: "Controlla", + matchSource: "Origine corrispondente", + matchDestination: "Destinazione corrispondente", + allowed: "Consentito", + denied: "Negato", + matchedIntentions: "{count} intenzioni corrispondenti", + details: "Dettagli", + serviceName: "Nome servizio", + compile: "Compila", + defaultProtocol: "protocollo predefinito", + configuredDatacenter: "datacenter configurato", + start: "Avvia", + next: "Successivo: {nodes}", + terminalTarget: "Terminale / destinazione", + upstreamTargets: "Destinazioni upstream ({count})", + peerName: "Nome peer", + peeringToken: "Token per stabilire il peering", + generateToken: "Genera token", + establish: "Stabilisci", + editExportedServices: "Modifica voce exported-services", + serviceMeshConfigEntry: "Voce di configurazione della mesh di servizi", + applyWithCas: "Applica con CAS", + reviewMeshChanges: "Rivedi modifiche alla mesh di servizi", + deleteConfig: "Eliminare {kind}/{name}?", + deleteIntention: "Eliminare l'intenzione {id}?", + deleteIntentionExact: "Eliminare l'intenzione {source} -> {destination}?", + deletePeering: "Eliminare il peering {name}?", + permissions: "{count} permessi", + actionRule: "regola di azione", + tools: "Strumenti Consul", + preparedQueries: "Query preparate", + events: "Eventi", + coordinates: "Coordinate di rete", + queryName: "Nome query", + targetService: "Servizio di destinazione", + targetServiceValue: "Servizio di destinazione: {service}", + cancelEdit: "Annulla modifica", + execute: "Esegui", + explain: "Spiega", + eventName: "Nome evento", + payload: "Payload", + fire: "Invia", + deletePreparedQuery: "Eliminare la query preparata {id}?", + nodesDatacenter: "{count} nodi · {datacenter}", + coordinateError: "{segment} · errore {error}", + preparedQueriesDescription: + "Query riutilizzabili per l'individuazione dei servizi, memorizzate in Consul. Esegui risolve le istanze integre corrispondenti; Spiega mostra la query effettiva. L'editor semplice modifica solo nome e servizio di destinazione, mantenendo i campi avanzati già memorizzati da Consul.", + eventsDescription: "Messaggi leggeri distribuiti tramite gossip di Consul senza garanzia di consegna. Gli eventi sono diagnostica o notifiche transitorie, non una coda di messaggi persistente.", + coordinatesDescription: "Coordinate di rete in sola lettura stimate da Consul per confrontare la prossimità di rete. Non sono posizioni geografiche.", + noPreparedQueries: "Nessuna query preparata", + noEvents: "Nessun evento recente", + noCoordinates: "Nessuna coordinata di rete", + queryExecutionResult: "Risultato dell'esecuzione · {count} istanze · {datacenter}", + noQueryNodes: "Nessuna istanza di servizio corrisponde a questa query", + queryExplanation: "Query effettiva", + eventNodeFilter: "Regex del nodo (facoltativa)", + eventServiceFilter: "Regex del servizio (facoltativa)", + eventTagFilter: "Regex dei tag (facoltativa)", + eventPayloadBytes: "Payload {count} / 100 byte", + segment: "Segmento", + error: "Errore", + adjustment: "Correzione", + height: "Altezza", + operatorReadOnly: "Operatore (sola lettura)", + snapshot: "Snapshot", + snapshotRestore: "Ripristino snapshot", + targetDatacenter: "Datacenter di destinazione", + restoreSnapshot: "Ripristina snapshot", + restoreSnapshotConfirmation: "RESTORE SNAPSHOT {datacenter}", + autopilotUpdate: "Aggiornamento Autopilot", + cleanupDeadServers: "Rimuovi server inattivi", + updateAutopilot: "Aggiorna Autopilot", + updateAutopilotConfirmation: "UPDATE AUTOPILOT", + raftOperations: "Operazioni Raft", + serverId: "ID server", + peerAddress: "Indirizzo peer (solo rimozione)", + reenterIdAddress: "Reinserisci ID o indirizzo", + transferLeader: "Trasferisci leadership", + removePeer: "Rimuovi peer", + gossipKeyring: "Portachiavi gossip", + operation: "Operazione", + install: "Installa", + use: "Usa", + remove: "Rimuovi", + gossipKey: "Chiave gossip", + changeKeyring: "Modifica portachiavi", + changeKeyringConfirmation: "CHANGE KEYRING", + licenseUpdate: "Aggiornamento licenza", + license: "Licenza", + updateLicense: "Aggiorna licenza", + updateLicenseConfirmation: "UPDATE LICENSE", + }, + tools: { + search: "Cerca", + searchTitle: "Cerca in Consul KV", + searchQuery: "Testo da cercare", + prefixOptional: "Prefisso (facoltativo)", + searchAll: "Chiavi e valori", + searchKeys: "Solo chiavi", + searchValues: "Solo valori", + caseSensitive: "Distingui maiuscole e minuscole", + scanned: "{count} chiavi esaminate", + searchLimited: "I risultati sono limitati per proteggere la connessione.", + noSearchResults: "Nessuna chiave corrispondente", + searchSummary: "{matched} corrispondenze su {scanned} chiavi esaminate", + exportSearchResults: "Esporta risultati", + searchResultsFileType: "Risultati di ricerca Consul KV", + searchResultsExported: "{count} risultati di ricerca esportati", + exportPrefix: "Esporta prefisso", + prefix: "Prefisso", + emptyPrefixAll: "Lascia vuoto per tutte le chiavi accessibili", + exportLimitHint: "Le esportazioni includono l'ambito attuale e conservano i metadati delle chiavi necessari per un'importazione sicura.", + exported: "{count} chiavi esportate", + import: "Importa", + importTitle: "Importa pacchetto Consul KV", + invalidBundle: "Questo file non è un pacchetto DBX Consul KV valido", + importApplied: "{count} chiavi importate", + migrate: "Migra", + migrateTitle: "Migra Consul KV", + sourcePrefix: "Prefisso di origine", + targetConnection: "Connessione di destinazione", + selectTarget: "Seleziona una connessione di destinazione", + targetReadOnly: "La connessione di destinazione è di sola lettura.", + conflictPolicy: "Policy per i conflitti", + policyAbort: "Interrompi in caso di conflitto", + policySkip: "Ignora conflitti", + policyCas: "Usa CAS", + bundleSummary: "{count} chiavi · Datacenter {dc} · Namespace {ns} · Partizione {partition}", + creates: "Crea {count}", + updates: "Aggiorna {count}", + unchanged: "Invariato {count}", + skipped: "Ignorato {count}", + conflicts: "Conflitti {count}", + loadPreview: "Carica anteprima", + loadingPreview: "Caricamento anteprima...", + apply: "Applica", + preview: "Anteprima", + deletePrefix: "Elimina prefisso", + deletePrefixTitle: "Elimina prefisso Consul KV", + deletePrefixPlaceholder: "Prefisso da eliminare", + deletePrefixWarning: "Questa operazione elimina tutte le chiavi visibili sotto il prefisso. Controlla l'anteprima prima di confermare.", + candidates: "Candidati {count}", + lockedCount: "Bloccate {count}", + filtered: "filtrato", + complete: "Completo", + confirmDeletePrefix: "Elimina chiavi confermate", + prefixDeleted: "{count} chiavi eliminate", + operation: { create: "Crea", update: "Aggiorna", unchanged: "Invariato", skipped: "Ignorato", conflict: "Conflitto", locked: "Bloccato", succeeded: "Riuscito", conflicted: "In conflitto", failed: "Non riuscito" }, + }, +} satisfies ConsulMessages; diff --git a/apps/desktop/src/i18n/locales/consulJa.ts b/apps/desktop/src/i18n/locales/consulJa.ts new file mode 100644 index 0000000000..cf822a3deb --- /dev/null +++ b/apps/desktop/src/i18n/locales/consulJa.ts @@ -0,0 +1,471 @@ +import type { ConsulMessages } from "./consulUi"; + +export const consulJaMessages = { + ui: { + unknown: "不明", + peeringPending: "保留中", + peeringEstablishing: "接続確立中", + peeringActive: "有効", + peeringFailing: "障害発生中", + peeringDeleting: "削除中", + peeringTerminated: "終了", + refresh: "更新", + cancel: "キャンセル", + create: "作成", + update: "更新", + save: "保存", + delete: "削除", + edit: "編集", + apply: "適用", + close: "閉じる", + hide: "非表示", + reveal: "表示", + copy: "コピー", + copied: "コピーしました", + copyFailed: "コピーに失敗しました", + copyOnce: "一度だけコピー", + pause: "一時停止", + watchAction: "監視", + watchPrefix: "プレフィックスを監視", + watchModePrefix: "プレフィックス", + watchModeKey: "完全一致キー", + sessionProtected: "セッションで保護されています", + sessionProtectedHint: "この分散ロックを保護するため、編集と削除は無効です。", + atomicTransaction: "アトミックトランザクション", + nonAtomicBatches: "{count} バッチ全体のアトミック性は保証されません", + batchOperation: "バッチ {batch} · 操作インデックス {op}", + operationTotals: "成功 {succeeded} · 競合 {conflicted} · スキップ {skipped} · 失敗 {failed}", + deleteOperationTotals: "成功 {succeeded} · 競合 {conflicted} · 失敗 {failed}", + clientSideMigration: "DBX が移行元から読み取り、移行先に書き込みます。Consul ネイティブのデータセンター間レプリケーションではありません。", + bundleFileType: "DBX Consul KV バンドル", + sourceKeyMissingModifyIndex: "移行元キーに ModifyIndex がありません", + transactionRejected: "Consul がトランザクションを拒否しました", + overview: "クラスター概要", + capabilities: "機能", + probeLoading: "読み込み中", + probeReady: "準備完了", + probeForbidden: "権限なし", + probeUnsupported: "非対応", + probeError: "エラー", + autopilotHealth: "Autopilot の健全性", + datacenter: "データセンター", + agentNode: "Agent ノード", + agentAddress: "Agent アドレス", + version: "バージョン", + mode: "モード", + server: "サーバー", + client: "クライアント", + leader: "リーダー", + raftPeers: "Raft ピア", + membersAlive: "稼働中のメンバー", + members: "メンバー", + node: "ノード", + address: "アドレス", + status: "状態", + alive: "稼働中", + leaving: "離脱中", + failed: "障害", + previousPage: "前のページ", + nextPage: "次のページ", + pageStatus: "{page} / {pages} · 合計 {total} 件", + searchAllServices: "すべてのサービスを検索", + searchAllNodes: "すべてのノードを検索", + searchLocalServices: "ローカル Agent サービスを検索", + query: "クエリ", + searchHealthChecks: "チェック名、ID、ノード、サービス、出力、メモを検索", + allCheckTypes: "すべてのチェック種別", + clearFilters: "フィルターを解除", + healthResultCount: "{total} 件中 {filtered} 件のチェック", + services: "サービス", + nodes: "ノード", + service: "サービス", + catalogServices: "Catalog サービス", + catalogNodes: "Catalog ノード", + noVisibleServices: "表示可能なサービスはありません", + noVisibleNodes: "表示可能なノードはありません", + noMatchingServices: "一致するサービスはありません", + noMatchingNodes: "一致するノードはありません", + agentTarget: "対象 Agent: {target}", + agentTargetVerifying: "対象 Agent を確認中", + unknownWritesDisabled: "不明 — 書き込みは無効です", + targetAgent: "対象 Agent", + agentWriteReady: "書き込み可能", + agentReadOnly: "読み取り専用", + agentWriteDisabledHint: "一致する対象 Agent が設定されていないため、メンテナンスと登録解除は無効です。検出された Agent: {target}。", + agentWriteBlocked: { + connectionUnavailable: "接続設定を取得できません。再接続してから操作してください。", + readOnly: "この接続は読み取り専用です。サービスの登録解除は無効です。", + transport: "トランスポート層経由では Agent に書き込めません。対象 Agent に直接接続してください。", + targetRequired: "接続を編集して対象 Agent のノードとアドレスを設定してください。ノードは現在の Agent と、アドレスは接続先と一致する必要があります。", + identityUnavailable: "Agent の識別情報を取得できないため、書き込みは無効です。接続と Agent の読み取り権限を確認して更新してください。", + nodeMismatch: "設定された対象ノードが現在の Agent と一致しません。接続設定を確認してください。", + directAddressRequired: "Agent への書き込みには IP または localhost への直接接続が必要です。DNS 名や負荷分散アドレスは使用できません。", + addressMismatch: "対象 Agent のアドレスが接続先と一致しません。接続設定を確認してください。", + invalidAddress: "Consul の接続アドレスが無効です。接続設定を確認してください。", + }, + register: "登録", + registrationHint: "HTTP 経由の Agent 登録は対象 Agent の実行時に適用され、永続設定ファイルは変更しません。", + name: "名前", + id: "ID", + port: "ポート", + tags: "タグ(カンマ区切り)", + registerOn: "{node} に登録", + catalogInstances: "Catalog インスタンス", + nodeServices: "ノードのサービス", + serviceId: "サービス ID", + localAgentServices: "ローカル Agent サービス", + enableMaintenance: "メンテナンスを有効化", + disableMaintenance: "メンテナンスを無効化", + deregister: "登録解除", + deregisterService: "{node} からローカルサービス {id} の登録を解除しますか?", + deregistering: "登録解除中", + deregisterServiceHint: "サービス登録と関連チェックを削除し、その後 Catalog が同期されます。サービスプロセスは停止せず、再登録される場合があります。", + deregisterServiceSucceeded: "{node} からサービス {id} の登録を解除しました。Catalog の同期には少し時間がかかる場合があります。アプリが再登録するとサービスが再表示されることがあります。", + deregisterRefreshFailed: "サービスの登録は解除されましたが、更新に失敗しました。手動で更新してください", + maintenanceReason: "DBX ユーザーの要求", + serviceDetails: "{service} の詳細", + kind: "種類", + serviceKind: "サービス種別(ServiceKind)", + standard: "標準", + metadata: "メタデータ", + nodeMeta: "ノードのメタデータ", + serviceMeta: "サービスのメタデータ", + nodeId: "ノード ID", + serviceWeights: "正常 / 警告の重み", + taggedAddresses: "タグ付きアドレス", + enableTagOverride: "タグ上書きの許可", + agent: "Agent", + watch: "監視", + writeOperation: "書き込み操作", + localServiceDetails: "ローカルサービスの詳細", + agentIdentityRequestTimedOut: "Agent 識別情報の読み込みがタイムアウトしました。", + localServicesRequestTimedOut: "ローカル Agent サービスの読み込みがタイムアウトしました。", + localChecksRequestTimedOut: "ローカル Agent チェックの読み込みがタイムアウトしました。", + healthChecks: "ヘルスチェック", + state: "状態", + nodeName: "ノード名", + allStates: "すべての状態", + passing: "正常", + warning: "警告", + critical: "重大", + watchPaused: "監視を一時停止中", + watchingIndex: "インデックス {index} を監視中", + pauseWatch: "監視を一時停止", + startWatch: "監視を開始", + checkRegistrationHint: "Agent チェックは {node} の実行時登録であり、Agent の設定ファイルには保存されません。", + type: "種別", + ttl: "TTL", + http: "HTTP", + tcp: "TCP", + grpc: "gRPC", + docker: "Docker", + script: "スクリプト", + arguments: "引数", + containerId: "コンテナー ID", + endpoint: "エンドポイント", + interval: "間隔", + timeout: "タイムアウト", + commandArguments: "コマンド引数", + clusterHealth: "クラスターの健全性", + nodeHealth: "ノードの健全性: {node}", + serviceHealth: "サービスの健全性: {service}", + noMatchingHealthChecks: "一致するヘルスチェックはありません", + serviceInstances: "サービスインスタンス", + localAgentChecks: "ローカル Agent チェック", + maintenance: "メンテナンス", + ttlPass: "TTL を正常に設定", + ttlWarn: "TTL を警告に設定", + ttlFail: "TTL を異常に設定", + deregisterCheck: "{node} からチェック {id} の登録を解除しますか?", + checkDetails: "{check} の詳細", + checkId: "チェック ID", + notes: "メモ", + output: "出力", + definition: "定義", + indexes: "CreateIndex / ModifyIndex", + sessionsAndLocks: "セッションとロック", + sessions: "セッション", + sessionDescription: "セッションは Consul KV ロックで使用するリースに似た契約です。TTL 付きセッションには更新が必要です。TTL なしのセッションは明示的に破棄されるか、チェックで無効化されるまで存続します。", + createSession: "セッションを作成", + searchSessions: "セッション名、ID、ノード、チェックを検索", + sessionResultCount: "{total} 件中 {filtered} 件のセッションを表示", + noMatchingSessions: "一致するセッションはありません", + allSessionTypes: "すべてのセッション種別", + ttlSessions: "TTL 付きセッション", + persistentSessions: "TTL なしのセッション", + allBehaviors: "すべての動作", + aclFilteredSessions: "セッション一覧は ACL によってフィルターされています", + sessionRequestTimedOut: "セッションの読み込みがタイムアウトしました。Consul 接続を確認して再試行してください。", + complete: "完全", + lock: "ロック", + lockManagement: "KV ロック管理", + lockIndex: "LockIndex {index}", + lockDelay: "ロック遅延", + lockDelayHint: "0s~60s。無効化後の再取得を遅延させます。", + nodeOptional: "ノード(任意)", + behavior: "動作", + behaviorRelease: "解放(release)", + behaviorDelete: "削除(delete)", + behaviorHint: "セッション失効時に release は保持中のキーを残し、delete は削除します。", + releaseLocks: "ロックを解放", + deleteKeys: "キーを削除", + deleteBehaviorWarning: "Behavior=delete はセッション無効化時に保持中のすべてのキーを削除します。続行しますか?", + checks: "チェック", + nodeChecks: "ノードのチェック", + serviceChecks: "サービスのチェック", + nodeCheckShort: "ノード", + serviceCheckShort: "サービス", + serviceChecksPlaceholder: "service:api:health{'@'}namespace-a", + serviceChecksHint: "チェック ID をカンマで区切ります。名前空間を指定する場合は ID{'@'}namespace を使用してください。", + lockHint: "キーを調べ、セッションを選択してからアドバイザリロックを取得または解放してください。", + key: "キー", + inspectKey: "キーを調査", + keyExists: "キーは存在します", + keyNotFound: "キーは存在しません", + keyUnlocked: "キーは現在保持されていません", + keyHeldBy: "セッション {session} が保持中", + sessionValue: "セッション {id}", + modifyIndexValue: "ModifyIndex {index}", + createIndex: "CreateIndex", + modifyIndexLabel: "ModifyIndex", + selectSession: "セッションを選択", + sessionId: "セッション ID", + expectedModifyIndex: "期待する ModifyIndex(新規キーは 0)", + value: "値", + releaseMatchingSession: "解放", + acquire: "取得", + unnamedSession: "名前のないセッション", + heldKeys: "保持中のキー", + heldKeysIncomplete: "結果が不完全、または ACL でフィルターされています", + stop: "停止", + renewNow: "今すぐ延長", + autoRenew: "自動延長", + autoRenewPageHint: "自動延長は、この接続とページがアクティブな間のみ実行されます。", + noRenewRequired: "延長不要", + noTtl: "TTL なし", + ttlOptional: "TTL(任意)", + ttlRangeHint: "永続セッションは空欄にし、それ以外は 10s~24h を指定してください。", + invalidSessionTtl: "TTL は空欄、または 10s~24h の有効な期間にしてください。", + invalidLockDelay: "ロック遅延は 0s~60s の有効な期間にしてください。", + destroy: "破棄", + noHeldKeys: "保持中のキーはありません", + noVisibleSessions: "表示可能なセッションはありません", + destroySession: "セッション {id} を破棄しますか?このセッションのロックは動作設定に応じて解放または削除されます。", + destroySessionImpact: "セッション {id} を破棄しますか?動作: {behavior}。保持中のキー({count}): {keys}", + sessionImpactIncomplete: "セッションの影響範囲が不完全、または ACL でフィルターされています。破棄はブロックされました。", + sessionDetails: "TTL {ttl} · {behavior} · チェック {checks}", + tokens: "トークン", + policies: "ポリシー", + roles: "ロール", + authMethods: "認証方式", + bindingRules: "バインド規則", + templatedPolicies: "テンプレートポリシー", + capability: "機能: {status}", + capabilitySupported: "対応", + capabilityUnsupported: "非対応", + capabilityDisabled: "無効", + capabilityForbidden: "権限なし", + capabilityUnknown: "不明", + loading: "読み込み中...", + viewOrEdit: "表示または編集", + cloneToken: "トークンを複製", + deleteAndInspectReferences: "削除と参照の確認", + noResources: "リソースはありません", + editResource: "{kind} を編集", + createResource: "{kind} を作成", + knownImpact: "既知の影響: トークン {tokens}、ロール {roles}、バインド規則 {bindingRules}", + incomplete: "(不完全)", + reviewAclChanges: "ACL の変更を確認", + deleteResource: "{label} を削除", + tokenReferences: "トークン参照: {tokens} · ロール参照: {roles} · バインド規則参照: {bindingRules}", + impactBlocked: "影響範囲が不完全、または ACL でフィルターされています。削除はブロックされました。", + cloneTokenDescription: "複製するトークンの説明", + scope: "Consul のスコープ", + adminPartition: "管理パーティション", + namespace: "名前空間", + default: "既定", + applyScope: "スコープを適用", + enterpriseCapability: "Enterprise 機能: {status}。ライフサイクル操作は利用できません。", + namespaces: "名前空間", + lifecycleImpact: "スコープ内のリソースへの影響", + inspectImpactAndDelete: "影響を確認して削除", + impactAclFiltered: "Consul の結果が ACL でフィルターされているため、削除はブロックされました。", + impactUnavailable: "列挙できないリソース: {resources}", + impactResource: { + services: "サービス", + nodes: "ノード", + kvKeys: "KV キー", + healthChecks: "ヘルスチェック", + sessions: "セッション", + configEntries: "設定エントリ", + intentions: "通信許可規則", + peerings: "ピアリング", + namespaces: "名前空間", + aclTokens: "ACL トークン", + aclPolicies: "ACL ポリシー", + aclRoles: "ACL ロール", + aclAuthMethods: "ACL 認証方式", + aclBindingRules: "ACL バインド規則", + }, + configEntries: "設定エントリ", + intentions: "通信許可規則", + discoveryChain: "サービス検出チェーン", + peering: "ピアリング", + exportedServices: "公開サービス", + configEntryKind: "設定エントリの種別", + loadKind: "種別を読み込む", + newJson: "新規 JSON", + modifyIndex: "ModifyIndex {index}", + rawJson: "元の JSON", + newIntention: "通信許可規則を作成", + sourceService: "送信元サービス", + destinationService: "送信先サービス", + check: "確認", + matchSource: "送信元を照合", + matchDestination: "送信先を照合", + allowed: "許可", + denied: "拒否", + matchedIntentions: "一致する通信許可規則: {count} 件", + details: "詳細", + serviceName: "サービス名", + compile: "コンパイル", + defaultProtocol: "既定のプロトコル", + configuredDatacenter: "設定済みデータセンター", + start: "開始", + next: "次: {nodes}", + terminalTarget: "終端 / 対象", + upstreamTargets: "上流の対象({count})", + peerName: "ピア名", + peeringToken: "接続確立用ピアリングトークン", + generateToken: "トークンを生成", + establish: "接続を確立", + editExportedServices: "exported-services エントリを編集", + serviceMeshConfigEntry: "サービスメッシュ設定エントリ", + applyWithCas: "CAS で適用", + reviewMeshChanges: "サービスメッシュの変更を確認", + deleteConfig: "{kind}/{name} を削除しますか?", + deleteIntention: "通信許可規則 {id} を削除しますか?", + deleteIntentionExact: "通信許可規則 {source} -> {destination} を削除しますか?", + deletePeering: "ピアリング {name} を削除しますか?", + permissions: "権限 {count} 件", + actionRule: "操作規則", + tools: "Consul ツール", + preparedQueries: "保存済みクエリ", + events: "イベント", + coordinates: "ネットワーク座標", + queryName: "クエリ名", + targetService: "対象サービス", + targetServiceValue: "対象サービス: {service}", + cancelEdit: "編集をキャンセル", + execute: "実行", + explain: "内容を確認", + eventName: "イベント名", + payload: "ペイロード", + fire: "発行", + deletePreparedQuery: "保存済みクエリ {id} を削除しますか?", + nodesDatacenter: "ノード {count} 件 · {datacenter}", + coordinateError: "{segment} · 誤差 {error}", + preparedQueriesDescription: "Consul に保存された再利用可能なサービス検出クエリです。「実行」は一致する正常なサービスインスタンスを解決し、「内容を確認」は有効なクエリを表示します。簡易エディターは名前と対象サービスのみを変更し、Consul に保存済みの詳細フィールドを保持します。", + eventsDescription: "Consul の gossip で配信する軽量なベストエフォート型メッセージです。イベントは一時的な診断や通知であり、永続メッセージキューではありません。", + coordinatesDescription: "ネットワークの近さを比較するために Consul が推定した読み取り専用の座標です。地理的な位置ではありません。", + noPreparedQueries: "保存済みクエリはありません", + noEvents: "最近のイベントはありません", + noCoordinates: "ネットワーク座標はありません", + queryExecutionResult: "実行結果 · インスタンス {count} 件 · {datacenter}", + noQueryNodes: "このクエリに一致するサービスインスタンスはありません", + queryExplanation: "有効なクエリ", + eventNodeFilter: "ノードの正規表現(任意)", + eventServiceFilter: "サービスの正規表現(任意)", + eventTagFilter: "タグの正規表現(任意)", + eventPayloadBytes: "ペイロード {count} / 100 バイト", + segment: "セグメント", + error: "エラー", + adjustment: "補正値", + height: "高さ", + operatorReadOnly: "運用管理(読み取り専用)", + snapshot: "スナップショット", + snapshotRestore: "スナップショット復元", + targetDatacenter: "対象データセンター", + restoreSnapshot: "スナップショットを復元", + restoreSnapshotConfirmation: "RESTORE SNAPSHOT {datacenter}", + autopilotUpdate: "Autopilot 更新", + cleanupDeadServers: "停止したサーバーを除去", + updateAutopilot: "Autopilot を更新", + updateAutopilotConfirmation: "UPDATE AUTOPILOT", + raftOperations: "Raft 操作", + serverId: "サーバー ID", + peerAddress: "ピアアドレス(削除のみ)", + reenterIdAddress: "ID またはアドレスを再入力", + transferLeader: "リーダーを移譲", + removePeer: "ピアを削除", + gossipKeyring: "Gossip キーリング", + operation: "操作", + install: "インストール", + use: "使用", + remove: "削除", + gossipKey: "Gossip キー", + changeKeyring: "キーリングを変更", + changeKeyringConfirmation: "CHANGE KEYRING", + licenseUpdate: "ライセンス更新", + license: "ライセンス", + updateLicense: "ライセンスを更新", + updateLicenseConfirmation: "UPDATE LICENSE", + }, + tools: { + search: "検索", + searchTitle: "Consul KV を検索", + searchQuery: "検索するテキスト", + prefixOptional: "プレフィックス(任意)", + searchAll: "キーと値", + searchKeys: "キーのみ", + searchValues: "値のみ", + caseSensitive: "大文字と小文字を区別", + scanned: "{count} 件のキーをスキャン済み", + searchLimited: "接続を保護するため、結果を制限しています。", + noSearchResults: "一致するキーはありません", + searchSummary: "スキャンした {scanned} 件のキーのうち {matched} 件が一致", + exportSearchResults: "結果をエクスポート", + searchResultsFileType: "Consul KV 検索結果", + searchResultsExported: "検索結果を {count} 件エクスポートしました", + exportPrefix: "プレフィックスをエクスポート", + prefix: "プレフィックス", + emptyPrefixAll: "空欄の場合はアクセス可能なすべてのキーが対象です", + exportLimitHint: "エクスポートには現在のスコープが含まれ、安全なインポートに必要なキーのメタデータが保持されます。", + exported: "{count} 件のキーをエクスポートしました", + import: "インポート", + importTitle: "Consul KV バンドルをインポート", + invalidBundle: "このファイルは有効な DBX Consul KV バンドルではありません", + importApplied: "{count} 件のキーをインポートしました", + migrate: "移行", + migrateTitle: "Consul KV を移行", + sourcePrefix: "移行元プレフィックス", + targetConnection: "移行先接続", + selectTarget: "移行先接続を選択", + targetReadOnly: "移行先接続は読み取り専用です。", + conflictPolicy: "競合時の処理", + policyAbort: "競合時に中止", + policySkip: "競合をスキップ", + policyCas: "CAS を使用", + bundleSummary: "キー {count} 件 · データセンター {dc} · 名前空間 {ns} · パーティション {partition}", + creates: "作成 {count}", + updates: "更新 {count}", + unchanged: "変更なし {count}", + skipped: "スキップ {count}", + conflicts: "競合 {count}", + loadPreview: "プレビューを読み込む", + loadingPreview: "プレビューを読み込み中...", + apply: "適用", + preview: "プレビュー", + deletePrefix: "プレフィックスを削除", + deletePrefixTitle: "Consul KV プレフィックスを削除", + deletePrefixPlaceholder: "削除するプレフィックス", + deletePrefixWarning: "この操作はプレフィックス配下の表示可能なすべてのキーを削除します。確認前にプレビューを確認してください。", + candidates: "対象候補 {count}", + lockedCount: "ロック中 {count}", + filtered: "フィルター済み", + complete: "完全", + confirmDeletePrefix: "確認済みのキーを削除", + prefixDeleted: "{count} 件のキーを削除しました", + operation: { create: "作成", update: "更新", unchanged: "変更なし", skipped: "スキップ", conflict: "競合", locked: "ロック中", succeeded: "成功", conflicted: "競合", failed: "失敗" }, + }, +} satisfies ConsulMessages; diff --git a/apps/desktop/src/i18n/locales/consulKo.ts b/apps/desktop/src/i18n/locales/consulKo.ts new file mode 100644 index 0000000000..63f1a52ca6 --- /dev/null +++ b/apps/desktop/src/i18n/locales/consulKo.ts @@ -0,0 +1,471 @@ +import type { ConsulMessages } from "./consulUi"; + +export const consulKoMessages = { + ui: { + unknown: "알 수 없음", + peeringPending: "대기 중", + peeringEstablishing: "연결 설정 중", + peeringActive: "활성", + peeringFailing: "오류 발생", + peeringDeleting: "삭제 중", + peeringTerminated: "종료됨", + refresh: "새로 고침", + cancel: "취소", + create: "생성", + update: "업데이트", + save: "저장", + delete: "삭제", + edit: "편집", + apply: "적용", + close: "닫기", + hide: "숨기기", + reveal: "표시", + copy: "복사", + copied: "복사됨", + copyFailed: "복사 실패", + copyOnce: "한 번 복사", + pause: "일시 중지", + watchAction: "감시", + watchPrefix: "접두사 감시", + watchModePrefix: "접두사", + watchModeKey: "정확한 키", + sessionProtected: "세션으로 보호됨", + sessionProtectedHint: "이 분산 잠금을 보호하기 위해 편집 및 삭제가 비활성화되어 있습니다.", + atomicTransaction: "원자적 트랜잭션", + nonAtomicBatches: "{count}개 배치 간 원자성 보장 안 됨", + batchOperation: "배치 {batch} · OpIndex {op}", + operationTotals: "성공 {succeeded} · 충돌 {conflicted} · 건너뜀 {skipped} · 실패 {failed}", + deleteOperationTotals: "성공 {succeeded} · 충돌 {conflicted} · 실패 {failed}", + clientSideMigration: "DBX가 원본에서 읽어 대상에 씁니다. Consul의 기본 데이터센터 간 복제 기능이 아닙니다.", + bundleFileType: "DBX Consul KV 번들", + sourceKeyMissingModifyIndex: "원본 키에 ModifyIndex가 없습니다", + transactionRejected: "Consul이 트랜잭션을 거부했습니다", + overview: "클러스터 개요", + capabilities: "기능", + probeLoading: "불러오는 중", + probeReady: "준비됨", + probeForbidden: "권한 없음", + probeUnsupported: "지원 안 함", + probeError: "오류", + autopilotHealth: "Autopilot 상태", + datacenter: "데이터센터", + agentNode: "에이전트 노드", + agentAddress: "에이전트 주소", + version: "버전", + mode: "모드", + server: "서버", + client: "클라이언트", + leader: "리더", + raftPeers: "Raft 피어", + membersAlive: "활성 멤버", + members: "멤버", + node: "노드", + address: "주소", + status: "상태", + alive: "활성", + leaving: "이탈 중", + failed: "실패", + previousPage: "이전 페이지", + nextPage: "다음 페이지", + pageStatus: "{page} / {pages} · 총 {total}개", + searchAllServices: "모든 서비스 검색", + searchAllNodes: "모든 노드 검색", + searchLocalServices: "로컬 에이전트 서비스 검색", + query: "조회", + searchHealthChecks: "검사 이름, ID, 노드, 서비스, 출력 또는 메모 검색", + allCheckTypes: "모든 검사 유형", + clearFilters: "필터 지우기", + healthResultCount: "전체 {total}개 중 {filtered}개 검사", + services: "서비스", + nodes: "노드", + service: "서비스", + catalogServices: "카탈로그 서비스", + catalogNodes: "카탈로그 노드", + noVisibleServices: "표시할 서비스가 없습니다", + noVisibleNodes: "표시할 노드가 없습니다", + noMatchingServices: "일치하는 서비스가 없습니다", + noMatchingNodes: "일치하는 노드가 없습니다", + agentTarget: "대상 에이전트: {target}", + agentTargetVerifying: "대상 에이전트 확인 중", + unknownWritesDisabled: "알 수 없음 - 쓰기 비활성화됨", + targetAgent: "대상 에이전트", + agentWriteReady: "쓰기 가능", + agentReadOnly: "읽기 전용", + agentWriteDisabledHint: "일치하는 대상 에이전트가 설정되지 않아 유지보수 및 등록 해제가 비활성화되어 있습니다. 감지된 에이전트: {target}.", + agentWriteBlocked: { + connectionUnavailable: "연결 구성을 사용할 수 없습니다. 쓰기 전에 다시 연결하세요.", + readOnly: "이 연결은 읽기 전용입니다. 서비스 등록 해제가 비활성화되어 있습니다.", + transport: "전송 계층을 통한 에이전트 쓰기는 지원되지 않습니다. 대상 에이전트에 직접 연결하세요.", + targetRequired: "연결을 편집하여 대상 에이전트의 노드와 주소를 설정하세요. 노드는 현재 에이전트와 일치해야 하고 주소는 연결 엔드포인트와 일치해야 합니다.", + identityUnavailable: "에이전트 식별 정보를 읽을 수 없어 쓰기가 비활성화되었습니다. 연결 및 에이전트 읽기 권한을 확인한 후 새로 고치세요.", + nodeMismatch: "설정된 대상 노드가 현재 에이전트와 일치하지 않습니다. 연결 설정을 확인하세요.", + directAddressRequired: "에이전트 쓰기에는 직접 연결하는 IP 또는 localhost 엔드포인트가 필요합니다. DNS 및 로드 밸런싱 주소는 지원되지 않습니다.", + addressMismatch: "대상 에이전트 주소가 연결 엔드포인트와 일치하지 않습니다. 연결 설정을 확인하세요.", + invalidAddress: "Consul 연결 주소가 올바르지 않습니다. 연결 설정을 확인하세요.", + }, + register: "등록", + registrationHint: "HTTP를 통한 에이전트 등록은 대상 에이전트의 실행 상태에 속하며 영구 구성 파일을 변경하지 않습니다.", + name: "이름", + id: "ID", + port: "포트", + tags: "태그 (쉼표로 구분)", + registerOn: "{node}에 등록", + catalogInstances: "카탈로그 인스턴스", + nodeServices: "노드 서비스", + serviceId: "서비스 ID", + localAgentServices: "로컬 에이전트 서비스", + enableMaintenance: "유지보수 활성화", + disableMaintenance: "유지보수 비활성화", + deregister: "등록 해제", + deregisterService: "{node}에서 로컬 서비스 {id}의 등록을 해제하시겠습니까?", + deregistering: "등록 해제 중", + deregisterServiceHint: "서비스 등록 및 관련 검사가 제거됩니다. 이후 카탈로그가 동기화됩니다. 서비스 프로세스는 계속 실행되며 다시 등록될 수 있습니다.", + deregisterServiceSucceeded: "{node}에서 서비스 {id}의 등록을 해제했습니다. 카탈로그 동기화에는 잠시 시간이 걸릴 수 있으며 애플리케이션이 다시 등록하면 서비스가 다시 나타날 수 있습니다.", + deregisterRefreshFailed: "서비스 등록은 해제되었지만 새로 고침에 실패했습니다. 수동으로 새로 고치세요", + maintenanceReason: "DBX 사용자 요청", + serviceDetails: "{service} 세부 정보", + kind: "종류", + serviceKind: "ServiceKind", + standard: "표준", + metadata: "메타데이터", + nodeMeta: "노드 메타데이터", + serviceMeta: "서비스 메타데이터", + nodeId: "노드 ID", + serviceWeights: "정상 / 경고", + taggedAddresses: "TaggedAddresses", + enableTagOverride: "EnableTagOverride", + agent: "에이전트", + watch: "감시", + writeOperation: "쓰기 작업", + localServiceDetails: "로컬 서비스 세부 정보", + agentIdentityRequestTimedOut: "에이전트 식별 정보 불러오기 시간이 초과되었습니다.", + localServicesRequestTimedOut: "로컬 에이전트 서비스 불러오기 시간이 초과되었습니다.", + localChecksRequestTimedOut: "로컬 에이전트 검사 불러오기 시간이 초과되었습니다.", + healthChecks: "상태 검사", + state: "상태", + nodeName: "노드 이름", + allStates: "모든 상태", + passing: "정상", + warning: "경고", + critical: "심각", + watchPaused: "감시 일시 중지됨", + watchingIndex: "인덱스 {index} 감시 중", + pauseWatch: "감시 일시 중지", + startWatch: "감시 시작", + checkRegistrationHint: "에이전트 검사는 {node}의 실행 중 등록 정보이며 에이전트 구성 파일에 영구 저장되지 않습니다.", + type: "유형", + ttl: "TTL", + http: "HTTP", + tcp: "TCP", + grpc: "gRPC", + docker: "Docker", + script: "스크립트", + arguments: "인수", + containerId: "컨테이너 ID", + endpoint: "엔드포인트", + interval: "간격", + timeout: "시간 제한", + commandArguments: "명령 인수", + clusterHealth: "클러스터 상태", + nodeHealth: "노드 상태: {node}", + serviceHealth: "서비스 상태: {service}", + noMatchingHealthChecks: "일치하는 상태 검사가 없습니다", + serviceInstances: "서비스 인스턴스", + localAgentChecks: "로컬 에이전트 검사", + maintenance: "유지보수", + ttlPass: "TTL 정상", + ttlWarn: "TTL 경고", + ttlFail: "TTL 실패", + deregisterCheck: "{node}에서 검사 {id}의 등록을 해제하시겠습니까?", + checkDetails: "{check} 세부 정보", + checkId: "검사 ID", + notes: "메모", + output: "출력", + definition: "정의", + indexes: "CreateIndex / ModifyIndex", + sessionsAndLocks: "세션 및 잠금", + sessions: "세션", + sessionDescription: "세션은 Consul KV 잠금에 사용되는 임대와 유사한 계약입니다. TTL 세션은 갱신이 필요합니다. TTL이 없는 세션은 명시적으로 삭제하거나 검사에 의해 무효화될 때까지 유지됩니다.", + createSession: "세션 생성", + searchSessions: "세션 이름, ID, 노드 또는 검사 검색", + sessionResultCount: "전체 {total}개 중 {filtered}개 세션 표시", + noMatchingSessions: "일치하는 세션이 없습니다", + allSessionTypes: "모든 세션 유형", + ttlSessions: "TTL 세션", + persistentSessions: "TTL 없는 세션", + allBehaviors: "모든 동작", + aclFilteredSessions: "세션 목록이 ACL로 필터링되었습니다", + sessionRequestTimedOut: "세션 불러오기 시간이 초과되었습니다. Consul 연결을 확인하고 다시 시도하세요.", + complete: "완료", + lock: "잠금", + lockManagement: "KV 잠금 관리", + lockIndex: "LockIndex {index}", + lockDelay: "잠금 지연", + lockDelayHint: "0s–60s; 무효화 후 잠금 재획득을 지연합니다.", + nodeOptional: "노드 (선택 사항)", + behavior: "동작", + behaviorRelease: "해제", + behaviorDelete: "삭제", + behaviorHint: "세션이 만료되면 release는 보유 키를 유지하고 delete는 삭제합니다.", + releaseLocks: "잠금 해제", + deleteKeys: "키 삭제", + deleteBehaviorWarning: "Behavior=delete는 이 세션이 무효화될 때 보유한 모든 키를 삭제합니다. 계속하시겠습니까?", + checks: "검사", + nodeChecks: "노드 검사", + serviceChecks: "서비스 검사", + nodeCheckShort: "노드", + serviceCheckShort: "서비스", + serviceChecksPlaceholder: "service:api:health{'@'}namespace-a", + serviceChecksHint: "검사 ID를 쉼표로 구분하세요. 범위가 지정된 검사는 ID{'@'}namespace 형식을 사용하세요.", + lockHint: "키를 확인하고 세션을 선택한 다음 협력적 잠금을 획득하거나 해제하세요.", + key: "키", + inspectKey: "키 확인", + keyExists: "키가 존재합니다", + keyNotFound: "키가 존재하지 않습니다", + keyUnlocked: "현재 키를 보유한 세션이 없습니다", + keyHeldBy: "세션 {session}에서 보유 중", + sessionValue: "세션 {id}", + modifyIndexValue: "ModifyIndex {index}", + createIndex: "CreateIndex", + modifyIndexLabel: "ModifyIndex", + selectSession: "세션 선택", + sessionId: "세션 ID", + expectedModifyIndex: "예상 ModifyIndex (새 키는 0)", + value: "값", + releaseMatchingSession: "해제", + acquire: "획득", + unnamedSession: "이름 없는 세션", + heldKeys: "보유 키", + heldKeysIncomplete: "결과가 불완전하거나 ACL로 필터링되었습니다", + stop: "중지", + renewNow: "지금 갱신", + autoRenew: "자동 갱신", + autoRenewPageHint: "이 연결과 페이지가 활성 상태인 동안에만 자동으로 갱신됩니다.", + noRenewRequired: "갱신 필요 없음", + noTtl: "TTL 없음", + ttlOptional: "TTL (선택 사항)", + ttlRangeHint: "영구 세션은 비워 두거나 10s–24h 범위의 값을 입력하세요.", + invalidSessionTtl: "TTL은 비워 두거나 10s–24h 범위의 유효한 기간이어야 합니다.", + invalidLockDelay: "잠금 지연은 0s–60s 범위의 유효한 기간이어야 합니다.", + destroy: "삭제", + noHeldKeys: "보유 키가 없습니다", + noVisibleSessions: "표시할 세션이 없습니다", + destroySession: "세션 {id}을(를) 삭제하시겠습니까? 이 세션을 사용하는 잠금은 설정된 동작에 따라 해제되거나 삭제될 수 있습니다.", + destroySessionImpact: "세션 {id}을(를) 삭제하시겠습니까? 동작: {behavior}. 보유 키 ({count}개): {keys}", + sessionImpactIncomplete: "세션 영향 범위가 불완전하거나 ACL로 필터링되어 삭제가 차단되었습니다.", + sessionDetails: "TTL {ttl} · {behavior} · 검사 {checks}", + tokens: "토큰", + policies: "정책", + roles: "역할", + authMethods: "인증 방법", + bindingRules: "바인딩 규칙", + templatedPolicies: "템플릿 정책", + capability: "기능: {status}", + capabilitySupported: "지원", + capabilityUnsupported: "지원 안 함", + capabilityDisabled: "비활성화됨", + capabilityForbidden: "권한 없음", + capabilityUnknown: "알 수 없음", + loading: "불러오는 중...", + viewOrEdit: "보기 또는 편집", + cloneToken: "토큰 복제", + deleteAndInspectReferences: "삭제 및 참조 확인", + noResources: "리소스가 없습니다", + editResource: "{kind} 편집", + createResource: "{kind} 생성", + knownImpact: "확인된 영향: 토큰 {tokens}개, 역할 {roles}개, 바인딩 규칙 {bindingRules}개", + incomplete: "(불완전)", + reviewAclChanges: "ACL 변경 사항 검토", + deleteResource: "{label} 삭제", + tokenReferences: "토큰 참조: {tokens} · 역할 참조: {roles} · 바인딩 규칙 참조: {bindingRules}", + impactBlocked: "영향 범위가 불완전하거나 ACL로 필터링되어 삭제가 차단되었습니다.", + cloneTokenDescription: "복제된 토큰 설명", + scope: "Consul 범위", + adminPartition: "관리 파티션", + namespace: "네임스페이스", + default: "기본값", + applyScope: "범위 적용", + enterpriseCapability: "Enterprise 기능: {status}. 수명 주기 작업을 사용할 수 없습니다.", + namespaces: "네임스페이스", + lifecycleImpact: "범위 내 리소스 영향", + inspectImpactAndDelete: "영향 확인 및 삭제", + impactAclFiltered: "Consul에서 ACL로 필터링된 결과를 반환하여 삭제가 차단되었습니다.", + impactUnavailable: "열거할 수 없음: {resources}", + impactResource: { + services: "서비스", + nodes: "노드", + kvKeys: "KV 키", + healthChecks: "상태 검사", + sessions: "세션", + configEntries: "구성 항목", + intentions: "통신 의도", + peerings: "피어링", + namespaces: "네임스페이스", + aclTokens: "ACL 토큰", + aclPolicies: "ACL 정책", + aclRoles: "ACL 역할", + aclAuthMethods: "ACL 인증 방법", + aclBindingRules: "ACL 바인딩 규칙", + }, + configEntries: "구성 항목", + intentions: "통신 의도", + discoveryChain: "검색 체인", + peering: "피어링", + exportedServices: "내보낸 서비스", + configEntryKind: "구성 항목 종류", + loadKind: "종류 불러오기", + newJson: "새 JSON", + modifyIndex: "ModifyIndex {index}", + rawJson: "원본 JSON", + newIntention: "새 통신 의도", + sourceService: "원본 서비스", + destinationService: "대상 서비스", + check: "확인", + matchSource: "일치시킬 원본", + matchDestination: "일치시킬 대상", + allowed: "허용됨", + denied: "거부됨", + matchedIntentions: "일치하는 통신 의도 {count}개", + details: "세부 정보", + serviceName: "서비스 이름", + compile: "컴파일", + defaultProtocol: "기본 프로토콜", + configuredDatacenter: "설정된 데이터센터", + start: "시작", + next: "다음: {nodes}", + terminalTarget: "종단 / 대상", + upstreamTargets: "업스트림 대상 ({count}개)", + peerName: "피어 이름", + peeringToken: "연결 설정용 피어링 토큰", + generateToken: "토큰 생성", + establish: "연결 설정", + editExportedServices: "exported-services 항목 편집", + serviceMeshConfigEntry: "서비스 메시 구성 항목", + applyWithCas: "CAS로 적용", + reviewMeshChanges: "서비스 메시 변경 사항 검토", + deleteConfig: "{kind}/{name}을(를) 삭제하시겠습니까?", + deleteIntention: "통신 의도 {id}을(를) 삭제하시겠습니까?", + deleteIntentionExact: "통신 의도 {source} -> {destination}을(를) 삭제하시겠습니까?", + deletePeering: "피어링 {name}을(를) 삭제하시겠습니까?", + permissions: "권한 {count}개", + actionRule: "동작 규칙", + tools: "Consul 도구", + preparedQueries: "준비된 쿼리", + events: "이벤트", + coordinates: "네트워크 좌표", + queryName: "쿼리 이름", + targetService: "대상 서비스", + targetServiceValue: "대상 서비스: {service}", + cancelEdit: "편집 취소", + execute: "실행", + explain: "설명", + eventName: "이벤트 이름", + payload: "페이로드", + fire: "발송", + deletePreparedQuery: "준비된 쿼리 {id}을(를) 삭제하시겠습니까?", + nodesDatacenter: "노드 {count}개 · {datacenter}", + coordinateError: "{segment} · 오차 {error}", + preparedQueriesDescription: "Consul에 저장된 재사용 가능한 서비스 검색 쿼리입니다. 실행은 일치하는 정상 서비스 인스턴스를 찾고, 설명은 실제 적용되는 쿼리를 표시합니다. 간편 편집기는 이름과 대상 서비스만 변경하며 Consul에 저장된 고급 필드는 유지합니다.", + eventsDescription: "Consul gossip을 통해 최선형 방식으로 전달되는 경량 메시지입니다. 이벤트는 일시적인 진단 정보나 알림이며 영구 메시지 큐가 아닙니다.", + coordinatesDescription: "네트워크 근접도를 비교하기 위해 Consul이 추정한 읽기 전용 네트워크 좌표입니다. 지리적 위치가 아닙니다.", + noPreparedQueries: "준비된 쿼리가 없습니다", + noEvents: "최근 이벤트가 없습니다", + noCoordinates: "네트워크 좌표가 없습니다", + queryExecutionResult: "실행 결과 · 인스턴스 {count}개 · {datacenter}", + noQueryNodes: "이 쿼리와 일치하는 서비스 인스턴스가 없습니다", + queryExplanation: "실제 적용 쿼리", + eventNodeFilter: "노드 정규식 (선택 사항)", + eventServiceFilter: "서비스 정규식 (선택 사항)", + eventTagFilter: "태그 정규식 (선택 사항)", + eventPayloadBytes: "페이로드 {count} / 100바이트", + segment: "세그먼트", + error: "오차", + adjustment: "조정값", + height: "높이", + operatorReadOnly: "운영 관리 (읽기 전용)", + snapshot: "스냅샷", + snapshotRestore: "스냅샷 복원", + targetDatacenter: "대상 데이터센터", + restoreSnapshot: "스냅샷 복원", + restoreSnapshotConfirmation: "RESTORE SNAPSHOT {datacenter}", + autopilotUpdate: "Autopilot 업데이트", + cleanupDeadServers: "비활성 서버 정리", + updateAutopilot: "Autopilot 업데이트", + updateAutopilotConfirmation: "UPDATE AUTOPILOT", + raftOperations: "Raft 작업", + serverId: "서버 ID", + peerAddress: "피어 주소 (제거 전용)", + reenterIdAddress: "ID 또는 주소 다시 입력", + transferLeader: "리더 이전", + removePeer: "피어 제거", + gossipKeyring: "Gossip 키링", + operation: "작업", + install: "설치", + use: "사용", + remove: "제거", + gossipKey: "Gossip 키", + changeKeyring: "키링 변경", + changeKeyringConfirmation: "CHANGE KEYRING", + licenseUpdate: "라이선스 업데이트", + license: "라이선스", + updateLicense: "라이선스 업데이트", + updateLicenseConfirmation: "UPDATE LICENSE", + }, + tools: { + search: "검색", + searchTitle: "Consul KV 검색", + searchQuery: "검색할 텍스트", + prefixOptional: "접두사 (선택 사항)", + searchAll: "키 및 값", + searchKeys: "키만", + searchValues: "값만", + caseSensitive: "대소문자 구분", + scanned: "키 {count}개 검색됨", + searchLimited: "연결을 보호하기 위해 결과가 제한됩니다.", + noSearchResults: "일치하는 키가 없습니다", + searchSummary: "검색한 키 {scanned}개 중 {matched}개 일치", + exportSearchResults: "결과 내보내기", + searchResultsFileType: "Consul KV 검색 결과", + searchResultsExported: "검색 결과 {count}개 내보냄", + exportPrefix: "접두사 내보내기", + prefix: "접두사", + emptyPrefixAll: "접근 가능한 모든 키를 포함하려면 비워 두세요", + exportLimitHint: "내보내기에는 현재 범위가 포함되며 안전한 가져오기에 필요한 키 메타데이터가 보존됩니다.", + exported: "키 {count}개 내보냄", + import: "가져오기", + importTitle: "Consul KV 번들 가져오기", + invalidBundle: "이 파일은 유효한 DBX Consul KV 번들이 아닙니다", + importApplied: "키 {count}개 가져옴", + migrate: "마이그레이션", + migrateTitle: "Consul KV 마이그레이션", + sourcePrefix: "원본 접두사", + targetConnection: "대상 연결", + selectTarget: "대상 연결 선택", + targetReadOnly: "대상 연결은 읽기 전용입니다.", + conflictPolicy: "충돌 정책", + policyAbort: "충돌 시 중단", + policySkip: "충돌 건너뛰기", + policyCas: "CAS 사용", + bundleSummary: "키 {count}개 · 데이터센터 {dc} · 네임스페이스 {ns} · 파티션 {partition}", + creates: "생성 {count}개", + updates: "업데이트 {count}개", + unchanged: "변경 없음 {count}개", + skipped: "건너뜀 {count}개", + conflicts: "충돌 {count}개", + loadPreview: "미리 보기 불러오기", + loadingPreview: "미리 보기 불러오는 중...", + apply: "적용", + preview: "미리 보기", + deletePrefix: "접두사 삭제", + deletePrefixTitle: "Consul KV 접두사 삭제", + deletePrefixPlaceholder: "삭제할 접두사", + deletePrefixWarning: "이 작업은 접두사 아래의 표시 가능한 모든 키를 삭제합니다. 확인하기 전에 미리 보기를 검토하세요.", + candidates: "대상 {count}개", + lockedCount: "잠김 {count}개", + filtered: "필터링됨", + complete: "완전함", + confirmDeletePrefix: "확인된 키 삭제", + prefixDeleted: "키 {count}개 삭제됨", + operation: { create: "생성", update: "업데이트", unchanged: "변경 없음", skipped: "건너뜀", conflict: "충돌", locked: "잠김", succeeded: "성공", conflicted: "충돌 발생", failed: "실패" }, + }, +} satisfies ConsulMessages; diff --git a/apps/desktop/src/i18n/locales/consulPtBR.ts b/apps/desktop/src/i18n/locales/consulPtBR.ts new file mode 100644 index 0000000000..04df22db0a --- /dev/null +++ b/apps/desktop/src/i18n/locales/consulPtBR.ts @@ -0,0 +1,472 @@ +import type { ConsulMessages } from "./consulUi"; + +export const consulPtBRMessages = { + ui: { + unknown: "Desconhecido", + peeringPending: "Pendente", + peeringEstablishing: "Estabelecendo conexão", + peeringActive: "Ativo", + peeringFailing: "Com falha", + peeringDeleting: "Excluindo", + peeringTerminated: "Encerrado", + refresh: "Atualizar", + cancel: "Cancelar", + create: "Criar", + update: "Atualizar", + save: "Salvar", + delete: "Excluir", + edit: "Editar", + apply: "Aplicar", + close: "Fechar", + hide: "Ocultar", + reveal: "Mostrar", + copy: "Copiar", + copied: "Copiado", + copyFailed: "Falha ao copiar", + copyOnce: "Copiar uma vez", + pause: "Pausar", + watchAction: "Monitorar", + watchPrefix: "Monitorar prefixo", + watchModePrefix: "Prefixo", + watchModeKey: "Chave exata", + sessionProtected: "Protegido por uma sessão", + sessionProtectedHint: "A edição e a exclusão estão desativadas para proteger este bloqueio distribuído.", + atomicTransaction: "Transação atômica", + nonAtomicBatches: "Não atômica entre {count} lotes", + batchOperation: "Lote {batch} · OpIndex {op}", + operationTotals: "Concluídas {succeeded} · Em conflito {conflicted} · Ignoradas {skipped} · Com falha {failed}", + deleteOperationTotals: "Concluídas {succeeded} · Em conflito {conflicted} · Com falha {failed}", + clientSideMigration: "O DBX lê da origem e grava no destino. Não é a replicação nativa do Consul entre datacenters.", + bundleFileType: "Pacote DBX Consul KV", + sourceKeyMissingModifyIndex: "A chave de origem não tem ModifyIndex", + transactionRejected: "O Consul rejeitou a transação", + overview: "Visão geral do cluster", + capabilities: "Recursos", + probeLoading: "Carregando", + probeReady: "Pronto", + probeForbidden: "Acesso negado", + probeUnsupported: "Não compatível", + probeError: "Erro", + autopilotHealth: "Integridade do Autopilot", + datacenter: "Datacenter", + agentNode: "Nó do agente", + agentAddress: "Endereço do agente", + version: "Versão", + mode: "Modo", + server: "Servidor", + client: "Cliente", + leader: "Líder", + raftPeers: "Pares Raft", + membersAlive: "Membros ativos", + members: "Membros", + node: "Nó", + address: "Endereço", + status: "Status", + alive: "ativo", + leaving: "saindo", + failed: "Com falha", + previousPage: "Página anterior", + nextPage: "Próxima página", + pageStatus: "{page} / {pages} · {total} no total", + searchAllServices: "Pesquisar todos os serviços", + searchAllNodes: "Pesquisar todos os nós", + searchLocalServices: "Pesquisar serviços do agente local", + query: "Consulta", + searchHealthChecks: "Pesquisar nome da verificação, ID, nó, serviço, saída ou notas", + allCheckTypes: "Todos os tipos de verificação", + clearFilters: "Limpar filtros", + healthResultCount: "{filtered} de {total} verificações", + services: "Serviços", + nodes: "Nós", + service: "Serviço", + catalogServices: "Serviços do catálogo", + catalogNodes: "Nós do catálogo", + noVisibleServices: "Nenhum serviço visível", + noVisibleNodes: "Nenhum nó visível", + noMatchingServices: "Nenhum serviço correspondente", + noMatchingNodes: "Nenhum nó correspondente", + agentTarget: "Agente de destino: {target}", + agentTargetVerifying: "Verificando agente de destino", + unknownWritesDisabled: "desconhecido - gravações desativadas", + targetAgent: "o agente de destino", + agentWriteReady: "Gravação permitida", + agentReadOnly: "Somente leitura", + agentWriteDisabledHint: "Nenhum agente de destino correspondente está configurado; a manutenção e a remoção de registro estão desativadas. Agente detectado: {target}.", + agentWriteBlocked: { + connectionUnavailable: "A configuração da conexão não está disponível. Reconecte antes de gravar.", + readOnly: "Esta conexão é somente leitura. A remoção do registro de serviços está desativada.", + transport: "A gravação no agente não está disponível por camadas de transporte. Conecte diretamente ao agente de destino.", + targetRequired: "Edite a conexão e configure o nó e o endereço do agente de destino. O nó deve corresponder ao agente atual e o endereço ao endpoint da conexão.", + identityUnavailable: "Não foi possível ler a identidade do agente. Gravações desativadas. Verifique a conexão e as permissões de leitura do agente e atualize.", + nodeMismatch: "O nó de destino configurado não corresponde ao agente atual. Verifique as configurações da conexão.", + directAddressRequired: "A gravação no agente exige um endpoint IP direto ou localhost. DNS e endereços com balanceamento de carga não são compatíveis.", + addressMismatch: "O endereço do agente de destino não corresponde ao endpoint da conexão. Verifique as configurações da conexão.", + invalidAddress: "O endereço da conexão Consul é inválido. Verifique as configurações da conexão.", + }, + register: "Registrar", + registrationHint: "Os registros HTTP do agente pertencem ao ambiente de execução do agente de destino e não alteram seus arquivos de configuração persistentes.", + name: "Nome", + id: "ID", + port: "Porta", + tags: "Tags (separadas por vírgulas)", + registerOn: "Registrar em {node}", + catalogInstances: "Instâncias do catálogo", + nodeServices: "Serviços do nó", + serviceId: "ID do serviço", + localAgentServices: "Serviços do agente local", + enableMaintenance: "Ativar manutenção", + disableMaintenance: "Desativar manutenção", + deregister: "Remover registro", + deregisterService: "Remover o registro do serviço local {id} de {node}?", + deregistering: "Removendo registro", + deregisterServiceHint: "Isso remove o registro do serviço e as verificações associadas. O catálogo será sincronizado em seguida. O processo do serviço continua em execução e pode se registrar novamente.", + deregisterServiceSucceeded: "O registro do serviço {id} foi removido de {node}. A sincronização do catálogo pode levar um momento; o serviço pode reaparecer se o aplicativo o registrar novamente.", + deregisterRefreshFailed: "Registro do serviço removido, mas houve falha ao atualizar. Atualize manualmente", + maintenanceReason: "Solicitação do usuário DBX", + serviceDetails: "Detalhes de {service}", + kind: "Categoria", + serviceKind: "ServiceKind", + standard: "padrão", + metadata: "Metadados", + nodeMeta: "Metadados do nó", + serviceMeta: "Metadados do serviço", + nodeId: "ID do nó", + serviceWeights: "Aprovado / Aviso", + taggedAddresses: "TaggedAddresses", + enableTagOverride: "EnableTagOverride", + agent: "Agente", + watch: "Monitoramento", + writeOperation: "Operação de gravação", + localServiceDetails: "Detalhes do serviço local", + agentIdentityRequestTimedOut: "Tempo limite ao carregar a identidade do agente.", + localServicesRequestTimedOut: "Tempo limite ao carregar os serviços do agente local.", + localChecksRequestTimedOut: "Tempo limite ao carregar as verificações do agente local.", + healthChecks: "Verificações de integridade", + state: "Estado", + nodeName: "Nome do nó", + allStates: "Todos os estados", + passing: "Aprovado", + warning: "Aviso", + critical: "Crítico", + watchPaused: "Monitoramento pausado", + watchingIndex: "Monitorando o índice {index}", + pauseWatch: "Pausar monitoramento", + startWatch: "Iniciar monitoramento", + checkRegistrationHint: "As verificações do agente são registros em tempo de execução em {node} e não são persistidas nos arquivos de configuração do agente.", + type: "Tipo", + ttl: "TTL", + http: "HTTP", + tcp: "TCP", + grpc: "gRPC", + docker: "Docker", + script: "Script", + arguments: "Argumentos", + containerId: "ID do contêiner", + endpoint: "Endpoint", + interval: "Intervalo", + timeout: "Tempo limite", + commandArguments: "Argumentos do comando", + clusterHealth: "Integridade do cluster", + nodeHealth: "Integridade do nó: {node}", + serviceHealth: "Integridade do serviço: {service}", + noMatchingHealthChecks: "Nenhuma verificação de integridade correspondente", + serviceInstances: "Instâncias do serviço", + localAgentChecks: "Verificações do agente local", + maintenance: "manutenção", + ttlPass: "TTL aprovado", + ttlWarn: "TTL com aviso", + ttlFail: "TTL com falha", + deregisterCheck: "Remover o registro da verificação {id} de {node}?", + checkDetails: "Detalhes de {check}", + checkId: "ID da verificação", + notes: "Notas", + output: "Saída", + definition: "Definição", + indexes: "CreateIndex / ModifyIndex", + sessionsAndLocks: "Sessões e bloqueios", + sessions: "Sessões", + sessionDescription: "Uma sessão é um contrato semelhante a uma concessão usado pelos bloqueios Consul KV. Sessões TTL exigem renovação; sessões sem TTL permanecem até serem destruídas explicitamente ou invalidadas por suas verificações.", + createSession: "Criar sessão", + searchSessions: "Pesquisar nome da sessão, ID, nó ou verificação", + sessionResultCount: "Exibindo {filtered} de {total} sessões", + noMatchingSessions: "Nenhuma sessão correspondente", + allSessionTypes: "Todos os tipos de sessão", + ttlSessions: "Sessões TTL", + persistentSessions: "Sessões sem TTL", + allBehaviors: "Todos os comportamentos", + aclFilteredSessions: "A lista de sessões foi filtrada pelas ACLs", + sessionRequestTimedOut: "Tempo limite ao carregar sessões. Verifique a conexão Consul e tente novamente.", + complete: "Completo", + lock: "Bloqueio", + lockManagement: "Gerenciamento de bloqueios KV", + lockIndex: "LockIndex {index}", + lockDelay: "Atraso do bloqueio", + lockDelayHint: "0s–60s; adia a reaquisição após a invalidação.", + nodeOptional: "Nó (opcional)", + behavior: "Comportamento", + behaviorRelease: "Liberar (release)", + behaviorDelete: "Excluir (delete)", + behaviorHint: "release mantém as chaves bloqueadas; delete as remove quando a sessão expira.", + releaseLocks: "Liberar bloqueios", + deleteKeys: "Excluir chaves", + deleteBehaviorWarning: "Behavior=delete remove todas as chaves bloqueadas por esta sessão quando ela é invalidada. Continuar?", + checks: "Verificações", + nodeChecks: "Verificações do nó", + serviceChecks: "Verificações do serviço", + nodeCheckShort: "Nó", + serviceCheckShort: "Serviço", + serviceChecksPlaceholder: "service:api:health{'@'}namespace-a", + serviceChecksHint: "IDs de verificação separados por vírgulas; use ID{'@'}namespace para uma verificação com escopo.", + lockHint: "Inspecione a chave, selecione uma sessão e adquira ou libere o bloqueio consultivo.", + key: "Chave", + inspectKey: "Inspecionar chave", + keyExists: "A chave existe", + keyNotFound: "A chave não existe", + keyUnlocked: "A chave não está bloqueada no momento", + keyHeldBy: "Bloqueada pela sessão {session}", + sessionValue: "Sessão {id}", + modifyIndexValue: "ModifyIndex {index}", + createIndex: "CreateIndex", + modifyIndexLabel: "ModifyIndex", + selectSession: "Selecionar uma sessão", + sessionId: "ID da sessão", + expectedModifyIndex: "ModifyIndex esperado (0 para nova chave)", + value: "Valor", + releaseMatchingSession: "Liberar", + acquire: "Adquirir", + unnamedSession: "Sessão sem nome", + heldKeys: "Chaves bloqueadas", + heldKeysIncomplete: "Os resultados estão incompletos ou filtrados por ACL", + stop: "Parar", + renewNow: "Renovar agora", + autoRenew: "Renovação automática", + autoRenewPageHint: "A renovação automática só funciona enquanto esta conexão e esta página permanecerem ativas.", + noRenewRequired: "Nenhuma renovação necessária", + noTtl: "Sem TTL", + ttlOptional: "TTL (opcional)", + ttlRangeHint: "Deixe vazio para uma sessão persistente ou use 10s–24h.", + invalidSessionTtl: "TTL deve estar vazio ou ser uma duração válida entre 10s e 24h.", + invalidLockDelay: "O atraso do bloqueio deve ser uma duração válida entre 0s e 60s.", + destroy: "Destruir", + noHeldKeys: "Nenhuma chave bloqueada", + noVisibleSessions: "Nenhuma sessão visível", + destroySession: "Destruir a sessão {id}? Os bloqueios que usam esta sessão podem ser liberados ou excluídos conforme seu comportamento.", + destroySessionImpact: "Destruir a sessão {id}? Comportamento: {behavior}. Chaves bloqueadas ({count}): {keys}", + sessionImpactIncomplete: "O impacto da sessão está incompleto ou filtrado por ACL. A destruição está bloqueada.", + sessionDetails: "TTL {ttl} · {behavior} · verificações {checks}", + tokens: "Tokens", + policies: "Políticas", + roles: "Funções", + authMethods: "Métodos de autenticação", + bindingRules: "Regras de vinculação", + templatedPolicies: "Políticas de modelo", + capability: "Recurso: {status}", + capabilitySupported: "Compatível", + capabilityUnsupported: "Não compatível", + capabilityDisabled: "Desativado", + capabilityForbidden: "Sem permissão", + capabilityUnknown: "Desconhecido", + loading: "Carregando...", + viewOrEdit: "Visualizar ou editar", + cloneToken: "Clonar token", + deleteAndInspectReferences: "Excluir e inspecionar referências", + noResources: "Nenhum recurso", + editResource: "Editar {kind}", + createResource: "Criar {kind}", + knownImpact: "Impacto conhecido: {tokens} tokens, {roles} funções, {bindingRules} regras de vinculação", + incomplete: "(incompleto)", + reviewAclChanges: "Revisar alterações de ACL", + deleteResource: "Excluir {label}", + tokenReferences: "Referências a tokens: {tokens} · A funções: {roles} · A regras de vinculação: {bindingRules}", + impactBlocked: "O impacto está incompleto ou filtrado por ACL. A exclusão está bloqueada.", + cloneTokenDescription: "Descrição do token clonado", + scope: "Escopo do Consul", + adminPartition: "Partição administrativa", + namespace: "Namespace", + default: "padrão", + applyScope: "Aplicar escopo", + enterpriseCapability: "Recurso Enterprise: {status}. As ações de ciclo de vida não estão disponíveis.", + namespaces: "Namespaces", + lifecycleImpact: "Impacto nos recursos do escopo", + inspectImpactAndDelete: "Inspecionar impacto e excluir", + impactAclFiltered: "O Consul informa resultados filtrados por ACL; a exclusão está bloqueada.", + impactUnavailable: "Não foi possível listar: {resources}", + impactResource: { + services: "Serviços", + nodes: "Nós", + kvKeys: "Chaves KV", + healthChecks: "Verificações de integridade", + sessions: "Sessões", + configEntries: "Entradas de configuração", + intentions: "Intenções", + peerings: "Conexões de peering", + namespaces: "Namespaces", + aclTokens: "Tokens ACL", + aclPolicies: "Políticas ACL", + aclRoles: "Funções ACL", + aclAuthMethods: "Métodos de autenticação ACL", + aclBindingRules: "Regras de vinculação ACL", + }, + configEntries: "Entradas de configuração", + intentions: "Intenções", + discoveryChain: "Cadeia de descoberta", + peering: "Peering", + exportedServices: "Serviços exportados", + configEntryKind: "Tipo de entrada de configuração", + loadKind: "Carregar tipo", + newJson: "Novo JSON", + modifyIndex: "ModifyIndex {index}", + rawJson: "JSON bruto", + newIntention: "Nova intenção", + sourceService: "Serviço de origem", + destinationService: "Serviço de destino", + check: "Verificar", + matchSource: "Corresponder origem", + matchDestination: "Corresponder destino", + allowed: "Permitido", + denied: "Negado", + matchedIntentions: "{count} intenções correspondentes", + details: "Detalhes", + serviceName: "Nome do serviço", + compile: "Compilar", + defaultProtocol: "protocolo padrão", + configuredDatacenter: "datacenter configurado", + start: "Iniciar", + next: "Próximo: {nodes}", + terminalTarget: "Terminal / destino", + upstreamTargets: "Destinos upstream ({count})", + peerName: "Nome do par", + peeringToken: "Token para estabelecer peering", + generateToken: "Gerar token", + establish: "Estabelecer", + editExportedServices: "Editar entrada exported-services", + serviceMeshConfigEntry: "Entrada de configuração da malha de serviços", + applyWithCas: "Aplicar com CAS", + reviewMeshChanges: "Revisar alterações da malha de serviços", + deleteConfig: "Excluir {kind}/{name}?", + deleteIntention: "Excluir a intenção {id}?", + deleteIntentionExact: "Excluir a intenção {source} -> {destination}?", + deletePeering: "Excluir o peering {name}?", + permissions: "{count} permissões", + actionRule: "regra de ação", + tools: "Ferramentas do Consul", + preparedQueries: "Consultas preparadas", + events: "Eventos", + coordinates: "Coordenadas de rede", + queryName: "Nome da consulta", + targetService: "Serviço de destino", + targetServiceValue: "Serviço de destino: {service}", + cancelEdit: "Cancelar edição", + execute: "Executar", + explain: "Explicar", + eventName: "Nome do evento", + payload: "Carga útil", + fire: "Disparar", + deletePreparedQuery: "Excluir a consulta preparada {id}?", + nodesDatacenter: "{count} nós · {datacenter}", + coordinateError: "{segment} · erro {error}", + preparedQueriesDescription: + "Consultas reutilizáveis de descoberta de serviços armazenadas no Consul. Executar resolve as instâncias íntegras correspondentes; Explicar mostra a consulta efetiva. O editor simples altera apenas o nome e o serviço de destino, preservando os campos avançados já armazenados pelo Consul.", + eventsDescription: "Mensagens leves distribuídas pelo gossip do Consul sem garantia de entrega. Os eventos são diagnósticos ou notificações transitórios, não uma fila de mensagens durável.", + coordinatesDescription: "Coordenadas de rede somente leitura estimadas pelo Consul para comparar a proximidade na rede. Não são localizações geográficas.", + noPreparedQueries: "Nenhuma consulta preparada", + noEvents: "Nenhum evento recente", + noCoordinates: "Nenhuma coordenada de rede", + queryExecutionResult: "Resultado da execução · {count} instâncias · {datacenter}", + noQueryNodes: "Nenhuma instância de serviço corresponde a esta consulta", + queryExplanation: "Consulta efetiva", + eventNodeFilter: "Regex do nó (opcional)", + eventServiceFilter: "Regex do serviço (opcional)", + eventTagFilter: "Regex da tag (opcional)", + eventPayloadBytes: "Carga útil {count} / 100 bytes", + segment: "Segmento", + error: "Erro", + adjustment: "Ajuste", + height: "Altura", + operatorReadOnly: "Operador (somente leitura)", + snapshot: "Snapshot", + snapshotRestore: "Restauração de snapshot", + targetDatacenter: "Datacenter de destino", + restoreSnapshot: "Restaurar snapshot", + restoreSnapshotConfirmation: "RESTORE SNAPSHOT {datacenter}", + autopilotUpdate: "Atualização do Autopilot", + cleanupDeadServers: "Limpar servidores inativos", + updateAutopilot: "Atualizar Autopilot", + updateAutopilotConfirmation: "UPDATE AUTOPILOT", + raftOperations: "Operações Raft", + serverId: "ID do servidor", + peerAddress: "Endereço do par (somente remoção)", + reenterIdAddress: "Digite novamente o ID ou endereço", + transferLeader: "Transferir liderança", + removePeer: "Remover par", + gossipKeyring: "Chaveiro gossip", + operation: "Operação", + install: "Instalar", + use: "Usar", + remove: "Remover", + gossipKey: "Chave gossip", + changeKeyring: "Alterar chaveiro", + changeKeyringConfirmation: "CHANGE KEYRING", + licenseUpdate: "Atualização de licença", + license: "Licença", + updateLicense: "Atualizar licença", + updateLicenseConfirmation: "UPDATE LICENSE", + }, + tools: { + search: "Pesquisar", + searchTitle: "Pesquisar no Consul KV", + searchQuery: "Texto a pesquisar", + prefixOptional: "Prefixo (opcional)", + searchAll: "Chaves e valores", + searchKeys: "Somente chaves", + searchValues: "Somente valores", + caseSensitive: "Diferenciar maiúsculas e minúsculas", + scanned: "{count} chaves examinadas", + searchLimited: "Os resultados são limitados para proteger a conexão.", + noSearchResults: "Nenhuma chave correspondente", + searchSummary: "{matched} correspondências em {scanned} chaves examinadas", + exportSearchResults: "Exportar resultados", + searchResultsFileType: "Resultados da pesquisa Consul KV", + searchResultsExported: "{count} resultados da pesquisa exportados", + exportPrefix: "Exportar prefixo", + prefix: "Prefixo", + emptyPrefixAll: "Deixe vazio para todas as chaves acessíveis", + exportLimitHint: "As exportações incluem o escopo atual e preservam os metadados das chaves necessários para uma importação segura.", + exported: "{count} chaves exportadas", + import: "Importar", + importTitle: "Importar pacote Consul KV", + invalidBundle: "Este arquivo não é um pacote DBX Consul KV válido", + importApplied: "{count} chaves importadas", + migrate: "Migrar", + migrateTitle: "Migrar Consul KV", + sourcePrefix: "Prefixo de origem", + targetConnection: "Conexão de destino", + selectTarget: "Selecionar uma conexão de destino", + targetReadOnly: "A conexão de destino é somente leitura.", + conflictPolicy: "Política de conflitos", + policyAbort: "Interromper em caso de conflito", + policySkip: "Ignorar conflitos", + policyCas: "Usar CAS", + bundleSummary: "{count} chaves · Datacenter {dc} · Namespace {ns} · Partição {partition}", + creates: "Criar {count}", + updates: "Atualizar {count}", + unchanged: "Sem alterações {count}", + skipped: "Ignorado {count}", + conflicts: "Conflitos {count}", + loadPreview: "Carregar prévia", + loadingPreview: "Carregando prévia...", + apply: "Aplicar", + preview: "Prévia", + deletePrefix: "Excluir prefixo", + deletePrefixTitle: "Excluir prefixo Consul KV", + deletePrefixPlaceholder: "Prefixo a excluir", + deletePrefixWarning: "Esta operação exclui todas as chaves visíveis sob o prefixo. Revise a prévia antes de confirmar.", + candidates: "Candidatos {count}", + lockedCount: "Bloqueadas {count}", + filtered: "filtrado", + complete: "Completo", + confirmDeletePrefix: "Excluir chaves confirmadas", + prefixDeleted: "{count} chaves excluídas", + operation: { create: "Criar", update: "Atualizar", unchanged: "Sem alterações", skipped: "Ignorado", conflict: "Conflito", locked: "Bloqueado", succeeded: "Concluído", conflicted: "Em conflito", failed: "Com falha" }, + }, +} satisfies ConsulMessages; diff --git a/apps/desktop/src/i18n/locales/consulTr.ts b/apps/desktop/src/i18n/locales/consulTr.ts new file mode 100644 index 0000000000..dcdd16adc7 --- /dev/null +++ b/apps/desktop/src/i18n/locales/consulTr.ts @@ -0,0 +1,471 @@ +import type { ConsulMessages } from "./consulUi"; + +export const consulTrMessages = { + ui: { + unknown: "Bilinmiyor", + peeringPending: "Bekliyor", + peeringEstablishing: "Kuruluyor", + peeringActive: "Etkin", + peeringFailing: "Başarısız oluyor", + peeringDeleting: "Siliniyor", + peeringTerminated: "Sonlandırıldı", + refresh: "Yenile", + cancel: "İptal", + create: "Oluştur", + update: "Güncelle", + save: "Kaydet", + delete: "Sil", + edit: "Düzenle", + apply: "Uygula", + close: "Kapat", + hide: "Gizle", + reveal: "Göster", + copy: "Kopyala", + copied: "Kopyalandı", + copyFailed: "Kopyalanamadı", + copyOnce: "Bir kez kopyala", + pause: "Duraklat", + watchAction: "İzle", + watchPrefix: "Öneki izle", + watchModePrefix: "Önek", + watchModeKey: "Tam anahtar", + sessionProtected: "Oturum tarafından korunuyor", + sessionProtectedHint: "Bu dağıtık kilidi korumak için düzenleme ve silme devre dışı bırakıldı.", + atomicTransaction: "Atomik işlem", + nonAtomicBatches: "{count} toplu işlem arasında atomik değil", + batchOperation: "Toplu işlem {batch} · OpIndex {op}", + operationTotals: "Başarılı {succeeded} · Çakışan {conflicted} · Atlanan {skipped} · Başarısız {failed}", + deleteOperationTotals: "Başarılı {succeeded} · Çakışan {conflicted} · Başarısız {failed}", + clientSideMigration: "DBX kaynaktan okur ve hedefe yazar. Bu işlem Consul'un yerel veri merkezleri arası çoğaltması değildir.", + bundleFileType: "DBX Consul KV paketi", + sourceKeyMissingModifyIndex: "Kaynak anahtarın ModifyIndex değeri yok", + transactionRejected: "Consul işlemi reddetti", + overview: "Küme genel bakışı", + capabilities: "Yetenekler", + probeLoading: "Yükleniyor", + probeReady: "Hazır", + probeForbidden: "Erişim yasak", + probeUnsupported: "Desteklenmiyor", + probeError: "Hata", + autopilotHealth: "Autopilot sağlığı", + datacenter: "Veri merkezi", + agentNode: "Agent düğümü", + agentAddress: "Agent adresi", + version: "Sürüm", + mode: "Mod", + server: "Sunucu", + client: "İstemci", + leader: "Lider", + raftPeers: "Raft eşleri", + membersAlive: "Etkin üyeler", + members: "Üyeler", + node: "Düğüm", + address: "Adres", + status: "Durum", + alive: "etkin", + leaving: "ayrılıyor", + failed: "Başarısız", + previousPage: "Önceki sayfa", + nextPage: "Sonraki sayfa", + pageStatus: "{page} / {pages} · toplam {total}", + searchAllServices: "Tüm servislerde ara", + searchAllNodes: "Tüm düğümlerde ara", + searchLocalServices: "Yerel Agent servislerinde ara", + query: "Sorgu", + searchHealthChecks: "Kontrol adı, kimlik, düğüm, servis, çıktı veya notlarda ara", + allCheckTypes: "Tüm kontrol türleri", + clearFilters: "Filtreleri temizle", + healthResultCount: "{total} kontrolden {filtered} tanesi", + services: "Servisler", + nodes: "Düğümler", + service: "Servis", + catalogServices: "Katalog servisleri", + catalogNodes: "Katalog düğümleri", + noVisibleServices: "Görünür servis yok", + noVisibleNodes: "Görünür düğüm yok", + noMatchingServices: "Eşleşen servis yok", + noMatchingNodes: "Eşleşen düğüm yok", + agentTarget: "Agent hedefi: {target}", + agentTargetVerifying: "Agent hedefi doğrulanıyor", + unknownWritesDisabled: "bilinmiyor - yazma devre dışı", + targetAgent: "hedef Agent", + agentWriteReady: "Yazılabilir", + agentReadOnly: "Salt okunur", + agentWriteDisabledHint: "Eşleşen bir Agent hedefi yapılandırılmadığından bakım ve kayıt silme devre dışı. Algılanan Agent: {target}.", + agentWriteBlocked: { + connectionUnavailable: "Bağlantı yapılandırması kullanılamıyor. Yazmadan önce yeniden bağlanın.", + readOnly: "Bu bağlantı salt okunur. Servis kaydını silme devre dışı.", + transport: "Taşıma katmanları üzerinden Agent yazma işlemleri kullanılamıyor. Hedef Agent'a doğrudan bağlanın.", + targetRequired: "Bağlantıyı düzenleyerek Agent hedef düğümünü ve adresini yapılandırın. Düğüm mevcut Agent ile, adres ise bağlantı uç noktasıyla eşleşmelidir.", + identityUnavailable: "Agent kimliği okunamıyor. Yazma devre dışı. Bağlantıyı ve Agent okuma izinlerini kontrol edip yenileyin.", + nodeMismatch: "Yapılandırılan hedef düğüm mevcut Agent ile eşleşmiyor. Bağlantı ayarlarını kontrol edin.", + directAddressRequired: "Agent yazma işlemleri doğrudan bir IP veya localhost uç noktası gerektirir. DNS ve yük dengelemeli adresler desteklenmez.", + addressMismatch: "Agent hedef adresi bağlantı uç noktasıyla eşleşmiyor. Bağlantı ayarlarını kontrol edin.", + invalidAddress: "Consul bağlantı adresi geçersiz. Bağlantı ayarlarını kontrol edin.", + }, + register: "Kaydet", + registrationHint: "HTTP Agent kayıtları hedef Agent'ın çalışma zamanına aittir; kalıcı yapılandırma dosyalarını değiştirmez.", + name: "Ad", + id: "ID", + port: "Port", + tags: "Etiketler (virgülle ayrılmış)", + registerOn: "{node} üzerinde kaydet", + catalogInstances: "Katalog örnekleri", + nodeServices: "Düğüm servisleri", + serviceId: "Servis ID", + localAgentServices: "Yerel Agent servisleri", + enableMaintenance: "Bakımı etkinleştir", + disableMaintenance: "Bakımı devre dışı bırak", + deregister: "Kaydı sil", + deregisterService: "{node} üzerindeki {id} yerel servisinin kaydı silinsin mi?", + deregistering: "Kayıt siliniyor", + deregisterServiceHint: "Bu işlem servis kaydını ve ilişkili kontrolleri kaldırır. Katalog daha sonra eşitlenir. Servis süreci çalışmaya devam eder ve kendini yeniden kaydedebilir.", + deregisterServiceSucceeded: "{node} üzerindeki {id} servisinin kaydı silindi. Katalog eşitlemesi biraz zaman alabilir; uygulama yeniden kaydederse servis tekrar görünebilir.", + deregisterRefreshFailed: "Servis kaydı silindi ancak yenileme başarısız oldu. El ile yenileyin", + maintenanceReason: "DBX kullanıcı isteği", + serviceDetails: "{service} ayrıntıları", + kind: "Tür", + serviceKind: "ServiceKind", + standard: "standart", + metadata: "Meta veriler", + nodeMeta: "Düğüm meta verileri", + serviceMeta: "Servis meta verileri", + nodeId: "Düğüm ID", + serviceWeights: "Başarılı / Uyarı", + taggedAddresses: "TaggedAddresses", + enableTagOverride: "EnableTagOverride", + agent: "Agent", + watch: "İzleme", + writeOperation: "Yazma işlemi", + localServiceDetails: "Yerel servis ayrıntıları", + agentIdentityRequestTimedOut: "Agent kimliği yüklenirken zaman aşımı oluştu.", + localServicesRequestTimedOut: "Yerel Agent servisleri yüklenirken zaman aşımı oluştu.", + localChecksRequestTimedOut: "Yerel Agent kontrolleri yüklenirken zaman aşımı oluştu.", + healthChecks: "Sağlık kontrolleri", + state: "Durum", + nodeName: "Düğüm adı", + allStates: "Tüm durumlar", + passing: "Başarılı", + warning: "Uyarı", + critical: "Kritik", + watchPaused: "İzleme duraklatıldı", + watchingIndex: "{index} dizini izleniyor", + pauseWatch: "İzlemeyi duraklat", + startWatch: "İzlemeyi başlat", + checkRegistrationHint: "Agent kontrolleri {node} üzerinde çalışma zamanı kayıtlarıdır ve Agent yapılandırma dosyalarına kalıcı olarak kaydedilmez.", + type: "Tür", + ttl: "TTL", + http: "HTTP", + tcp: "TCP", + grpc: "gRPC", + docker: "Docker", + script: "Betik", + arguments: "Argümanlar", + containerId: "Konteyner ID", + endpoint: "Uç nokta", + interval: "Aralık", + timeout: "Zaman aşımı", + commandArguments: "Komut argümanları", + clusterHealth: "Küme sağlığı", + nodeHealth: "Düğüm sağlığı: {node}", + serviceHealth: "Servis sağlığı: {service}", + noMatchingHealthChecks: "Eşleşen sağlık kontrolü yok", + serviceInstances: "Servis örnekleri", + localAgentChecks: "Yerel Agent kontrolleri", + maintenance: "bakım", + ttlPass: "TTL başarılı", + ttlWarn: "TTL uyarısı", + ttlFail: "TTL başarısız", + deregisterCheck: "{node} üzerindeki {id} kontrolünün kaydı silinsin mi?", + checkDetails: "{check} ayrıntıları", + checkId: "Kontrol ID", + notes: "Notlar", + output: "Çıktı", + definition: "Tanım", + indexes: "CreateIndex / ModifyIndex", + sessionsAndLocks: "Oturumlar ve kilitler", + sessions: "Oturumlar", + sessionDescription: "Oturum, Consul KV kilitlerinin kullandığı kira benzeri bir sözleşmedir. TTL oturumları yenileme gerektirir; TTL içermeyen oturumlar açıkça yok edilene veya kontrolleri tarafından geçersiz kılınana kadar kalır.", + createSession: "Oturum oluştur", + searchSessions: "Oturum adı, ID, düğüm veya kontrolde ara", + sessionResultCount: "{total} oturumdan {filtered} tanesi gösteriliyor", + noMatchingSessions: "Eşleşen oturum yok", + allSessionTypes: "Tüm oturum türleri", + ttlSessions: "TTL oturumları", + persistentSessions: "TTL içermeyen oturumlar", + allBehaviors: "Tüm davranışlar", + aclFilteredSessions: "Oturum listesi ACL'ler tarafından filtrelendi", + sessionRequestTimedOut: "Oturumlar yüklenirken zaman aşımı oluştu. Consul bağlantısını kontrol edip yeniden deneyin.", + complete: "Tamamlandı", + lock: "Kilit", + lockManagement: "KV kilit yönetimi", + lockIndex: "LockIndex {index}", + lockDelay: "Kilit gecikmesi", + lockDelayHint: "0s–60s; geçersiz kılınma sonrası yeniden edinmeyi geciktirir.", + nodeOptional: "Düğüm (isteğe bağlı)", + behavior: "Davranış", + behaviorRelease: "serbest bırak (release)", + behaviorDelete: "sil (delete)", + behaviorHint: "release tutulan anahtarları korur; delete oturumun süresi dolduğunda bunları siler.", + releaseLocks: "Kilitleri serbest bırak", + deleteKeys: "Anahtarları sil", + deleteBehaviorWarning: "Behavior=delete, bu oturum geçersiz kılındığında tuttuğu tüm anahtarları siler. Devam edilsin mi?", + checks: "Kontroller", + nodeChecks: "Düğüm kontrolleri", + serviceChecks: "Servis kontrolleri", + nodeCheckShort: "Düğüm", + serviceCheckShort: "Servis", + serviceChecksPlaceholder: "service:api:health{'@'}namespace-a", + serviceChecksHint: "Virgülle ayrılmış kontrol ID'leri; kapsamlı bir kontrol için ID{'@'}namespace kullanın.", + lockHint: "Anahtarı inceleyin, bir oturum seçin, ardından tavsiye niteliğindeki kilidi edinin veya serbest bırakın.", + key: "Anahtar", + inspectKey: "Anahtarı incele", + keyExists: "Anahtar mevcut", + keyNotFound: "Anahtar mevcut değil", + keyUnlocked: "Anahtar şu anda tutulmuyor", + keyHeldBy: "{session} oturumu tarafından tutuluyor", + sessionValue: "Oturum {id}", + modifyIndexValue: "ModifyIndex {index}", + createIndex: "CreateIndex", + modifyIndexLabel: "ModifyIndex", + selectSession: "Bir oturum seçin", + sessionId: "Oturum ID", + expectedModifyIndex: "Beklenen ModifyIndex (yeni anahtar için 0)", + value: "Değer", + releaseMatchingSession: "Serbest bırak", + acquire: "Edin", + unnamedSession: "Adsız oturum", + heldKeys: "Tutulan anahtarlar", + heldKeysIncomplete: "Sonuçlar eksik veya ACL ile filtrelenmiş", + stop: "Durdur", + renewNow: "Şimdi yenile", + autoRenew: "Otomatik yenile", + autoRenewPageHint: "Otomatik yenileme yalnızca bu bağlantı ve sayfa etkin kaldığı sürece çalışır.", + noRenewRequired: "Yenileme gerekmiyor", + noTtl: "TTL yok", + ttlOptional: "TTL (isteğe bağlı)", + ttlRangeHint: "Kalıcı bir oturum için boş bırakın veya 10s–24h kullanın.", + invalidSessionTtl: "TTL boş veya 10s ile 24h arasında geçerli bir süre olmalıdır.", + invalidLockDelay: "Kilit gecikmesi 0s ile 60s arasında geçerli bir süre olmalıdır.", + destroy: "Yok et", + noHeldKeys: "Tutulan anahtar yok", + noVisibleSessions: "Görünür oturum yok", + destroySession: "{id} oturumu yok edilsin mi? Bu oturumu kullanan kilitler davranışına göre serbest bırakılabilir veya silinebilir.", + destroySessionImpact: "{id} oturumu yok edilsin mi? Davranış: {behavior}. Tutulan anahtarlar ({count}): {keys}", + sessionImpactIncomplete: "Oturum etkisi eksik veya ACL ile filtrelenmiş. Yok etme engellendi.", + sessionDetails: "TTL {ttl} · {behavior} · kontroller {checks}", + tokens: "Belirteçler", + policies: "Politikalar", + roles: "Roller", + authMethods: "Kimlik doğrulama yöntemleri", + bindingRules: "Bağlama kuralları", + templatedPolicies: "Şablonlu politikalar", + capability: "Yetenek: {status}", + capabilitySupported: "Destekleniyor", + capabilityUnsupported: "Desteklenmiyor", + capabilityDisabled: "Devre dışı", + capabilityForbidden: "Yetki yok", + capabilityUnknown: "Bilinmiyor", + loading: "Yükleniyor...", + viewOrEdit: "Görüntüle veya düzenle", + cloneToken: "Belirteci çoğalt", + deleteAndInspectReferences: "Sil ve başvuruları incele", + noResources: "Kaynak yok", + editResource: "{kind} düzenle", + createResource: "{kind} oluştur", + knownImpact: "Bilinen etki: {tokens} belirteç, {roles} rol, {bindingRules} bağlama kuralı", + incomplete: "(eksik)", + reviewAclChanges: "ACL değişikliklerini gözden geçir", + deleteResource: "{label} sil", + tokenReferences: "Belirteç başvuruları: {tokens} · Rol başvuruları: {roles} · Bağlama kuralı başvuruları: {bindingRules}", + impactBlocked: "Etki eksik veya ACL ile filtrelenmiş. Silme engellendi.", + cloneTokenDescription: "Çoğaltılan belirtecin açıklaması", + scope: "Consul kapsamı", + adminPartition: "Yönetim bölümü", + namespace: "Ad alanı", + default: "varsayılan", + applyScope: "Kapsamı uygula", + enterpriseCapability: "Enterprise yeteneği: {status}. Yaşam döngüsü işlemleri kullanılamıyor.", + namespaces: "Ad alanları", + lifecycleImpact: "Kapsamlı kaynak etkisi", + inspectImpactAndDelete: "Etkiyi incele ve sil", + impactAclFiltered: "Consul, ACL ile filtrelenmiş sonuçlar bildiriyor; silme engellendi.", + impactUnavailable: "Listelenemedi: {resources}", + impactResource: { + services: "Servisler", + nodes: "Düğümler", + kvKeys: "KV anahtarları", + healthChecks: "Sağlık kontrolleri", + sessions: "Oturumlar", + configEntries: "Yapılandırma girdileri", + intentions: "Erişim kuralları", + peerings: "Eşlemeler", + namespaces: "Ad alanları", + aclTokens: "ACL belirteçleri", + aclPolicies: "ACL politikaları", + aclRoles: "ACL rolleri", + aclAuthMethods: "ACL kimlik doğrulama yöntemleri", + aclBindingRules: "ACL bağlama kuralları", + }, + configEntries: "Yapılandırma girdileri", + intentions: "Erişim kuralları", + discoveryChain: "Keşif zinciri", + peering: "Eşleme", + exportedServices: "Dışa aktarılan servisler", + configEntryKind: "Yapılandırma girdisi türü", + loadKind: "Türü yükle", + newJson: "Yeni JSON", + modifyIndex: "ModifyIndex {index}", + rawJson: "Ham JSON", + newIntention: "Yeni erişim kuralı", + sourceService: "Kaynak servis", + destinationService: "Hedef servis", + check: "Kontrol et", + matchSource: "Kaynağı eşleştir", + matchDestination: "Hedefi eşleştir", + allowed: "İzin verildi", + denied: "Reddedildi", + matchedIntentions: "{count} erişim kuralı eşleşti", + details: "Ayrıntılar", + serviceName: "Servis adı", + compile: "Derle", + defaultProtocol: "varsayılan protokol", + configuredDatacenter: "yapılandırılmış veri merkezi", + start: "Başlat", + next: "Sonraki: {nodes}", + terminalTarget: "Son / hedef", + upstreamTargets: "Üst servis hedefleri ({count})", + peerName: "Eş adı", + peeringToken: "Eşleme kurma belirteci", + generateToken: "Belirteç oluştur", + establish: "Kur", + editExportedServices: "exported-services girdisini düzenle", + serviceMeshConfigEntry: "Servis ağı yapılandırma girdisi", + applyWithCas: "CAS ile uygula", + reviewMeshChanges: "Servis ağı değişikliklerini gözden geçir", + deleteConfig: "{kind}/{name} silinsin mi?", + deleteIntention: "{id} erişim kuralı silinsin mi?", + deleteIntentionExact: "{source} -> {destination} erişim kuralı silinsin mi?", + deletePeering: "{name} eşlemesi silinsin mi?", + permissions: "{count} izin", + actionRule: "işlem kuralı", + tools: "Consul araçları", + preparedQueries: "Hazırlanmış sorgular", + events: "Olaylar", + coordinates: "Ağ koordinatları", + queryName: "Sorgu adı", + targetService: "Hedef servis", + targetServiceValue: "Hedef servis: {service}", + cancelEdit: "Düzenlemeyi iptal et", + execute: "Çalıştır", + explain: "Açıkla", + eventName: "Olay adı", + payload: "Yük", + fire: "Gönder", + deletePreparedQuery: "{id} hazırlanmış sorgusu silinsin mi?", + nodesDatacenter: "{count} düğüm · {datacenter}", + coordinateError: "{segment} · hata {error}", + preparedQueriesDescription: "Consul'da saklanan, yeniden kullanılabilir servis keşif sorguları. Çalıştır, eşleşen sağlıklı servis örneklerini bulur; Açıkla, etkin sorguyu gösterir. Basit düzenleyici yalnızca adı ve hedef servisi değiştirir; Consul'da zaten saklanan gelişmiş alanları korur.", + eventsDescription: "Consul gossip üzerinden dağıtılan, teslimi garanti edilmeyen hafif mesajlar. Olaylar geçici tanılama veya bildirimlerdir; kalıcı bir mesaj kuyruğu değildir.", + coordinatesDescription: "Ağ yakınlığını karşılaştırmak için Consul tarafından tahmin edilen salt okunur ağ koordinatları. Coğrafi konumlar değildir.", + noPreparedQueries: "Hazırlanmış sorgu yok", + noEvents: "Son olay yok", + noCoordinates: "Ağ koordinatı yok", + queryExecutionResult: "Çalıştırma sonucu · {count} örnek · {datacenter}", + noQueryNodes: "Bu sorguyla eşleşen servis örneği yok", + queryExplanation: "Etkin sorgu", + eventNodeFilter: "Düğüm düzenli ifadesi (isteğe bağlı)", + eventServiceFilter: "Servis düzenli ifadesi (isteğe bağlı)", + eventTagFilter: "Etiket düzenli ifadesi (isteğe bağlı)", + eventPayloadBytes: "Yük {count} / 100 bayt", + segment: "Bölüt", + error: "Hata", + adjustment: "Ayarlama", + height: "Yükseklik", + operatorReadOnly: "Operatör (salt okunur)", + snapshot: "Anlık görüntü", + snapshotRestore: "Anlık görüntüyü geri yükleme", + targetDatacenter: "Hedef veri merkezi", + restoreSnapshot: "Anlık görüntüyü geri yükle", + restoreSnapshotConfirmation: "RESTORE SNAPSHOT {datacenter}", + autopilotUpdate: "Autopilot güncellemesi", + cleanupDeadServers: "Çalışmayan sunucuları temizle", + updateAutopilot: "Autopilot'u güncelle", + updateAutopilotConfirmation: "UPDATE AUTOPILOT", + raftOperations: "Raft işlemleri", + serverId: "Sunucu ID", + peerAddress: "Eş adresi (yalnızca kaldırma)", + reenterIdAddress: "ID veya adresi yeniden girin", + transferLeader: "Liderliği devret", + removePeer: "Eşi kaldır", + gossipKeyring: "Gossip anahtarlığı", + operation: "İşlem", + install: "Yükle", + use: "Kullan", + remove: "Kaldır", + gossipKey: "Gossip anahtarı", + changeKeyring: "Anahtarlığı değiştir", + changeKeyringConfirmation: "CHANGE KEYRING", + licenseUpdate: "Lisans güncellemesi", + license: "Lisans", + updateLicense: "Lisansı güncelle", + updateLicenseConfirmation: "UPDATE LICENSE", + }, + tools: { + search: "Ara", + searchTitle: "Consul KV'de ara", + searchQuery: "Aranacak metin", + prefixOptional: "Önek (isteğe bağlı)", + searchAll: "Anahtarlar ve değerler", + searchKeys: "Yalnızca anahtarlar", + searchValues: "Yalnızca değerler", + caseSensitive: "Büyük/küçük harfe duyarlı", + scanned: "{count} anahtar tarandı", + searchLimited: "Bağlantıyı korumak için sonuçlar sınırlandırıldı.", + noSearchResults: "Eşleşen anahtar yok", + searchSummary: "Taranan {scanned} anahtarda {matched} eşleşme", + exportSearchResults: "Sonuçları dışa aktar", + searchResultsFileType: "Consul KV arama sonuçları", + searchResultsExported: "{count} arama sonucu dışa aktarıldı", + exportPrefix: "Öneki dışa aktar", + prefix: "Önek", + emptyPrefixAll: "Erişilebilir tüm anahtarlar için boş bırakın", + exportLimitHint: "Dışa aktarımlar geçerli kapsamı içerir ve güvenli içe aktarma için gerekli anahtar meta verilerini korur.", + exported: "{count} anahtar dışa aktarıldı", + import: "İçe aktar", + importTitle: "Consul KV paketini içe aktar", + invalidBundle: "Bu dosya geçerli bir DBX Consul KV paketi değil", + importApplied: "{count} anahtar içe aktarıldı", + migrate: "Taşı", + migrateTitle: "Consul KV'yi taşı", + sourcePrefix: "Kaynak önek", + targetConnection: "Hedef bağlantı", + selectTarget: "Bir hedef bağlantı seçin", + targetReadOnly: "Hedef bağlantı salt okunur.", + conflictPolicy: "Çakışma politikası", + policyAbort: "Çakışmada durdur", + policySkip: "Çakışmaları atla", + policyCas: "CAS kullan", + bundleSummary: "{count} anahtar · Veri merkezi {dc} · Ad alanı {ns} · Bölüm {partition}", + creates: "Oluştur {count}", + updates: "Güncelle {count}", + unchanged: "Değişmedi {count}", + skipped: "Atlandı {count}", + conflicts: "Çakışmalar {count}", + loadPreview: "Önizlemeyi yükle", + loadingPreview: "Önizleme yükleniyor...", + apply: "Uygula", + preview: "Önizleme", + deletePrefix: "Öneki sil", + deletePrefixTitle: "Consul KV önekini sil", + deletePrefixPlaceholder: "Silinecek önek", + deletePrefixWarning: "Bu işlem önek altındaki tüm görünür anahtarları siler. Onaylamadan önce önizlemeyi inceleyin.", + candidates: "Adaylar {count}", + lockedCount: "Kilitli {count}", + filtered: "filtrelendi", + complete: "Tam", + confirmDeletePrefix: "Onaylanan anahtarları sil", + prefixDeleted: "{count} anahtar silindi", + operation: { create: "Oluştur", update: "Güncelle", unchanged: "Değişmedi", skipped: "Atlandı", conflict: "Çakışma", locked: "Kilitli", succeeded: "Başarılı", conflicted: "Çakıştı", failed: "Başarısız" }, + }, +} satisfies ConsulMessages; diff --git a/apps/desktop/src/i18n/locales/consulUi.ts b/apps/desktop/src/i18n/locales/consulUi.ts index b6bc4f88b2..5cdec3c39f 100644 --- a/apps/desktop/src/i18n/locales/consulUi.ts +++ b/apps/desktop/src/i18n/locales/consulUi.ts @@ -1,4 +1,5 @@ -// Shared fallback for Consul's advanced workspaces. Individual locales may override these keys. +// Canonical English messages and key schema for Consul's advanced workspaces. +// Operator confirmation phrases are checked verbatim by the backend; keep them in English in every locale. export const consulUiMessages = { ui: { unknown: "Unknown", @@ -91,6 +92,17 @@ export const consulUiMessages = { agentWriteReady: "Writable", agentReadOnly: "Read-only", agentWriteDisabledHint: "No matching Agent target is configured, so maintenance and deregistration are disabled. Detected Agent: {target}.", + agentWriteBlocked: { + connectionUnavailable: "Connection configuration is unavailable. Reconnect before writing.", + readOnly: "This connection is read-only. Service deregistration is disabled.", + transport: "Agent writes are unavailable through Transport Layers. Connect directly to the target Agent.", + targetRequired: "Edit the connection and configure the Agent target node and address. The node must match the current Agent, and the address must match the connection endpoint.", + identityUnavailable: "Unable to read the Agent identity. Writes are disabled. Check the connection and Agent read permissions, then refresh.", + nodeMismatch: "The configured target node does not match the current Agent. Check the connection settings.", + directAddressRequired: "Agent writes require a direct IP or localhost endpoint. DNS and load-balanced addresses are not supported.", + addressMismatch: "The Agent target address does not match the connection endpoint. Check the connection settings.", + invalidAddress: "The Consul connection address is invalid. Check the connection settings.", + }, register: "Register", registrationHint: "HTTP Agent registrations belong to the target Agent runtime and do not modify its persistent configuration files.", name: "Name", @@ -106,6 +118,10 @@ export const consulUiMessages = { disableMaintenance: "Disable maintenance", deregister: "Deregister", deregisterService: "Deregister local service {id} from {node}?", + deregistering: "Deregistering", + deregisterServiceHint: "This removes the service registration and associated checks. The Catalog will sync afterward. The service process keeps running and may register itself again.", + deregisterServiceSucceeded: "Service {id} was deregistered from {node}. Catalog synchronization may take a moment; the service may reappear if the application registers it again.", + deregisterRefreshFailed: "Service deregistered, but refreshing failed. Refresh manually", maintenanceReason: "DBX user request", serviceDetails: "{service} details", kind: "Kind", @@ -199,8 +215,8 @@ export const consulUiMessages = { serviceChecks: "Service checks", nodeCheckShort: "Node", serviceCheckShort: "Service", - serviceChecksPlaceholder: "service:api:health@namespace-a", - serviceChecksHint: "Comma-separated check IDs; use ID@namespace for a scoped check.", + serviceChecksPlaceholder: "service:api:health{'@'}namespace-a", + serviceChecksHint: "Comma-separated check IDs; use ID{'@'}namespace for a scoped check.", lockHint: "Inspect the key, select a Session, then acquire or release the advisory lock.", key: "Key", inspectKey: "Inspect key", @@ -453,3 +469,7 @@ export const consulUiMessages = { operation: { create: "Create", update: "Update", unchanged: "Unchanged", skipped: "Skipped", conflict: "Conflict", locked: "Locked", succeeded: "Succeeded", conflicted: "Conflicted", failed: "Failed" }, }, } as const; + +type LocalizedMessages = { [Key in keyof T]: T[Key] extends string ? string : LocalizedMessages }; + +export type ConsulMessages = LocalizedMessages; diff --git a/apps/desktop/src/i18n/locales/consulZhCN.ts b/apps/desktop/src/i18n/locales/consulZhCN.ts index 24ba5c25b0..84d6f2b8e6 100644 --- a/apps/desktop/src/i18n/locales/consulZhCN.ts +++ b/apps/desktop/src/i18n/locales/consulZhCN.ts @@ -4,6 +4,8 @@ export const consul = { ...consulUiMessages, ui: { ...consulUiMessages.ui, + hide: "隐藏", + script: "脚本", atomicTransaction: "单事务原子执行", nonAtomicBatches: "跨 {count} 个批次不具备整体原子性", batchOperation: "批次 {batch} · OpIndex {op}", @@ -75,6 +77,17 @@ export const consul = { agentWriteReady: "可操作", agentReadOnly: "只读", agentWriteDisabledHint: "未配置匹配的 Agent 目标,因此维护和注销操作已禁用。当前检测到:{target}。", + agentWriteBlocked: { + connectionUnavailable: "连接配置不可用,请重新连接后再操作。", + readOnly: "当前连接处于只读状态,无法注销服务。", + transport: "使用传输层的连接不支持 Agent 写操作,请直接连接目标 Agent。", + targetRequired: "请在编辑连接中填写「Agent 目标节点」和「Agent 目标地址」。节点须与当前 Agent 一致,地址须与连接地址匹配。", + identityUnavailable: "无法获取 Agent 身份,写操作已禁用。请检查连接和 Agent 读取权限后刷新。", + nodeMismatch: "配置的 Agent 目标节点与当前 Agent 不一致,请检查连接设置。", + directAddressRequired: "Agent 写操作要求使用 IP 或 localhost 直连,不支持域名或负载均衡地址。", + addressMismatch: "Agent 目标地址与连接地址不匹配,请检查连接设置。", + invalidAddress: "Consul 连接地址无效,请检查连接设置。", + }, register: "注册", registrationHint: "HTTP Agent 注册仅作用于目标 Agent 的运行时,不会修改其持久化配置文件。", name: "名称", @@ -89,6 +102,10 @@ export const consul = { disableMaintenance: "停用维护模式", deregister: "注销", deregisterService: "从 {node} 注销本地服务 {id}?", + deregistering: "正在注销", + deregisterServiceHint: "这会移除服务注册及关联检查,Catalog 将随后同步。服务进程不会停止,应用再次注册后可能重新出现。", + deregisterServiceSucceeded: "已从 {node} 注销服务 {id}。Catalog 同步可能稍有延迟;若应用再次注册,服务可能重新出现。", + deregisterRefreshFailed: "服务已注销,但刷新失败,请手动刷新", maintenanceReason: "DBX 用户请求", serviceDetails: "{service} 详情", kind: "类型", @@ -118,7 +135,7 @@ export const consul = { checkRegistrationHint: "Agent 检查仅注册在 {node} 的运行时中,不会持久化到 Agent 配置文件。", type: "类型", arguments: "参数", - containerId: "Container ID", + containerId: "容器 ID", endpoint: "端点", interval: "间隔", timeout: "超时", @@ -179,7 +196,7 @@ export const consul = { mode: "模式", server: "服务端", client: "客户端", - leader: "Leader", + leader: "领导节点", raftPeers: "Raft 对等节点", membersAlive: "存活成员", members: "成员", @@ -237,8 +254,8 @@ export const consul = { serviceChecks: "服务检查", nodeCheckShort: "节点", serviceCheckShort: "服务", - serviceChecksPlaceholder: "service:api:health@namespace-a", - serviceChecksHint: "多个检查 ID 用逗号分隔;作用域检查可写为 ID@命名空间。", + serviceChecksPlaceholder: "service:api:health{'@'}namespace-a", + serviceChecksHint: "多个检查 ID 用逗号分隔;作用域检查可写为 ID{'@'}命名空间。", lockHint: "先检查 Key,再选择会话执行获取或释放。", key: "Key", inspectKey: "检查 Key", @@ -505,8 +522,8 @@ export const consul = { partitions: "管理分区", enterprise: "Enterprise", community: "Community", - serverMode: "Server", - clientMode: "Client", + serverMode: "服务端", + clientMode: "客户端", capability: { supported: "支持", unsupported: "不支持", diff --git a/apps/desktop/src/i18n/locales/consulZhTW.ts b/apps/desktop/src/i18n/locales/consulZhTW.ts new file mode 100644 index 0000000000..36d06ee908 --- /dev/null +++ b/apps/desktop/src/i18n/locales/consulZhTW.ts @@ -0,0 +1,471 @@ +import type { ConsulMessages } from "./consulUi"; + +export const consulZhTWMessages = { + ui: { + unknown: "未知", + peeringPending: "待處理", + peeringEstablishing: "正在建立", + peeringActive: "運作中", + peeringFailing: "發生故障", + peeringDeleting: "正在刪除", + peeringTerminated: "已終止", + refresh: "重新整理", + cancel: "取消", + create: "新增", + update: "更新", + save: "儲存", + delete: "刪除", + edit: "編輯", + apply: "套用", + close: "關閉", + hide: "隱藏", + reveal: "顯示", + copy: "複製", + copied: "已複製", + copyFailed: "複製失敗", + copyOnce: "複製一次", + pause: "暫停", + watchAction: "監視", + watchPrefix: "監視前綴", + watchModePrefix: "前綴", + watchModeKey: "精確鍵名", + sessionProtected: "受工作階段保護", + sessionProtectedHint: "為保護此分散式鎖定,已停用編輯與刪除。", + atomicTransaction: "原子交易", + nonAtomicBatches: "跨 {count} 個批次不保證原子性", + batchOperation: "批次 {batch} · 操作索引 {op}", + operationTotals: "成功 {succeeded} · 衝突 {conflicted} · 略過 {skipped} · 失敗 {failed}", + deleteOperationTotals: "成功 {succeeded} · 衝突 {conflicted} · 失敗 {failed}", + clientSideMigration: "DBX 從來源讀取並寫入目標。這不是 Consul 原生的跨資料中心複寫。", + bundleFileType: "DBX Consul KV 資料套件", + sourceKeyMissingModifyIndex: "來源鍵缺少 ModifyIndex", + transactionRejected: "Consul 拒絕了交易", + overview: "叢集概覽", + capabilities: "功能", + probeLoading: "載入中", + probeReady: "就緒", + probeForbidden: "無權限", + probeUnsupported: "不支援", + probeError: "錯誤", + autopilotHealth: "Autopilot 健康狀態", + datacenter: "資料中心", + agentNode: "Agent 節點", + agentAddress: "Agent 位址", + version: "版本", + mode: "模式", + server: "伺服器", + client: "用戶端", + leader: "領導節點", + raftPeers: "Raft 對等節點", + membersAlive: "存活成員", + members: "成員", + node: "節點", + address: "位址", + status: "狀態", + alive: "存活", + leaving: "離開中", + failed: "故障", + previousPage: "上一頁", + nextPage: "下一頁", + pageStatus: "{page} / {pages} · 共 {total} 筆", + searchAllServices: "搜尋所有服務", + searchAllNodes: "搜尋所有節點", + searchLocalServices: "搜尋本機 Agent 服務", + query: "查詢", + searchHealthChecks: "搜尋檢查名稱、ID、節點、服務、輸出或備註", + allCheckTypes: "所有檢查類型", + clearFilters: "清除篩選", + healthResultCount: "共 {total} 個檢查,顯示 {filtered} 個", + services: "服務", + nodes: "節點", + service: "服務", + catalogServices: "Catalog 服務", + catalogNodes: "Catalog 節點", + noVisibleServices: "沒有可見的服務", + noVisibleNodes: "沒有可見的節點", + noMatchingServices: "沒有符合條件的服務", + noMatchingNodes: "沒有符合條件的節點", + agentTarget: "目標 Agent:{target}", + agentTargetVerifying: "正在確認目標 Agent", + unknownWritesDisabled: "未知,已停用寫入", + targetAgent: "目標 Agent", + agentWriteReady: "可寫入", + agentReadOnly: "唯讀", + agentWriteDisabledHint: "尚未設定符合的目標 Agent,已停用維護與取消註冊操作。偵測到的 Agent:{target}。", + agentWriteBlocked: { + connectionUnavailable: "無法取得連線設定,請重新連線後再操作。", + readOnly: "此連線為唯讀,已停用服務取消註冊。", + transport: "透過傳輸層的連線不支援 Agent 寫入,請直接連線至目標 Agent。", + targetRequired: "請編輯連線並設定目標 Agent 節點與位址。節點須與目前 Agent 一致,位址須與連線端點相符。", + identityUnavailable: "無法取得 Agent 身分,已停用寫入。請檢查連線與 Agent 讀取權限後重新整理。", + nodeMismatch: "設定的目標節點與目前 Agent 不一致,請檢查連線設定。", + directAddressRequired: "Agent 寫入須使用 IP 或 localhost 直接連線,不支援 DNS 名稱或負載平衡位址。", + addressMismatch: "目標 Agent 位址與連線端點不符,請檢查連線設定。", + invalidAddress: "Consul 連線位址無效,請檢查連線設定。", + }, + register: "註冊", + registrationHint: "透過 HTTP 註冊的服務僅作用於目標 Agent 的執行階段,不會修改其持久設定檔。", + name: "名稱", + id: "ID", + port: "連接埠", + tags: "標籤(以逗號分隔)", + registerOn: "註冊至 {node}", + catalogInstances: "Catalog 執行個體", + nodeServices: "節點服務", + serviceId: "服務 ID", + localAgentServices: "本機 Agent 服務", + enableMaintenance: "啟用維護模式", + disableMaintenance: "停用維護模式", + deregister: "取消註冊", + deregisterService: "要從 {node} 取消註冊本機服務 {id} 嗎?", + deregistering: "正在取消註冊", + deregisterServiceHint: "這會移除服務註冊及相關檢查,Catalog 隨後將同步。服務處理程序不會停止,應用程式可能再次註冊。", + deregisterServiceSucceeded: "已從 {node} 取消註冊服務 {id}。Catalog 同步可能稍有延遲;若應用程式再次註冊,服務可能重新出現。", + deregisterRefreshFailed: "已取消註冊服務,但重新整理失敗,請手動重新整理", + maintenanceReason: "DBX 使用者要求", + serviceDetails: "{service} 詳細資料", + kind: "種類", + serviceKind: "服務種類(ServiceKind)", + standard: "標準", + metadata: "中繼資料", + nodeMeta: "節點中繼資料", + serviceMeta: "服務中繼資料", + nodeId: "節點 ID", + serviceWeights: "通過 / 警告權重", + taggedAddresses: "標記位址", + enableTagOverride: "允許覆寫標籤", + agent: "Agent", + watch: "監視", + writeOperation: "寫入操作", + localServiceDetails: "本機服務詳細資料", + agentIdentityRequestTimedOut: "載入 Agent 身分逾時。", + localServicesRequestTimedOut: "載入本機 Agent 服務逾時。", + localChecksRequestTimedOut: "載入本機 Agent 檢查逾時。", + healthChecks: "健康檢查", + state: "狀態", + nodeName: "節點名稱", + allStates: "所有狀態", + passing: "通過", + warning: "警告", + critical: "嚴重", + watchPaused: "已暫停監視", + watchingIndex: "正在監視索引 {index}", + pauseWatch: "暫停監視", + startWatch: "開始監視", + checkRegistrationHint: "Agent 檢查是 {node} 上的執行階段註冊,不會儲存至 Agent 設定檔。", + type: "類型", + ttl: "TTL", + http: "HTTP", + tcp: "TCP", + grpc: "gRPC", + docker: "Docker", + script: "指令碼", + arguments: "引數", + containerId: "容器 ID", + endpoint: "端點", + interval: "間隔", + timeout: "逾時", + commandArguments: "命令引數", + clusterHealth: "叢集健康狀態", + nodeHealth: "節點健康狀態:{node}", + serviceHealth: "服務健康狀態:{service}", + noMatchingHealthChecks: "沒有符合條件的健康檢查", + serviceInstances: "服務執行個體", + localAgentChecks: "本機 Agent 檢查", + maintenance: "維護模式", + ttlPass: "將 TTL 設為通過", + ttlWarn: "將 TTL 設為警告", + ttlFail: "將 TTL 設為失敗", + deregisterCheck: "要從 {node} 取消註冊檢查 {id} 嗎?", + checkDetails: "{check} 詳細資料", + checkId: "檢查 ID", + notes: "備註", + output: "輸出", + definition: "定義", + indexes: "CreateIndex / ModifyIndex", + sessionsAndLocks: "工作階段與鎖定", + sessions: "工作階段", + sessionDescription: "工作階段是 Consul KV 鎖定使用的類租約機制。含 TTL 的工作階段須續期;無 TTL 的工作階段會持續存在,直到明確銷毀或因檢查而失效。", + createSession: "新增工作階段", + searchSessions: "搜尋工作階段名稱、ID、節點或檢查", + sessionResultCount: "共 {total} 個工作階段,顯示 {filtered} 個", + noMatchingSessions: "沒有符合條件的工作階段", + allSessionTypes: "所有工作階段類型", + ttlSessions: "含 TTL 的工作階段", + persistentSessions: "無 TTL 的工作階段", + allBehaviors: "所有行為", + aclFilteredSessions: "工作階段清單已被 ACL 篩選", + sessionRequestTimedOut: "載入工作階段逾時,請檢查 Consul 連線後再試。", + complete: "完整", + lock: "鎖定", + lockManagement: "KV 鎖定管理", + lockIndex: "LockIndex {index}", + lockDelay: "鎖定延遲", + lockDelayHint: "0s~60s;失效後延遲重新取得鎖定。", + nodeOptional: "節點(選填)", + behavior: "行為", + behaviorRelease: "釋放(release)", + behaviorDelete: "刪除(delete)", + behaviorHint: "工作階段到期時,release 保留所持有的鍵;delete 則刪除這些鍵。", + releaseLocks: "釋放鎖定", + deleteKeys: "刪除鍵", + deleteBehaviorWarning: "Behavior=delete 會在工作階段失效時刪除其持有的所有鍵。要繼續嗎?", + checks: "檢查", + nodeChecks: "節點檢查", + serviceChecks: "服務檢查", + nodeCheckShort: "節點", + serviceCheckShort: "服務", + serviceChecksPlaceholder: "service:api:health{'@'}namespace-a", + serviceChecksHint: "以逗號分隔檢查 ID;若要指定命名空間,請使用 ID{'@'}namespace。", + lockHint: "先檢視鍵並選擇工作階段,再取得或釋放協調式鎖定。", + key: "鍵", + inspectKey: "檢視鍵", + keyExists: "鍵已存在", + keyNotFound: "鍵不存在", + keyUnlocked: "此鍵目前未被持有", + keyHeldBy: "由工作階段 {session} 持有", + sessionValue: "工作階段 {id}", + modifyIndexValue: "ModifyIndex {index}", + createIndex: "CreateIndex", + modifyIndexLabel: "ModifyIndex", + selectSession: "選擇工作階段", + sessionId: "工作階段 ID", + expectedModifyIndex: "預期 ModifyIndex(新鍵填 0)", + value: "值", + releaseMatchingSession: "釋放", + acquire: "取得", + unnamedSession: "未命名工作階段", + heldKeys: "持有的鍵", + heldKeysIncomplete: "結果不完整或已被 ACL 篩選", + stop: "停止", + renewNow: "立即續期", + autoRenew: "自動續期", + autoRenewPageHint: "自動續期僅在此連線與頁面保持作用中時執行。", + noRenewRequired: "無須續期", + noTtl: "無 TTL", + ttlOptional: "TTL(選填)", + ttlRangeHint: "留空建立持久工作階段,或輸入 10s~24h。", + invalidSessionTtl: "TTL 須留空或為 10s~24h 的有效時間長度。", + invalidLockDelay: "鎖定延遲須為 0s~60s 的有效時間長度。", + destroy: "銷毀", + noHeldKeys: "沒有持有的鍵", + noVisibleSessions: "沒有可見的工作階段", + destroySession: "要銷毀工作階段 {id} 嗎?其鎖定可能依行為設定而釋放或刪除。", + destroySessionImpact: "要銷毀工作階段 {id} 嗎?行為:{behavior}。持有的鍵({count}):{keys}", + sessionImpactIncomplete: "工作階段影響範圍不完整或已被 ACL 篩選,已阻止銷毀。", + sessionDetails: "TTL {ttl} · {behavior} · 檢查 {checks}", + tokens: "權杖", + policies: "原則", + roles: "角色", + authMethods: "驗證方式", + bindingRules: "繫結規則", + templatedPolicies: "範本原則", + capability: "功能:{status}", + capabilitySupported: "支援", + capabilityUnsupported: "不支援", + capabilityDisabled: "已停用", + capabilityForbidden: "無權限", + capabilityUnknown: "未知", + loading: "載入中...", + viewOrEdit: "檢視或編輯", + cloneToken: "複製權杖", + deleteAndInspectReferences: "刪除並檢視參照", + noResources: "沒有資源", + editResource: "編輯 {kind}", + createResource: "新增 {kind}", + knownImpact: "已知影響:{tokens} 個權杖、{roles} 個角色、{bindingRules} 條繫結規則", + incomplete: "(不完整)", + reviewAclChanges: "檢視 ACL 變更", + deleteResource: "刪除 {label}", + tokenReferences: "權杖參照:{tokens} · 角色參照:{roles} · 繫結規則參照:{bindingRules}", + impactBlocked: "影響範圍不完整或已被 ACL 篩選,已阻止刪除。", + cloneTokenDescription: "複製權杖的說明", + scope: "Consul 作用域", + adminPartition: "管理分區", + namespace: "命名空間", + default: "預設", + applyScope: "套用作用域", + enterpriseCapability: "Enterprise 功能:{status}。無法使用生命週期操作。", + namespaces: "命名空間", + lifecycleImpact: "作用域內資源影響", + inspectImpactAndDelete: "檢視影響並刪除", + impactAclFiltered: "Consul 回報結果已被 ACL 篩選,已阻止刪除。", + impactUnavailable: "無法列舉:{resources}", + impactResource: { + services: "服務", + nodes: "節點", + kvKeys: "KV 鍵", + healthChecks: "健康檢查", + sessions: "工作階段", + configEntries: "設定項目", + intentions: "通訊意圖規則", + peerings: "對等連線", + namespaces: "命名空間", + aclTokens: "ACL 權杖", + aclPolicies: "ACL 原則", + aclRoles: "ACL 角色", + aclAuthMethods: "ACL 驗證方式", + aclBindingRules: "ACL 繫結規則", + }, + configEntries: "設定項目", + intentions: "通訊意圖規則", + discoveryChain: "服務探索鏈", + peering: "對等連線", + exportedServices: "匯出服務", + configEntryKind: "設定項目種類", + loadKind: "載入種類", + newJson: "新增 JSON", + modifyIndex: "ModifyIndex {index}", + rawJson: "原始 JSON", + newIntention: "新增通訊意圖規則", + sourceService: "來源服務", + destinationService: "目標服務", + check: "檢查", + matchSource: "比對來源", + matchDestination: "比對目標", + allowed: "允許", + denied: "拒絕", + matchedIntentions: "符合 {count} 條通訊意圖規則", + details: "詳細資料", + serviceName: "服務名稱", + compile: "編譯", + defaultProtocol: "預設通訊協定", + configuredDatacenter: "已設定的資料中心", + start: "開始", + next: "下一步:{nodes}", + terminalTarget: "終端 / 目標", + upstreamTargets: "上游目標({count})", + peerName: "對等節點名稱", + peeringToken: "用於建立對等連線的權杖", + generateToken: "產生權杖", + establish: "建立連線", + editExportedServices: "編輯 exported-services 項目", + serviceMeshConfigEntry: "服務網格設定項目", + applyWithCas: "以 CAS 套用", + reviewMeshChanges: "檢視服務網格變更", + deleteConfig: "要刪除 {kind}/{name} 嗎?", + deleteIntention: "要刪除通訊意圖規則 {id} 嗎?", + deleteIntentionExact: "要刪除通訊意圖規則 {source} -> {destination} 嗎?", + deletePeering: "要刪除對等連線 {name} 嗎?", + permissions: "{count} 項權限", + actionRule: "操作規則", + tools: "Consul 工具", + preparedQueries: "預存查詢", + events: "事件", + coordinates: "網路座標", + queryName: "查詢名稱", + targetService: "目標服務", + targetServiceValue: "目標服務:{service}", + cancelEdit: "取消編輯", + execute: "執行", + explain: "檢視有效查詢", + eventName: "事件名稱", + payload: "承載內容", + fire: "發送", + deletePreparedQuery: "要刪除預存查詢 {id} 嗎?", + nodesDatacenter: "{count} 個節點 · {datacenter}", + coordinateError: "{segment} · 誤差 {error}", + preparedQueriesDescription: "儲存在 Consul 中、可重複使用的服務探索查詢。「執行」會解析符合條件的健康服務執行個體;「檢視有效查詢」會顯示實際生效的查詢。簡易編輯器僅修改名稱與目標服務,保留 Consul 已儲存的進階欄位。", + eventsDescription: "透過 Consul gossip 傳播的輕量盡力傳遞訊息。事件是暫時性的診斷或通知,不是持久訊息佇列。", + coordinatesDescription: "Consul 估算的唯讀網路座標,用於比較網路距離,並非地理位置。", + noPreparedQueries: "沒有預存查詢", + noEvents: "沒有近期事件", + noCoordinates: "沒有網路座標", + queryExecutionResult: "執行結果 · {count} 個執行個體 · {datacenter}", + noQueryNodes: "沒有服務執行個體符合此查詢", + queryExplanation: "有效查詢", + eventNodeFilter: "節點正規表示式(選填)", + eventServiceFilter: "服務正規表示式(選填)", + eventTagFilter: "標籤正規表示式(選填)", + eventPayloadBytes: "承載內容 {count} / 100 位元組", + segment: "區段", + error: "錯誤", + adjustment: "調整值", + height: "高度", + operatorReadOnly: "維運(唯讀)", + snapshot: "快照", + snapshotRestore: "快照還原", + targetDatacenter: "目標資料中心", + restoreSnapshot: "還原快照", + restoreSnapshotConfirmation: "RESTORE SNAPSHOT {datacenter}", + autopilotUpdate: "Autopilot 更新", + cleanupDeadServers: "清除失效伺服器", + updateAutopilot: "更新 Autopilot", + updateAutopilotConfirmation: "UPDATE AUTOPILOT", + raftOperations: "Raft 操作", + serverId: "伺服器 ID", + peerAddress: "對等節點位址(僅供移除)", + reenterIdAddress: "再次輸入 ID 或位址", + transferLeader: "轉移領導節點", + removePeer: "移除對等節點", + gossipKeyring: "Gossip 金鑰環", + operation: "操作", + install: "安裝", + use: "使用", + remove: "移除", + gossipKey: "Gossip 金鑰", + changeKeyring: "變更金鑰環", + changeKeyringConfirmation: "CHANGE KEYRING", + licenseUpdate: "授權更新", + license: "授權", + updateLicense: "更新授權", + updateLicenseConfirmation: "UPDATE LICENSE", + }, + tools: { + search: "搜尋", + searchTitle: "搜尋 Consul KV", + searchQuery: "要尋找的文字", + prefixOptional: "前綴(選填)", + searchAll: "鍵與值", + searchKeys: "僅鍵", + searchValues: "僅值", + caseSensitive: "區分大小寫", + scanned: "已掃描 {count} 個鍵", + searchLimited: "為保護連線,已限制結果數量。", + noSearchResults: "沒有符合條件的鍵", + searchSummary: "已掃描 {scanned} 個鍵,符合 {matched} 個", + exportSearchResults: "匯出結果", + searchResultsFileType: "Consul KV 搜尋結果", + searchResultsExported: "已匯出 {count} 筆搜尋結果", + exportPrefix: "匯出前綴", + prefix: "前綴", + emptyPrefixAll: "留空代表所有可存取的鍵", + exportLimitHint: "匯出內容包含目前作用域,並保留安全匯入所需的鍵中繼資料。", + exported: "已匯出 {count} 個鍵", + import: "匯入", + importTitle: "匯入 Consul KV 資料套件", + invalidBundle: "此檔案不是有效的 DBX Consul KV 資料套件", + importApplied: "已匯入 {count} 個鍵", + migrate: "移轉", + migrateTitle: "移轉 Consul KV", + sourcePrefix: "來源前綴", + targetConnection: "目標連線", + selectTarget: "選擇目標連線", + targetReadOnly: "目標連線為唯讀。", + conflictPolicy: "衝突處理原則", + policyAbort: "發生衝突時中止", + policySkip: "略過衝突", + policyCas: "使用 CAS", + bundleSummary: "{count} 個鍵 · 資料中心 {dc} · 命名空間 {ns} · 分區 {partition}", + creates: "新增 {count}", + updates: "更新 {count}", + unchanged: "未變更 {count}", + skipped: "已略過 {count}", + conflicts: "衝突 {count}", + loadPreview: "載入預覽", + loadingPreview: "正在載入預覽...", + apply: "套用", + preview: "預覽", + deletePrefix: "刪除前綴", + deletePrefixTitle: "刪除 Consul KV 前綴", + deletePrefixPlaceholder: "要刪除的前綴", + deletePrefixWarning: "此操作會刪除前綴下所有可見的鍵,請先檢視預覽再確認。", + candidates: "候選項 {count}", + lockedCount: "已鎖定 {count}", + filtered: "已篩選", + complete: "完整", + confirmDeletePrefix: "刪除已確認的鍵", + prefixDeleted: "已刪除 {count} 個鍵", + operation: { create: "新增", update: "更新", unchanged: "未變更", skipped: "已略過", conflict: "衝突", locked: "已鎖定", succeeded: "成功", conflicted: "衝突", failed: "失敗" }, + }, +} satisfies ConsulMessages; diff --git a/apps/desktop/src/i18n/locales/es.ts b/apps/desktop/src/i18n/locales/es.ts index fc08ed92c6..0d9107f969 100644 --- a/apps/desktop/src/i18n/locales/es.ts +++ b/apps/desktop/src/i18n/locales/es.ts @@ -2,60 +2,60 @@ import { withEnglishFallback } from "./fallback"; import { meilisearchManagementEs } from "./meilisearchManagement"; import { redisGroupingEs as redisGrouping } from "./redisGrouping"; import docs from "./docs/es"; -import { consulUiMessages } from "./consulUi"; +import { consulEsMessages } from "./consulEs"; import { nacosAccessControlMessages, nacosAccessControlTabs } from "./nacosAccessControl"; import { sqlServerTraceMessages as sqlServerTrace } from "./sqlServerTraceMessages"; const consul = { - ...consulUiMessages, + ...consulEsMessages, redisGrouping, - prefixPlaceholder: "Key prefix, e.g. app/ or services/", - newKey: "New Key", - loadingKeys: "Loading keys...", - empty: "No keys found", - loadMore: "Load more", - selectKey: "Select a key to view its value", - loadingValue: "Loading value...", - notFound: "Key not found", - edit: "Edit", - editKey: "Edit Key", - delete: "Delete", - deleteTitle: "Delete Consul KV key", + prefixPlaceholder: "Prefijo de clave, p. ej., app/ o services/", + newKey: "Nueva clave", + loadingKeys: "Cargando claves...", + empty: "No se encontraron claves", + loadMore: "Cargar más", + selectKey: "Seleccione una clave para ver su valor", + loadingValue: "Cargando valor...", + notFound: "Clave no encontrada", + edit: "Editar", + editKey: "Editar clave", + delete: "Eliminar", + deleteTitle: "Eliminar clave KV de Consul", keyLabel: "Clave (Key)", keyPlaceholder: "path/to/key", - keyRequired: "Key is required", - rootReadonly: "The root prefix cannot be modified. Enter a key path.", - saved: "Key saved", - deleted: "Key deleted", - base64Readonly: "Edit binary values in Base64 mode.", + keyRequired: "La clave es obligatoria", + rootReadonly: "El prefijo raíz no se puede modificar. Introduzca una ruta de clave.", + saved: "Clave guardada", + deleted: "Clave eliminada", + base64Readonly: "Edite los valores binarios en modo Base64.", rename: "Renombrar", clone: "Clonar", copyKey: "Copiar clave", export: "Exportar", - value: "Value", + value: "Valor", valueContent: "Valor", format: "Formato", - metadata: "KV metadata", - prettyJson: "Pretty", - invalidJson: "Invalid JSON", - summarySize: "Size", - conflict: "This Key changed after it was loaded. Refresh it and try again.", - keyAlreadyExists: "A Key with this name already exists. Choose another name or edit the existing Key.", - aclFiltered: "Some Consul KV keys are hidden by ACL policies.", - locked: "This Key is held by a Consul Session and cannot be edited or deleted.", - valueTooLarge: "Consul KV values cannot exceed 512 KiB.", + metadata: "Metadatos KV", + prettyJson: "Formatear", + invalidJson: "JSON no válido", + summarySize: "Tamaño", + conflict: "Esta clave cambió después de cargarla. Actualícela e inténtelo de nuevo.", + keyAlreadyExists: "Ya existe una clave con este nombre. Elija otro nombre o edite la clave existente.", + aclFiltered: "Algunas claves KV de Consul están ocultas por políticas ACL.", + locked: "Una sesión de Consul retiene esta clave y no se puede editar ni eliminar.", + valueTooLarge: "Los valores KV de Consul no pueden superar los 512 KiB.", watchKey: "Vigilar", stopWatching: "Detener", workspace: { overview: "Resumen", kv: "KV", - services: "Services", - health: "Health", - sessions: "Sessions", - scope: "Scope", - mesh: "Service Mesh", - tools: "Tools", - operator: "Operator", + services: "Servicios", + health: "Estado", + sessions: "Sesiones", + scope: "Ámbito", + mesh: "Malla de servicios", + tools: "Herramientas", + operator: "Operaciones", refresh: "Actualizar capacidades", loading: "Cargando capacidades de Consul...", agentIdentity: "Identidad del agente", @@ -655,34 +655,34 @@ export default withEnglishFallback({ etcdClientCertBrowse: "Elegir certificado de cliente", etcdClientKeyBrowse: "Elegir clave privada de cliente", etcdClientCertPairRequired: "El certificado y la clave privada deben proporcionarse juntos.", - consulAddress: "Consul API address", - consulAddressInvalid: "Enter an absolute HTTP or HTTPS Consul API address without credentials, query parameters, or a fragment.", - consulToken: "ACL Token", - consulTokenPlaceholder: "Optional Consul ACL Token", - consulDatacenter: "Datacenter", - consulNamespace: "Namespace", - consulPartition: "Admin Partition", - consulAgentTargetNode: "Agent target node", - consulAgentTargetAddress: "Agent direct address", - consulAgentTargetHint: "Required for Agent writes. DNS/load-balanced and Transport Layer endpoints stay read-only.", - consulMeshFeatures: "Service mesh", - consulMeshVisible: "Show advanced service mesh workspace", - consulMeshVisibleHint: "Enable only to manage Connect, intentions, or peering. When disabled, the workspace stays hidden.", - consulOperatorWrites: "Operator writes", - consulOperatorVisible: "Show experimental Operator workspace", - consulOperatorSnapshotRestore: "Enable snapshot restore", - consulOperatorAutopilot: "Enable Autopilot updates", - consulOperatorRaft: "Enable Raft changes", - consulOperatorKeyring: "Enable Keyring changes", - consulOperatorLicense: "Enable License updates", - consulAgentTargetIncomplete: "Agent target node and direct address must be configured together.", - consulAgentTargetAddressMismatch: "Agent direct address must match the Consul endpoint host.", - consulConsistency: "Read consistency", - consulConsistencyDefault: "Default", - consulConsistencyStale: "Stale", - consulConsistencyConsistent: "Consistent", - consulTlsSkipVerify: "Skip certificate verification", - consulTlsSkipVerifyHint: "Use only for trusted self-signed Consul endpoints.", + consulAddress: "Dirección de la API de Consul", + consulAddressInvalid: "Introduzca una dirección absoluta HTTP o HTTPS de la API de Consul sin credenciales, parámetros de consulta ni fragmentos.", + consulToken: "Token ACL", + consulTokenPlaceholder: "Token ACL de Consul (opcional)", + consulDatacenter: "Centro de datos", + consulNamespace: "Espacio de nombres", + consulPartition: "Partición administrativa", + consulAgentTargetNode: "Nodo del agente de destino", + consulAgentTargetAddress: "Dirección directa del agente", + consulAgentTargetHint: "Necesario para escribir en el agente. Los extremos DNS, con balanceo de carga o mediante capas de transporte permanecen en modo de solo lectura.", + consulMeshFeatures: "Malla de servicios", + consulMeshVisible: "Mostrar el espacio de trabajo avanzado de la malla de servicios", + consulMeshVisibleHint: "Habilítelo solo para gestionar Connect, intenciones o emparejamientos. Si se deshabilita, el espacio de trabajo permanece oculto.", + consulOperatorWrites: "Escrituras de operaciones", + consulOperatorVisible: "Mostrar el espacio de trabajo experimental de operaciones", + consulOperatorSnapshotRestore: "Habilitar restauración de instantáneas", + consulOperatorAutopilot: "Habilitar actualizaciones de Autopilot", + consulOperatorRaft: "Habilitar cambios de Raft", + consulOperatorKeyring: "Habilitar cambios del llavero", + consulOperatorLicense: "Habilitar actualizaciones de licencia", + consulAgentTargetIncomplete: "El nodo de destino y la dirección directa del agente deben configurarse juntos.", + consulAgentTargetAddressMismatch: "La dirección directa del agente debe coincidir con el host del extremo de Consul.", + consulConsistency: "Consistencia de lectura", + consulConsistencyDefault: "Predeterminada", + consulConsistencyStale: "Lectura obsoleta (Stale)", + consulConsistencyConsistent: "Lectura consistente (Consistent)", + consulTlsSkipVerify: "Omitir la verificación del certificado", + consulTlsSkipVerifyHint: "Úselo solo para extremos de Consul de confianza con certificados autofirmados.", zookeeperConnectString: "Cadena de conexión", zookeeperConnectStringHint: "Entradas host:puerto separadas por coma o por línea. Déjalo en blanco para usar el host y puerto de arriba.", zookeeperCreateModePersistent: "Persistente", diff --git a/apps/desktop/src/i18n/locales/it.ts b/apps/desktop/src/i18n/locales/it.ts index fa1a31e13a..0428f584b3 100644 --- a/apps/desktop/src/i18n/locales/it.ts +++ b/apps/desktop/src/i18n/locales/it.ts @@ -2,69 +2,69 @@ import { withEnglishFallback } from "./fallback"; import { meilisearchManagementIt } from "./meilisearchManagement"; import { redisGroupingIt as redisGrouping } from "./redisGrouping"; import docs from "./docs/it"; -import { consulUiMessages } from "./consulUi"; +import { consulItMessages } from "./consulIt"; import { nacosAccessControlMessages, nacosAccessControlTabs } from "./nacosAccessControl"; import { sqlServerTraceMessages as sqlServerTrace } from "./sqlServerTraceMessages"; const consul = { - ...consulUiMessages, + ...consulItMessages, redisGrouping, - prefixPlaceholder: "Key prefix, e.g. app/ or services/", - newKey: "New Key", - loadingKeys: "Loading keys...", - empty: "No keys found", - loadMore: "Load more", - selectKey: "Select a key to view its value", - loadingValue: "Loading value...", - notFound: "Key not found", - edit: "Edit", - editKey: "Edit Key", - delete: "Delete", - deleteTitle: "Delete Consul KV key", - keyLabel: "Chiave (Key)", - keyPlaceholder: "path/to/key", - keyRequired: "Key is required", - rootReadonly: "The root prefix cannot be modified. Enter a key path.", - saved: "Key saved", - deleted: "Key deleted", - base64Readonly: "Edit binary values in Base64 mode.", + prefixPlaceholder: "Prefisso chiave, ad es. app/ o services/", + newKey: "Nuova chiave", + loadingKeys: "Caricamento chiavi...", + empty: "Nessuna chiave trovata", + loadMore: "Carica altro", + selectKey: "Seleziona una chiave per visualizzarne il valore", + loadingValue: "Caricamento valore...", + notFound: "Chiave non trovata", + edit: "Modifica", + editKey: "Modifica chiave", + delete: "Elimina", + deleteTitle: "Elimina chiave Consul KV", + keyLabel: "Chiave", + keyPlaceholder: "percorso/della/chiave", + keyRequired: "La chiave è obbligatoria", + rootReadonly: "Il prefisso radice non può essere modificato. Inserisci il percorso di una chiave.", + saved: "Chiave salvata", + deleted: "Chiave eliminata", + base64Readonly: "Modifica i valori binari in modalità Base64.", rename: "Rinomina", clone: "Clona", copyKey: "Copia chiave", export: "Esporta", - value: "Value", + value: "Valore", valueContent: "Valore", format: "Formato", - metadata: "KV metadata", - prettyJson: "Pretty", - invalidJson: "Invalid JSON", - summarySize: "Size", - conflict: "This Key changed after it was loaded. Refresh it and try again.", - keyAlreadyExists: "A Key with this name already exists. Choose another name or edit the existing Key.", - aclFiltered: "Some Consul KV keys are hidden by ACL policies.", - locked: "This Key is held by a Consul Session and cannot be edited or deleted.", - valueTooLarge: "Consul KV values cannot exceed 512 KiB.", + metadata: "Metadati KV", + prettyJson: "Formatta", + invalidJson: "JSON non valido", + summarySize: "Dimensione", + conflict: "Questa chiave è cambiata dopo il caricamento. Aggiornala e riprova.", + keyAlreadyExists: "Esiste già una chiave con questo nome. Scegli un altro nome o modifica la chiave esistente.", + aclFiltered: "Alcune chiavi Consul KV sono nascoste dalle policy ACL.", + locked: "Questa chiave è bloccata da una sessione Consul e non può essere modificata o eliminata.", + valueTooLarge: "I valori Consul KV non possono superare 512 KiB.", watchKey: "Monitora", stopWatching: "Interrompi", workspace: { overview: "Panoramica", kv: "KV", - services: "Services", - health: "Health", - sessions: "Sessions", - scope: "Scope", - mesh: "Service Mesh", - tools: "Tools", - operator: "Operator", + services: "Servizi", + health: "Integrità", + sessions: "Sessioni", + scope: "Ambito", + mesh: "Mesh di servizi", + tools: "Strumenti", + operator: "Operatore", refresh: "Aggiorna capacità", loading: "Caricamento delle capacità Consul...", - agentIdentity: "Identità agent", + agentIdentity: "Identità dell'agente", capabilities: "Capacità", version: "Versione", edition: "Edizione", datacenter: "Datacenter", - node: "Nodo agent", - mode: "Modalità agent", - agent: "API agent", + node: "Nodo dell'agente", + mode: "Modalità dell'agente", + agent: "API dell'agente", acl: "ACL", namespaces: "Namespace", partitions: "Partizioni amministrative", @@ -654,34 +654,34 @@ export default withEnglishFallback({ etcdClientCertBrowse: "Scegli certificato client", etcdClientKeyBrowse: "Scegli chiave privata client", etcdClientCertPairRequired: "Il certificato client e la chiave privata devono essere forniti insieme.", - consulAddress: "Consul API address", - consulAddressInvalid: "Enter an absolute HTTP or HTTPS Consul API address without credentials, query parameters, or a fragment.", - consulToken: "ACL Token", - consulTokenPlaceholder: "Optional Consul ACL Token", + consulAddress: "Indirizzo API Consul", + consulAddressInvalid: "Inserisci un indirizzo API Consul HTTP o HTTPS assoluto, senza credenziali, parametri di query o frammenti.", + consulToken: "Token ACL", + consulTokenPlaceholder: "Token ACL Consul facoltativo", consulDatacenter: "Datacenter", consulNamespace: "Namespace", - consulPartition: "Admin Partition", - consulAgentTargetNode: "Agent target node", - consulAgentTargetAddress: "Agent direct address", - consulAgentTargetHint: "Required for Agent writes. DNS/load-balanced and Transport Layer endpoints stay read-only.", - consulMeshFeatures: "Service mesh", - consulMeshVisible: "Show advanced service mesh workspace", - consulMeshVisibleHint: "Enable only to manage Connect, intentions, or peering. When disabled, the workspace stays hidden.", - consulOperatorWrites: "Operator writes", - consulOperatorVisible: "Show experimental Operator workspace", - consulOperatorSnapshotRestore: "Enable snapshot restore", - consulOperatorAutopilot: "Enable Autopilot updates", - consulOperatorRaft: "Enable Raft changes", - consulOperatorKeyring: "Enable Keyring changes", - consulOperatorLicense: "Enable License updates", - consulAgentTargetIncomplete: "Agent target node and direct address must be configured together.", - consulAgentTargetAddressMismatch: "Agent direct address must match the Consul endpoint host.", - consulConsistency: "Read consistency", - consulConsistencyDefault: "Default", - consulConsistencyStale: "Stale", - consulConsistencyConsistent: "Consistent", - consulTlsSkipVerify: "Skip certificate verification", - consulTlsSkipVerifyHint: "Use only for trusted self-signed Consul endpoints.", + consulPartition: "Partizione amministrativa", + consulAgentTargetNode: "Nodo dell'agente di destinazione", + consulAgentTargetAddress: "Indirizzo diretto dell'agente", + consulAgentTargetHint: "Obbligatorio per scrivere sull'agente. Gli endpoint DNS, con bilanciamento del carico o con livelli di trasporto restano di sola lettura.", + consulMeshFeatures: "Mesh di servizi", + consulMeshVisible: "Mostra l'area avanzata della mesh di servizi", + consulMeshVisibleHint: "Abilita solo per gestire Connect, intenzioni o peering. Se disabilitata, l'area resta nascosta.", + consulOperatorWrites: "Scritture dell'operatore", + consulOperatorVisible: "Mostra l'area sperimentale dell'operatore", + consulOperatorSnapshotRestore: "Abilita ripristino snapshot", + consulOperatorAutopilot: "Abilita aggiornamenti Autopilot", + consulOperatorRaft: "Abilita modifiche Raft", + consulOperatorKeyring: "Abilita modifiche al portachiavi", + consulOperatorLicense: "Abilita aggiornamenti della licenza", + consulAgentTargetIncomplete: "Il nodo dell'agente di destinazione e l'indirizzo diretto devono essere configurati insieme.", + consulAgentTargetAddressMismatch: "L'indirizzo diretto dell'agente deve corrispondere all'host dell'endpoint Consul.", + consulConsistency: "Coerenza di lettura", + consulConsistencyDefault: "Predefinita", + consulConsistencyStale: "Potenzialmente obsoleta (stale)", + consulConsistencyConsistent: "Coerente (consistent)", + consulTlsSkipVerify: "Ignora verifica del certificato", + consulTlsSkipVerifyHint: "Usa solo per endpoint Consul attendibili con certificati autofirmati.", zookeeperConnectString: "Stringa di connessione", zookeeperConnectStringHint: "Voci host:porta separate da virgola o da riga. Lascia vuoto per usare l'host e la porta sopra.", zookeeperCreateModePersistent: "Persistente", diff --git a/apps/desktop/src/i18n/locales/ja.ts b/apps/desktop/src/i18n/locales/ja.ts index 21c97dbb06..08a0b8e352 100644 --- a/apps/desktop/src/i18n/locales/ja.ts +++ b/apps/desktop/src/i18n/locales/ja.ts @@ -1,61 +1,61 @@ import { withEnglishFallback } from "./fallback"; import docs from "./docs/ja"; -import { consulUiMessages } from "./consulUi"; +import { consulJaMessages } from "./consulJa"; import { nacosAccessControlMessages, nacosAccessControlTabs } from "./nacosAccessControl"; import { sqlServerTraceMessages as sqlServerTrace } from "./sqlServerTraceMessages"; import { meilisearchManagementJa } from "./meilisearchManagement"; import { redisGroupingJa as redisGrouping } from "./redisGrouping"; const consul = { - ...consulUiMessages, + ...consulJaMessages, redisGrouping, - prefixPlaceholder: "Key prefix, e.g. app/ or services/", - newKey: "New Key", - loadingKeys: "Loading keys...", - empty: "No keys found", - loadMore: "Load more", - selectKey: "Select a key to view its value", - loadingValue: "Loading value...", - notFound: "Key not found", - edit: "Edit", - editKey: "Edit Key", - delete: "Delete", - deleteTitle: "Delete Consul KV key", + prefixPlaceholder: "キープレフィックス(例: app/、services/)", + newKey: "キーを作成", + loadingKeys: "キーを読み込み中...", + empty: "キーが見つかりません", + loadMore: "さらに読み込む", + selectKey: "キーを選択して値を表示", + loadingValue: "値を読み込み中...", + notFound: "キーが見つかりません", + edit: "編集", + editKey: "キーを編集", + delete: "削除", + deleteTitle: "Consul KV キーを削除", keyLabel: "キー(Key)", keyPlaceholder: "path/to/key", - keyRequired: "Key is required", - rootReadonly: "The root prefix cannot be modified. Enter a key path.", - saved: "Key saved", - deleted: "Key deleted", - base64Readonly: "Edit binary values in Base64 mode.", + keyRequired: "キーは必須です", + rootReadonly: "ルートプレフィックスは変更できません。キーのパスを入力してください。", + saved: "キーを保存しました", + deleted: "キーを削除しました", + base64Readonly: "バイナリ値は Base64 モードで編集してください。", rename: "名前を変更", clone: "複製", copyKey: "Keyをコピー", export: "エクスポート", - value: "Value", + value: "値", valueContent: "値", format: "形式", - metadata: "KV metadata", - prettyJson: "Pretty", - invalidJson: "Invalid JSON", - summarySize: "Size", - conflict: "This Key changed after it was loaded. Refresh it and try again.", - keyAlreadyExists: "A Key with this name already exists. Choose another name or edit the existing Key.", - aclFiltered: "Some Consul KV keys are hidden by ACL policies.", - locked: "This Key is held by a Consul Session and cannot be edited or deleted.", - valueTooLarge: "Consul KV values cannot exceed 512 KiB.", + metadata: "KV メタデータ", + prettyJson: "整形", + invalidJson: "無効な JSON", + summarySize: "サイズ", + conflict: "読み込み後にこのキーが変更されました。更新して再試行してください。", + keyAlreadyExists: "同名のキーが既に存在します。別の名前を指定するか、既存のキーを編集してください。", + aclFiltered: "一部の Consul KV キーは ACL ポリシーによって非表示になっています。", + locked: "このキーは Consul セッションが保持しているため、編集や削除はできません。", + valueTooLarge: "Consul KV の値は 512 KiB を超えることはできません。", watchKey: "監視", stopWatching: "停止", workspace: { overview: "概要", kv: "KV", - services: "Services", - health: "Health", - sessions: "Sessions", - scope: "Scope", - mesh: "Service Mesh", - tools: "Tools", - operator: "Operator", + services: "サービス", + health: "ヘルスチェック", + sessions: "セッション", + scope: "スコープ", + mesh: "サービスメッシュ", + tools: "ツール", + operator: "運用管理", refresh: "機能情報を更新", loading: "Consul機能を読み込み中...", agentIdentity: "Agent情報", @@ -71,8 +71,8 @@ const consul = { partitions: "管理パーティション", enterprise: "Enterprise", community: "Community", - serverMode: "Server", - clientMode: "Client", + serverMode: "サーバー", + clientMode: "クライアント", capability: { supported: "対応", unsupported: "非対応", @@ -941,34 +941,34 @@ export default withEnglishFallback({ colorBlue: "青", colorPurple: "紫", colorCustom: "カスタム色", - consulAddress: "Consul API address", - consulAddressInvalid: "Enter an absolute HTTP or HTTPS Consul API address without credentials, query parameters, or a fragment.", - consulToken: "ACL Token", - consulTokenPlaceholder: "Optional Consul ACL Token", - consulDatacenter: "Datacenter", - consulNamespace: "Namespace", - consulPartition: "Admin Partition", - consulAgentTargetNode: "Agent target node", - consulAgentTargetAddress: "Agent direct address", - consulAgentTargetHint: "Required for Agent writes. DNS/load-balanced and Transport Layer endpoints stay read-only.", - consulMeshFeatures: "Service mesh", - consulMeshVisible: "Show advanced service mesh workspace", - consulMeshVisibleHint: "Enable only to manage Connect, intentions, or peering. When disabled, the workspace stays hidden.", - consulOperatorWrites: "Operator writes", - consulOperatorVisible: "Show experimental Operator workspace", - consulOperatorSnapshotRestore: "Enable snapshot restore", - consulOperatorAutopilot: "Enable Autopilot updates", - consulOperatorRaft: "Enable Raft changes", - consulOperatorKeyring: "Enable Keyring changes", - consulOperatorLicense: "Enable License updates", - consulAgentTargetIncomplete: "Agent target node and direct address must be configured together.", - consulAgentTargetAddressMismatch: "Agent direct address must match the Consul endpoint host.", - consulConsistency: "Read consistency", - consulConsistencyDefault: "Default", - consulConsistencyStale: "Stale", - consulConsistencyConsistent: "Consistent", - consulTlsSkipVerify: "Skip certificate verification", - consulTlsSkipVerifyHint: "Use only for trusted self-signed Consul endpoints.", + consulAddress: "Consul API アドレス", + consulAddressInvalid: "認証情報、クエリパラメーター、フラグメントを含まない HTTP または HTTPS の Consul API 絶対アドレスを入力してください。", + consulToken: "ACL トークン", + consulTokenPlaceholder: "Consul ACL トークン(任意)", + consulDatacenter: "データセンター", + consulNamespace: "名前空間", + consulPartition: "管理パーティション", + consulAgentTargetNode: "対象 Agent ノード", + consulAgentTargetAddress: "Agent の直接接続アドレス", + consulAgentTargetHint: "Agent への書き込みに必要です。DNS 名、負荷分散、トランスポート層経由の接続は読み取り専用です。", + consulMeshFeatures: "サービスメッシュ", + consulMeshVisible: "サービスメッシュの詳細ワークスペースを表示", + consulMeshVisibleHint: "Connect、通信許可規則、ピアリングを管理する場合にのみ有効にしてください。無効の場合、ワークスペースは非表示になります。", + consulOperatorWrites: "運用管理の書き込み", + consulOperatorVisible: "試験的な運用管理ワークスペースを表示", + consulOperatorSnapshotRestore: "スナップショット復元を有効化", + consulOperatorAutopilot: "Autopilot 更新を有効化", + consulOperatorRaft: "Raft 変更を有効化", + consulOperatorKeyring: "キーリング変更を有効化", + consulOperatorLicense: "ライセンス更新を有効化", + consulAgentTargetIncomplete: "対象 Agent のノードと直接接続アドレスは両方設定する必要があります。", + consulAgentTargetAddressMismatch: "Agent の直接接続アドレスは Consul 接続先のホストと一致する必要があります。", + consulConsistency: "読み取り整合性", + consulConsistencyDefault: "既定", + consulConsistencyStale: "古いデータを許可(stale)", + consulConsistencyConsistent: "強い整合性(consistent)", + consulTlsSkipVerify: "証明書の検証をスキップ", + consulTlsSkipVerifyHint: "信頼できる自己署名証明書を使用する Consul 接続先にのみ使用してください。", zookeeperConnectString: "接続文字列", zookeeperConnectStringHint: "カンマまたは改行区切りの host:port エントリ。空欄の場合は上のホストとポートを使用します。", zookeeperCreateModePersistent: "永続", diff --git a/apps/desktop/src/i18n/locales/ko.ts b/apps/desktop/src/i18n/locales/ko.ts index bc0265ad80..f6543397b5 100644 --- a/apps/desktop/src/i18n/locales/ko.ts +++ b/apps/desktop/src/i18n/locales/ko.ts @@ -2,76 +2,76 @@ import { withEnglishFallback } from "./fallback"; import { meilisearchManagementKo } from "./meilisearchManagement"; import { redisGroupingKo as redisGrouping } from "./redisGrouping"; import docs from "./docs/ko"; -import { consulUiMessages } from "./consulUi"; +import { consulKoMessages } from "./consulKo"; import { sqlServerTraceMessages as sqlServerTrace } from "./sqlServerTraceMessages"; const consul = { - ...consulUiMessages, + ...consulKoMessages, redisGrouping, - prefixPlaceholder: "Key prefix, e.g. app/ or services/", - newKey: "New Key", - loadingKeys: "Loading keys...", - empty: "No keys found", - loadMore: "Load more", - selectKey: "Select a key to view its value", - loadingValue: "Loading value...", - notFound: "Key not found", - edit: "Edit", - editKey: "Edit Key", - delete: "Delete", - deleteTitle: "Delete Consul KV key", + prefixPlaceholder: "키 접두사, 예: app/ 또는 services/", + newKey: "새 키", + loadingKeys: "키 불러오는 중...", + empty: "키가 없습니다", + loadMore: "더 불러오기", + selectKey: "값을 보려면 키를 선택하세요", + loadingValue: "값 불러오는 중...", + notFound: "키를 찾을 수 없습니다", + edit: "편집", + editKey: "키 편집", + delete: "삭제", + deleteTitle: "Consul KV 키 삭제", keyLabel: "키(Key)", keyPlaceholder: "path/to/key", - keyRequired: "Key is required", - rootReadonly: "The root prefix cannot be modified. Enter a key path.", - saved: "Key saved", - deleted: "Key deleted", - base64Readonly: "Edit binary values in Base64 mode.", + keyRequired: "키를 입력하세요", + rootReadonly: "루트 접두사는 수정할 수 없습니다. 키 경로를 입력하세요.", + saved: "키가 저장되었습니다", + deleted: "키가 삭제되었습니다", + base64Readonly: "바이너리 값은 Base64 모드에서 편집하세요.", rename: "이름 변경", clone: "복제", - copyKey: "Key 복사", + copyKey: "키 복사", export: "내보내기", - value: "Value", + value: "값", valueContent: "값", format: "형식", - metadata: "KV metadata", - prettyJson: "Pretty", - invalidJson: "Invalid JSON", - summarySize: "Size", - conflict: "This Key changed after it was loaded. Refresh it and try again.", - keyAlreadyExists: "A Key with this name already exists. Choose another name or edit the existing Key.", - aclFiltered: "Some Consul KV keys are hidden by ACL policies.", - locked: "This Key is held by a Consul Session and cannot be edited or deleted.", - valueTooLarge: "Consul KV values cannot exceed 512 KiB.", + metadata: "KV 메타데이터", + prettyJson: "보기 좋게 정렬", + invalidJson: "잘못된 JSON", + summarySize: "크기", + conflict: "불러온 후 키가 변경되었습니다. 새로 고친 후 다시 시도하세요.", + keyAlreadyExists: "같은 이름의 키가 이미 존재합니다. 다른 이름을 선택하거나 기존 키를 편집하세요.", + aclFiltered: "일부 Consul KV 키가 ACL 정책에 의해 숨겨져 있습니다.", + locked: "이 키는 Consul 세션이 보유하고 있어 편집하거나 삭제할 수 없습니다.", + valueTooLarge: "Consul KV 값은 512 KiB를 초과할 수 없습니다.", watchKey: "감시", stopWatching: "중지", workspace: { overview: "개요", kv: "KV", - services: "Services", - health: "Health", - sessions: "Sessions", - scope: "Scope", - mesh: "Service Mesh", - tools: "Tools", - operator: "Operator", + services: "서비스", + health: "상태", + sessions: "세션", + scope: "범위", + mesh: "서비스 메시", + tools: "도구", + operator: "운영 관리", refresh: "기능 정보 새로 고침", loading: "Consul 기능을 불러오는 중...", - agentIdentity: "Agent 정보", + agentIdentity: "에이전트 정보", capabilities: "기능", version: "버전", edition: "에디션", datacenter: "데이터센터", - node: "Agent 노드", - mode: "Agent 모드", - agent: "Agent API", + node: "에이전트 노드", + mode: "에이전트 모드", + agent: "에이전트 API", acl: "ACL", namespaces: "네임스페이스", partitions: "관리 파티션", enterprise: "Enterprise", community: "Community", - serverMode: "Server", - clientMode: "Client", + serverMode: "서버", + clientMode: "클라이언트", capability: { supported: "지원", unsupported: "지원 안 함", @@ -679,34 +679,34 @@ export default withEnglishFallback({ etcdClientCertBrowse: "클라이언트 인증서 선택", etcdClientKeyBrowse: "클라이언트 개인 키 선택", etcdClientCertPairRequired: "클라이언트 인증서와 개인 키를 함께 제공해야 합니다.", - consulAddress: "Consul API address", - consulAddressInvalid: "Enter an absolute HTTP or HTTPS Consul API address without credentials, query parameters, or a fragment.", - consulToken: "ACL Token", - consulTokenPlaceholder: "Optional Consul ACL Token", - consulDatacenter: "Datacenter", - consulNamespace: "Namespace", - consulPartition: "Admin Partition", - consulAgentTargetNode: "Agent target node", - consulAgentTargetAddress: "Agent direct address", - consulAgentTargetHint: "Required for Agent writes. DNS/load-balanced and Transport Layer endpoints stay read-only.", - consulMeshFeatures: "Service mesh", - consulMeshVisible: "Show advanced service mesh workspace", - consulMeshVisibleHint: "Enable only to manage Connect, intentions, or peering. When disabled, the workspace stays hidden.", - consulOperatorWrites: "Operator writes", - consulOperatorVisible: "Show experimental Operator workspace", - consulOperatorSnapshotRestore: "Enable snapshot restore", - consulOperatorAutopilot: "Enable Autopilot updates", - consulOperatorRaft: "Enable Raft changes", - consulOperatorKeyring: "Enable Keyring changes", - consulOperatorLicense: "Enable License updates", - consulAgentTargetIncomplete: "Agent target node and direct address must be configured together.", - consulAgentTargetAddressMismatch: "Agent direct address must match the Consul endpoint host.", - consulConsistency: "Read consistency", - consulConsistencyDefault: "Default", - consulConsistencyStale: "Stale", - consulConsistencyConsistent: "Consistent", - consulTlsSkipVerify: "Skip certificate verification", - consulTlsSkipVerifyHint: "Use only for trusted self-signed Consul endpoints.", + consulAddress: "Consul API 주소", + consulAddressInvalid: "자격 증명, 쿼리 매개변수 또는 프래그먼트가 없는 HTTP 또는 HTTPS Consul API 절대 주소를 입력하세요.", + consulToken: "ACL 토큰", + consulTokenPlaceholder: "Consul ACL 토큰 (선택 사항)", + consulDatacenter: "데이터센터", + consulNamespace: "네임스페이스", + consulPartition: "관리 파티션", + consulAgentTargetNode: "대상 에이전트 노드", + consulAgentTargetAddress: "에이전트 직접 연결 주소", + consulAgentTargetHint: "에이전트 쓰기에 필요합니다. DNS, 로드 밸런싱 및 전송 계층 엔드포인트는 읽기 전용으로 유지됩니다.", + consulMeshFeatures: "서비스 메시", + consulMeshVisible: "고급 서비스 메시 작업 영역 표시", + consulMeshVisibleHint: "Connect, 통신 의도 또는 피어링을 관리할 때만 활성화하세요. 비활성화하면 작업 영역이 숨겨집니다.", + consulOperatorWrites: "운영 관리 쓰기", + consulOperatorVisible: "실험적 운영 관리 작업 영역 표시", + consulOperatorSnapshotRestore: "스냅샷 복원 활성화", + consulOperatorAutopilot: "Autopilot 업데이트 활성화", + consulOperatorRaft: "Raft 변경 활성화", + consulOperatorKeyring: "키링 변경 활성화", + consulOperatorLicense: "라이선스 업데이트 활성화", + consulAgentTargetIncomplete: "대상 에이전트 노드와 직접 연결 주소를 함께 설정해야 합니다.", + consulAgentTargetAddressMismatch: "에이전트 직접 연결 주소는 Consul 엔드포인트 호스트와 일치해야 합니다.", + consulConsistency: "읽기 일관성", + consulConsistencyDefault: "기본값", + consulConsistencyStale: "오래된 읽기 허용 (Stale)", + consulConsistencyConsistent: "일관된 읽기 (Consistent)", + consulTlsSkipVerify: "인증서 검증 건너뛰기", + consulTlsSkipVerifyHint: "신뢰할 수 있는 자체 서명 Consul 엔드포인트에만 사용하세요.", zookeeperConnectString: "연결 문자열", zookeeperConnectStringHint: "쉼표 또는 줄바꿈으로 구분된 host:port 항목. 비워두면 위의 호스트와 포트를 사용합니다.", zookeeperCreateModePersistent: "영구", diff --git a/apps/desktop/src/i18n/locales/pt-BR.ts b/apps/desktop/src/i18n/locales/pt-BR.ts index a849ffaeeb..bedd3630a0 100644 --- a/apps/desktop/src/i18n/locales/pt-BR.ts +++ b/apps/desktop/src/i18n/locales/pt-BR.ts @@ -2,60 +2,60 @@ import { withEnglishFallback } from "./fallback"; import { meilisearchManagementPtBR } from "./meilisearchManagement"; import { redisGroupingPtBR as redisGrouping } from "./redisGrouping"; import docs from "./docs/pt-BR"; -import { consulUiMessages } from "./consulUi"; +import { consulPtBRMessages } from "./consulPtBR"; import { nacosAccessControlMessages, nacosAccessControlTabs } from "./nacosAccessControl"; import { sqlServerTraceMessages as sqlServerTrace } from "./sqlServerTraceMessages"; const consul = { - ...consulUiMessages, + ...consulPtBRMessages, redisGrouping, - prefixPlaceholder: "Key prefix, e.g. app/ or services/", - newKey: "New Key", - loadingKeys: "Loading keys...", - empty: "No keys found", - loadMore: "Load more", - selectKey: "Select a key to view its value", - loadingValue: "Loading value...", - notFound: "Key not found", - edit: "Edit", - editKey: "Edit Key", - delete: "Delete", - deleteTitle: "Delete Consul KV key", - keyLabel: "Chave (Key)", - keyPlaceholder: "path/to/key", - keyRequired: "Key is required", - rootReadonly: "The root prefix cannot be modified. Enter a key path.", - saved: "Key saved", - deleted: "Key deleted", - base64Readonly: "Edit binary values in Base64 mode.", + prefixPlaceholder: "Prefixo da chave, por exemplo app/ ou services/", + newKey: "Nova chave", + loadingKeys: "Carregando chaves...", + empty: "Nenhuma chave encontrada", + loadMore: "Carregar mais", + selectKey: "Selecione uma chave para visualizar seu valor", + loadingValue: "Carregando valor...", + notFound: "Chave não encontrada", + edit: "Editar", + editKey: "Editar chave", + delete: "Excluir", + deleteTitle: "Excluir chave Consul KV", + keyLabel: "Chave", + keyPlaceholder: "caminho/da/chave", + keyRequired: "A chave é obrigatória", + rootReadonly: "O prefixo raiz não pode ser alterado. Digite o caminho de uma chave.", + saved: "Chave salva", + deleted: "Chave excluída", + base64Readonly: "Edite valores binários no modo Base64.", rename: "Renomear", clone: "Clonar", copyKey: "Copiar chave", export: "Exportar", - value: "Value", + value: "Valor", valueContent: "Valor", format: "Formato", - metadata: "KV metadata", - prettyJson: "Pretty", - invalidJson: "Invalid JSON", - summarySize: "Size", - conflict: "This Key changed after it was loaded. Refresh it and try again.", - keyAlreadyExists: "A Key with this name already exists. Choose another name or edit the existing Key.", - aclFiltered: "Some Consul KV keys are hidden by ACL policies.", - locked: "This Key is held by a Consul Session and cannot be edited or deleted.", - valueTooLarge: "Consul KV values cannot exceed 512 KiB.", + metadata: "Metadados KV", + prettyJson: "Formatar", + invalidJson: "JSON inválido", + summarySize: "Tamanho", + conflict: "Esta chave foi alterada após o carregamento. Atualize e tente novamente.", + keyAlreadyExists: "Já existe uma chave com este nome. Escolha outro nome ou edite a chave existente.", + aclFiltered: "Algumas chaves Consul KV estão ocultas pelas políticas ACL.", + locked: "Esta chave está bloqueada por uma sessão Consul e não pode ser editada ou excluída.", + valueTooLarge: "Os valores Consul KV não podem exceder 512 KiB.", watchKey: "Monitorar", stopWatching: "Parar", workspace: { overview: "Visão geral", kv: "KV", - services: "Services", - health: "Health", - sessions: "Sessions", - scope: "Scope", - mesh: "Service Mesh", - tools: "Tools", - operator: "Operator", + services: "Serviços", + health: "Integridade", + sessions: "Sessões", + scope: "Escopo", + mesh: "Malha de serviços", + tools: "Ferramentas", + operator: "Operador", refresh: "Atualizar recursos", loading: "Carregando recursos do Consul...", agentIdentity: "Identidade do agente", @@ -655,34 +655,34 @@ export default withEnglishFallback({ etcdClientCertBrowse: "Escolher certificado do cliente", etcdClientKeyBrowse: "Escolher chave privada do cliente", etcdClientCertPairRequired: "O certificado e a chave privada do cliente devem ser fornecidos juntos.", - consulAddress: "Consul API address", - consulAddressInvalid: "Enter an absolute HTTP or HTTPS Consul API address without credentials, query parameters, or a fragment.", - consulToken: "ACL Token", - consulTokenPlaceholder: "Optional Consul ACL Token", + consulAddress: "Endereço da API Consul", + consulAddressInvalid: "Digite um endereço absoluto HTTP ou HTTPS da API Consul, sem credenciais, parâmetros de consulta ou fragmento.", + consulToken: "Token ACL", + consulTokenPlaceholder: "Token ACL Consul opcional", consulDatacenter: "Datacenter", consulNamespace: "Namespace", - consulPartition: "Admin Partition", - consulAgentTargetNode: "Agent target node", - consulAgentTargetAddress: "Agent direct address", - consulAgentTargetHint: "Required for Agent writes. DNS/load-balanced and Transport Layer endpoints stay read-only.", - consulMeshFeatures: "Service mesh", - consulMeshVisible: "Show advanced service mesh workspace", - consulMeshVisibleHint: "Enable only to manage Connect, intentions, or peering. When disabled, the workspace stays hidden.", - consulOperatorWrites: "Operator writes", - consulOperatorVisible: "Show experimental Operator workspace", - consulOperatorSnapshotRestore: "Enable snapshot restore", - consulOperatorAutopilot: "Enable Autopilot updates", - consulOperatorRaft: "Enable Raft changes", - consulOperatorKeyring: "Enable Keyring changes", - consulOperatorLicense: "Enable License updates", - consulAgentTargetIncomplete: "Agent target node and direct address must be configured together.", - consulAgentTargetAddressMismatch: "Agent direct address must match the Consul endpoint host.", - consulConsistency: "Read consistency", - consulConsistencyDefault: "Default", - consulConsistencyStale: "Stale", - consulConsistencyConsistent: "Consistent", - consulTlsSkipVerify: "Skip certificate verification", - consulTlsSkipVerifyHint: "Use only for trusted self-signed Consul endpoints.", + consulPartition: "Partição administrativa", + consulAgentTargetNode: "Nó do agente de destino", + consulAgentTargetAddress: "Endereço direto do agente", + consulAgentTargetHint: "Obrigatório para gravar no agente. Endpoints DNS, com balanceamento de carga ou com camadas de transporte permanecem somente leitura.", + consulMeshFeatures: "Malha de serviços", + consulMeshVisible: "Mostrar área avançada da malha de serviços", + consulMeshVisibleHint: "Ative apenas para gerenciar Connect, intenções ou peering. Quando desativada, a área permanece oculta.", + consulOperatorWrites: "Gravações do operador", + consulOperatorVisible: "Mostrar área experimental do operador", + consulOperatorSnapshotRestore: "Ativar restauração de snapshot", + consulOperatorAutopilot: "Ativar atualizações do Autopilot", + consulOperatorRaft: "Ativar alterações de Raft", + consulOperatorKeyring: "Ativar alterações do chaveiro", + consulOperatorLicense: "Ativar atualizações de licença", + consulAgentTargetIncomplete: "O nó do agente de destino e o endereço direto devem ser configurados juntos.", + consulAgentTargetAddressMismatch: "O endereço direto do agente deve corresponder ao host do endpoint Consul.", + consulConsistency: "Consistência de leitura", + consulConsistencyDefault: "Padrão", + consulConsistencyStale: "Possivelmente desatualizada (stale)", + consulConsistencyConsistent: "Consistente (consistent)", + consulTlsSkipVerify: "Ignorar verificação do certificado", + consulTlsSkipVerifyHint: "Use apenas em endpoints Consul confiáveis com certificados autoassinados.", zookeeperConnectString: "String de Conexão", zookeeperConnectStringHint: "Entradas host:porta separadas por vírgula ou linha. Deixe em branco para usar o host e porta acima.", zookeeperCreateModePersistent: "Persistente", diff --git a/apps/desktop/src/i18n/locales/tr.ts b/apps/desktop/src/i18n/locales/tr.ts index 7f4c320f1b..ef7ee49b77 100644 --- a/apps/desktop/src/i18n/locales/tr.ts +++ b/apps/desktop/src/i18n/locales/tr.ts @@ -1,12 +1,12 @@ import { withEnglishFallback } from "./fallback"; import docs from "./docs/tr"; -import { consulUiMessages } from "./consulUi"; +import { consulTrMessages } from "./consulTr"; import { sqlServerTraceMessages as sqlServerTrace } from "./sqlServerTraceMessages"; import { meilisearchManagementTr } from "./meilisearchManagement"; import { redisGroupingTr as redisGrouping } from "./redisGrouping"; const consul = { - ...consulUiMessages, + ...consulTrMessages, redisGrouping, prefixPlaceholder: "Anahtar öneki, örn. app/ veya services/", newKey: "Yeni Anahtar", @@ -52,9 +52,9 @@ const consul = { health: "Sağlık", sessions: "Oturumlar", scope: "Kapsam", - mesh: "Service Mesh", + mesh: "Servis ağı", tools: "Araçlar", - operator: "Operator", + operator: "Operatör", refresh: "Yetenekleri yenile", loading: "Consul yetenekleri yükleniyor...", agentIdentity: "Agent kimliği", @@ -68,8 +68,8 @@ const consul = { acl: "ACL", namespaces: "Ad alanları", partitions: "Yönetim Bölümleri", - enterprise: "Enterprise", - community: "Community", + enterprise: "Kurumsal", + community: "Topluluk", serverMode: "Sunucu", clientMode: "İstemci", capability: { @@ -696,15 +696,15 @@ export default withEnglishFallback({ consulAgentTargetNode: "Agent hedef düğümü", consulAgentTargetAddress: "Agent doğrudan adresi", consulAgentTargetHint: "Agent yazma işlemleri için zorunludur. DNS/yük dengelemeli ve Taşıma Katmanı uç noktaları salt okunur kalır.", - consulMeshFeatures: "Service mesh", - consulMeshVisible: "Gelişmiş service mesh çalışma alanını göster", - consulMeshVisibleHint: "Yalnızca Connect, intention veya peering yönetmek için etkinleştirin. Kapalıyken çalışma alanı gizli kalır.", - consulOperatorWrites: "Operator yazma işlemleri", - consulOperatorVisible: "Deneysel Operator çalışma alanını göster", + consulMeshFeatures: "Servis ağı", + consulMeshVisible: "Gelişmiş servis ağı çalışma alanını göster", + consulMeshVisibleHint: "Yalnızca Connect, erişim kuralları veya eşlemeleri yönetmek için etkinleştirin. Kapalıyken çalışma alanı gizli kalır.", + consulOperatorWrites: "Operatör yazma işlemleri", + consulOperatorVisible: "Deneysel operatör çalışma alanını göster", consulOperatorSnapshotRestore: "Anlık görüntü geri yüklemeyi etkinleştir", consulOperatorAutopilot: "Autopilot güncellemelerini etkinleştir", consulOperatorRaft: "Raft değişikliklerini etkinleştir", - consulOperatorKeyring: "Keyring değişikliklerini etkinleştir", + consulOperatorKeyring: "Anahtarlık değişikliklerini etkinleştir", consulOperatorLicense: "Lisans güncellemelerini etkinleştir", consulAgentTargetIncomplete: "Agent hedef düğümü ve doğrudan adresi birlikte yapılandırılmalıdır.", consulAgentTargetAddressMismatch: "Agent doğrudan adresi, Consul uç noktası sunucusuyla eşleşmelidir.", diff --git a/apps/desktop/src/i18n/locales/zh-TW.ts b/apps/desktop/src/i18n/locales/zh-TW.ts index ff11ad0369..1f2a5257db 100644 --- a/apps/desktop/src/i18n/locales/zh-TW.ts +++ b/apps/desktop/src/i18n/locales/zh-TW.ts @@ -2,12 +2,12 @@ import { redisGroupingZhTW as redisGrouping } from "./redisGrouping"; import { withEnglishFallback } from "./fallback"; import { meilisearchManagementZhTW } from "./meilisearchManagement"; import docs from "./docs/zh-TW"; -import { consulUiMessages } from "./consulUi"; +import { consulZhTWMessages } from "./consulZhTW"; import { nacosAccessControlMessages, nacosAccessControlTabs } from "./nacosAccessControl"; import { sqlServerTraceMessages as sqlServerTrace } from "./sqlServerTraceMessages"; const consul = { - ...consulUiMessages, + ...consulZhTWMessages, prefixPlaceholder: "Key 前綴,例如 app/ 或 services/", newKey: "新增 Key", loadingKeys: "正在載入 Key...", @@ -50,11 +50,11 @@ const consul = { kv: "KV", services: "服務", health: "健康檢查", - sessions: "Session", + sessions: "工作階段", scope: "作用域", - mesh: "Service Mesh", + mesh: "服務網格", tools: "工具", - operator: "Operator", + operator: "維運", refresh: "重新整理能力資訊", loading: "正在載入 Consul 能力...", agentIdentity: "Agent 身分", @@ -70,8 +70,8 @@ const consul = { partitions: "管理分區", enterprise: "Enterprise", community: "Community", - serverMode: "Server", - clientMode: "Client", + serverMode: "伺服器", + clientMode: "用戶端", capability: { supported: "支援", unsupported: "不支援", @@ -657,24 +657,24 @@ export default withEnglishFallback({ etcdClientCertPairRequired: "用戶端憑證和私鑰必須一起填寫。", consulAddress: "Consul API 位址", consulAddressInvalid: "請輸入不包含憑證、查詢參數或片段的 HTTP/HTTPS Consul API 絕對位址。", - consulToken: "ACL Token", - consulTokenPlaceholder: "選填的 Consul ACL Token", + consulToken: "ACL 權杖", + consulTokenPlaceholder: "Consul ACL 權杖(選填)", consulDatacenter: "資料中心", consulNamespace: "命名空間", consulPartition: "管理分區", consulAgentTargetNode: "目標 Agent 節點", consulAgentTargetAddress: "Agent 直連位址", - consulAgentTargetHint: "Agent 寫入操作必填。DNS/負載均衡和 Transport Layer 連線維持唯讀。", + consulAgentTargetHint: "Agent 寫入操作必填。DNS、負載平衡及傳輸層連線維持唯讀。", consulMeshFeatures: "服務網格", consulMeshVisible: "顯示服務網格進階功能", - consulMeshVisibleHint: "僅在需要管理 Connect、服務意圖或對等連線時開啟;關閉後主導覽不會顯示服務網格。", - consulOperatorWrites: "Operator 寫入", - consulOperatorVisible: "顯示實驗性 Operator 工作台", - consulOperatorSnapshotRestore: "啟用 Snapshot 還原", + consulMeshVisibleHint: "僅在需要管理 Connect、通訊意圖規則或對等連線時開啟;關閉後主導覽不會顯示服務網格。", + consulOperatorWrites: "維運寫入", + consulOperatorVisible: "顯示實驗性維運工作台", + consulOperatorSnapshotRestore: "啟用快照還原", consulOperatorAutopilot: "啟用 Autopilot 修改", consulOperatorRaft: "啟用 Raft 修改", - consulOperatorKeyring: "啟用 Keyring 修改", - consulOperatorLicense: "啟用 License 修改", + consulOperatorKeyring: "啟用金鑰環修改", + consulOperatorLicense: "啟用授權修改", consulAgentTargetIncomplete: "目標 Agent 節點和直連位址必須同時設定。", consulAgentTargetAddressMismatch: "Agent 直連位址必須與 Consul 位址的主機一致。", consulConsistency: "讀取一致性", diff --git a/apps/desktop/src/lib/consul/agentTarget.ts b/apps/desktop/src/lib/consul/agentTarget.ts index cdbc0e7f40..7f91e64abc 100644 --- a/apps/desktop/src/lib/consul/agentTarget.ts +++ b/apps/desktop/src/lib/consul/agentTarget.ts @@ -34,23 +34,34 @@ export function consulAgentAddressesMatch(left: string, right: string): boolean return a === b || (a === "localhost" && isLoopback(b)) || (b === "localhost" && isLoopback(a)); } -export function consulAgentWriteTargetSafe(connection: AgentTargetConnection | undefined, identityNode: string | undefined): boolean { - if (!connection || connectionIsEffectivelyReadOnly(connection) || connection.transport_layers?.some((layer) => layer.enabled !== false)) return false; +export type ConsulAgentWriteBlockedReason = "connectionUnavailable" | "readOnly" | "transport" | "targetRequired" | "identityUnavailable" | "nodeMismatch" | "directAddressRequired" | "addressMismatch" | "invalidAddress"; + +export function consulAgentWriteBlockedReason(connection: AgentTargetConnection | undefined, identityNode: string | undefined): ConsulAgentWriteBlockedReason | null { + if (!connection) return "connectionUnavailable"; + if (connectionIsEffectivelyReadOnly(connection)) return "readOnly"; + if (connection.transport_layers?.some((layer) => layer.enabled !== false)) return "transport"; const external = connection.external_config; - if (!external || typeof external !== "object" || Array.isArray(external)) return false; + if (!external || typeof external !== "object" || Array.isArray(external)) return "targetRequired"; const config = external as Record; const rawTarget = config.agentTarget || config.agent_target; - if (!rawTarget || typeof rawTarget !== "object" || Array.isArray(rawTarget)) return false; + if (!rawTarget || typeof rawTarget !== "object" || Array.isArray(rawTarget)) return "targetRequired"; const target = rawTarget as Record; const node = String(target.node || "").trim(); const address = String(target.address || "").trim(); - if (!node || !address || node !== identityNode) return false; + if (!node || !address) return "targetRequired"; const serverAddress = String(config.serverAddr || config.server_addr || "").trim(); try { const host = normalizeAddress(new URL(serverAddress).hostname); - if (host !== "localhost" && !isIpv4(host) && !isIpv6(host)) return false; - return consulAgentAddressesMatch(host, address); + if (host !== "localhost" && !isIpv4(host) && !isIpv6(host)) return "directAddressRequired"; + if (!consulAgentAddressesMatch(host, address)) return "addressMismatch"; } catch { - return false; + return "invalidAddress"; } + if (!identityNode) return "identityUnavailable"; + if (node !== identityNode) return "nodeMismatch"; + return null; +} + +export function consulAgentWriteTargetSafe(connection: AgentTargetConnection | undefined, identityNode: string | undefined): boolean { + return consulAgentWriteBlockedReason(connection, identityNode) === null; }