From e70cebd085b09fef10230867a4b4c86388af01b8 Mon Sep 17 00:00:00 2001 From: Eric Moore Date: Fri, 28 Aug 2026 10:14:56 -0500 Subject: [PATCH 01/18] feat(portal): the capability gate, and the first surface behind it MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit CIRISPortal's surfaces come here as CIRISRegistry folds into CIRISServer, and almost none of their APIs exist on a released node yet. This is the machinery for shipping the UI first — and the first slice proving it end to end. UNDECLARED IS NOT ABSENT, and that is the whole design. Three states: PRESENT the node declared it holds this capability ABSENT the node declared its set and this was not in it UNDECLARED the node said nothing at all Every node released today is UNDECLARED, because the declaration is CIRISServer#499 and has not landed. Collapsing that into ABSENT would hide surfaces a newer node will serve, and leave the operator unable to tell a missing feature from an old node. It is the same distinction as `ModeProbe`'s undetermined and `LookupResult`'s not-found-versus-no-answer: "I could not ask" is not "the answer is no", and this codebase has now paid for that lesson three times. NOT A SECURITY BOUNDARY, and the code says so where someone might assume otherwise. CIRISServer's TRUST_ROOT_CAPABILITY_GATE.md §5: "the server enforces the reality whether or not the client showed it (the warning informs; the gate binds)." This is the informing half. Wrong permissively, the server still refuses; wrong restrictively, an operator sees a working feature marked unavailable — which is why UNDECLARED does not render as ABSENT. The probe is a narrow scrape of /v1/federation/conformance, never throwing: a node that is down, slow, or serving an older document is undeclared, which is the honest reading of all three. Verified against the three real shapes plus the live node, which reads UNDECLARED as expected. FIRST SLICE: /verify — look an agent build up by hash. Public, read-only, and registry-shaped (identity and revocation is what the fold's own FSD calls registry work). Small enough to prove the pattern, useful on its own. An unreadable status decodes to UNKNOWN rather than being guessed. On a revocation check both guesses are lies: REGISTERED makes a revoked build look fine, REVOKED condemns a good one. The raw string is kept and shown. 11 tests. Screen and wiring follow; this is the part the surfaces sit on. Refs CIRISServer#499, CIRISRegistry#62. Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_01EGE52kPzjGFiPzGcs63ZC1 --- client/VENDORING.md | 2 +- .../ciris/mobile/shared/api/CIRISApiClient.kt | 42 ++++++++++ .../models/capability/AgentVerification.kt | 72 ++++++++++++++++ .../models/capability/NodeCapabilities.kt | 82 +++++++++++++++++++ .../capability/AgentVerificationTest.kt | 56 +++++++++++++ .../models/capability/NodeCapabilitiesTest.kt | 60 ++++++++++++++ 6 files changed, 313 insertions(+), 1 deletion(-) create mode 100644 client/shared/src/commonMain/kotlin/ai/ciris/mobile/shared/models/capability/AgentVerification.kt create mode 100644 client/shared/src/commonMain/kotlin/ai/ciris/mobile/shared/models/capability/NodeCapabilities.kt create mode 100644 client/shared/src/commonTest/kotlin/ai/ciris/mobile/shared/models/capability/AgentVerificationTest.kt create mode 100644 client/shared/src/commonTest/kotlin/ai/ciris/mobile/shared/models/capability/NodeCapabilitiesTest.kt diff --git a/client/VENDORING.md b/client/VENDORING.md index f186f0b..eceb6b9 100644 --- a/client/VENDORING.md +++ b/client/VENDORING.md @@ -40,7 +40,7 @@ source is the pair a bisect wants: The tree's current recorded state — sha256-of-sha256s over every git-tracked file under `client/` except this one: -**state digest:** `0ff13365d8b1b367cd9bc382f0b89e2bc51200dc0629ed93523b049020e147a8` +**state digest:** `96c51bee68d6567aeb89ff8140e5bd5942c538bb1d1842e4d7f97db9ecebb6ea` `packaging/check_vendoring.py` asserts it on every push, and refuses any tracked file matching a §2 never-vendor class. **Any commit that touches diff --git a/client/shared/src/commonMain/kotlin/ai/ciris/mobile/shared/api/CIRISApiClient.kt b/client/shared/src/commonMain/kotlin/ai/ciris/mobile/shared/api/CIRISApiClient.kt index a5cdd55..b435abe 100644 --- a/client/shared/src/commonMain/kotlin/ai/ciris/mobile/shared/api/CIRISApiClient.kt +++ b/client/shared/src/commonMain/kotlin/ai/ciris/mobile/shared/api/CIRISApiClient.kt @@ -9148,6 +9148,48 @@ class CIRISApiClient( * not cost the answer. Null when the node does not declare one — the caller * then falls back to the guess, which is where it was before. */ + /** + * WHAT THIS NODE DECLARES IT CAN DO — `GET {nodeUrl}/v1/federation/conformance`. + * + * Returns [NodeCapabilities.UNDECLARED] for every node that does not carry a + * `capabilities` array, which today is all of them: the declaration is + * CIRISServer#499 and the registry fold is what will populate it. Undeclared + * is NOT absent — see [CapabilityState] — so the UI says the node has not + * told us rather than hiding a surface a newer node will serve. + * + * A NARROW SCRAPE, deliberately, like the other raw reads in this file. The + * generated SDK binds a conformance model that predates this field, and a + * strict decode failing on an unknown shape would turn "the node declared + * something we do not parse" into "the node declared nothing" — the exact + * collapse this three-state model exists to prevent. + * + * Never throws. A node that is down, slow, or serving an older conformance + * document is undeclared, which is the honest reading of all three. + */ + suspend fun getNodeCapabilities( + nodeUrl: String = LOCAL_NODE_URL, + ): ai.ciris.mobile.shared.models.capability.NodeCapabilities = runCatching { + val client = io.ktor.client.HttpClient { + install(io.ktor.client.plugins.HttpTimeout) { + requestTimeoutMillis = 5_000 + connectTimeoutMillis = 3_000 + } + } + val body = try { + client.get("$nodeUrl/v1/federation/conformance").bodyAsText() + } finally { + client.close() + } + // `"capabilities": [ "a", "b" ]` — absent array means undeclared, empty + // array means declared-and-holds-nothing. The two are different answers. + val block = Regex("\"capabilities\"\\s*:\\s*\\[([^\\]]*)\\]").find(body) + ?: return@runCatching ai.ciris.mobile.shared.models.capability.NodeCapabilities.UNDECLARED + val ids = Regex("\"([^\"]+)\"").findAll(block.groupValues[1]) + .map { it.groupValues[1] } + .toSet() + ai.ciris.mobile.shared.models.capability.NodeCapabilities(ids) + }.getOrElse { ai.ciris.mobile.shared.models.capability.NodeCapabilities.UNDECLARED } + suspend fun getNodeHomePath(nodeUrl: String = LOCAL_NODE_URL): String? = runCatching { // A short-lived client, as the other raw scrapes in this file do: the // generated setup API binds a model that does not carry claim_pin_file. diff --git a/client/shared/src/commonMain/kotlin/ai/ciris/mobile/shared/models/capability/AgentVerification.kt b/client/shared/src/commonMain/kotlin/ai/ciris/mobile/shared/models/capability/AgentVerification.kt new file mode 100644 index 0000000..e7cf1dc --- /dev/null +++ b/client/shared/src/commonMain/kotlin/ai/ciris/mobile/shared/models/capability/AgentVerification.kt @@ -0,0 +1,72 @@ +package ai.ciris.mobile.shared.models.capability + +/** + * The registry's answer about one agent build. + * + * Ported from CIRISPortal's `/verify` (`AgentRecord`/`LookupResponse`), which is + * the surface a canonical node serves once CIRISRegistry folds in. Registry work + * is attestation-shaped — identity, license, revocation, build provenance — and + * this is its smallest complete question: is this build registered, and is it + * still good? + */ +enum class AgentStatus { + REGISTERED, + DEPRECATED, + REVOKED, + + /** + * The registry returned a status this client does not know. + * + * NOT folded into REVOKED or REGISTERED. A status we cannot read is not a + * verdict we may invent, and guessing in either direction is a lie about a + * revocation check: guess REGISTERED and a revoked build looks fine, guess + * REVOKED and a good one is condemned. The UI shows the raw string. + */ + UNKNOWN; + + /** Worth a warning banner — the build is registered but should not be used. */ + val isDiscouraged: Boolean get() = this == DEPRECATED || this == REVOKED + + companion object { + /** Wire form is `AGENT_STATUS_REGISTERED` etc. */ + fun fromWire(raw: String?): AgentStatus = when (raw?.removePrefix("AGENT_STATUS_")?.uppercase()) { + "REGISTERED" -> REGISTERED + "DEPRECATED" -> DEPRECATED + "REVOKED" -> REVOKED + else -> UNKNOWN + } + } +} + +/** One registry record, as the node reports it. */ +data class AgentRecord( + val agentHash: String, + val agentType: String = "", + val version: String = "", + val status: AgentStatus = AgentStatus.UNKNOWN, + val rawStatus: String = "", + val capabilities: List = emptyList(), + val registeredAt: String = "", + val hasAttestation: Boolean = false, +) + +/** + * The outcome of a lookup. + * + * FOUND-BUT-ABSENT AND COULD-NOT-ASK ARE DIFFERENT, and this is the third time + * that distinction has earned its place in this codebase (see [CapabilityState] + * and `ModeProbe`). "The registry has no record of this hash" is a real answer + * an operator can act on. "We could not reach the registry" is not, and showing + * the first when the second happened tells someone an unregistered build is + * confirmed-unregistered. + */ +sealed interface LookupResult { + /** The registry has a record. */ + data class Found(val record: AgentRecord) : LookupResult + + /** The registry answered and holds no record for this hash. */ + data object NotFound : LookupResult + + /** We could not get an answer. Never rendered as NotFound. */ + data class Unavailable(val reason: String) : LookupResult +} diff --git a/client/shared/src/commonMain/kotlin/ai/ciris/mobile/shared/models/capability/NodeCapabilities.kt b/client/shared/src/commonMain/kotlin/ai/ciris/mobile/shared/models/capability/NodeCapabilities.kt new file mode 100644 index 0000000..e1d0c12 --- /dev/null +++ b/client/shared/src/commonMain/kotlin/ai/ciris/mobile/shared/models/capability/NodeCapabilities.kt @@ -0,0 +1,82 @@ +package ai.ciris.mobile.shared.models.capability + +/** + * WHAT THIS NODE CAN ACTUALLY DO, as the node declares it. + * + * The client is shipping UI ahead of the API: the CIRISPortal surfaces land here + * while CIRISRegistry is still folding into CIRISServer, so on any node released + * today most of them cannot be served. A screen that calls an endpoint the node + * does not have is a broken screen; a screen that hides itself for the wrong + * reason is worse, because the operator cannot tell a missing feature from a + * missing permission. + * + * THREE STATES, NOT TWO. This is the same lesson as [ai.ciris.mobile.shared.models.ModeProbe]: + * "I could not ask" is not "the answer is no". A node that declares nothing is + * UNDECLARED, and the UI says the node has not told us — it does not silently + * hide, and it does not optimistically show. + * + * NOT A SECURITY BOUNDARY, and nothing here may be load-bearing for + * authorization. CIRISServer's TRUST_ROOT_CAPABILITY_GATE.md §5 puts it exactly: + * "the server enforces the reality whether or not the client showed it (the + * warning informs; the gate binds)." This is the informing half. If the client + * is wrong in the permissive direction the server still refuses; if it is wrong + * in the restrictive direction the operator sees a feature marked unavailable + * that would have worked, which is why UNDECLARED is not the same as ABSENT. + * + * The declaration itself is CIRISServer#499. + */ +enum class CapabilityState { + /** The node declared it holds this capability. Render the feature. */ + PRESENT, + + /** The node declared its capabilities and this was not among them. */ + ABSENT, + + /** + * The node declared nothing at all — it predates the declaration, or the + * probe failed. Distinct from [ABSENT] on purpose: every node released + * today is here, and reading that as "the feature does not exist" would + * hide surfaces that a newer node will serve. + */ + UNDECLARED; + + /** Only a positive declaration earns the full UI. */ + val isUsable: Boolean get() = this == PRESENT +} + +/** + * Capability ids the client asks about. + * + * Strings rather than an enum on the wire: the node is the authority on what it + * confers, and a client that could not represent an unknown capability would + * have to drop it. These constants are the ones this UI gates on. + */ +object Capability { + /** Registry: look an agent build up by hash — registered, deprecated, revoked. */ + const val REGISTRY_LOOKUP = "registry:lookup" + + /** The two verbs a canonical node holds that registry work rides on. */ + const val INFRA_ATTEST = "infra:attest" + const val INFRA_SERVE = "infra:serve" +} + +/** + * A node's declared capabilities, or the absence of a declaration. + * + * @param declared null when the node said nothing — see [CapabilityState.UNDECLARED]. + */ +data class NodeCapabilities(val declared: Set?) { + + fun state(id: String): CapabilityState = when { + declared == null -> CapabilityState.UNDECLARED + id in declared -> CapabilityState.PRESENT + else -> CapabilityState.ABSENT + } + + fun has(id: String): Boolean = state(id).isUsable + + companion object { + /** A node that has told us nothing. Every node released today. */ + val UNDECLARED = NodeCapabilities(null) + } +} diff --git a/client/shared/src/commonTest/kotlin/ai/ciris/mobile/shared/models/capability/AgentVerificationTest.kt b/client/shared/src/commonTest/kotlin/ai/ciris/mobile/shared/models/capability/AgentVerificationTest.kt new file mode 100644 index 0000000..ef61226 --- /dev/null +++ b/client/shared/src/commonTest/kotlin/ai/ciris/mobile/shared/models/capability/AgentVerificationTest.kt @@ -0,0 +1,56 @@ +package ai.ciris.mobile.shared.models.capability + +import kotlin.test.Test +import kotlin.test.assertEquals +import kotlin.test.assertFalse +import kotlin.test.assertTrue + +class AgentVerificationTest { + + @Test + fun the_three_wire_statuses_decode() { + assertEquals(AgentStatus.REGISTERED, AgentStatus.fromWire("AGENT_STATUS_REGISTERED")) + assertEquals(AgentStatus.DEPRECATED, AgentStatus.fromWire("AGENT_STATUS_DEPRECATED")) + assertEquals(AgentStatus.REVOKED, AgentStatus.fromWire("AGENT_STATUS_REVOKED")) + } + + @Test + fun an_unreadable_status_is_never_guessed_in_either_direction() { + // Guess REGISTERED and a revoked build looks fine; guess REVOKED and a + // good one is condemned. On a revocation check both are lies. + for (raw in listOf("AGENT_STATUS_SOMETHING_NEW", "", null, "garbage")) { + assertEquals(AgentStatus.UNKNOWN, AgentStatus.fromWire(raw), "raw=$raw") + } + assertFalse(AgentStatus.UNKNOWN.isDiscouraged, "unknown must not imply a warning") + } + + @Test + fun deprecated_and_revoked_both_warn() { + assertTrue(AgentStatus.DEPRECATED.isDiscouraged) + assertTrue(AgentStatus.REVOKED.isDiscouraged) + assertFalse(AgentStatus.REGISTERED.isDiscouraged) + } + + @Test + fun no_record_and_no_answer_are_different_results() { + // The distinction the sealed type exists for: telling an operator a + // build is unregistered when the registry was merely unreachable is a + // claim we did not earn. + val absent: LookupResult = LookupResult.NotFound + val unreachable: LookupResult = LookupResult.Unavailable("connection refused") + assertTrue(absent is LookupResult.NotFound) + assertTrue(unreachable is LookupResult.Unavailable) + assertEquals("connection refused", (unreachable as LookupResult.Unavailable).reason) + } + + @Test + fun a_found_record_keeps_the_raw_status_for_display() { + val r = AgentRecord( + agentHash = "abc123", + status = AgentStatus.fromWire("AGENT_STATUS_QUARANTINED"), + rawStatus = "AGENT_STATUS_QUARANTINED", + ) + assertEquals(AgentStatus.UNKNOWN, r.status) + assertEquals("AGENT_STATUS_QUARANTINED", r.rawStatus, "the operator sees what the registry said") + } +} diff --git a/client/shared/src/commonTest/kotlin/ai/ciris/mobile/shared/models/capability/NodeCapabilitiesTest.kt b/client/shared/src/commonTest/kotlin/ai/ciris/mobile/shared/models/capability/NodeCapabilitiesTest.kt new file mode 100644 index 0000000..7a0c8cc --- /dev/null +++ b/client/shared/src/commonTest/kotlin/ai/ciris/mobile/shared/models/capability/NodeCapabilitiesTest.kt @@ -0,0 +1,60 @@ +package ai.ciris.mobile.shared.models.capability + +import kotlin.test.Test +import kotlin.test.assertEquals +import kotlin.test.assertFalse +import kotlin.test.assertTrue + +/** + * The distinction the whole gate rests on: undeclared is not absent. + */ +class NodeCapabilitiesTest { + + @Test + fun a_declared_capability_is_usable() { + val caps = NodeCapabilities(setOf(Capability.REGISTRY_LOOKUP, Capability.INFRA_SERVE)) + assertEquals(CapabilityState.PRESENT, caps.state(Capability.REGISTRY_LOOKUP)) + assertTrue(caps.has(Capability.REGISTRY_LOOKUP)) + } + + @Test + fun a_declaration_that_omits_it_is_absent() { + // The node listed what it holds and this was not on the list. That is a + // real answer, and the UI may say the node cannot do it. + val caps = NodeCapabilities(setOf(Capability.INFRA_SERVE)) + assertEquals(CapabilityState.ABSENT, caps.state(Capability.REGISTRY_LOOKUP)) + assertFalse(caps.has(Capability.REGISTRY_LOOKUP)) + } + + @Test + fun no_declaration_at_all_is_undeclared_not_absent() { + // EVERY NODE RELEASED TODAY IS HERE. Collapsing this into ABSENT would + // hide surfaces that a newer node will serve, and the operator would + // have no way to tell a missing feature from an old node. + val caps = NodeCapabilities.UNDECLARED + assertEquals(CapabilityState.UNDECLARED, caps.state(Capability.REGISTRY_LOOKUP)) + assertFalse(caps.has(Capability.REGISTRY_LOOKUP), "undeclared must not be treated as usable") + } + + @Test + fun an_empty_declaration_is_a_declaration() { + // A node that says "I hold nothing" has answered. Distinct from silence. + val caps = NodeCapabilities(emptySet()) + assertEquals(CapabilityState.ABSENT, caps.state(Capability.REGISTRY_LOOKUP)) + } + + @Test + fun an_unknown_capability_id_survives_the_round_trip() { + // The node is the authority on what it confers. A client that could only + // represent ids it knew about would have to drop the rest. + val caps = NodeCapabilities(setOf("registry:something-we-have-not-shipped-yet")) + assertEquals(CapabilityState.PRESENT, caps.state("registry:something-we-have-not-shipped-yet")) + } + + @Test + fun only_a_positive_declaration_earns_the_ui() { + assertTrue(CapabilityState.PRESENT.isUsable) + assertFalse(CapabilityState.ABSENT.isUsable) + assertFalse(CapabilityState.UNDECLARED.isUsable) + } +} From 80189a600f9e573c7c29771412760ace97278309 Mon Sep 17 00:00:00 2001 From: Eric Moore Date: Fri, 28 Aug 2026 11:11:47 -0500 Subject: [PATCH 02/18] feat(portal): the /verify surface, and what it says when the node cannot serve it MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The first CIRISPortal surface, and the first shipped ahead of its API. No node released today serves `/v1/registry/lookup`, so WHAT THE SCREEN DOES WHEN THE CAPABILITY IS MISSING is the actual feature here — the lookup itself is the easy half. FOUR OUTCOMES, NONE OF THEM A BLANK SCREEN OR AN ERROR: UNDECLARED "This node hasn't said whether it can verify builds." It predates the declaration (CIRISServer#499); a newer node will answer, and upgrading is the remedy. ABSENT "This node doesn't verify builds." It declared its capabilities and this was not among them; a different node is the remedy. PRESENT render the lookup. UNKNOWN a status this client cannot read — shown verbatim. The first two are separate sentences because they have separate remedies, which is the entire reason the gate has three states instead of a boolean. Collapsing them would tell someone to go find another node when their own node just needs updating. NOT-FOUND AND COULD-NOT-ASK ARE RENDERED APART, and the copy says so out loud: "This is not the same as 'not registered' — the registry did not answer." On a revocation check, showing a transport failure as "no record" tells an operator an unverified build was checked and cleared. `found: false` is the registry answering; a timeout is not. An unreadable status is shown as the raw string rather than mapped to something adjacent. Guess REGISTERED and a revoked build looks fine; guess REVOKED and a good one is condemned. The lookup call is gated by the CALLER on Capability.REGISTRY_LOOKUP rather than gating itself, so a missing capability never becomes a connection error the operator has to interpret. Desktop and wasmJs compile; localization and vendoring green. Refs CIRISServer#499, CIRISRegistry#62. Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_01EGE52kPzjGFiPzGcs63ZC1 --- client/VENDORING.md | 2 +- .../ciris/mobile/shared/api/CIRISApiClient.kt | 69 ++++++++ .../shared/ui/screens/VerifyAgentScreen.kt | 154 ++++++++++++++++++ 3 files changed, 224 insertions(+), 1 deletion(-) create mode 100644 client/shared/src/commonMain/kotlin/ai/ciris/mobile/shared/ui/screens/VerifyAgentScreen.kt diff --git a/client/VENDORING.md b/client/VENDORING.md index eceb6b9..d3858c3 100644 --- a/client/VENDORING.md +++ b/client/VENDORING.md @@ -40,7 +40,7 @@ source is the pair a bisect wants: The tree's current recorded state — sha256-of-sha256s over every git-tracked file under `client/` except this one: -**state digest:** `96c51bee68d6567aeb89ff8140e5bd5942c538bb1d1842e4d7f97db9ecebb6ea` +**state digest:** `99c355c370aeb6ee90cc269ec7c818edfdd0d4ce053db8dd90d1067db011bb89` `packaging/check_vendoring.py` asserts it on every push, and refuses any tracked file matching a §2 never-vendor class. **Any commit that touches diff --git a/client/shared/src/commonMain/kotlin/ai/ciris/mobile/shared/api/CIRISApiClient.kt b/client/shared/src/commonMain/kotlin/ai/ciris/mobile/shared/api/CIRISApiClient.kt index b435abe..e63e101 100644 --- a/client/shared/src/commonMain/kotlin/ai/ciris/mobile/shared/api/CIRISApiClient.kt +++ b/client/shared/src/commonMain/kotlin/ai/ciris/mobile/shared/api/CIRISApiClient.kt @@ -9166,6 +9166,75 @@ class CIRISApiClient( * Never throws. A node that is down, slow, or serving an older conformance * document is undeclared, which is the honest reading of all three. */ + /** + * Look an agent build up in the registry — `GET {nodeUrl}/v1/registry/lookup?agent_hash=`. + * + * CIRISPortal's `/verify`, served by a canonical node once CIRISRegistry + * folds in. GATED BY THE CALLER on [Capability.REGISTRY_LOOKUP]: no node + * released today serves this, and calling it anyway would turn a missing + * capability into a connection error the operator has to interpret. + * + * The three outcomes are kept apart deliberately. `found: false` is the + * registry ANSWERING that it holds no record — actionable. A transport + * failure is not an answer, and rendering it as "not registered" tells + * someone an unverified build was checked and cleared. + */ + suspend fun lookupAgentHash( + agentHash: String, + nodeUrl: String = LOCAL_NODE_URL, + ): ai.ciris.mobile.shared.models.capability.LookupResult { + val method = "lookupAgentHash" + val client = io.ktor.client.HttpClient { + install(io.ktor.client.plugins.HttpTimeout) { + requestTimeoutMillis = 10_000 + connectTimeoutMillis = 5_000 + } + } + val body = try { + val resp = client.get("$nodeUrl/v1/registry/lookup") { + url.parameters.append("agent_hash", agentHash) + } + if (!resp.status.isSuccess()) { + logInfo(method, "registry lookup -> HTTP ${resp.status.value}") + return ai.ciris.mobile.shared.models.capability.LookupResult.Unavailable( + "the node answered HTTP ${resp.status.value}" + ) + } + resp.bodyAsText() + } catch (e: Exception) { + logInfo(method, "registry lookup unreachable: ${e.message?.take(80)}") + return ai.ciris.mobile.shared.models.capability.LookupResult.Unavailable( + e.message?.take(120) ?: "the registry could not be reached" + ) + } finally { + client.close() + } + + if (Regex("\"found\"\\s*:\\s*false").containsMatchIn(body)) { + return ai.ciris.mobile.shared.models.capability.LookupResult.NotFound + } + fun str(field: String): String = + Regex("\"$field\"\\s*:\\s*\"([^\"]*)\"").find(body)?.groupValues?.get(1) ?: "" + val raw = str("status") + if (raw.isBlank() && str("agentHash").isBlank()) { + // A 200 we cannot read is not a verdict. Same rule as the status enum. + return ai.ciris.mobile.shared.models.capability.LookupResult.Unavailable( + "the node returned a record this client could not read" + ) + } + return ai.ciris.mobile.shared.models.capability.LookupResult.Found( + ai.ciris.mobile.shared.models.capability.AgentRecord( + agentHash = str("agentHash").ifBlank { agentHash }, + agentType = str("agentType"), + version = str("version"), + status = ai.ciris.mobile.shared.models.capability.AgentStatus.fromWire(raw), + rawStatus = raw, + registeredAt = str("registeredAt"), + hasAttestation = Regex("\"hasAttestation\"\\s*:\\s*true").containsMatchIn(body), + ) + ) + } + suspend fun getNodeCapabilities( nodeUrl: String = LOCAL_NODE_URL, ): ai.ciris.mobile.shared.models.capability.NodeCapabilities = runCatching { diff --git a/client/shared/src/commonMain/kotlin/ai/ciris/mobile/shared/ui/screens/VerifyAgentScreen.kt b/client/shared/src/commonMain/kotlin/ai/ciris/mobile/shared/ui/screens/VerifyAgentScreen.kt new file mode 100644 index 0000000..bdbdbf8 --- /dev/null +++ b/client/shared/src/commonMain/kotlin/ai/ciris/mobile/shared/ui/screens/VerifyAgentScreen.kt @@ -0,0 +1,154 @@ +package ai.ciris.mobile.shared.ui.screens + +import ai.ciris.mobile.shared.models.capability.AgentStatus +import ai.ciris.mobile.shared.models.capability.Capability +import ai.ciris.mobile.shared.models.capability.CapabilityState +import ai.ciris.mobile.shared.models.capability.LookupResult +import ai.ciris.mobile.shared.models.capability.NodeCapabilities +import ai.ciris.mobile.shared.platform.testable +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.padding +import androidx.compose.material3.Card +import androidx.compose.material3.CardDefaults +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.unit.dp +import androidx.compose.ui.unit.sp + +/** + * The gate, rendered. + * + * Ported from CIRISPortal's `/verify`: look an agent build up by hash and say + * whether the registry has it and whether it is still good. This is the first + * surface shipped AHEAD of its API — no node released today can serve it — so + * what the screen does when the capability is missing is the actual feature. + * + * FOUR OUTCOMES, AND NONE OF THEM IS A BLANK SCREEN OR AN ERROR: + * + * UNDECLARED the node predates the declaration (CIRISServer#499). Say that. + * Not "unavailable", because a newer node will serve it and the + * operator should know an upgrade is the fix. + * ABSENT the node declared its capabilities and this was not among them. + * Say THAT — it is a different sentence with a different remedy, + * and conflating it with the above is what the three-state model + * exists to prevent. + * PRESENT render the lookup. + * UNKNOWN a status this client cannot read. Show the raw string rather + * than guessing; on a revocation check a guess is a lie. + */ +@Composable +fun VerifyAgentCapabilityNotice( + capabilities: NodeCapabilities, + modifier: Modifier = Modifier, +) { + val state = capabilities.state(Capability.REGISTRY_LOOKUP) + if (state == CapabilityState.PRESENT) return + + Card( + modifier = modifier.fillMaxWidth().testable("card_verify_capability"), + colors = CardDefaults.cardColors( + containerColor = MaterialTheme.colorScheme.surfaceVariant, + ), + ) { + Column(Modifier.padding(14.dp)) { + Text( + text = when (state) { + CapabilityState.UNDECLARED -> "This node hasn't said whether it can verify builds" + else -> "This node doesn't verify builds" + }, + fontWeight = FontWeight.Bold, + fontSize = 14.sp, + color = MaterialTheme.colorScheme.onSurfaceVariant, + ) + Spacer(Modifier.height(4.dp)) + Text( + // The two remedies are different, so the two sentences are. + text = when (state) { + CapabilityState.UNDECLARED -> + "It's running a version from before nodes declared what they can do. " + + "A newer node will answer this, and the check will appear here when it does." + else -> + "Build verification is part of the registry, and this node doesn't carry it. " + + "A node that does can answer the same question." + }, + fontSize = 13.sp, + color = MaterialTheme.colorScheme.onSurfaceVariant, + ) + } + } +} + +/** The lookup outcome, once the capability is [CapabilityState.PRESENT]. */ +@Composable +fun VerifyAgentResult( + result: LookupResult, + modifier: Modifier = Modifier, +) { + Card( + modifier = modifier.fillMaxWidth().testable("card_verify_result"), + colors = CardDefaults.cardColors( + containerColor = when (result) { + is LookupResult.Found -> + if (result.record.status.isDiscouraged) MaterialTheme.colorScheme.errorContainer + else MaterialTheme.colorScheme.surfaceVariant + else -> MaterialTheme.colorScheme.surfaceVariant + }, + ), + ) { + Column(Modifier.padding(14.dp), verticalArrangement = Arrangement.spacedBy(4.dp)) { + when (result) { + is LookupResult.Found -> { + val r = result.record + Text( + text = when (r.status) { + AgentStatus.REGISTERED -> "Registered" + AgentStatus.DEPRECATED -> "Deprecated" + AgentStatus.REVOKED -> "Revoked" + // The registry said something this build does not + // know. Show it verbatim rather than deciding. + AgentStatus.UNKNOWN -> r.rawStatus.ifBlank { "Status not recognised" } + }, + fontWeight = FontWeight.Bold, + fontSize = 15.sp, + ) + if (r.agentType.isNotBlank()) Text("${r.agentType} ${r.version}".trim(), fontSize = 13.sp) + Text(r.agentHash, fontSize = 12.sp) + if (r.registeredAt.isNotBlank()) Text("registered ${r.registeredAt}", fontSize = 12.sp) + if (r.status == AgentStatus.REVOKED) { + Text( + "This build has been revoked. Do not run it.", + fontSize = 13.sp, + fontWeight = FontWeight.Bold, + color = MaterialTheme.colorScheme.onErrorContainer, + ) + } + } + // ANSWERED, and the answer is no record. Actionable. + LookupResult.NotFound -> { + Text("No record of this build", fontWeight = FontWeight.Bold, fontSize = 15.sp) + Text( + "The registry answered and holds nothing for this hash.", + fontSize = 13.sp, + ) + } + // NOT ANSWERED. Never rendered as "no record": that would tell + // someone an unverified build was checked and cleared. + is LookupResult.Unavailable -> { + Text("Couldn't check", fontWeight = FontWeight.Bold, fontSize = 15.sp) + Text( + "This is not the same as 'not registered' — the registry did not answer. " + + result.reason, + fontSize = 13.sp, + ) + } + } + } + } +} From 6a781f24fea0ef476ccdfae56152a94b9d443f47 Mon Sep 17 00:00:00 2001 From: Eric Moore Date: Fri, 28 Aug 2026 11:24:48 -0500 Subject: [PATCH 03/18] fix(portal): could-not-ask is a fourth state, and the copy is not English-only MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Six findings, and the first is the one I should have caught: THE PROBE COMMITTED THE CONFLATION THE MODEL EXISTS TO PREVENT. `getNodeCapabilities` mapped every failure — timeout, refusal, unreadable document — onto UNDECLARED. The UI then told the operator their node predates capability declarations and recommends upgrading it. A current node with a dropped connection got a FALSE VERSION DIAGNOSIS, and I wrote that inside the model whose entire argument is that "I could not ask" is not "the answer is no". CapabilityState now has four: PRESENT declared, and holds it ABSENT declared, and does not UNDECLARED the document was READ and carries no list — an older node UNREACHABLE the document could not be read at all UNREACHABLE also wins over any set we happen to hold: a probe that failed cannot license the UI on a stale answer. The copy differs for it, because the remedy is neither "upgrade" nor "use another node" — it is "try again". AND FIVE MORE: - Cancellation was swallowed. `runCatching` and a broad `catch (Exception)` both consume CancellationException, so leaving the screen mid-request turned a cancelled coroutine into an ordinary result that then published state. Rethrown before mapping transport failures, in both calls. - Both calls defaulted to LOCAL_NODE_URL while the app may be attached to a remote node — the same wrong-node bug as the reset home resolution, two days younger. The node URL is now mandatory: there is no default to be wrong. - The record parser read camelCase only. The checked-in OpenAPI schemas are snake_case throughout and this request itself sends `agent_hash`; the Portal's TypeScript is camelCase because Next.js maps it. So type, timestamp and attestation were silently dropped — and `agentHash` fell back to the QUERIED value, which would have shown the operator the hash they typed as though the registry had returned it. Snake case first, camel as fallback. - Every string was hard-coded English, bypassing the bundles in 28 locales. 18 ids added; the lane fills the rest. Navigation wiring is next, and it is the remaining finding: these composables have no route and no caller yet, so the surface is not reachable. Refs CIRISServer#499. Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_01EGE52kPzjGFiPzGcs63ZC1 --- client/VENDORING.md | 2 +- .../src/main/assets/localization/en.json | 20 +++++- .../src/main/resources/localization/en.json | 20 +++++- client/iosApp/iosApp/localization/en.json | 20 +++++- .../ciris/mobile/shared/api/CIRISApiClient.kt | 62 ++++++++++++++----- .../models/capability/NodeCapabilities.kt | 40 +++++++++--- .../shared/ui/screens/VerifyAgentScreen.kt | 58 +++++++++-------- .../models/capability/NodeCapabilitiesTest.kt | 35 ++++++++++- .../resources/localization/en.json | 20 +++++- 9 files changed, 221 insertions(+), 56 deletions(-) diff --git a/client/VENDORING.md b/client/VENDORING.md index d3858c3..449fce5 100644 --- a/client/VENDORING.md +++ b/client/VENDORING.md @@ -40,7 +40,7 @@ source is the pair a bisect wants: The tree's current recorded state — sha256-of-sha256s over every git-tracked file under `client/` except this one: -**state digest:** `99c355c370aeb6ee90cc269ec7c818edfdd0d4ce053db8dd90d1067db011bb89` +**state digest:** `223728d93cd57bcc25ed1662d94d0b76e096e714be9b56ee760119b43006238b` `packaging/check_vendoring.py` asserts it on every push, and refuses any tracked file matching a §2 never-vendor class. **Any commit that touches diff --git a/client/androidApp/src/main/assets/localization/en.json b/client/androidApp/src/main/assets/localization/en.json index 17f1f9c..cd22766 100644 --- a/client/androidApp/src/main/assets/localization/en.json +++ b/client/androidApp/src/main/assets/localization/en.json @@ -2993,7 +2993,25 @@ "wallet_transfer_note": "Transfer to another Base address for fiat cashout", "wallet_transfer_success": "Transfer successful! TX: {tx}", "wallet_trust_degraded": "Hardware Trust Degraded", - "wallet_warning": "Warning" + "wallet_warning": "Warning", + "verify_title": "Verify a build", + "verify_hash_label": "Build hash", + "verify_button": "Check", + "verify_undeclared_title": "This node hasn't said whether it can verify builds", + "verify_undeclared_body": "It is running a version from before nodes declared what they can do. A newer node will answer this.", + "verify_absent_title": "This node does not verify builds", + "verify_absent_body": "Build verification is part of the registry, and this node does not carry it. A node that does can answer the same question.", + "verify_unreachable_title": "Could not reach this node", + "verify_unreachable_body": "The node did not answer, so we do not know whether it can verify builds. This is not a problem with the build you are checking.", + "verify_status_registered": "Registered", + "verify_status_deprecated": "Deprecated", + "verify_status_revoked": "Revoked", + "verify_status_unreadable": "Status not recognised", + "verify_revoked_warning": "This build has been revoked. Do not run it.", + "verify_not_found_title": "No record of this build", + "verify_not_found_body": "The registry answered and holds nothing for this hash.", + "verify_unavailable_title": "Could not check", + "verify_unavailable_body": "This is not the same as 'not registered' — the registry did not answer." }, "moderation": { "ladder": { diff --git a/client/desktopApp/src/main/resources/localization/en.json b/client/desktopApp/src/main/resources/localization/en.json index 17f1f9c..cd22766 100644 --- a/client/desktopApp/src/main/resources/localization/en.json +++ b/client/desktopApp/src/main/resources/localization/en.json @@ -2993,7 +2993,25 @@ "wallet_transfer_note": "Transfer to another Base address for fiat cashout", "wallet_transfer_success": "Transfer successful! TX: {tx}", "wallet_trust_degraded": "Hardware Trust Degraded", - "wallet_warning": "Warning" + "wallet_warning": "Warning", + "verify_title": "Verify a build", + "verify_hash_label": "Build hash", + "verify_button": "Check", + "verify_undeclared_title": "This node hasn't said whether it can verify builds", + "verify_undeclared_body": "It is running a version from before nodes declared what they can do. A newer node will answer this.", + "verify_absent_title": "This node does not verify builds", + "verify_absent_body": "Build verification is part of the registry, and this node does not carry it. A node that does can answer the same question.", + "verify_unreachable_title": "Could not reach this node", + "verify_unreachable_body": "The node did not answer, so we do not know whether it can verify builds. This is not a problem with the build you are checking.", + "verify_status_registered": "Registered", + "verify_status_deprecated": "Deprecated", + "verify_status_revoked": "Revoked", + "verify_status_unreadable": "Status not recognised", + "verify_revoked_warning": "This build has been revoked. Do not run it.", + "verify_not_found_title": "No record of this build", + "verify_not_found_body": "The registry answered and holds nothing for this hash.", + "verify_unavailable_title": "Could not check", + "verify_unavailable_body": "This is not the same as 'not registered' — the registry did not answer." }, "moderation": { "ladder": { diff --git a/client/iosApp/iosApp/localization/en.json b/client/iosApp/iosApp/localization/en.json index 17f1f9c..cd22766 100644 --- a/client/iosApp/iosApp/localization/en.json +++ b/client/iosApp/iosApp/localization/en.json @@ -2993,7 +2993,25 @@ "wallet_transfer_note": "Transfer to another Base address for fiat cashout", "wallet_transfer_success": "Transfer successful! TX: {tx}", "wallet_trust_degraded": "Hardware Trust Degraded", - "wallet_warning": "Warning" + "wallet_warning": "Warning", + "verify_title": "Verify a build", + "verify_hash_label": "Build hash", + "verify_button": "Check", + "verify_undeclared_title": "This node hasn't said whether it can verify builds", + "verify_undeclared_body": "It is running a version from before nodes declared what they can do. A newer node will answer this.", + "verify_absent_title": "This node does not verify builds", + "verify_absent_body": "Build verification is part of the registry, and this node does not carry it. A node that does can answer the same question.", + "verify_unreachable_title": "Could not reach this node", + "verify_unreachable_body": "The node did not answer, so we do not know whether it can verify builds. This is not a problem with the build you are checking.", + "verify_status_registered": "Registered", + "verify_status_deprecated": "Deprecated", + "verify_status_revoked": "Revoked", + "verify_status_unreadable": "Status not recognised", + "verify_revoked_warning": "This build has been revoked. Do not run it.", + "verify_not_found_title": "No record of this build", + "verify_not_found_body": "The registry answered and holds nothing for this hash.", + "verify_unavailable_title": "Could not check", + "verify_unavailable_body": "This is not the same as 'not registered' — the registry did not answer." }, "moderation": { "ladder": { diff --git a/client/shared/src/commonMain/kotlin/ai/ciris/mobile/shared/api/CIRISApiClient.kt b/client/shared/src/commonMain/kotlin/ai/ciris/mobile/shared/api/CIRISApiClient.kt index e63e101..3ddcd63 100644 --- a/client/shared/src/commonMain/kotlin/ai/ciris/mobile/shared/api/CIRISApiClient.kt +++ b/client/shared/src/commonMain/kotlin/ai/ciris/mobile/shared/api/CIRISApiClient.kt @@ -9181,7 +9181,7 @@ class CIRISApiClient( */ suspend fun lookupAgentHash( agentHash: String, - nodeUrl: String = LOCAL_NODE_URL, + nodeUrl: String, ): ai.ciris.mobile.shared.models.capability.LookupResult { val method = "lookupAgentHash" val client = io.ktor.client.HttpClient { @@ -9201,6 +9201,8 @@ class CIRISApiClient( ) } resp.bodyAsText() + } catch (e: kotlinx.coroutines.CancellationException) { + throw e } catch (e: Exception) { logInfo(method, "registry lookup unreachable: ${e.message?.take(80)}") return ai.ciris.mobile.shared.models.capability.LookupResult.Unavailable( @@ -9213,10 +9215,21 @@ class CIRISApiClient( if (Regex("\"found\"\\s*:\\s*false").containsMatchIn(body)) { return ai.ciris.mobile.shared.models.capability.LookupResult.NotFound } - fun str(field: String): String = - Regex("\"$field\"\\s*:\\s*\"([^\"]*)\"").find(body)?.groupValues?.get(1) ?: "" - val raw = str("status") - if (raw.isBlank() && str("agentHash").isBlank()) { + // SNAKE CASE FIRST. The checked-in OpenAPI schemas are snake_case + // throughout and this request itself sends `agent_hash`; the Portal's + // TypeScript interface is camelCase because Next.js maps it. Reading + // only camelCase silently dropped the type, timestamp and attestation + // flag — and substituted the QUERIED hash for the returned one, which + // would have displayed the hash the operator typed as though the + // registry had confirmed it (Codex, PR #20). + fun str(vararg names: String): String { + for (n in names) { + Regex("\"$n\"\\s*:\\s*\"([^\"]*)\"").find(body)?.let { return it.groupValues[1] } + } + return "" + } + val raw = str("status", "agent_status") + if (raw.isBlank() && str("agent_hash", "agentHash").isBlank()) { // A 200 we cannot read is not a verdict. Same rule as the status enum. return ai.ciris.mobile.shared.models.capability.LookupResult.Unavailable( "the node returned a record this client could not read" @@ -9224,20 +9237,22 @@ class CIRISApiClient( } return ai.ciris.mobile.shared.models.capability.LookupResult.Found( ai.ciris.mobile.shared.models.capability.AgentRecord( - agentHash = str("agentHash").ifBlank { agentHash }, - agentType = str("agentType"), + // The RETURNED hash, never the queried one — see above. + agentHash = str("agent_hash", "agentHash").ifBlank { agentHash }, + agentType = str("agent_type", "agentType"), version = str("version"), status = ai.ciris.mobile.shared.models.capability.AgentStatus.fromWire(raw), rawStatus = raw, - registeredAt = str("registeredAt"), - hasAttestation = Regex("\"hasAttestation\"\\s*:\\s*true").containsMatchIn(body), + registeredAt = str("registered_at", "registeredAt"), + hasAttestation = Regex("\"(has_attestation|hasAttestation)\"\\s*:\\s*true") + .containsMatchIn(body), ) ) } suspend fun getNodeCapabilities( - nodeUrl: String = LOCAL_NODE_URL, - ): ai.ciris.mobile.shared.models.capability.NodeCapabilities = runCatching { + nodeUrl: String, + ): ai.ciris.mobile.shared.models.capability.NodeCapabilities = try { val client = io.ktor.client.HttpClient { install(io.ktor.client.plugins.HttpTimeout) { requestTimeoutMillis = 5_000 @@ -9252,12 +9267,25 @@ class CIRISApiClient( // `"capabilities": [ "a", "b" ]` — absent array means undeclared, empty // array means declared-and-holds-nothing. The two are different answers. val block = Regex("\"capabilities\"\\s*:\\s*\\[([^\\]]*)\\]").find(body) - ?: return@runCatching ai.ciris.mobile.shared.models.capability.NodeCapabilities.UNDECLARED - val ids = Regex("\"([^\"]+)\"").findAll(block.groupValues[1]) - .map { it.groupValues[1] } - .toSet() - ai.ciris.mobile.shared.models.capability.NodeCapabilities(ids) - }.getOrElse { ai.ciris.mobile.shared.models.capability.NodeCapabilities.UNDECLARED } + if (block == null) { + // The document WAS read and carries no list: an older node. + ai.ciris.mobile.shared.models.capability.NodeCapabilities.UNDECLARED + } else { + val ids = Regex("\"([^\"]+)\"").findAll(block.groupValues[1]) + .map { it.groupValues[1] } + .toSet() + ai.ciris.mobile.shared.models.capability.NodeCapabilities(ids) + } + } catch (e: kotlinx.coroutines.CancellationException) { + // Structured concurrency: a cancelled probe must die, not publish state. + throw e + } catch (e: Exception) { + // COULD NOT ASK — not "the node is old". Mapping this to UNDECLARED made + // the UI tell an operator with a dropped connection that their current + // node predates capability declarations (Codex, PR #20). + logInfo("getNodeCapabilities", "conformance unreadable at $nodeUrl: ${e.message?.take(80)}") + ai.ciris.mobile.shared.models.capability.NodeCapabilities.UNREACHABLE + } suspend fun getNodeHomePath(nodeUrl: String = LOCAL_NODE_URL): String? = runCatching { // A short-lived client, as the other raw scrapes in this file do: the diff --git a/client/shared/src/commonMain/kotlin/ai/ciris/mobile/shared/models/capability/NodeCapabilities.kt b/client/shared/src/commonMain/kotlin/ai/ciris/mobile/shared/models/capability/NodeCapabilities.kt index e1d0c12..d68281a 100644 --- a/client/shared/src/commonMain/kotlin/ai/ciris/mobile/shared/models/capability/NodeCapabilities.kt +++ b/client/shared/src/commonMain/kotlin/ai/ciris/mobile/shared/models/capability/NodeCapabilities.kt @@ -33,12 +33,30 @@ enum class CapabilityState { ABSENT, /** - * The node declared nothing at all — it predates the declaration, or the - * probe failed. Distinct from [ABSENT] on purpose: every node released - * today is here, and reading that as "the feature does not exist" would - * hide surfaces that a newer node will serve. + * The node's declaration was READ, and carried no capability list — it + * predates CIRISServer#499. Every node released today is here. + * + * Distinct from [ABSENT]: reading it as "the feature does not exist" would + * hide surfaces a newer node will serve. */ - UNDECLARED; + UNDECLARED, + + /** + * WE COULD NOT ASK. The node was unreachable, slow, or answered something + * unreadable. + * + * A separate state because the first version of this probe mapped transport + * failure onto [UNDECLARED], and the UI then told the operator their node + * predates capability declarations and should be upgraded — a FALSE VERSION + * DIAGNOSIS from a dropped connection (Codex, PR #20). That is the + * could-not-ask-versus-answered conflation this whole model exists to + * prevent, committed inside the model's own probe. + * + * `LookupResult.Unavailable` keeps the same distinction one layer down, and + * `ModeProbe.undetermined` keeps it for the node-vs-agent gate. Three + * places, one rule: silence is not an answer. + */ + UNREACHABLE; /** Only a positive declaration earns the full UI. */ val isUsable: Boolean get() = this == PRESENT @@ -65,9 +83,14 @@ object Capability { * * @param declared null when the node said nothing — see [CapabilityState.UNDECLARED]. */ -data class NodeCapabilities(val declared: Set?) { +data class NodeCapabilities( + val declared: Set?, + /** True when the declaration could not be READ at all — see [CapabilityState.UNREACHABLE]. */ + val unreachable: Boolean = false, +) { fun state(id: String): CapabilityState = when { + unreachable -> CapabilityState.UNREACHABLE declared == null -> CapabilityState.UNDECLARED id in declared -> CapabilityState.PRESENT else -> CapabilityState.ABSENT @@ -76,7 +99,10 @@ data class NodeCapabilities(val declared: Set?) { fun has(id: String): Boolean = state(id).isUsable companion object { - /** A node that has told us nothing. Every node released today. */ + /** Read the document; it carried no capability list. Every node today. */ val UNDECLARED = NodeCapabilities(null) + + /** Could not read the document. NOT the same as the node being old. */ + val UNREACHABLE = NodeCapabilities(null, unreachable = true) } } diff --git a/client/shared/src/commonMain/kotlin/ai/ciris/mobile/shared/ui/screens/VerifyAgentScreen.kt b/client/shared/src/commonMain/kotlin/ai/ciris/mobile/shared/ui/screens/VerifyAgentScreen.kt index bdbdbf8..8c307e7 100644 --- a/client/shared/src/commonMain/kotlin/ai/ciris/mobile/shared/ui/screens/VerifyAgentScreen.kt +++ b/client/shared/src/commonMain/kotlin/ai/ciris/mobile/shared/ui/screens/VerifyAgentScreen.kt @@ -1,5 +1,6 @@ package ai.ciris.mobile.shared.ui.screens +import ai.ciris.mobile.shared.localization.localizedString import ai.ciris.mobile.shared.models.capability.AgentStatus import ai.ciris.mobile.shared.models.capability.Capability import ai.ciris.mobile.shared.models.capability.CapabilityState @@ -59,10 +60,13 @@ fun VerifyAgentCapabilityNotice( ) { Column(Modifier.padding(14.dp)) { Text( - text = when (state) { - CapabilityState.UNDECLARED -> "This node hasn't said whether it can verify builds" - else -> "This node doesn't verify builds" - }, + text = localizedString( + when (state) { + CapabilityState.UNDECLARED -> "mobile.verify_undeclared_title" + CapabilityState.UNREACHABLE -> "mobile.verify_unreachable_title" + else -> "mobile.verify_absent_title" + } + ), fontWeight = FontWeight.Bold, fontSize = 14.sp, color = MaterialTheme.colorScheme.onSurfaceVariant, @@ -70,14 +74,17 @@ fun VerifyAgentCapabilityNotice( Spacer(Modifier.height(4.dp)) Text( // The two remedies are different, so the two sentences are. - text = when (state) { - CapabilityState.UNDECLARED -> - "It's running a version from before nodes declared what they can do. " + - "A newer node will answer this, and the check will appear here when it does." - else -> - "Build verification is part of the registry, and this node doesn't carry it. " + - "A node that does can answer the same question." - }, + text = localizedString( + when (state) { + CapabilityState.UNDECLARED -> "mobile.verify_undeclared_body" + // COULD NOT ASK. Distinct copy, because the remedy is + // neither "upgrade" nor "use another node" — it is "try + // again", and telling someone their node is old because + // a request timed out is a false diagnosis. + CapabilityState.UNREACHABLE -> "mobile.verify_unreachable_body" + else -> "mobile.verify_absent_body" + } + ), fontSize = 13.sp, color = MaterialTheme.colorScheme.onSurfaceVariant, ) @@ -108,12 +115,15 @@ fun VerifyAgentResult( val r = result.record Text( text = when (r.status) { - AgentStatus.REGISTERED -> "Registered" - AgentStatus.DEPRECATED -> "Deprecated" - AgentStatus.REVOKED -> "Revoked" + AgentStatus.REGISTERED -> localizedString("mobile.verify_status_registered") + AgentStatus.DEPRECATED -> localizedString("mobile.verify_status_deprecated") + AgentStatus.REVOKED -> localizedString("mobile.verify_status_revoked") // The registry said something this build does not - // know. Show it verbatim rather than deciding. - AgentStatus.UNKNOWN -> r.rawStatus.ifBlank { "Status not recognised" } + // know. Show it verbatim rather than deciding — the + // raw string is not translated because it is the + // registry's own token, not our prose. + AgentStatus.UNKNOWN -> + r.rawStatus.ifBlank { localizedString("mobile.verify_status_unreadable") } }, fontWeight = FontWeight.Bold, fontSize = 15.sp, @@ -123,7 +133,7 @@ fun VerifyAgentResult( if (r.registeredAt.isNotBlank()) Text("registered ${r.registeredAt}", fontSize = 12.sp) if (r.status == AgentStatus.REVOKED) { Text( - "This build has been revoked. Do not run it.", + localizedString("mobile.verify_revoked_warning"), fontSize = 13.sp, fontWeight = FontWeight.Bold, color = MaterialTheme.colorScheme.onErrorContainer, @@ -132,19 +142,15 @@ fun VerifyAgentResult( } // ANSWERED, and the answer is no record. Actionable. LookupResult.NotFound -> { - Text("No record of this build", fontWeight = FontWeight.Bold, fontSize = 15.sp) - Text( - "The registry answered and holds nothing for this hash.", - fontSize = 13.sp, - ) + Text(localizedString("mobile.verify_not_found_title"), fontWeight = FontWeight.Bold, fontSize = 15.sp) + Text(localizedString("mobile.verify_not_found_body"), fontSize = 13.sp) } // NOT ANSWERED. Never rendered as "no record": that would tell // someone an unverified build was checked and cleared. is LookupResult.Unavailable -> { - Text("Couldn't check", fontWeight = FontWeight.Bold, fontSize = 15.sp) + Text(localizedString("mobile.verify_unavailable_title"), fontWeight = FontWeight.Bold, fontSize = 15.sp) Text( - "This is not the same as 'not registered' — the registry did not answer. " + - result.reason, + localizedString("mobile.verify_unavailable_body") + " " + result.reason, fontSize = 13.sp, ) } diff --git a/client/shared/src/commonTest/kotlin/ai/ciris/mobile/shared/models/capability/NodeCapabilitiesTest.kt b/client/shared/src/commonTest/kotlin/ai/ciris/mobile/shared/models/capability/NodeCapabilitiesTest.kt index 7a0c8cc..18f5162 100644 --- a/client/shared/src/commonTest/kotlin/ai/ciris/mobile/shared/models/capability/NodeCapabilitiesTest.kt +++ b/client/shared/src/commonTest/kotlin/ai/ciris/mobile/shared/models/capability/NodeCapabilitiesTest.kt @@ -57,4 +57,37 @@ class NodeCapabilitiesTest { assertFalse(CapabilityState.ABSENT.isUsable) assertFalse(CapabilityState.UNDECLARED.isUsable) } -} + + @Test + fun could_not_ask_is_not_the_node_being_old() { + // The probe first mapped transport failure onto UNDECLARED, so the UI + // told an operator with a dropped connection that their CURRENT node + // predates capability declarations and should be upgraded — a false + // version diagnosis from a timeout (Codex, PR #20). + val unreachable = NodeCapabilities.UNREACHABLE + assertEquals(CapabilityState.UNREACHABLE, unreachable.state(Capability.REGISTRY_LOOKUP)) + assertFalse(unreachable.has(Capability.REGISTRY_LOOKUP)) + + // and it is a DIFFERENT state from a document that was read and had no list + assertEquals(CapabilityState.UNDECLARED, NodeCapabilities.UNDECLARED.state(Capability.REGISTRY_LOOKUP)) + assertTrue( + unreachable.state(Capability.REGISTRY_LOOKUP) != NodeCapabilities.UNDECLARED.state(Capability.REGISTRY_LOOKUP), + "unreachable and undeclared must not collapse", + ) + } + + @Test + fun unreachable_wins_over_a_stale_declaration() { + // If we could not read the document, whatever we hold is not current. + val stale = NodeCapabilities(setOf(Capability.REGISTRY_LOOKUP), unreachable = true) + assertEquals(CapabilityState.UNREACHABLE, stale.state(Capability.REGISTRY_LOOKUP)) + assertFalse(stale.has(Capability.REGISTRY_LOOKUP), "a probe that failed cannot license the UI") + } + + @Test + fun no_state_except_present_is_usable() { + for (s in CapabilityState.entries) { + assertEquals(s == CapabilityState.PRESENT, s.isUsable, "$s") + } + } +} \ No newline at end of file diff --git a/client/shared/src/desktopMain/resources/localization/en.json b/client/shared/src/desktopMain/resources/localization/en.json index 17f1f9c..cd22766 100644 --- a/client/shared/src/desktopMain/resources/localization/en.json +++ b/client/shared/src/desktopMain/resources/localization/en.json @@ -2993,7 +2993,25 @@ "wallet_transfer_note": "Transfer to another Base address for fiat cashout", "wallet_transfer_success": "Transfer successful! TX: {tx}", "wallet_trust_degraded": "Hardware Trust Degraded", - "wallet_warning": "Warning" + "wallet_warning": "Warning", + "verify_title": "Verify a build", + "verify_hash_label": "Build hash", + "verify_button": "Check", + "verify_undeclared_title": "This node hasn't said whether it can verify builds", + "verify_undeclared_body": "It is running a version from before nodes declared what they can do. A newer node will answer this.", + "verify_absent_title": "This node does not verify builds", + "verify_absent_body": "Build verification is part of the registry, and this node does not carry it. A node that does can answer the same question.", + "verify_unreachable_title": "Could not reach this node", + "verify_unreachable_body": "The node did not answer, so we do not know whether it can verify builds. This is not a problem with the build you are checking.", + "verify_status_registered": "Registered", + "verify_status_deprecated": "Deprecated", + "verify_status_revoked": "Revoked", + "verify_status_unreadable": "Status not recognised", + "verify_revoked_warning": "This build has been revoked. Do not run it.", + "verify_not_found_title": "No record of this build", + "verify_not_found_body": "The registry answered and holds nothing for this hash.", + "verify_unavailable_title": "Could not check", + "verify_unavailable_body": "This is not the same as 'not registered' — the registry did not answer." }, "moderation": { "ladder": { From a69b45efab6d547fc349b8f0a2cfa913a64f30a2 Mon Sep 17 00:00:00 2001 From: Eric Moore Date: Fri, 28 Aug 2026 11:32:27 -0500 Subject: [PATCH 04/18] feat(portal): the surface is reachable, and two more fabricated answers are gone MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit WIRING — the remaining P1. The composables had no route and no caller, so the PR claimed a surface and shipped none. `Screen.VerifyAgent` is now a flow-only route (no sidebar, like ClaimNode), rendered in the main `when`, with a back target, and reached from ManageNodes beside "claim ownership" — both are registry-shaped questions about a node's identity and that is where an operator already goes to ask them. The compiler enforced most of this: two exhaustive `when`s refuse a route with no branch. The capability probe runs in `CIRISApp` against `nodeBaseUrl` and re-probes on a node switch, because a cached answer from the previous node licenses the wrong UI. It starts UNREACHABLE rather than UNDECLARED: before the first probe we have not asked. AND TWO MORE FABRICATED ANSWERS, both in code I had just "fixed": - A NON-SUCCESS CONFORMANCE RESPONSE STILL HAS A BODY, and that body has no capabilities array — so a 404 or 500 fell through to UNDECLARED and told the operator their node predates the declaration. I fixed the thrown path and left the status path: the same false version diagnosis, reached by a status code instead of an exception. - THE HASH GUARD WAS AN `AND`. A record carrying a status but no `agent_hash` passed it, and the fallback then displayed the hash the OPERATOR TYPED as though the registry had returned it. On a revocation check that is the worst available lie — it shows someone their own input, confirmed. The fallback is deleted; a record without the hash it verified is Unavailable. Both are the same shape as the six before them: a path that invents an answer rather than admitting it does not have one. That is the only thing this surface is really about, and it keeps being the thing I get wrong. Desktop and wasmJs compile; 14 capability tests green. Refs CIRISServer#499. Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_01EGE52kPzjGFiPzGcs63ZC1 --- client/VENDORING.md | 2 +- .../kotlin/ai/ciris/mobile/shared/CIRISApp.kt | 40 ++++++- .../ciris/mobile/shared/api/CIRISApiClient.kt | 31 +++++- .../shared/ui/screens/ManageNodesScreen.kt | 15 +++ .../shared/ui/screens/VerifyAgentScreen.kt | 103 ++++++++++++++++++ 5 files changed, 185 insertions(+), 6 deletions(-) diff --git a/client/VENDORING.md b/client/VENDORING.md index 449fce5..73554d4 100644 --- a/client/VENDORING.md +++ b/client/VENDORING.md @@ -40,7 +40,7 @@ source is the pair a bisect wants: The tree's current recorded state — sha256-of-sha256s over every git-tracked file under `client/` except this one: -**state digest:** `223728d93cd57bcc25ed1662d94d0b76e096e714be9b56ee760119b43006238b` +**state digest:** `9dc6ccbcd6fe922c85d17338f9668cb56753c95e9f4df0f78b5926162f97a5bd` `packaging/check_vendoring.py` asserts it on every push, and refuses any tracked file matching a §2 never-vendor class. **Any commit that touches diff --git a/client/shared/src/commonMain/kotlin/ai/ciris/mobile/shared/CIRISApp.kt b/client/shared/src/commonMain/kotlin/ai/ciris/mobile/shared/CIRISApp.kt index 84db773..3b49833 100644 --- a/client/shared/src/commonMain/kotlin/ai/ciris/mobile/shared/CIRISApp.kt +++ b/client/shared/src/commonMain/kotlin/ai/ciris/mobile/shared/CIRISApp.kt @@ -458,6 +458,28 @@ fun CIRISApp( TestAutomation.setCurrentScreen(currentScreen::class.simpleName ?: "unknown") } + // WHAT THIS NODE DECLARES IT CAN DO. + // + // Probed alongside the mode gate and re-probed on a node switch, because a + // different node confers different capabilities and a cached answer from + // the previous one would license the wrong UI. + // + // Starts UNREACHABLE, not UNDECLARED: before the first probe we have not + // asked, and rendering "this node predates capability declarations" before + // asking is the false version diagnosis that state exists to prevent + // (Codex, PR #20). + var nodeCapabilities by remember { + mutableStateOf(ai.ciris.mobile.shared.models.capability.NodeCapabilities.UNREACHABLE) + } + LaunchedEffect(nodeBaseUrl) { + nodeCapabilities = apiClient.getNodeCapabilities(nodeBaseUrl) + platformLog( + TAG, + "[INFO][caps] $nodeBaseUrl declares ${nodeCapabilities.declared?.size ?: "nothing"}" + + if (nodeCapabilities.unreachable) " (unreachable)" else "", + ) + } + // Handle system back button - navigate back to appropriate parent screen // homeTarget (the probed landing), not Screen.Interact: on the node client the landing surface is @@ -3586,6 +3608,19 @@ fun CIRISApp( ) } + Screen.VerifyAgent -> { + // CIRISPortal's /verify, shipped AHEAD of its API. On every node + // released today `nodeCapabilities` is UNDECLARED or UNREACHABLE + // and the notice explains which — the lookup form only appears + // once a node declares registry:lookup (CIRISServer#499). + PlatformLogger.d(TAG, "[Screen.VerifyAgent] caps=${nodeCapabilities.state(ai.ciris.mobile.shared.models.capability.Capability.REGISTRY_LOOKUP)}") + VerifyAgentScreen( + capabilities = nodeCapabilities, + onLookup = { hash -> apiClient.lookupAgentHash(hash, nodeBaseUrl) }, + onBack = { currentScreen = Screen.Interact }, + ) + } + Screen.ClaimNode -> { // Last UI piece of the founder flow: enter a node's NodeCode + // claim PIN → connect/identity-pin → claim SYSTEM_ADMIN. Drives @@ -3612,6 +3647,7 @@ fun CIRISApp( viewModel = nodeSwitcherViewModel, onBack = { currentScreen = Screen.Interact }, onClaimNode = { currentScreen = Screen.ClaimNode }, + onVerifyAgent = { currentScreen = Screen.VerifyAgent }, // Catch-up: legacy owner (no fed-ID) → guided Add Federation ID. // Manual entry returns to Manage Nodes (vs. the login auto- // present, which returns to Interact). @@ -4528,6 +4564,7 @@ fun CIRISApp( Screen.VizSettings -> Screen.Settings Screen.ServerConnection -> Screen.Interact Screen.ClaimNode -> Screen.Interact + Screen.VerifyAgent -> Screen.Interact // Sub-screens of the home (Interact) Screen.Adapters, Screen.Audit, @@ -5312,6 +5349,7 @@ private sealed class Screen { // Claim-Ownership: founder enters a node's NodeCode + claim PIN to become // its SYSTEM_ADMIN (connect → identity-pin → claim). Flow-only (no sidebar). object ClaimNode : Screen() + object VerifyAgent : Screen() // Node management (CRUD over saved NodeProfiles) — first-class Manage-group // surface, promoted from the in-page node-switcher dropdown. @@ -5492,7 +5530,7 @@ private fun screenToSurface(s: Screen): ai.ciris.mobile.shared.ui.nav.NavSurface Screen.Commons -> ai.ciris.mobile.shared.ui.nav.NavSurface.Commons // Flow-only / no sidebar Screen.Startup, Screen.Login, Screen.Setup, Screen.ServerConnection, Screen.ClaimNode, - Screen.AddFederationId, Screen.Help -> null + Screen.AddFederationId, Screen.Help, Screen.VerifyAgent -> null } private fun surfaceToScreen(s: ai.ciris.mobile.shared.ui.nav.NavSurface): Screen = when (s) { diff --git a/client/shared/src/commonMain/kotlin/ai/ciris/mobile/shared/api/CIRISApiClient.kt b/client/shared/src/commonMain/kotlin/ai/ciris/mobile/shared/api/CIRISApiClient.kt index 3ddcd63..651b2c5 100644 --- a/client/shared/src/commonMain/kotlin/ai/ciris/mobile/shared/api/CIRISApiClient.kt +++ b/client/shared/src/commonMain/kotlin/ai/ciris/mobile/shared/api/CIRISApiClient.kt @@ -9229,7 +9229,19 @@ class CIRISApiClient( return "" } val raw = str("status", "agent_status") - if (raw.isBlank() && str("agent_hash", "agentHash").isBlank()) { + val returnedHash = str("agent_hash", "agentHash") + // THE REGISTRY MUST SAY WHICH HASH IT VERIFIED. The guard was `raw AND + // hash both blank`, so a record carrying a status but no hash passed — + // and the fallback then displayed the hash the OPERATOR TYPED as though + // the registry had returned it (Codex, PR #20). On a revocation check + // that is the worst possible lie: it shows their input confirmed. + if (returnedHash.isBlank()) { + logInfo(method, "registry returned a record without a hash — not rendering it as an answer") + return ai.ciris.mobile.shared.models.capability.LookupResult.Unavailable( + "the node returned a record without the hash it verified" + ) + } + if (raw.isBlank()) { // A 200 we cannot read is not a verdict. Same rule as the status enum. return ai.ciris.mobile.shared.models.capability.LookupResult.Unavailable( "the node returned a record this client could not read" @@ -9237,8 +9249,9 @@ class CIRISApiClient( } return ai.ciris.mobile.shared.models.capability.LookupResult.Found( ai.ciris.mobile.shared.models.capability.AgentRecord( - // The RETURNED hash, never the queried one — see above. - agentHash = str("agent_hash", "agentHash").ifBlank { agentHash }, + // The RETURNED hash. No fallback to the queried value exists + // any more — its absence is handled above as Unavailable. + agentHash = returnedHash, agentType = str("agent_type", "agentType"), version = str("version"), status = ai.ciris.mobile.shared.models.capability.AgentStatus.fromWire(raw), @@ -9260,7 +9273,17 @@ class CIRISApiClient( } } val body = try { - client.get("$nodeUrl/v1/federation/conformance").bodyAsText() + val resp = client.get("$nodeUrl/v1/federation/conformance") + // A 404 or 500 STILL HAS A BODY, and that body has no capabilities + // array — so reading it fell through to UNDECLARED and told the + // operator their node predates the declaration. The thrown path was + // fixed and this one was not (Codex, PR #20): same false version + // diagnosis, reached by a status code instead of an exception. + if (!resp.status.isSuccess()) { + logInfo("getNodeCapabilities", "conformance -> HTTP ${resp.status.value} at $nodeUrl") + return ai.ciris.mobile.shared.models.capability.NodeCapabilities.UNREACHABLE + } + resp.bodyAsText() } finally { client.close() } diff --git a/client/shared/src/commonMain/kotlin/ai/ciris/mobile/shared/ui/screens/ManageNodesScreen.kt b/client/shared/src/commonMain/kotlin/ai/ciris/mobile/shared/ui/screens/ManageNodesScreen.kt index 5c976b0..5a9fef5 100644 --- a/client/shared/src/commonMain/kotlin/ai/ciris/mobile/shared/ui/screens/ManageNodesScreen.kt +++ b/client/shared/src/commonMain/kotlin/ai/ciris/mobile/shared/ui/screens/ManageNodesScreen.kt @@ -87,6 +87,8 @@ fun ManageNodesScreen( onBack: () -> Unit, /** Navigate to the claim-ownership flow (ClaimNodeScreen). */ onClaimNode: () -> Unit, + /** Routes to [VerifyAgentScreen] — look a build up in the registry. */ + onVerifyAgent: () -> Unit = {}, /** Navigate to the guided "Add Federation ID" catch-up flow (AddFederationIdScreen). * Only surfaced when the logged-in owner has NO fed-ID. */ onAddFederationId: () -> Unit = {}, @@ -165,6 +167,7 @@ fun ManageNodesScreen( NodesListView( viewModel = viewModel, onClaimNode = onClaimNode, + onVerifyAgent = onVerifyAgent, onAddFederationId = onAddFederationId, modifier = Modifier.weight(1f), ) @@ -205,6 +208,7 @@ private fun RowScope.ViewTab( private fun NodesListView( viewModel: NodeSwitcherViewModel, onClaimNode: () -> Unit, + onVerifyAgent: () -> Unit = {}, onAddFederationId: () -> Unit, modifier: Modifier = Modifier, ) { @@ -460,6 +464,17 @@ private fun NodesListView( Spacer(Modifier.height(8.dp)) // ── Claim ownership affordance ─────────────────────────────────── + // Verify a build against the registry. Sits beside claim because + // both are registry-shaped questions about a node's identity, and + // this is where an operator already comes to ask them. + Button( + onClick = onVerifyAgent, + modifier = Modifier.fillMaxWidth().testableClickable("btn_manage_nodes_verify") { onVerifyAgent() }, + ) { + Text(localizedString("mobile.verify_title")) + } + Spacer(Modifier.height(8.dp)) + Button( onClick = onClaimNode, modifier = Modifier.fillMaxWidth().testableClickable("btn_manage_nodes_claim") { onClaimNode() }, diff --git a/client/shared/src/commonMain/kotlin/ai/ciris/mobile/shared/ui/screens/VerifyAgentScreen.kt b/client/shared/src/commonMain/kotlin/ai/ciris/mobile/shared/ui/screens/VerifyAgentScreen.kt index 8c307e7..c6eb231 100644 --- a/client/shared/src/commonMain/kotlin/ai/ciris/mobile/shared/ui/screens/VerifyAgentScreen.kt +++ b/client/shared/src/commonMain/kotlin/ai/ciris/mobile/shared/ui/screens/VerifyAgentScreen.kt @@ -17,7 +17,19 @@ import androidx.compose.material3.Card import androidx.compose.material3.CardDefaults import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Text +import androidx.compose.foundation.rememberScrollState +import androidx.compose.foundation.text.KeyboardOptions +import androidx.compose.foundation.verticalScroll +import androidx.compose.material3.Button +import androidx.compose.material3.OutlinedTextField import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.rememberCoroutineScope +import androidx.compose.runtime.setValue +import ai.ciris.mobile.shared.platform.testableClickable +import kotlinx.coroutines.launch import androidx.compose.ui.Modifier import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.unit.dp @@ -158,3 +170,94 @@ fun VerifyAgentResult( } } } + + +/** + * The whole surface: a hash field, a check button, and whichever of the four + * outcomes applies. + * + * The lookup is INJECTED rather than reached for, so this composable has no + * opinion about which node answers — `CIRISApp` supplies the attached node's + * URL, which is the bug that made `LOCAL_NODE_URL` a bad default here and in + * the reset home resolution. + * + * The form only renders when the capability is PRESENT. That is not cosmetic: + * offering a field that cannot be submitted teaches the operator the feature is + * broken, when in fact this node simply does not serve it. + */ +@Composable +fun VerifyAgentScreen( + capabilities: NodeCapabilities, + onLookup: suspend (String) -> LookupResult, + onBack: () -> Unit, + modifier: Modifier = Modifier, +) { + val usable = capabilities.has(Capability.REGISTRY_LOOKUP) + var hash by remember { mutableStateOf("") } + var result by remember { mutableStateOf(null) } + var inFlight by remember { mutableStateOf(false) } + val scope = rememberCoroutineScope() + + Column( + modifier = modifier + .fillMaxWidth() + .verticalScroll(rememberScrollState()) + .padding(16.dp), + verticalArrangement = Arrangement.spacedBy(12.dp), + ) { + Text( + text = localizedString("mobile.verify_title"), + fontWeight = FontWeight.Bold, + fontSize = 20.sp, + modifier = Modifier.testable("txt_verify_title"), + ) + + // Says which of UNDECLARED / ABSENT / UNREACHABLE applies, and returns + // nothing at all when the capability is PRESENT. + VerifyAgentCapabilityNotice(capabilities) + + if (usable) { + OutlinedTextField( + value = hash, + onValueChange = { hash = it; result = null }, + label = { Text(localizedString("mobile.verify_hash_label")) }, + singleLine = true, + keyboardOptions = KeyboardOptions.Default, + modifier = Modifier.fillMaxWidth().testable("input_verify_hash"), + ) + Button( + onClick = { + if (!inFlight && hash.isNotBlank()) { + inFlight = true + scope.launch { + result = onLookup(hash.trim()) + inFlight = false + } + } + }, + enabled = !inFlight && hash.isNotBlank(), + modifier = Modifier + .fillMaxWidth() + .testableClickable("btn_verify_submit") { + if (!inFlight && hash.isNotBlank()) { + inFlight = true + scope.launch { + result = onLookup(hash.trim()) + inFlight = false + } + } + }, + ) { + Text(localizedString("mobile.verify_button")) + } + result?.let { VerifyAgentResult(it) } + } + + Button( + onClick = onBack, + modifier = Modifier.testableClickable("btn_verify_back") { onBack() }, + ) { + Text(localizedString("mobile.claim_node_back")) + } + } +} From c5c026e790a37eab3240f49fb46db9dd29507632 Mon Sep 17 00:00:00 2001 From: Eric Moore Date: Fri, 28 Aug 2026 11:35:52 -0500 Subject: [PATCH 05/18] fix(portal): a verdict belongs to the node that gave it MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Self-review, not a review finding — the reviewer is rate-limited and this is the class it had found eight times on this file, so I went looking rather than waiting to be told. `result`, `hash` and `inFlight` were remembered with no key, and nothing cleared them on a node switch. So: verify a hash against node A, switch to node B, look at the screen — A's verdict is still there, presented as B's answer. A revocation result attributed to a registry that never gave it, which is worse than no answer and looks identical to a good one. All three are keyed on the node URL now, and the screen takes that URL rather than inferring it, so the identity the result belongs to is explicit in the signature. Same shape as every finding on this PR: a path that displays an answer it does not have. The three-state gate exists because a boolean would have hidden them, and this one was hiding behind a `remember` with no key. Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_01EGE52kPzjGFiPzGcs63ZC1 --- client/VENDORING.md | 2 +- .../kotlin/ai/ciris/mobile/shared/CIRISApp.kt | 1 + .../mobile/shared/ui/screens/VerifyAgentScreen.kt | 14 +++++++++++--- 3 files changed, 13 insertions(+), 4 deletions(-) diff --git a/client/VENDORING.md b/client/VENDORING.md index 73554d4..1a4640a 100644 --- a/client/VENDORING.md +++ b/client/VENDORING.md @@ -40,7 +40,7 @@ source is the pair a bisect wants: The tree's current recorded state — sha256-of-sha256s over every git-tracked file under `client/` except this one: -**state digest:** `9dc6ccbcd6fe922c85d17338f9668cb56753c95e9f4df0f78b5926162f97a5bd` +**state digest:** `042320b0a4e9687a91d840b3d42496726d3006703fb86a91b05741069e949ea6` `packaging/check_vendoring.py` asserts it on every push, and refuses any tracked file matching a §2 never-vendor class. **Any commit that touches diff --git a/client/shared/src/commonMain/kotlin/ai/ciris/mobile/shared/CIRISApp.kt b/client/shared/src/commonMain/kotlin/ai/ciris/mobile/shared/CIRISApp.kt index 3b49833..cc212ec 100644 --- a/client/shared/src/commonMain/kotlin/ai/ciris/mobile/shared/CIRISApp.kt +++ b/client/shared/src/commonMain/kotlin/ai/ciris/mobile/shared/CIRISApp.kt @@ -3616,6 +3616,7 @@ fun CIRISApp( PlatformLogger.d(TAG, "[Screen.VerifyAgent] caps=${nodeCapabilities.state(ai.ciris.mobile.shared.models.capability.Capability.REGISTRY_LOOKUP)}") VerifyAgentScreen( capabilities = nodeCapabilities, + nodeUrl = nodeBaseUrl, onLookup = { hash -> apiClient.lookupAgentHash(hash, nodeBaseUrl) }, onBack = { currentScreen = Screen.Interact }, ) diff --git a/client/shared/src/commonMain/kotlin/ai/ciris/mobile/shared/ui/screens/VerifyAgentScreen.kt b/client/shared/src/commonMain/kotlin/ai/ciris/mobile/shared/ui/screens/VerifyAgentScreen.kt index c6eb231..85cb45e 100644 --- a/client/shared/src/commonMain/kotlin/ai/ciris/mobile/shared/ui/screens/VerifyAgentScreen.kt +++ b/client/shared/src/commonMain/kotlin/ai/ciris/mobile/shared/ui/screens/VerifyAgentScreen.kt @@ -188,14 +188,22 @@ fun VerifyAgentResult( @Composable fun VerifyAgentScreen( capabilities: NodeCapabilities, + /** Which node answers. Also the identity the result belongs to — see below. */ + nodeUrl: String, onLookup: suspend (String) -> LookupResult, onBack: () -> Unit, modifier: Modifier = Modifier, ) { val usable = capabilities.has(Capability.REGISTRY_LOOKUP) - var hash by remember { mutableStateOf("") } - var result by remember { mutableStateOf(null) } - var inFlight by remember { mutableStateOf(false) } + // KEYED ON THE NODE. Without this the state survives a node switch, so an + // operator who verifies a hash against node A, switches to node B, and looks + // at the screen sees A's verdict presented as B's answer — a revocation + // result attributed to a registry that never gave it. Self-review, after + // eight review findings on this file all of the same shape: a path that + // shows an answer it does not have. + var hash by remember(nodeUrl) { mutableStateOf("") } + var result by remember(nodeUrl) { mutableStateOf(null) } + var inFlight by remember(nodeUrl) { mutableStateOf(false) } val scope = rememberCoroutineScope() Column( From 97a1d8eba6e3784f063f2e922cd4d4f757e80bab Mon Sep 17 00:00:00 2001 From: Eric Moore Date: Fri, 28 Aug 2026 18:51:57 -0500 Subject: [PATCH 06/18] =?UTF-8?q?feat(portal):=20match=20the=20server's=20?= =?UTF-8?q?declaration=20=E2=80=94=20null=20is=20not=20a=20missing=20key?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit THE SERVER SHIPPED IT. `src/conformance.rs` now carries `capabilities: Option>` (CIRISServer#499), and its doc comment holds the line I asked for and states it better than my issue did: `null` when this node could not read its own key record, which is NOT the same fact as `[]` — "no capabilities" and "could not determine" must not collapse into one answer, or a client renders a transient directory error as a node with no authority. MY PARSER COLLAPSED EXACTLY THAT. It matched only the array form, so `"capabilities": null` read identically to a missing key and the UI told the operator of a CURRENT node that it predates the declaration. Third form of the same false version diagnosis on this surface. Four shapes, four answers: key absent UNDECLARED an older node — upgrade "capabilities": null UNDETERMINED the node cannot read its own key record — its answer, not our failure; retry "capabilities": [] ABSENT declared, holds nothing — another node "capabilities": [...] membership A key present but neither null nor an array reads UNREACHABLE rather than being guessed into one of the four. Three remedies, three states, and the server drew the same line independently — which is the useful signal here: the distinction is a property of the problem, not a preference of mine. ALSO THE ENGLISH, twice over. The Hausa reviewer rejected `verify_undeclared_body` for two reasons and both were mine: "running a VERSION from before" collides with the glossary's Version→Date mapping and read as a calendar date, and "a newer node will answer THIS" has no antecedent, so the translator added "the question" and was marked for adding nuance. Both words are gone: "This node is older than the capability declaration, so it cannot say. A newer node can verify builds." Refs CIRISServer#499. Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_01EGE52kPzjGFiPzGcs63ZC1 --- client/VENDORING.md | 2 +- .../src/main/assets/localization/en.json | 8 ++++--- .../src/main/resources/localization/en.json | 8 ++++--- client/iosApp/iosApp/localization/en.json | 8 ++++--- .../ciris/mobile/shared/api/CIRISApiClient.kt | 24 ++++++++++++++++--- .../models/capability/NodeCapabilities.kt | 23 ++++++++++++++++++ .../shared/ui/screens/VerifyAgentScreen.kt | 4 ++++ .../models/capability/NodeCapabilitiesTest.kt | 18 ++++++++++++++ .../resources/localization/en.json | 8 ++++--- 9 files changed, 87 insertions(+), 16 deletions(-) diff --git a/client/VENDORING.md b/client/VENDORING.md index 1a4640a..d5dfa03 100644 --- a/client/VENDORING.md +++ b/client/VENDORING.md @@ -40,7 +40,7 @@ source is the pair a bisect wants: The tree's current recorded state — sha256-of-sha256s over every git-tracked file under `client/` except this one: -**state digest:** `042320b0a4e9687a91d840b3d42496726d3006703fb86a91b05741069e949ea6` +**state digest:** `d93f2a270fa7477a25ca0852e08bcad5099e13b6fe1a20b7aff05dea3a299dd1` `packaging/check_vendoring.py` asserts it on every push, and refuses any tracked file matching a §2 never-vendor class. **Any commit that touches diff --git a/client/androidApp/src/main/assets/localization/en.json b/client/androidApp/src/main/assets/localization/en.json index cd22766..9d06947 100644 --- a/client/androidApp/src/main/assets/localization/en.json +++ b/client/androidApp/src/main/assets/localization/en.json @@ -2997,8 +2997,8 @@ "verify_title": "Verify a build", "verify_hash_label": "Build hash", "verify_button": "Check", - "verify_undeclared_title": "This node hasn't said whether it can verify builds", - "verify_undeclared_body": "It is running a version from before nodes declared what they can do. A newer node will answer this.", + "verify_undeclared_title": "This node cannot say whether it verifies builds", + "verify_undeclared_body": "This node is older than the capability declaration, so it cannot say. A newer node can verify builds.", "verify_absent_title": "This node does not verify builds", "verify_absent_body": "Build verification is part of the registry, and this node does not carry it. A node that does can answer the same question.", "verify_unreachable_title": "Could not reach this node", @@ -3011,7 +3011,9 @@ "verify_not_found_title": "No record of this build", "verify_not_found_body": "The registry answered and holds nothing for this hash.", "verify_unavailable_title": "Could not check", - "verify_unavailable_body": "This is not the same as 'not registered' — the registry did not answer." + "verify_unavailable_body": "This is not the same as 'not registered' — the registry did not answer.", + "verify_undetermined_title": "This node could not determine what it can do", + "verify_undetermined_body": "The node answered, but could not read its own key record. This is usually temporary — try again shortly." }, "moderation": { "ladder": { diff --git a/client/desktopApp/src/main/resources/localization/en.json b/client/desktopApp/src/main/resources/localization/en.json index cd22766..9d06947 100644 --- a/client/desktopApp/src/main/resources/localization/en.json +++ b/client/desktopApp/src/main/resources/localization/en.json @@ -2997,8 +2997,8 @@ "verify_title": "Verify a build", "verify_hash_label": "Build hash", "verify_button": "Check", - "verify_undeclared_title": "This node hasn't said whether it can verify builds", - "verify_undeclared_body": "It is running a version from before nodes declared what they can do. A newer node will answer this.", + "verify_undeclared_title": "This node cannot say whether it verifies builds", + "verify_undeclared_body": "This node is older than the capability declaration, so it cannot say. A newer node can verify builds.", "verify_absent_title": "This node does not verify builds", "verify_absent_body": "Build verification is part of the registry, and this node does not carry it. A node that does can answer the same question.", "verify_unreachable_title": "Could not reach this node", @@ -3011,7 +3011,9 @@ "verify_not_found_title": "No record of this build", "verify_not_found_body": "The registry answered and holds nothing for this hash.", "verify_unavailable_title": "Could not check", - "verify_unavailable_body": "This is not the same as 'not registered' — the registry did not answer." + "verify_unavailable_body": "This is not the same as 'not registered' — the registry did not answer.", + "verify_undetermined_title": "This node could not determine what it can do", + "verify_undetermined_body": "The node answered, but could not read its own key record. This is usually temporary — try again shortly." }, "moderation": { "ladder": { diff --git a/client/iosApp/iosApp/localization/en.json b/client/iosApp/iosApp/localization/en.json index cd22766..9d06947 100644 --- a/client/iosApp/iosApp/localization/en.json +++ b/client/iosApp/iosApp/localization/en.json @@ -2997,8 +2997,8 @@ "verify_title": "Verify a build", "verify_hash_label": "Build hash", "verify_button": "Check", - "verify_undeclared_title": "This node hasn't said whether it can verify builds", - "verify_undeclared_body": "It is running a version from before nodes declared what they can do. A newer node will answer this.", + "verify_undeclared_title": "This node cannot say whether it verifies builds", + "verify_undeclared_body": "This node is older than the capability declaration, so it cannot say. A newer node can verify builds.", "verify_absent_title": "This node does not verify builds", "verify_absent_body": "Build verification is part of the registry, and this node does not carry it. A node that does can answer the same question.", "verify_unreachable_title": "Could not reach this node", @@ -3011,7 +3011,9 @@ "verify_not_found_title": "No record of this build", "verify_not_found_body": "The registry answered and holds nothing for this hash.", "verify_unavailable_title": "Could not check", - "verify_unavailable_body": "This is not the same as 'not registered' — the registry did not answer." + "verify_unavailable_body": "This is not the same as 'not registered' — the registry did not answer.", + "verify_undetermined_title": "This node could not determine what it can do", + "verify_undetermined_body": "The node answered, but could not read its own key record. This is usually temporary — try again shortly." }, "moderation": { "ladder": { diff --git a/client/shared/src/commonMain/kotlin/ai/ciris/mobile/shared/api/CIRISApiClient.kt b/client/shared/src/commonMain/kotlin/ai/ciris/mobile/shared/api/CIRISApiClient.kt index 651b2c5..7266781 100644 --- a/client/shared/src/commonMain/kotlin/ai/ciris/mobile/shared/api/CIRISApiClient.kt +++ b/client/shared/src/commonMain/kotlin/ai/ciris/mobile/shared/api/CIRISApiClient.kt @@ -9289,10 +9289,28 @@ class CIRISApiClient( } // `"capabilities": [ "a", "b" ]` — absent array means undeclared, empty // array means declared-and-holds-nothing. The two are different answers. + // THREE SHAPES, THREE ANSWERS (CIRISServer#499, src/conformance.rs): + // key absent an older node that never had the field + // "capabilities": null the node could not read its own key record + // "capabilities": [...] the conferred set, possibly empty + // + // The server draws the middle distinction on purpose — "'no capabilities' + // and 'could not determine' must not collapse into one answer" — and my + // first parser matched only the array, so an explicit null read as a + // missing key and told a current node's operator to upgrade. + val hasKey = Regex("\"capabilities\"\\s*:").containsMatchIn(body) + val isNull = Regex("\"capabilities\"\\s*:\\s*null").containsMatchIn(body) val block = Regex("\"capabilities\"\\s*:\\s*\\[([^\\]]*)\\]").find(body) - if (block == null) { - // The document WAS read and carries no list: an older node. - ai.ciris.mobile.shared.models.capability.NodeCapabilities.UNDECLARED + if (isNull) { + ai.ciris.mobile.shared.models.capability.NodeCapabilities.UNDETERMINED + } else if (block == null) { + if (hasKey) { + // Present but neither null nor an array: we cannot read it, and + // guessing which of the other three it means would be inventing. + ai.ciris.mobile.shared.models.capability.NodeCapabilities.UNREACHABLE + } else { + ai.ciris.mobile.shared.models.capability.NodeCapabilities.UNDECLARED + } } else { val ids = Regex("\"([^\"]+)\"").findAll(block.groupValues[1]) .map { it.groupValues[1] } diff --git a/client/shared/src/commonMain/kotlin/ai/ciris/mobile/shared/models/capability/NodeCapabilities.kt b/client/shared/src/commonMain/kotlin/ai/ciris/mobile/shared/models/capability/NodeCapabilities.kt index d68281a..cd4ee12 100644 --- a/client/shared/src/commonMain/kotlin/ai/ciris/mobile/shared/models/capability/NodeCapabilities.kt +++ b/client/shared/src/commonMain/kotlin/ai/ciris/mobile/shared/models/capability/NodeCapabilities.kt @@ -41,6 +41,23 @@ enum class CapabilityState { */ UNDECLARED, + /** + * THE NODE ANSWERED "I DO NOT KNOW". It emitted `capabilities: null` — + * CIRISServer#499's shape for "could not read its own key record". + * + * The server draws this distinction deliberately and says why: "'no + * capabilities' and 'could not determine' must not collapse into one + * answer, or a client renders a transient directory error as a node with no + * authority" (`src/conformance.rs`). My first parser matched only the array + * form, so an explicit `null` read identically to a missing key and the UI + * told a CURRENT node's operator that their node predates the declaration. + * + * Distinct from [UNREACHABLE], which is OUR side failing to ask, and from + * [UNDECLARED], which is an older node that never had the field. Three + * different remedies: retry or look at the node, check the network, upgrade. + */ + UNDETERMINED, + /** * WE COULD NOT ASK. The node was unreachable, slow, or answered something * unreadable. @@ -87,10 +104,13 @@ data class NodeCapabilities( val declared: Set?, /** True when the declaration could not be READ at all — see [CapabilityState.UNREACHABLE]. */ val unreachable: Boolean = false, + /** True when the node emitted `capabilities: null` — see [CapabilityState.UNDETERMINED]. */ + val undetermined: Boolean = false, ) { fun state(id: String): CapabilityState = when { unreachable -> CapabilityState.UNREACHABLE + undetermined -> CapabilityState.UNDETERMINED declared == null -> CapabilityState.UNDECLARED id in declared -> CapabilityState.PRESENT else -> CapabilityState.ABSENT @@ -104,5 +124,8 @@ data class NodeCapabilities( /** Could not read the document. NOT the same as the node being old. */ val UNREACHABLE = NodeCapabilities(null, unreachable = true) + + /** The node said `null`: it could not determine its own. Its answer, not ours. */ + val UNDETERMINED = NodeCapabilities(null, undetermined = true) } } diff --git a/client/shared/src/commonMain/kotlin/ai/ciris/mobile/shared/ui/screens/VerifyAgentScreen.kt b/client/shared/src/commonMain/kotlin/ai/ciris/mobile/shared/ui/screens/VerifyAgentScreen.kt index 85cb45e..7770d25 100644 --- a/client/shared/src/commonMain/kotlin/ai/ciris/mobile/shared/ui/screens/VerifyAgentScreen.kt +++ b/client/shared/src/commonMain/kotlin/ai/ciris/mobile/shared/ui/screens/VerifyAgentScreen.kt @@ -76,6 +76,7 @@ fun VerifyAgentCapabilityNotice( when (state) { CapabilityState.UNDECLARED -> "mobile.verify_undeclared_title" CapabilityState.UNREACHABLE -> "mobile.verify_unreachable_title" + CapabilityState.UNDETERMINED -> "mobile.verify_undetermined_title" else -> "mobile.verify_absent_title" } ), @@ -94,6 +95,9 @@ fun VerifyAgentCapabilityNotice( // again", and telling someone their node is old because // a request timed out is a false diagnosis. CapabilityState.UNREACHABLE -> "mobile.verify_unreachable_body" + // The NODE said it does not know — its answer, not our + // failure to ask. Remedy is retry, not upgrade. + CapabilityState.UNDETERMINED -> "mobile.verify_undetermined_body" else -> "mobile.verify_absent_body" } ), diff --git a/client/shared/src/commonTest/kotlin/ai/ciris/mobile/shared/models/capability/NodeCapabilitiesTest.kt b/client/shared/src/commonTest/kotlin/ai/ciris/mobile/shared/models/capability/NodeCapabilitiesTest.kt index 18f5162..b822b4b 100644 --- a/client/shared/src/commonTest/kotlin/ai/ciris/mobile/shared/models/capability/NodeCapabilitiesTest.kt +++ b/client/shared/src/commonTest/kotlin/ai/ciris/mobile/shared/models/capability/NodeCapabilitiesTest.kt @@ -90,4 +90,22 @@ class NodeCapabilitiesTest { assertEquals(s == CapabilityState.PRESENT, s.isUsable, "$s") } } + + @Test + fun the_node_saying_it_does_not_know_is_its_own_answer() { + // CIRISServer#499 emits `capabilities: null` when the node cannot read + // its own key record, and says explicitly that this must not collapse + // with `[]`. Three different remedies, so three different states. + val undetermined = NodeCapabilities.UNDETERMINED + assertEquals(CapabilityState.UNDETERMINED, undetermined.state(Capability.REGISTRY_LOOKUP)) + assertFalse(undetermined.has(Capability.REGISTRY_LOOKUP)) + + val all = listOf( + NodeCapabilities.UNDETERMINED.state(Capability.REGISTRY_LOOKUP), + NodeCapabilities.UNREACHABLE.state(Capability.REGISTRY_LOOKUP), + NodeCapabilities.UNDECLARED.state(Capability.REGISTRY_LOOKUP), + NodeCapabilities(emptySet()).state(Capability.REGISTRY_LOOKUP), + ) + assertEquals(all.size, all.toSet().size, "all four not-usable answers must stay distinct") + } } \ No newline at end of file diff --git a/client/shared/src/desktopMain/resources/localization/en.json b/client/shared/src/desktopMain/resources/localization/en.json index cd22766..9d06947 100644 --- a/client/shared/src/desktopMain/resources/localization/en.json +++ b/client/shared/src/desktopMain/resources/localization/en.json @@ -2997,8 +2997,8 @@ "verify_title": "Verify a build", "verify_hash_label": "Build hash", "verify_button": "Check", - "verify_undeclared_title": "This node hasn't said whether it can verify builds", - "verify_undeclared_body": "It is running a version from before nodes declared what they can do. A newer node will answer this.", + "verify_undeclared_title": "This node cannot say whether it verifies builds", + "verify_undeclared_body": "This node is older than the capability declaration, so it cannot say. A newer node can verify builds.", "verify_absent_title": "This node does not verify builds", "verify_absent_body": "Build verification is part of the registry, and this node does not carry it. A node that does can answer the same question.", "verify_unreachable_title": "Could not reach this node", @@ -3011,7 +3011,9 @@ "verify_not_found_title": "No record of this build", "verify_not_found_body": "The registry answered and holds nothing for this hash.", "verify_unavailable_title": "Could not check", - "verify_unavailable_body": "This is not the same as 'not registered' — the registry did not answer." + "verify_unavailable_body": "This is not the same as 'not registered' — the registry did not answer.", + "verify_undetermined_title": "This node could not determine what it can do", + "verify_undetermined_body": "The node answered, but could not read its own key record. This is usually temporary — try again shortly." }, "moderation": { "ladder": { From 6e2ad9eba51ed225ec30d6a8d8bedeb5370bc350 Mon Sep 17 00:00:00 2001 From: Eric Moore Date: Fri, 28 Aug 2026 19:02:49 -0500 Subject: [PATCH 07/18] fix(portal): bind verification to the node actually selected MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Four findings, and the first is a repeat offence. THE PROBE WAS KEYED ON THE IMMUTABLE PARAMETER. `NodeSwitcherViewModel.switchTo` repoints `apiClient.baseUrl` and `activeProfileId`; `nodeBaseUrl` is a CIRISApp argument, fixed for the composition, and never moves. So after a switch the probe did not re-run, and the per-node `remember(nodeUrl)` I added in self-review never reset — meaning the staleness I thought I had closed was still open, and one registry's registered/revoked verdict could be shown as the selected node's answer. This is the SECOND time I have reached for that parameter where the mutable value was needed. The first was the reset home resolution, where I wrote a comment claiming to pass the current URL while passing the stale one. Same class, same file, days apart. Now derived from `activeProfile`, which the VM's own documentation says is the screen's responsibility to react to. A RETURNED HASH MUST BE THE HASH WE ASKED ABOUT. Rejecting only a blank one still accepted a record for a different build and showed its verdict beside the operator's query. Hashes are long and visually similar, so rendering the returned value is not enough to catch it — the mismatch is now Unavailable. THE PROBE WAS ONE-SHOT. UNREACHABLE and UNDETERMINED are both transient, the copy tells the operator to try again shortly, and nothing could: the effect was keyed only on a URL that does not change, so a node that recovered stayed unusable for the session. There is a "Check again" now, offered ONLY for the two transient states — a retry on ABSENT or UNDECLARED invites pressing a button that cannot change the answer. BACK WENT TO AN AGENT SURFACE. Verify is opened from Manage Nodes, and both back paths sent the operator to Interact — which the node-mode gate removes from the sidebar, so a bare-node user exited onto a screen their node cannot serve. Both go back to Manage Nodes. Refs CIRISServer#499. Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_01EGE52kPzjGFiPzGcs63ZC1 --- client/VENDORING.md | 2 +- .../src/main/assets/localization/en.json | 3 +- .../src/main/resources/localization/en.json | 3 +- client/iosApp/iosApp/localization/en.json | 3 +- .../kotlin/ai/ciris/mobile/shared/CIRISApp.kt | 69 +++++++++++-------- .../ciris/mobile/shared/api/CIRISApiClient.kt | 13 ++++ .../shared/ui/screens/VerifyAgentScreen.kt | 19 ++++- .../resources/localization/en.json | 3 +- 8 files changed, 82 insertions(+), 33 deletions(-) diff --git a/client/VENDORING.md b/client/VENDORING.md index d5dfa03..be987eb 100644 --- a/client/VENDORING.md +++ b/client/VENDORING.md @@ -40,7 +40,7 @@ source is the pair a bisect wants: The tree's current recorded state — sha256-of-sha256s over every git-tracked file under `client/` except this one: -**state digest:** `d93f2a270fa7477a25ca0852e08bcad5099e13b6fe1a20b7aff05dea3a299dd1` +**state digest:** `dbe8ef405fb05ba8e1dde3b8cf20160fc4fdfdada0314d0945ecfde53bccdb16` `packaging/check_vendoring.py` asserts it on every push, and refuses any tracked file matching a §2 never-vendor class. **Any commit that touches diff --git a/client/androidApp/src/main/assets/localization/en.json b/client/androidApp/src/main/assets/localization/en.json index 9d06947..f7da724 100644 --- a/client/androidApp/src/main/assets/localization/en.json +++ b/client/androidApp/src/main/assets/localization/en.json @@ -3013,7 +3013,8 @@ "verify_unavailable_title": "Could not check", "verify_unavailable_body": "This is not the same as 'not registered' — the registry did not answer.", "verify_undetermined_title": "This node could not determine what it can do", - "verify_undetermined_body": "The node answered, but could not read its own key record. This is usually temporary — try again shortly." + "verify_undetermined_body": "The node answered, but could not read its own key record. This is usually temporary — try again shortly.", + "verify_retry": "Check again" }, "moderation": { "ladder": { diff --git a/client/desktopApp/src/main/resources/localization/en.json b/client/desktopApp/src/main/resources/localization/en.json index 9d06947..f7da724 100644 --- a/client/desktopApp/src/main/resources/localization/en.json +++ b/client/desktopApp/src/main/resources/localization/en.json @@ -3013,7 +3013,8 @@ "verify_unavailable_title": "Could not check", "verify_unavailable_body": "This is not the same as 'not registered' — the registry did not answer.", "verify_undetermined_title": "This node could not determine what it can do", - "verify_undetermined_body": "The node answered, but could not read its own key record. This is usually temporary — try again shortly." + "verify_undetermined_body": "The node answered, but could not read its own key record. This is usually temporary — try again shortly.", + "verify_retry": "Check again" }, "moderation": { "ladder": { diff --git a/client/iosApp/iosApp/localization/en.json b/client/iosApp/iosApp/localization/en.json index 9d06947..f7da724 100644 --- a/client/iosApp/iosApp/localization/en.json +++ b/client/iosApp/iosApp/localization/en.json @@ -3013,7 +3013,8 @@ "verify_unavailable_title": "Could not check", "verify_unavailable_body": "This is not the same as 'not registered' — the registry did not answer.", "verify_undetermined_title": "This node could not determine what it can do", - "verify_undetermined_body": "The node answered, but could not read its own key record. This is usually temporary — try again shortly." + "verify_undetermined_body": "The node answered, but could not read its own key record. This is usually temporary — try again shortly.", + "verify_retry": "Check again" }, "moderation": { "ladder": { diff --git a/client/shared/src/commonMain/kotlin/ai/ciris/mobile/shared/CIRISApp.kt b/client/shared/src/commonMain/kotlin/ai/ciris/mobile/shared/CIRISApp.kt index cc212ec..f97bf24 100644 --- a/client/shared/src/commonMain/kotlin/ai/ciris/mobile/shared/CIRISApp.kt +++ b/client/shared/src/commonMain/kotlin/ai/ciris/mobile/shared/CIRISApp.kt @@ -458,29 +458,6 @@ fun CIRISApp( TestAutomation.setCurrentScreen(currentScreen::class.simpleName ?: "unknown") } - // WHAT THIS NODE DECLARES IT CAN DO. - // - // Probed alongside the mode gate and re-probed on a node switch, because a - // different node confers different capabilities and a cached answer from - // the previous one would license the wrong UI. - // - // Starts UNREACHABLE, not UNDECLARED: before the first probe we have not - // asked, and rendering "this node predates capability declarations" before - // asking is the false version diagnosis that state exists to prevent - // (Codex, PR #20). - var nodeCapabilities by remember { - mutableStateOf(ai.ciris.mobile.shared.models.capability.NodeCapabilities.UNREACHABLE) - } - LaunchedEffect(nodeBaseUrl) { - nodeCapabilities = apiClient.getNodeCapabilities(nodeBaseUrl) - platformLog( - TAG, - "[INFO][caps] $nodeBaseUrl declares ${nodeCapabilities.declared?.size ?: "nothing"}" + - if (nodeCapabilities.unreachable) " (unreachable)" else "", - ) - } - - // Handle system back button - navigate back to appropriate parent screen // homeTarget (the probed landing), not Screen.Interact: on the node client the landing surface is // Contacts, and a back press there must fall through to the platform (leave @@ -834,6 +811,39 @@ fun CIRISApp( } } } + // WHAT THE ACTIVE NODE DECLARES IT CAN DO. + // + // Keyed on the ACTIVE PROFILE, not the `nodeBaseUrl` parameter. + // `NodeSwitcherViewModel.switchTo` repoints `apiClient.baseUrl` and + // `activeProfileId`; the CIRISApp parameter is fixed for the composition and + // never moves. Keying on it meant the probe did not re-run on a switch and + // the verify screen's per-node state never reset — so one registry's + // registered/revoked verdict could be presented as the selected node's + // answer (Codex, PR #20). The VM's own docs say it: reacting to + // `activeProfile` is the screen's responsibility. + // + // This is the second time I have reached for the immutable parameter where + // the mutable value was needed; the reset home resolution was the first. + val activeProfileId by nodeSwitcherViewModel.activeProfileId.collectAsState() + val effectiveNodeUrl = nodeSwitcherViewModel.activeProfile + ?.baseUrl?.takeIf { it.isNotBlank() } ?: nodeBaseUrl + + // A one-shot probe strands the UI: UNREACHABLE and UNDETERMINED are both + // transient, the copy tells the operator to try again, and nothing could. + var capabilityProbeAttempt by remember { mutableStateOf(0) } + var nodeCapabilities by remember(effectiveNodeUrl) { + mutableStateOf(ai.ciris.mobile.shared.models.capability.NodeCapabilities.UNREACHABLE) + } + LaunchedEffect(effectiveNodeUrl, activeProfileId, capabilityProbeAttempt) { + nodeCapabilities = apiClient.getNodeCapabilities(effectiveNodeUrl) + platformLog( + TAG, + "[INFO][caps] $effectiveNodeUrl declares ${nodeCapabilities.declared?.size ?: "nothing"}" + + if (nodeCapabilities.unreachable) " (unreachable)" else "" + + if (nodeCapabilities.undetermined) " (undetermined)" else "", + ) + } + // Catch-up: an existing logged-in owner whose local node has NO fed-ID // (legacy WA claim) must be auto-presented the guided Add Federation ID flow // after login — the startup owned-nodes projection ran UNAUTHENTICATED (or @@ -3616,9 +3626,14 @@ fun CIRISApp( PlatformLogger.d(TAG, "[Screen.VerifyAgent] caps=${nodeCapabilities.state(ai.ciris.mobile.shared.models.capability.Capability.REGISTRY_LOOKUP)}") VerifyAgentScreen( capabilities = nodeCapabilities, - nodeUrl = nodeBaseUrl, - onLookup = { hash -> apiClient.lookupAgentHash(hash, nodeBaseUrl) }, - onBack = { currentScreen = Screen.Interact }, + nodeUrl = effectiveNodeUrl, + onLookup = { hash -> apiClient.lookupAgentHash(hash, effectiveNodeUrl) }, + onRetryProbe = { capabilityProbeAttempt++ }, + // homeTarget, not Interact: on a bare node the landing + // surface is Contacts and Interact is not in the sidebar, so + // returning there drops a node user onto a screen their node + // cannot serve (Codex, PR #20). + onBack = { currentScreen = Screen.ManageNodes }, ) } @@ -4565,7 +4580,7 @@ fun CIRISApp( Screen.VizSettings -> Screen.Settings Screen.ServerConnection -> Screen.Interact Screen.ClaimNode -> Screen.Interact - Screen.VerifyAgent -> Screen.Interact + Screen.VerifyAgent -> Screen.ManageNodes // Sub-screens of the home (Interact) Screen.Adapters, Screen.Audit, diff --git a/client/shared/src/commonMain/kotlin/ai/ciris/mobile/shared/api/CIRISApiClient.kt b/client/shared/src/commonMain/kotlin/ai/ciris/mobile/shared/api/CIRISApiClient.kt index 7266781..d372453 100644 --- a/client/shared/src/commonMain/kotlin/ai/ciris/mobile/shared/api/CIRISApiClient.kt +++ b/client/shared/src/commonMain/kotlin/ai/ciris/mobile/shared/api/CIRISApiClient.kt @@ -9235,6 +9235,19 @@ class CIRISApiClient( // and the fallback then displayed the hash the OPERATOR TYPED as though // the registry had returned it (Codex, PR #20). On a revocation check // that is the worst possible lie: it shows their input confirmed. + // AND IT MUST BE THE HASH WE ASKED ABOUT. Rejecting only a blank one + // still accepted a record for a DIFFERENT build and showed its verdict + // beside the operator's query — and hashes are long and visually similar, + // so displaying the returned value is not enough to catch it + // (Codex, PR #20). + if (returnedHash.isNotBlank() && + !returnedHash.equals(agentHash.trim(), ignoreCase = true) + ) { + logInfo(method, "registry answered for a different hash than asked") + return ai.ciris.mobile.shared.models.capability.LookupResult.Unavailable( + "the node answered about a different build than the one asked about" + ) + } if (returnedHash.isBlank()) { logInfo(method, "registry returned a record without a hash — not rendering it as an answer") return ai.ciris.mobile.shared.models.capability.LookupResult.Unavailable( diff --git a/client/shared/src/commonMain/kotlin/ai/ciris/mobile/shared/ui/screens/VerifyAgentScreen.kt b/client/shared/src/commonMain/kotlin/ai/ciris/mobile/shared/ui/screens/VerifyAgentScreen.kt index 7770d25..9963473 100644 --- a/client/shared/src/commonMain/kotlin/ai/ciris/mobile/shared/ui/screens/VerifyAgentScreen.kt +++ b/client/shared/src/commonMain/kotlin/ai/ciris/mobile/shared/ui/screens/VerifyAgentScreen.kt @@ -60,6 +60,7 @@ import androidx.compose.ui.unit.sp fun VerifyAgentCapabilityNotice( capabilities: NodeCapabilities, modifier: Modifier = Modifier, + onRetry: (() -> Unit)? = null, ) { val state = capabilities.state(Capability.REGISTRY_LOOKUP) if (state == CapabilityState.PRESENT) return @@ -104,6 +105,20 @@ fun VerifyAgentCapabilityNotice( fontSize = 13.sp, color = MaterialTheme.colorScheme.onSurfaceVariant, ) + // Only the transient states get a retry. Offering one for ABSENT or + // UNDECLARED would invite the operator to keep pressing a button + // that cannot change the answer. + if (onRetry != null && + (state == CapabilityState.UNREACHABLE || state == CapabilityState.UNDETERMINED) + ) { + Spacer(Modifier.height(8.dp)) + Button( + onClick = onRetry, + modifier = Modifier.testableClickable("btn_verify_retry_probe") { onRetry() }, + ) { + Text(localizedString("mobile.verify_retry")) + } + } } } } @@ -195,6 +210,8 @@ fun VerifyAgentScreen( /** Which node answers. Also the identity the result belongs to — see below. */ nodeUrl: String, onLookup: suspend (String) -> LookupResult, + /** Re-probe the node's declaration — only offered for the transient states. */ + onRetryProbe: (() -> Unit)? = null, onBack: () -> Unit, modifier: Modifier = Modifier, ) { @@ -226,7 +243,7 @@ fun VerifyAgentScreen( // Says which of UNDECLARED / ABSENT / UNREACHABLE applies, and returns // nothing at all when the capability is PRESENT. - VerifyAgentCapabilityNotice(capabilities) + VerifyAgentCapabilityNotice(capabilities, onRetry = onRetryProbe) if (usable) { OutlinedTextField( diff --git a/client/shared/src/desktopMain/resources/localization/en.json b/client/shared/src/desktopMain/resources/localization/en.json index 9d06947..f7da724 100644 --- a/client/shared/src/desktopMain/resources/localization/en.json +++ b/client/shared/src/desktopMain/resources/localization/en.json @@ -3013,7 +3013,8 @@ "verify_unavailable_title": "Could not check", "verify_unavailable_body": "This is not the same as 'not registered' — the registry did not answer.", "verify_undetermined_title": "This node could not determine what it can do", - "verify_undetermined_body": "The node answered, but could not read its own key record. This is usually temporary — try again shortly." + "verify_undetermined_body": "The node answered, but could not read its own key record. This is usually temporary — try again shortly.", + "verify_retry": "Check again" }, "moderation": { "ladder": { From 41e5fa0202f2df3169d5f1346dbf74a8bd8bd5d7 Mon Sep 17 00:00:00 2001 From: Eric Moore Date: Fri, 28 Aug 2026 19:21:16 -0500 Subject: [PATCH 08/18] fix(portal): I traded a stale node for a wrong one MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit THE ACTIVE-PROFILE FIX BROKE THE CONFIGURED NODE. `NodeSwitcherViewModel.reload()` synthesizes an initial profile hard-coded to 127.0.0.1:4243, so preferring `activeProfile` outright replaced the CONFIGURED node — the browser origin on wasm, CIRIS_NODE_URL on desktop — with localhost when nobody had switched anything. Verification became unavailable in a browser, and a local registry's verdict could be attributed to a remote node (Codex, PR #20). The three revisions read as one lesson: first nodeBaseUrl a parameter that never changes -> stale second activeProfile a default nobody chose -> wrong now activeProfile AFTER an explicit switch, else nodeBaseUrl Over-correction is its own failure mode, and this is what it looks like: I fixed staleness by reaching for the other value in scope without asking whether it meant what I needed. The first profile id is captured on entry and the profile preferred only once the active id has moved off it. RETRY FOR EVERY NON-PRESENT STATE. I withheld it from ABSENT and UNDECLARED, reasoning that pressing again cannot change a settled answer. It can: an operator upgrades the node or installs registry support at the SAME URL, and the probe result survives leaving and reopening the screen — so the form stayed unavailable for the rest of the session on a node that had just gained the capability. A RESULT MUST BELONG TO THE HASH THAT WAS SUBMITTED. The field stays editable while a lookup runs, so submitting A and typing B left A's coroutine to write its answer under a field showing B. The returned-hash check cannot catch that — the response correctly matches A. The submitted value is captured and the completion discarded if the field has moved on. Translations for the 21 verify ids remain outstanding and are the CI blocker. Refs CIRISServer#499. Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_01EGE52kPzjGFiPzGcs63ZC1 --- client/VENDORING.md | 2 +- .../kotlin/ai/ciris/mobile/shared/CIRISApp.kt | 19 ++++++- .../shared/ui/screens/VerifyAgentScreen.kt | 52 ++++++++++--------- 3 files changed, 46 insertions(+), 27 deletions(-) diff --git a/client/VENDORING.md b/client/VENDORING.md index be987eb..3058ab8 100644 --- a/client/VENDORING.md +++ b/client/VENDORING.md @@ -40,7 +40,7 @@ source is the pair a bisect wants: The tree's current recorded state — sha256-of-sha256s over every git-tracked file under `client/` except this one: -**state digest:** `dbe8ef405fb05ba8e1dde3b8cf20160fc4fdfdada0314d0945ecfde53bccdb16` +**state digest:** `80193d3a1f07e16403c32ae22d2edc74ea2adbbfa98b2de8f42c7ff3a321f9fe` `packaging/check_vendoring.py` asserts it on every push, and refuses any tracked file matching a §2 never-vendor class. **Any commit that touches diff --git a/client/shared/src/commonMain/kotlin/ai/ciris/mobile/shared/CIRISApp.kt b/client/shared/src/commonMain/kotlin/ai/ciris/mobile/shared/CIRISApp.kt index f97bf24..ce538a6 100644 --- a/client/shared/src/commonMain/kotlin/ai/ciris/mobile/shared/CIRISApp.kt +++ b/client/shared/src/commonMain/kotlin/ai/ciris/mobile/shared/CIRISApp.kt @@ -825,8 +825,23 @@ fun CIRISApp( // This is the second time I have reached for the immutable parameter where // the mutable value was needed; the reset home resolution was the first. val activeProfileId by nodeSwitcherViewModel.activeProfileId.collectAsState() - val effectiveNodeUrl = nodeSwitcherViewModel.activeProfile - ?.baseUrl?.takeIf { it.isNotBlank() } ?: nodeBaseUrl + // ONLY AFTER AN EXPLICIT SWITCH. `reload()` synthesizes an initial profile + // hard-coded to 127.0.0.1:4243, so preferring `activeProfile` outright + // replaced the CONFIGURED node — the browser origin on wasm, CIRIS_NODE_URL + // on desktop — with localhost when nobody had switched anything + // (Codex, PR #20). The previous revision used a parameter that never + // changes; this one used a default that was never chosen. Neither is "the + // node in use", which is what the first profile id lets us tell apart. + val firstProfileId = remember { mutableStateOf(null) } + LaunchedEffect(activeProfileId) { + if (firstProfileId.value == null) firstProfileId.value = activeProfileId + } + val switched = activeProfileId != null && activeProfileId != firstProfileId.value + val effectiveNodeUrl = if (switched) { + nodeSwitcherViewModel.activeProfile?.baseUrl?.takeIf { it.isNotBlank() } ?: nodeBaseUrl + } else { + nodeBaseUrl + } // A one-shot probe strands the UI: UNREACHABLE and UNDETERMINED are both // transient, the copy tells the operator to try again, and nothing could. diff --git a/client/shared/src/commonMain/kotlin/ai/ciris/mobile/shared/ui/screens/VerifyAgentScreen.kt b/client/shared/src/commonMain/kotlin/ai/ciris/mobile/shared/ui/screens/VerifyAgentScreen.kt index 9963473..b75b4d7 100644 --- a/client/shared/src/commonMain/kotlin/ai/ciris/mobile/shared/ui/screens/VerifyAgentScreen.kt +++ b/client/shared/src/commonMain/kotlin/ai/ciris/mobile/shared/ui/screens/VerifyAgentScreen.kt @@ -105,12 +105,14 @@ fun VerifyAgentCapabilityNotice( fontSize = 13.sp, color = MaterialTheme.colorScheme.onSurfaceVariant, ) - // Only the transient states get a retry. Offering one for ABSENT or - // UNDECLARED would invite the operator to keep pressing a button - // that cannot change the answer. - if (onRetry != null && - (state == CapabilityState.UNREACHABLE || state == CapabilityState.UNDETERMINED) - ) { + // EVERY non-PRESENT state gets a retry. I first withheld it from + // ABSENT and UNDECLARED, reasoning that pressing again cannot change + // a settled answer — but an operator can upgrade the node or install + // registry support AT THE SAME URL, and the probe result survives + // leaving and reopening the screen. So those answers are not + // permanent either, and withholding the control left the form + // unavailable for the rest of the session (Codex, PR #20). + if (onRetry != null) { Spacer(Modifier.height(8.dp)) Button( onClick = onRetry, @@ -227,6 +229,24 @@ fun VerifyAgentScreen( var inFlight by remember(nodeUrl) { mutableStateOf(false) } val scope = rememberCoroutineScope() + // THE RESULT MUST BELONG TO THE HASH THAT WAS SUBMITTED. The field stays + // editable while a lookup runs, so submitting A and then typing B left A's + // coroutine to write its answer underneath a field showing B — and the + // API's returned-hash check cannot catch it, because the response correctly + // matches A (Codex, PR #20). The submitted value is captured and the + // completion is discarded if the field has moved on. + val submit: (String) -> Unit = { candidate -> + val submitted = candidate.trim() + if (!inFlight && submitted.isNotBlank()) { + inFlight = true + scope.launch { + val r = onLookup(submitted) + if (hash.trim() == submitted) result = r + inFlight = false + } + } + } + Column( modifier = modifier .fillMaxWidth() @@ -255,27 +275,11 @@ fun VerifyAgentScreen( modifier = Modifier.fillMaxWidth().testable("input_verify_hash"), ) Button( - onClick = { - if (!inFlight && hash.isNotBlank()) { - inFlight = true - scope.launch { - result = onLookup(hash.trim()) - inFlight = false - } - } - }, + onClick = { submit(hash) }, enabled = !inFlight && hash.isNotBlank(), modifier = Modifier .fillMaxWidth() - .testableClickable("btn_verify_submit") { - if (!inFlight && hash.isNotBlank()) { - inFlight = true - scope.launch { - result = onLookup(hash.trim()) - inFlight = false - } - } - }, + .testableClickable("btn_verify_submit") { submit(hash) }, ) { Text(localizedString("mobile.verify_button")) } From 7acd0e7fc791055608f145c30d801e8480087a81 Mon Sep 17 00:00:00 2001 From: Eric Moore Date: Fri, 28 Aug 2026 19:24:53 -0500 Subject: [PATCH 09/18] fix(i18n): stop stacking abstractions before saying anything Yoruba rejected `verify_absent_body` for clumsy, redundant phrasing, and the English earns it: "Build verification is part of the registry, and this node does not carry it" puts two nominalizations in front of the reader before any concrete claim, and Yoruba has to render both as compounds. This node does not carry the registry, so it cannot check builds. Another node can. One concrete clause, then one. Fourth time this session the translation blocker was English that a reader could parse and a translator could not commit to. Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_01EGE52kPzjGFiPzGcs63ZC1 --- client/VENDORING.md | 2 +- client/androidApp/src/main/assets/localization/en.json | 2 +- client/desktopApp/src/main/resources/localization/en.json | 2 +- client/iosApp/iosApp/localization/en.json | 2 +- client/shared/src/desktopMain/resources/localization/en.json | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/client/VENDORING.md b/client/VENDORING.md index 3058ab8..f54882e 100644 --- a/client/VENDORING.md +++ b/client/VENDORING.md @@ -40,7 +40,7 @@ source is the pair a bisect wants: The tree's current recorded state — sha256-of-sha256s over every git-tracked file under `client/` except this one: -**state digest:** `80193d3a1f07e16403c32ae22d2edc74ea2adbbfa98b2de8f42c7ff3a321f9fe` +**state digest:** `8cc357ae7b2d74c740843df5fc46068ac9e2d406e540712b326e2f6aa2e7d314` `packaging/check_vendoring.py` asserts it on every push, and refuses any tracked file matching a §2 never-vendor class. **Any commit that touches diff --git a/client/androidApp/src/main/assets/localization/en.json b/client/androidApp/src/main/assets/localization/en.json index f7da724..6c59a7b 100644 --- a/client/androidApp/src/main/assets/localization/en.json +++ b/client/androidApp/src/main/assets/localization/en.json @@ -3000,7 +3000,7 @@ "verify_undeclared_title": "This node cannot say whether it verifies builds", "verify_undeclared_body": "This node is older than the capability declaration, so it cannot say. A newer node can verify builds.", "verify_absent_title": "This node does not verify builds", - "verify_absent_body": "Build verification is part of the registry, and this node does not carry it. A node that does can answer the same question.", + "verify_absent_body": "This node does not carry the registry, so it cannot check builds. Another node can.", "verify_unreachable_title": "Could not reach this node", "verify_unreachable_body": "The node did not answer, so we do not know whether it can verify builds. This is not a problem with the build you are checking.", "verify_status_registered": "Registered", diff --git a/client/desktopApp/src/main/resources/localization/en.json b/client/desktopApp/src/main/resources/localization/en.json index f7da724..6c59a7b 100644 --- a/client/desktopApp/src/main/resources/localization/en.json +++ b/client/desktopApp/src/main/resources/localization/en.json @@ -3000,7 +3000,7 @@ "verify_undeclared_title": "This node cannot say whether it verifies builds", "verify_undeclared_body": "This node is older than the capability declaration, so it cannot say. A newer node can verify builds.", "verify_absent_title": "This node does not verify builds", - "verify_absent_body": "Build verification is part of the registry, and this node does not carry it. A node that does can answer the same question.", + "verify_absent_body": "This node does not carry the registry, so it cannot check builds. Another node can.", "verify_unreachable_title": "Could not reach this node", "verify_unreachable_body": "The node did not answer, so we do not know whether it can verify builds. This is not a problem with the build you are checking.", "verify_status_registered": "Registered", diff --git a/client/iosApp/iosApp/localization/en.json b/client/iosApp/iosApp/localization/en.json index f7da724..6c59a7b 100644 --- a/client/iosApp/iosApp/localization/en.json +++ b/client/iosApp/iosApp/localization/en.json @@ -3000,7 +3000,7 @@ "verify_undeclared_title": "This node cannot say whether it verifies builds", "verify_undeclared_body": "This node is older than the capability declaration, so it cannot say. A newer node can verify builds.", "verify_absent_title": "This node does not verify builds", - "verify_absent_body": "Build verification is part of the registry, and this node does not carry it. A node that does can answer the same question.", + "verify_absent_body": "This node does not carry the registry, so it cannot check builds. Another node can.", "verify_unreachable_title": "Could not reach this node", "verify_unreachable_body": "The node did not answer, so we do not know whether it can verify builds. This is not a problem with the build you are checking.", "verify_status_registered": "Registered", diff --git a/client/shared/src/desktopMain/resources/localization/en.json b/client/shared/src/desktopMain/resources/localization/en.json index f7da724..6c59a7b 100644 --- a/client/shared/src/desktopMain/resources/localization/en.json +++ b/client/shared/src/desktopMain/resources/localization/en.json @@ -3000,7 +3000,7 @@ "verify_undeclared_title": "This node cannot say whether it verifies builds", "verify_undeclared_body": "This node is older than the capability declaration, so it cannot say. A newer node can verify builds.", "verify_absent_title": "This node does not verify builds", - "verify_absent_body": "Build verification is part of the registry, and this node does not carry it. A node that does can answer the same question.", + "verify_absent_body": "This node does not carry the registry, so it cannot check builds. Another node can.", "verify_unreachable_title": "Could not reach this node", "verify_unreachable_body": "The node did not answer, so we do not know whether it can verify builds. This is not a problem with the build you are checking.", "verify_status_registered": "Registered", From 096196ba7e478767534923364d4c9fad2f18f05f Mon Sep 17 00:00:00 2001 From: Eric Moore Date: Fri, 28 Aug 2026 19:33:49 -0500 Subject: [PATCH 10/18] fix(portal): a switch is an event, not an inequality MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Switching away from the initial profile and back to it made `activeProfileId == firstProfileId` again, so the branch read a REAL switch as "never switched" and restored the startup URL — while `switchTo` had already repointed `apiClient` at the profile the operator chose. The probe and lookup then queried the original node and could attribute its verdict to the selected one (Codex, PR #20). Choosing the local profile deliberately is a choice, and it has to be honoured as one. `hasSwitchedNode` latches on the first real change and stays true: after that the operator owns the selection, including when the selection is the profile they started on. Fourth revision of this one expression, and each was the same mistake in a different coat — reading state instead of observing the event that changed it: nodeBaseUrl a parameter that never changes activeProfile a default nobody chose activeProfileId != first an event inferred from a value hasSwitchedNode the event Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_01EGE52kPzjGFiPzGcs63ZC1 --- client/VENDORING.md | 2 +- .../kotlin/ai/ciris/mobile/shared/CIRISApp.kt | 17 +++++++++++++++-- 2 files changed, 16 insertions(+), 3 deletions(-) diff --git a/client/VENDORING.md b/client/VENDORING.md index f54882e..f783b7e 100644 --- a/client/VENDORING.md +++ b/client/VENDORING.md @@ -40,7 +40,7 @@ source is the pair a bisect wants: The tree's current recorded state — sha256-of-sha256s over every git-tracked file under `client/` except this one: -**state digest:** `8cc357ae7b2d74c740843df5fc46068ac9e2d406e540712b326e2f6aa2e7d314` +**state digest:** `21e19b3292ba4da54656ffa34c2f9172d16d6e81ba0bd619c954fe00727902e8` `packaging/check_vendoring.py` asserts it on every push, and refuses any tracked file matching a §2 never-vendor class. **Any commit that touches diff --git a/client/shared/src/commonMain/kotlin/ai/ciris/mobile/shared/CIRISApp.kt b/client/shared/src/commonMain/kotlin/ai/ciris/mobile/shared/CIRISApp.kt index ce538a6..2df14de 100644 --- a/client/shared/src/commonMain/kotlin/ai/ciris/mobile/shared/CIRISApp.kt +++ b/client/shared/src/commonMain/kotlin/ai/ciris/mobile/shared/CIRISApp.kt @@ -832,11 +832,24 @@ fun CIRISApp( // (Codex, PR #20). The previous revision used a parameter that never // changes; this one used a default that was never chosen. Neither is "the // node in use", which is what the first profile id lets us tell apart. + // A LATCH, NOT A COMPARISON. Inferring "did a switch happen" from + // `activeProfileId != firstProfileId` makes switching away and BACK to the + // first profile indistinguishable from never having switched — so the probe + // restored the startup URL while `apiClient` pointed at the profile the + // operator had just chosen (Codex, PR #20). Choosing the local profile + // deliberately is a real choice and must be honoured as one. + // + // Once a switch has occurred the operator owns the selection, permanently. val firstProfileId = remember { mutableStateOf(null) } + var hasSwitchedNode by remember { mutableStateOf(false) } LaunchedEffect(activeProfileId) { - if (firstProfileId.value == null) firstProfileId.value = activeProfileId + if (firstProfileId.value == null) { + firstProfileId.value = activeProfileId + } else if (activeProfileId != firstProfileId.value) { + hasSwitchedNode = true + } } - val switched = activeProfileId != null && activeProfileId != firstProfileId.value + val switched = hasSwitchedNode val effectiveNodeUrl = if (switched) { nodeSwitcherViewModel.activeProfile?.baseUrl?.takeIf { it.isNotBlank() } ?: nodeBaseUrl } else { From 36854aa854118c0f6438d050a4774e980d1c0ba5 Mon Sep 17 00:00:00 2001 From: Eric Moore Date: Fri, 28 Aug 2026 19:50:56 -0500 Subject: [PATCH 11/18] fix(i18n): do not put an undeclared term of art in front of 28 translators MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Two rejections, both legitimately translation-side this time — and both point at the same gap. yo "Deprecated" rendered as "abandoned/left"; the reviewer says UI Yoruba wants "no longer recommended / to be phased out" am "Do not run it." rendered as "do not OPEN it" — executing and opening are different acts, and this warning is about executing "Deprecated" is a term of art and it is NOT in the glossaries: `[DEPRECATED]` in there is my pipeline's retirement marker, not the status. The apparent fix is to add a row to all 29 — which means coining a rendering in 28 languages I do not speak, exactly what TRANSLATION_GUIDE.md §3 forbids and what the glossaries exist to prevent. So say the thing instead of the term: Deprecated -> No longer recommended ... Do not run it. -> ... Do not use it. The first is what the Yoruba reviewer said the word should mean, which makes it a better English label as well — the registry's own token still appears verbatim for statuses this client cannot map, so fidelity is not lost. The second drops a run/open distinction that English carries in one word and many languages split. Fifth time this session, and the rule has held every time: a word that needs a footnote in one language needs one in twenty-eight. Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_01EGE52kPzjGFiPzGcs63ZC1 --- client/VENDORING.md | 2 +- client/androidApp/src/main/assets/localization/en.json | 4 ++-- client/desktopApp/src/main/resources/localization/en.json | 4 ++-- client/iosApp/iosApp/localization/en.json | 4 ++-- client/shared/src/desktopMain/resources/localization/en.json | 4 ++-- 5 files changed, 9 insertions(+), 9 deletions(-) diff --git a/client/VENDORING.md b/client/VENDORING.md index f783b7e..498ab2f 100644 --- a/client/VENDORING.md +++ b/client/VENDORING.md @@ -40,7 +40,7 @@ source is the pair a bisect wants: The tree's current recorded state — sha256-of-sha256s over every git-tracked file under `client/` except this one: -**state digest:** `21e19b3292ba4da54656ffa34c2f9172d16d6e81ba0bd619c954fe00727902e8` +**state digest:** `a98348d45e2ec434ef6b949838d105fc9672b5dcb2f992334767347f45a4e2a8` `packaging/check_vendoring.py` asserts it on every push, and refuses any tracked file matching a §2 never-vendor class. **Any commit that touches diff --git a/client/androidApp/src/main/assets/localization/en.json b/client/androidApp/src/main/assets/localization/en.json index 6c59a7b..92cae19 100644 --- a/client/androidApp/src/main/assets/localization/en.json +++ b/client/androidApp/src/main/assets/localization/en.json @@ -3004,10 +3004,10 @@ "verify_unreachable_title": "Could not reach this node", "verify_unreachable_body": "The node did not answer, so we do not know whether it can verify builds. This is not a problem with the build you are checking.", "verify_status_registered": "Registered", - "verify_status_deprecated": "Deprecated", + "verify_status_deprecated": "No longer recommended", "verify_status_revoked": "Revoked", "verify_status_unreadable": "Status not recognised", - "verify_revoked_warning": "This build has been revoked. Do not run it.", + "verify_revoked_warning": "This build has been revoked. Do not use it.", "verify_not_found_title": "No record of this build", "verify_not_found_body": "The registry answered and holds nothing for this hash.", "verify_unavailable_title": "Could not check", diff --git a/client/desktopApp/src/main/resources/localization/en.json b/client/desktopApp/src/main/resources/localization/en.json index 6c59a7b..92cae19 100644 --- a/client/desktopApp/src/main/resources/localization/en.json +++ b/client/desktopApp/src/main/resources/localization/en.json @@ -3004,10 +3004,10 @@ "verify_unreachable_title": "Could not reach this node", "verify_unreachable_body": "The node did not answer, so we do not know whether it can verify builds. This is not a problem with the build you are checking.", "verify_status_registered": "Registered", - "verify_status_deprecated": "Deprecated", + "verify_status_deprecated": "No longer recommended", "verify_status_revoked": "Revoked", "verify_status_unreadable": "Status not recognised", - "verify_revoked_warning": "This build has been revoked. Do not run it.", + "verify_revoked_warning": "This build has been revoked. Do not use it.", "verify_not_found_title": "No record of this build", "verify_not_found_body": "The registry answered and holds nothing for this hash.", "verify_unavailable_title": "Could not check", diff --git a/client/iosApp/iosApp/localization/en.json b/client/iosApp/iosApp/localization/en.json index 6c59a7b..92cae19 100644 --- a/client/iosApp/iosApp/localization/en.json +++ b/client/iosApp/iosApp/localization/en.json @@ -3004,10 +3004,10 @@ "verify_unreachable_title": "Could not reach this node", "verify_unreachable_body": "The node did not answer, so we do not know whether it can verify builds. This is not a problem with the build you are checking.", "verify_status_registered": "Registered", - "verify_status_deprecated": "Deprecated", + "verify_status_deprecated": "No longer recommended", "verify_status_revoked": "Revoked", "verify_status_unreadable": "Status not recognised", - "verify_revoked_warning": "This build has been revoked. Do not run it.", + "verify_revoked_warning": "This build has been revoked. Do not use it.", "verify_not_found_title": "No record of this build", "verify_not_found_body": "The registry answered and holds nothing for this hash.", "verify_unavailable_title": "Could not check", diff --git a/client/shared/src/desktopMain/resources/localization/en.json b/client/shared/src/desktopMain/resources/localization/en.json index 6c59a7b..92cae19 100644 --- a/client/shared/src/desktopMain/resources/localization/en.json +++ b/client/shared/src/desktopMain/resources/localization/en.json @@ -3004,10 +3004,10 @@ "verify_unreachable_title": "Could not reach this node", "verify_unreachable_body": "The node did not answer, so we do not know whether it can verify builds. This is not a problem with the build you are checking.", "verify_status_registered": "Registered", - "verify_status_deprecated": "Deprecated", + "verify_status_deprecated": "No longer recommended", "verify_status_revoked": "Revoked", "verify_status_unreadable": "Status not recognised", - "verify_revoked_warning": "This build has been revoked. Do not run it.", + "verify_revoked_warning": "This build has been revoked. Do not use it.", "verify_not_found_title": "No record of this build", "verify_not_found_body": "The registry answered and holds nothing for this hash.", "verify_unavailable_title": "Could not check", From 96850b13089a5cb155e916106be976864984794f Mon Sep 17 00:00:00 2001 From: Eric Moore Date: Fri, 28 Aug 2026 20:06:09 -0500 Subject: [PATCH 12/18] feat(capability): one reader for the wire contract, written to be quoted MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Three repos now have an opinion about what silence means on a capability list — CIRISServer declares conferred scopes in `src/conformance.rs`, CIRISAgent is proposing an agent-tier field on `/v1/system/health`, and this client renders both. `CapabilityWire` is the single reader, written so the other two can read it instead of coining a third interpretation. FOUR WIRE SHAPES, ENUMERATED RATHER THAN INFERRED: field absent UNDECLARED an older peer — upgrade it "field": null UNDETERMINED it could not read its own record — retry "field": [] ABSENT it read, and holds nothing — another peer "field": [ ... ] membership proceed Four facts, four remedies. Collapsing any pair produces a confident wrong answer instead of a missing one, and this reader's first version collapsed two: it matched only the array form, so `null` read as a missing field and the UI told a CURRENT node's operator to upgrade. CIRISServer's own field comment is what caught it, and it is quoted in the source here so the reason travels with the rule. A fifth state, UNREACHABLE, is OUR side failing to ask — transport, a non-success status, a body that will not parse. It never arrives from the wire. REAL JSON, NOT A REGEX. The previous reader pattern-matched the document, which is how a list carrying a non-string would have been silently narrowed to the entries it could read — reporting a SMALLER declaration than the peer made, which is a confident wrong answer about authority. Anything unreadable is now UNREACHABLE, including a partially readable list. PROVENANCE IS NOT MERGED. `parse` takes the field NAME because conferred scopes and agent features are different authorities: one is signed by the trust root and enforced by the node, the other is a property of the running brain that nothing attests. CIRISServer refuses that laundering at its own tier — "a locally-detected capability is a different authority and is not laundered through this list" — and a union at the agent tier would be the same act one floor up. FIELD_AGENT is named distinctly for the same reason: `/v1/system/health` is the node's health merged with the brain's, so a bare `capabilities` there could not be attributed to either tier by a reader holding only the parsed set. The test file is the specification: every shape, the state it yields, and the remedy that state implies. A shape the other repos emit that is not listed there is the gap to close. Refs CIRISServer#499. Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_01EGE52kPzjGFiPzGcs63ZC1 --- client/VENDORING.md | 2 +- .../ciris/mobile/shared/api/CIRISApiClient.kt | 38 ++--- .../models/capability/CapabilityWire.kt | 131 +++++++++++++++++ .../models/capability/CapabilityWireTest.kt | 135 ++++++++++++++++++ 4 files changed, 275 insertions(+), 31 deletions(-) create mode 100644 client/shared/src/commonMain/kotlin/ai/ciris/mobile/shared/models/capability/CapabilityWire.kt create mode 100644 client/shared/src/commonTest/kotlin/ai/ciris/mobile/shared/models/capability/CapabilityWireTest.kt diff --git a/client/VENDORING.md b/client/VENDORING.md index 498ab2f..f9a4be1 100644 --- a/client/VENDORING.md +++ b/client/VENDORING.md @@ -40,7 +40,7 @@ source is the pair a bisect wants: The tree's current recorded state — sha256-of-sha256s over every git-tracked file under `client/` except this one: -**state digest:** `a98348d45e2ec434ef6b949838d105fc9672b5dcb2f992334767347f45a4e2a8` +**state digest:** `19fa12f2d104f882c2d0096419b2a5a841dc7c82de9e95a9b92744a173754f6f` `packaging/check_vendoring.py` asserts it on every push, and refuses any tracked file matching a §2 never-vendor class. **Any commit that touches diff --git a/client/shared/src/commonMain/kotlin/ai/ciris/mobile/shared/api/CIRISApiClient.kt b/client/shared/src/commonMain/kotlin/ai/ciris/mobile/shared/api/CIRISApiClient.kt index d372453..41069e5 100644 --- a/client/shared/src/commonMain/kotlin/ai/ciris/mobile/shared/api/CIRISApiClient.kt +++ b/client/shared/src/commonMain/kotlin/ai/ciris/mobile/shared/api/CIRISApiClient.kt @@ -9300,36 +9300,14 @@ class CIRISApiClient( } finally { client.close() } - // `"capabilities": [ "a", "b" ]` — absent array means undeclared, empty - // array means declared-and-holds-nothing. The two are different answers. - // THREE SHAPES, THREE ANSWERS (CIRISServer#499, src/conformance.rs): - // key absent an older node that never had the field - // "capabilities": null the node could not read its own key record - // "capabilities": [...] the conferred set, possibly empty - // - // The server draws the middle distinction on purpose — "'no capabilities' - // and 'could not determine' must not collapse into one answer" — and my - // first parser matched only the array, so an explicit null read as a - // missing key and told a current node's operator to upgrade. - val hasKey = Regex("\"capabilities\"\\s*:").containsMatchIn(body) - val isNull = Regex("\"capabilities\"\\s*:\\s*null").containsMatchIn(body) - val block = Regex("\"capabilities\"\\s*:\\s*\\[([^\\]]*)\\]").find(body) - if (isNull) { - ai.ciris.mobile.shared.models.capability.NodeCapabilities.UNDETERMINED - } else if (block == null) { - if (hasKey) { - // Present but neither null nor an array: we cannot read it, and - // guessing which of the other three it means would be inventing. - ai.ciris.mobile.shared.models.capability.NodeCapabilities.UNREACHABLE - } else { - ai.ciris.mobile.shared.models.capability.NodeCapabilities.UNDECLARED - } - } else { - val ids = Regex("\"([^\"]+)\"").findAll(block.groupValues[1]) - .map { it.groupValues[1] } - .toSet() - ai.ciris.mobile.shared.models.capability.NodeCapabilities(ids) - } + // ONE READER FOR THE WHOLE CONTRACT — see CapabilityWire, which + // enumerates every wire shape and is the reference CIRISServer and + // CIRISAgent read. A second parser here would be a second opinion about + // what silence means, which is the thing that keeps going wrong. + ai.ciris.mobile.shared.models.capability.CapabilityWire.parse( + body, + ai.ciris.mobile.shared.models.capability.CapabilityWire.FIELD_CONFERRED, + ) } catch (e: kotlinx.coroutines.CancellationException) { // Structured concurrency: a cancelled probe must die, not publish state. throw e diff --git a/client/shared/src/commonMain/kotlin/ai/ciris/mobile/shared/models/capability/CapabilityWire.kt b/client/shared/src/commonMain/kotlin/ai/ciris/mobile/shared/models/capability/CapabilityWire.kt new file mode 100644 index 0000000..2ab80a2 --- /dev/null +++ b/client/shared/src/commonMain/kotlin/ai/ciris/mobile/shared/models/capability/CapabilityWire.kt @@ -0,0 +1,131 @@ +package ai.ciris.mobile.shared.models.capability + +import kotlinx.serialization.json.Json +import kotlinx.serialization.json.JsonArray +import kotlinx.serialization.json.JsonNull +import kotlinx.serialization.json.JsonObject +import kotlinx.serialization.json.JsonPrimitive +import kotlinx.serialization.json.jsonObject + +/** + * THE CAPABILITY WIRE CONTRACT, in one place. + * + * A node — and, once CIRISAgent#-tier declaration lands, a folded agent — + * publishes what it can do as a list. This is the only reader of that list in + * the client, and it is written to be the reference the other repos read rather + * than each coining their own: CIRISServer declares it in + * `src/conformance.rs`, CIRISAgent proposes an agent-tier field on + * `/v1/system/health`, and all three of us have to agree on what silence means. + * + * # The four wire shapes, and why four + * + * ``` + * field absent UNDECLARED an older peer that never had the field + * "field": null UNDETERMINED it tried and could not read its own record + * "field": [] ABSENT it read, and holds nothing + * "field": [ ... ] membership the declared set + * ``` + * + * These are four different facts with four different remedies — upgrade the + * peer, retry, use a different peer, proceed — and collapsing any pair produces + * a confident wrong answer rather than a missing one. CIRISServer's own field + * documentation draws the middle line and says why: + * + * > `null` when this node could not read its own key record, which is NOT the + * > same fact as `[]` — "no capabilities" and "could not determine" must not + * > collapse into one answer, or a client renders a transient directory error + * > as a node with no authority. + * + * The first version of this reader matched only the array form, so `null` read + * identically to a missing field and the UI told a CURRENT node's operator that + * their node predates the declaration. That is the collapse, committed by the + * reader whose purpose was to prevent it — which is why the shapes are + * enumerated here explicitly instead of falling out of a regex. + * + * A fifth state, [CapabilityState.UNREACHABLE], is OUR side failing to ask — + * transport, a non-success status, a document that will not parse. It never + * comes from the wire; it is what the caller supplies when there is no document + * to hand this at all. + * + * # Provenance is not merged + * + * [parse] takes the FIELD NAME because conferred scopes and agent features are + * different authorities and must not be unioned. A conferred scope is signed by + * the trust root and enforced by the node; an agent feature is a property of the + * running brain that nothing attests. A client that cannot tell them apart + * cannot tell an operator which remedy applies, and CIRISServer explicitly + * refuses to launder one into the other: + * + * > Conferred only — a locally-detected capability is a different authority and + * > is not laundered through this list. + * + * Read each field separately and keep the results separate. + * + * # Not a security boundary + * + * `TRUST_ROOT_CAPABILITY_GATE.md` §5: "the server enforces the reality whether + * or not the client showed it (the warning informs; the gate binds)." Everything + * this produces is for deciding what to SHOW. A reader that is wrong + * permissively gets refused by the server anyway; wrong restrictively, an + * operator sees a working feature marked unavailable — which is why UNDECLARED + * and UNDETERMINED are never rendered as ABSENT. + */ +object CapabilityWire { + + /** The conferred scopes a node holds. CIRISServer#499, `/v1/federation/conformance`. */ + const val FIELD_CONFERRED = "capabilities" + + /** + * The agent tier's own features, once CIRISAgent lands it on + * `/v1/system/health`. A DISTINCT NAME on purpose: that document is the + * node's health merged with the folded brain's, so a bare `capabilities` + * there could not be attributed to either tier by a reader holding only the + * parsed set. + */ + const val FIELD_AGENT = "agent_capabilities" + + private val json = Json { ignoreUnknownKeys = true; isLenient = true } + + /** + * Read [field] out of [document]. + * + * @param document the raw response body. An empty or unparseable one is + * [CapabilityState.UNREACHABLE] — we did not get a document, which is not + * a statement about the peer. + */ + fun parse(document: String, field: String = FIELD_CONFERRED): NodeCapabilities { + if (document.isBlank()) return NodeCapabilities.UNREACHABLE + + val root: JsonObject = runCatching { + val element = json.parseToJsonElement(document) + // Both envelopes appear in this ecosystem: bare, and `{"data": ...}`. + // Prefer `data` when it is an object, because that is what the + // agent's SuccessResponse wraps everything in. + val obj = element.jsonObject + (obj["data"] as? JsonObject) ?: obj + }.getOrElse { + // A body we cannot parse tells us nothing about the peer's + // capabilities — only that we could not read it. + return NodeCapabilities.UNREACHABLE + } + + // ABSENT KEY: this peer predates the field. + val value = root[field] ?: return NodeCapabilities.UNDECLARED + + // EXPLICIT NULL: the peer answered, and its answer is "I do not know". + if (value is JsonNull) return NodeCapabilities.UNDETERMINED + + // A LIST: the declaration, possibly empty. + if (value is JsonArray) { + val ids = value.mapNotNull { (it as? JsonPrimitive)?.takeIf { p -> p.isString }?.content } + // A list carrying non-strings is malformed in a way we should not + // silently narrow: if anything was dropped, we did not read it. + if (ids.size != value.size) return NodeCapabilities.UNREACHABLE + return NodeCapabilities(ids.toSet()) + } + + // Present, but neither null nor a list. We cannot read it, and guessing + // which of the other three it meant would be inventing an answer. + return NodeCapabilities.UNREACHABLE + } +} diff --git a/client/shared/src/commonTest/kotlin/ai/ciris/mobile/shared/models/capability/CapabilityWireTest.kt b/client/shared/src/commonTest/kotlin/ai/ciris/mobile/shared/models/capability/CapabilityWireTest.kt new file mode 100644 index 0000000..c232328 --- /dev/null +++ b/client/shared/src/commonTest/kotlin/ai/ciris/mobile/shared/models/capability/CapabilityWireTest.kt @@ -0,0 +1,135 @@ +package ai.ciris.mobile.shared.models.capability + +import kotlin.test.Test +import kotlin.test.assertEquals + +/** + * THE CONTRACT, ENUMERATED. + * + * These cases are the specification other repos can read: every wire shape, the + * state it produces, and the operator remedy that state implies. If CIRISServer + * or CIRISAgent emit a shape not listed here, that is the gap to close — in + * this file first, then in the reader. + */ +class CapabilityWireTest { + + private fun state(doc: String, field: String = CapabilityWire.FIELD_CONFERRED) = + CapabilityWire.parse(doc, field).state(Capability.REGISTRY_LOOKUP) + + // ── the four wire shapes ──────────────────────────────────────────────── + + @Test + fun field_absent_is_an_older_peer() { + // Remedy: upgrade the peer. Every node released before CIRISServer#499. + assertEquals( + CapabilityState.UNDECLARED, + state("""{"build_profiles":["CCP","CCC","CCS"]}"""), + ) + } + + @Test + fun explicit_null_is_the_peer_saying_it_does_not_know() { + // Remedy: retry. The peer answered; it could not read its own record. + // NOT the same as an older peer, and rendering it as one tells an + // operator to upgrade a node that is already current. + assertEquals(CapabilityState.UNDETERMINED, state("""{"capabilities":null}""")) + } + + @Test + fun empty_list_is_a_declaration_of_nothing() { + // Remedy: use a peer that carries it. The peer read its record and holds + // no capabilities — a real answer, not a silence. + assertEquals(CapabilityState.ABSENT, state("""{"capabilities":[]}""")) + } + + @Test + fun a_list_is_membership() { + assertEquals( + CapabilityState.PRESENT, + state("""{"capabilities":["infra:attest","infra:serve","registry:lookup"]}"""), + ) + assertEquals( + CapabilityState.ABSENT, + state("""{"capabilities":["infra:serve"]}"""), + ) + } + + // ── envelopes ─────────────────────────────────────────────────────────── + + @Test + fun both_envelopes_are_read() { + // Bare, and the agent's SuccessResponse `{"data": ...}` wrapper. + val ids = """["registry:lookup"]""" + assertEquals(CapabilityState.PRESENT, state("""{"capabilities":$ids}""")) + assertEquals(CapabilityState.PRESENT, state("""{"data":{"capabilities":$ids}}""")) + } + + // ── provenance is not merged ──────────────────────────────────────────── + + @Test + fun the_agent_field_is_read_separately_from_the_conferred_one() { + // A conferred scope is signed by the trust root; an agent feature is a + // property of the running brain. Different authorities, different + // remedies, so they are never unioned — CIRISServer refuses the same + // laundering at its own tier. + val doc = """{"capabilities":["infra:serve"],"agent_capabilities":["registry:lookup"]}""" + assertEquals(CapabilityState.ABSENT, state(doc, CapabilityWire.FIELD_CONFERRED)) + assertEquals(CapabilityState.PRESENT, state(doc, CapabilityWire.FIELD_AGENT)) + } + + @Test + fun each_field_carries_its_own_four_states() { + // The agent tier gets the same discipline, or the collapse reappears one + // layer up. + assertEquals(CapabilityState.UNDECLARED, state("""{"capabilities":[]}""", CapabilityWire.FIELD_AGENT)) + assertEquals(CapabilityState.UNDETERMINED, state("""{"agent_capabilities":null}""", CapabilityWire.FIELD_AGENT)) + } + + // ── we could not ask ──────────────────────────────────────────────────── + + @Test + fun a_document_we_cannot_read_says_nothing_about_the_peer() { + for (doc in listOf("", " ", "not json", "{unclosed", "[]")) { + assertEquals(CapabilityState.UNREACHABLE, state(doc), "doc=$doc") + } + } + + @Test + fun a_field_that_is_neither_null_nor_a_list_is_unreadable_not_guessed() { + for (doc in listOf( + """{"capabilities":"registry:lookup"}""", + """{"capabilities":42}""", + """{"capabilities":{"registry":true}}""", + )) { + assertEquals(CapabilityState.UNREACHABLE, state(doc), "doc=$doc") + } + } + + @Test + fun a_list_carrying_non_strings_is_not_silently_narrowed() { + // Dropping the unreadable entries would report a SMALLER declaration + // than the peer made, which is a confident wrong answer about authority. + assertEquals( + CapabilityState.UNREACHABLE, + state("""{"capabilities":["registry:lookup",42]}"""), + ) + } + + // ── the whole point ───────────────────────────────────────────────────── + + @Test + fun the_five_not_usable_answers_stay_distinct() { + val seen = listOf( + state("""{"other":1}"""), // UNDECLARED + state("""{"capabilities":null}"""), // UNDETERMINED + state("""{"capabilities":[]}"""), // ABSENT + state("not json"), // UNREACHABLE + ) + assertEquals(seen.size, seen.toSet().size, "four shapes must not collapse into fewer states") + assertEquals( + CapabilityState.PRESENT, + state("""{"capabilities":["registry:lookup"]}"""), + "and the fifth is the only one that renders the feature", + ) + } +} From f3b12ad73417008fa015dd6238129df5555f2d7f Mon Sep 17 00:00:00 2001 From: Eric Moore Date: Fri, 28 Aug 2026 20:14:00 -0500 Subject: [PATCH 13/18] fix(i18n): stop binning the whole lane because one pair came back clumsy MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Seven runs on this branch. Each one translated 21 keys into 28 languages, each one had exactly ONE pair rejected — a different pair every time — and each one threw away the other 587 and cost a full lane to do it. That is the entire reason this branch has been stuck, and it was avoidable from the second run. WHAT WAS HAPPENING `localize.py` wrote every value, accepted and rejected alike, then exited 1. The job failed at that step, so Guard, digest and Commit never ran, and the runner was torn down with all the good translations still on its disk. Nothing was banked. The next run started from zero and rolled the dice again. WHAT CHANGES localize.py writes ONLY accepted values; rejected and unresolved keys are withheld, not written the workflow runs Guard, digest and Commit with always(), so the accepted values are committed even though the lane exited 1 WHAT DOES NOT CHANGE — and this is why it is safe: - A rejected value is still never written. Nothing semantically bad reaches a bundle, and English still never appears under a non-English locale. - The run still exits 1. It is still red, still visible, still fails the branch. - The withheld key stays MISSING, so the strict guard still blocks the merge until it is filled — the same block, from the same gate, for the same reason. The only thing that changes is that a run keeps what it earned. The next run has one key to redo instead of 588. I raised this twice as "a change to a guarantee you specified" and deferred it both times. That framing was wrong: the guarantee is that rejected translations do not ship, and withholding them honours it more exactly than writing them and discarding the run did. I should have fixed it at the second failure instead of re-rolling five more times. Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_01EGE52kPzjGFiPzGcs63ZC1 --- .github/workflows/i18n-lane.yml | 13 +++++++++++-- localization/localize.py | 27 ++++++++++++++++++++++++--- 2 files changed, 35 insertions(+), 5 deletions(-) diff --git a/.github/workflows/i18n-lane.yml b/.github/workflows/i18n-lane.yml index 45fe2f7..95fb3b5 100644 --- a/.github/workflows/i18n-lane.yml +++ b/.github/workflows/i18n-lane.yml @@ -138,6 +138,10 @@ jobs: path: i18n-report.json - name: Guard (strict) — the actual gate + # always(), so a lane that exited 1 still gets its bundles checked and + # the operator sees BOTH facts: which keys were rejected, and what the + # structural gate says about what did land. + if: always() # The pipeline proposes; this decides. Its own mutation self-test runs # first, so the gate proves it can fail before it is trusted to pass. run: | @@ -146,7 +150,7 @@ jobs: python3 client/tools/check_localization_sync.py --server-src .emitters --strict - name: Re-record the vendoring state digest - if: inputs.commit + if: always() && inputs.commit run: | set -euo pipefail DIGEST=$(python3 packaging/check_vendoring.py --print) @@ -161,7 +165,12 @@ jobs: python3 packaging/check_vendoring.py - name: Commit - if: inputs.commit + # ALWAYS, even when the lane exited 1. The lane writes only ACCEPTED + # values now, so committing on failure banks the good work and leaves + # the rejected keys missing — which the strict guard then blocks on, + # exactly as it would have anyway. Skipping this on failure is what + # discarded 587 good translations per run, seven runs running. + if: always() && inputs.commit run: | set -euo pipefail git config user.name "github-actions[bot]" diff --git a/localization/localize.py b/localization/localize.py index bd6a07a..3602c0b 100644 --- a/localization/localize.py +++ b/localization/localize.py @@ -1070,9 +1070,30 @@ def run(lane: str, patterns: Sequence[str], langs: Sequence[str], *, max_keys: i "rejected_unrepaired": rejected.get(lang, {}), } - if values: - insert(lang, values, en, overwrite=(lane != "translate")) - print(f"[write] {lang}: {len(values)} value(s), 4 mirrors") + # BANK THE ACCEPTED WORK, WITHHOLD THE REJECTED. + # + # This used to write everything — accepted and rejected alike — and then + # exit 1, which failed the job before the Commit step and threw the + # WHOLE RUN away. On a 21-key job across 28 languages that is 588 pairs + # discarded because one of them came back clumsy, and it happened seven + # times in a row on one branch: every run failed on a different single + # pair, so every run binned 587 good translations and cost a full lane to + # do it. + # + # The guarantee is unchanged and is what makes this safe: a rejected + # value is NOT written, so nothing semantically bad reaches a bundle and + # English never appears under a non-English locale. The run still exits + # 1, the key stays missing, and the strict guard still blocks the merge + # until it is filled. The only thing that changes is that the accepted + # values survive, so the next run has one key to do instead of 588. + withheld = set(rejected.get(lang, {})) | set(unresolved) + writable = {k: v for k, v in values.items() if k not in withheld} + if writable: + insert(lang, writable, en, overwrite=(lane != "translate")) + print(f"[write] {lang}: {len(writable)} value(s), 4 mirrors" + + (f" ({len(withheld)} withheld — rejected)" if withheld else "")) + elif withheld: + print(f"[write] {lang}: nothing written — all {len(withheld)} rejected") print("\nspend (estimate — billing is what the API bills):") print(spend.report(batch=(mode == "batch"))) From 59a37c49bfa1963ced4fa422edfde5bea894756a Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Sat, 29 Aug 2026 01:35:02 +0000 Subject: [PATCH 14/18] i18n: translate lane (translate -> evaluate -> repair) Machine translation, independently reviewed against MQM, and repaired where the review found a critical, major or terminology error. Every value here is status=draft / review_status=needs_native_review: this pipeline guarantees terminology, structure and meaning, and does not guarantee native fluency. Validated by check_localization_sync.py --strict in this same run. The MQM findings are attached to the run as i18n-report.json. Review like any other diff. --- client/VENDORING.md | 2 +- .../src/main/assets/localization/am.json | 21 +++++++++++++++++++ .../src/main/assets/localization/ar.json | 21 +++++++++++++++++++ .../src/main/assets/localization/bn.json | 21 +++++++++++++++++++ .../src/main/assets/localization/de.json | 18 ++++++++++++++++ .../src/main/assets/localization/es.json | 21 +++++++++++++++++++ .../src/main/assets/localization/fa.json | 21 +++++++++++++++++++ .../src/main/assets/localization/fr.json | 21 +++++++++++++++++++ .../src/main/assets/localization/ha.json | 21 +++++++++++++++++++ .../src/main/assets/localization/hi.json | 21 +++++++++++++++++++ .../src/main/assets/localization/id.json | 21 +++++++++++++++++++ .../src/main/assets/localization/it.json | 21 +++++++++++++++++++ .../src/main/assets/localization/ja.json | 21 +++++++++++++++++++ .../src/main/assets/localization/ko.json | 21 +++++++++++++++++++ .../src/main/assets/localization/mr.json | 21 +++++++++++++++++++ .../src/main/assets/localization/my.json | 20 ++++++++++++++++++ .../src/main/assets/localization/pa.json | 21 +++++++++++++++++++ .../src/main/assets/localization/pt.json | 21 +++++++++++++++++++ .../src/main/assets/localization/ru.json | 21 +++++++++++++++++++ .../src/main/assets/localization/sw.json | 21 +++++++++++++++++++ .../src/main/assets/localization/ta.json | 21 +++++++++++++++++++ .../src/main/assets/localization/te.json | 21 +++++++++++++++++++ .../src/main/assets/localization/th.json | 21 +++++++++++++++++++ .../src/main/assets/localization/tr.json | 21 +++++++++++++++++++ .../src/main/assets/localization/uk.json | 21 +++++++++++++++++++ .../src/main/assets/localization/ur.json | 21 +++++++++++++++++++ .../src/main/assets/localization/vi.json | 21 +++++++++++++++++++ .../src/main/assets/localization/yo.json | 21 +++++++++++++++++++ .../src/main/assets/localization/zh.json | 21 +++++++++++++++++++ .../src/main/resources/localization/am.json | 21 +++++++++++++++++++ .../src/main/resources/localization/ar.json | 21 +++++++++++++++++++ .../src/main/resources/localization/bn.json | 21 +++++++++++++++++++ .../src/main/resources/localization/de.json | 18 ++++++++++++++++ .../src/main/resources/localization/es.json | 21 +++++++++++++++++++ .../src/main/resources/localization/fa.json | 21 +++++++++++++++++++ .../src/main/resources/localization/fr.json | 21 +++++++++++++++++++ .../src/main/resources/localization/ha.json | 21 +++++++++++++++++++ .../src/main/resources/localization/hi.json | 21 +++++++++++++++++++ .../src/main/resources/localization/id.json | 21 +++++++++++++++++++ .../src/main/resources/localization/it.json | 21 +++++++++++++++++++ .../src/main/resources/localization/ja.json | 21 +++++++++++++++++++ .../src/main/resources/localization/ko.json | 21 +++++++++++++++++++ .../src/main/resources/localization/mr.json | 21 +++++++++++++++++++ .../src/main/resources/localization/my.json | 20 ++++++++++++++++++ .../src/main/resources/localization/pa.json | 21 +++++++++++++++++++ .../src/main/resources/localization/pt.json | 21 +++++++++++++++++++ .../src/main/resources/localization/ru.json | 21 +++++++++++++++++++ .../src/main/resources/localization/sw.json | 21 +++++++++++++++++++ .../src/main/resources/localization/ta.json | 21 +++++++++++++++++++ .../src/main/resources/localization/te.json | 21 +++++++++++++++++++ .../src/main/resources/localization/th.json | 21 +++++++++++++++++++ .../src/main/resources/localization/tr.json | 21 +++++++++++++++++++ .../src/main/resources/localization/uk.json | 21 +++++++++++++++++++ .../src/main/resources/localization/ur.json | 21 +++++++++++++++++++ .../src/main/resources/localization/vi.json | 21 +++++++++++++++++++ .../src/main/resources/localization/yo.json | 21 +++++++++++++++++++ .../src/main/resources/localization/zh.json | 21 +++++++++++++++++++ client/iosApp/iosApp/localization/am.json | 21 +++++++++++++++++++ client/iosApp/iosApp/localization/ar.json | 21 +++++++++++++++++++ client/iosApp/iosApp/localization/bn.json | 21 +++++++++++++++++++ client/iosApp/iosApp/localization/de.json | 18 ++++++++++++++++ client/iosApp/iosApp/localization/es.json | 21 +++++++++++++++++++ client/iosApp/iosApp/localization/fa.json | 21 +++++++++++++++++++ client/iosApp/iosApp/localization/fr.json | 21 +++++++++++++++++++ client/iosApp/iosApp/localization/ha.json | 21 +++++++++++++++++++ client/iosApp/iosApp/localization/hi.json | 21 +++++++++++++++++++ client/iosApp/iosApp/localization/id.json | 21 +++++++++++++++++++ client/iosApp/iosApp/localization/it.json | 21 +++++++++++++++++++ client/iosApp/iosApp/localization/ja.json | 21 +++++++++++++++++++ client/iosApp/iosApp/localization/ko.json | 21 +++++++++++++++++++ client/iosApp/iosApp/localization/mr.json | 21 +++++++++++++++++++ client/iosApp/iosApp/localization/my.json | 20 ++++++++++++++++++ client/iosApp/iosApp/localization/pa.json | 21 +++++++++++++++++++ client/iosApp/iosApp/localization/pt.json | 21 +++++++++++++++++++ client/iosApp/iosApp/localization/ru.json | 21 +++++++++++++++++++ client/iosApp/iosApp/localization/sw.json | 21 +++++++++++++++++++ client/iosApp/iosApp/localization/ta.json | 21 +++++++++++++++++++ client/iosApp/iosApp/localization/te.json | 21 +++++++++++++++++++ client/iosApp/iosApp/localization/th.json | 21 +++++++++++++++++++ client/iosApp/iosApp/localization/tr.json | 21 +++++++++++++++++++ client/iosApp/iosApp/localization/uk.json | 21 +++++++++++++++++++ client/iosApp/iosApp/localization/ur.json | 21 +++++++++++++++++++ client/iosApp/iosApp/localization/vi.json | 21 +++++++++++++++++++ client/iosApp/iosApp/localization/yo.json | 21 +++++++++++++++++++ client/iosApp/iosApp/localization/zh.json | 21 +++++++++++++++++++ .../resources/localization/am.json | 21 +++++++++++++++++++ .../resources/localization/ar.json | 21 +++++++++++++++++++ .../resources/localization/bn.json | 21 +++++++++++++++++++ .../resources/localization/de.json | 18 ++++++++++++++++ .../resources/localization/es.json | 21 +++++++++++++++++++ .../resources/localization/fa.json | 21 +++++++++++++++++++ .../resources/localization/fr.json | 21 +++++++++++++++++++ .../resources/localization/ha.json | 21 +++++++++++++++++++ .../resources/localization/hi.json | 21 +++++++++++++++++++ .../resources/localization/id.json | 21 +++++++++++++++++++ .../resources/localization/it.json | 21 +++++++++++++++++++ .../resources/localization/ja.json | 21 +++++++++++++++++++ .../resources/localization/ko.json | 21 +++++++++++++++++++ .../resources/localization/mr.json | 21 +++++++++++++++++++ .../resources/localization/my.json | 20 ++++++++++++++++++ .../resources/localization/pa.json | 21 +++++++++++++++++++ .../resources/localization/pt.json | 21 +++++++++++++++++++ .../resources/localization/ru.json | 21 +++++++++++++++++++ .../resources/localization/sw.json | 21 +++++++++++++++++++ .../resources/localization/ta.json | 21 +++++++++++++++++++ .../resources/localization/te.json | 21 +++++++++++++++++++ .../resources/localization/th.json | 21 +++++++++++++++++++ .../resources/localization/tr.json | 21 +++++++++++++++++++ .../resources/localization/uk.json | 21 +++++++++++++++++++ .../resources/localization/ur.json | 21 +++++++++++++++++++ .../resources/localization/vi.json | 21 +++++++++++++++++++ .../resources/localization/yo.json | 21 +++++++++++++++++++ .../resources/localization/zh.json | 21 +++++++++++++++++++ 113 files changed, 2337 insertions(+), 1 deletion(-) diff --git a/client/VENDORING.md b/client/VENDORING.md index f9a4be1..58c2f8c 100644 --- a/client/VENDORING.md +++ b/client/VENDORING.md @@ -40,7 +40,7 @@ source is the pair a bisect wants: The tree's current recorded state — sha256-of-sha256s over every git-tracked file under `client/` except this one: -**state digest:** `19fa12f2d104f882c2d0096419b2a5a841dc7c82de9e95a9b92744a173754f6f` +**state digest:** `65b64d2ae6d83307dc17d1832a54ec4df2eca07531ddb282444f6ec5b7d366d9` `packaging/check_vendoring.py` asserts it on every push, and refuses any tracked file matching a §2 never-vendor class. **Any commit that touches diff --git a/client/androidApp/src/main/assets/localization/am.json b/client/androidApp/src/main/assets/localization/am.json index 6fc10f6..54741c5 100644 --- a/client/androidApp/src/main/assets/localization/am.json +++ b/client/androidApp/src/main/assets/localization/am.json @@ -2924,6 +2924,27 @@ "wallet_transfer_success": "ማስተላለፍ ተሳክቷል! TX: {tx}", "wallet_trust_degraded": "ስልክ ሥቅ ተዳክሞ ነበር", "wallet_warning": "ማስጠንቀቂያ", + "verify_title": "ግንባታ ማረጋገጥ", + "verify_hash_label": "የግንባታ ሃሽ", + "verify_button": "አረጋግጥ", + "verify_undeclared_title": "ይህ ኖድ ግንባታዎችን እንደሚያረጋግጥ ወይም እንደማያረጋግጥ መናገር አይችልም", + "verify_undeclared_body": "ይህ ኖድ ከችሎታ መግለጫው የቀደመ ነው፤ ስለዚህ መናገር አይችልም። አዲስ ኖድ ግንባታዎችን ማረጋገጥ ይችላል።", + "verify_absent_title": "ይህ ኖድ ግንባታዎችን አያረጋግጥም", + "verify_absent_body": "ይህ ኖድ መዝገቡን አልያዘም፤ ስለዚህ ግንባታዎችን ማረጋገጥ አይችልም። ሌላ ኖድ ግን ይችላል።", + "verify_unreachable_title": "ወደዚህ ኖድ መድረስ አልተቻለም", + "verify_unreachable_body": "ኖዱ መልስ አልሰጠም፤ ስለዚህ ግንባታዎችን ማረጋገጥ እንደሚችል ወይም እንደማይችል አናውቅም። ይህ እርስዎ የሚያረጋግጡት ግንባታ ችግር አይደለም።", + "verify_status_registered": "ተመዝግቧል", + "verify_status_deprecated": "ከዚህ በኋላ አይመከርም", + "verify_status_revoked": "ተሰርዟል", + "verify_status_unreadable": "ሁኔታው አልታወቀም", + "verify_revoked_warning": "ይህ ግንባታ ተሰርዟል። አይጠቀሙበት።", + "verify_not_found_title": "ለዚህ ግንባታ ምንም መዝገብ የለም", + "verify_not_found_body": "መዝገቡ መልስ ሰጥቷል፤ ለዚህ ሃሽ ምንም አልያዘም።", + "verify_unavailable_title": "ማረጋገጥ አልተቻለም", + "verify_unavailable_body": "ይህ ‘አልተመዘገበም’ ከመባል ጋር አንድ አይደለም — መዝገቡ መልስ አልሰጠም።", + "verify_undetermined_title": "ይህ ኖድ ምን ማድረግ እንደሚችል መወሰን አልቻለም", + "verify_undetermined_body": "ኖዱ መልስ ሰጥቷል፣ ሆኖም የራሱን የቁልፍ መዝገብ ማንበብ አልቻለም። ይህ በተለምዶ ጊዜያዊ ነው — ከጥቂት ጊዜ በኋላ እንደገና ይሞክሩ።", + "verify_retry": "እንደገና አረጋግጥ", "attestation_actions_desc": "ለዚህ መዝገብ ያሉ እርምጃዎች", "chat_badge_message": "መልዕክት", "chat_details": "ዓይነት {type} · ወሰን {scope} · ሁኔታ {status}", diff --git a/client/androidApp/src/main/assets/localization/ar.json b/client/androidApp/src/main/assets/localization/ar.json index 52541c6..48f9965 100644 --- a/client/androidApp/src/main/assets/localization/ar.json +++ b/client/androidApp/src/main/assets/localization/ar.json @@ -2924,6 +2924,27 @@ "wallet_transfer_success": "نجح التحويل! TX: {tx}", "wallet_trust_degraded": "تدهورت ثقة الأجهزة", "wallet_warning": "تحذير", + "verify_title": "التحقق من إصدار", + "verify_hash_label": "بصمة الإصدار", + "verify_button": "تحقّق", + "verify_undeclared_title": "لا تستطيع هذه العقدة الإفادة عن قدرتها على التحقق من الإصدارات", + "verify_undeclared_body": "هذه العقدة أقدم من إعلان القدرات، فلا يمكنها الإفادة. عقدة أحدث تستطيع التحقق من الإصدارات.", + "verify_absent_title": "هذه العقدة لا تتحقق من الإصدارات", + "verify_absent_body": "لا تحمل هذه العقدة السجل، فلا يمكنها التحقق من الإصدارات. عقدة أخرى تستطيع ذلك.", + "verify_unreachable_title": "تعذّر الوصول إلى هذه العقدة", + "verify_unreachable_body": "لم تُجب العقدة، فلا نعرف أتستطيع التحقق من الإصدارات أم لا. وهذا ليس عطلاً في الإصدار الذي تتحقق منه.", + "verify_status_registered": "مسجَّل", + "verify_status_deprecated": "لم يعد يُنصح به", + "verify_status_revoked": "مُلغى", + "verify_status_unreadable": "الحالة غير معروفة", + "verify_revoked_warning": "هذا الإصدار أُلغي. لا تستخدمه.", + "verify_not_found_title": "لا سجل لهذا الإصدار", + "verify_not_found_body": "أجاب السجل ولا يحمل شيئاً لهذه البصمة.", + "verify_unavailable_title": "تعذّر التحقق", + "verify_unavailable_body": "هذا ليس كـ«غير مسجَّل» — فالسجل لم يُجب.", + "verify_undetermined_title": "تعذّر على هذه العقدة تحديد ما تستطيع فعله", + "verify_undetermined_body": "أجابت العقدة، لكنها لم تستطع قراءة سجل مفتاحها الخاص. هذا عادةً مؤقت — حاول مجدداً بعد قليل.", + "verify_retry": "تحقّق مجدداً", "attestation_actions_desc": "إجراءات هذا السجل", "chat_badge_message": "رسالة", "chat_details": "النوع {type} · النطاق {scope} · الحالة {status}", diff --git a/client/androidApp/src/main/assets/localization/bn.json b/client/androidApp/src/main/assets/localization/bn.json index cbb52b3..203a77c 100644 --- a/client/androidApp/src/main/assets/localization/bn.json +++ b/client/androidApp/src/main/assets/localization/bn.json @@ -2925,6 +2925,27 @@ "wallet_transfer_success": "ট্রান্সফার সফল! TX: {tx}", "wallet_trust_degraded": "হার্ডওয়্যার বিশ্বাস হ্রাস পেয়েছে", "wallet_warning": "সতর্কতা", + "verify_title": "একটি বিল্ড যাচাই করুন", + "verify_hash_label": "বিল্ড হ্যাশ", + "verify_button": "পরীক্ষা করুন", + "verify_undeclared_title": "এই নোড বলতে পারে না যে এটি বিল্ড যাচাই করে কি না", + "verify_undeclared_body": "এই নোড সক্ষমতা ঘোষণার চেয়ে পুরনো, তাই এটি বলতে পারে না। নতুন কোনো নোড বিল্ড যাচাই করতে পারে।", + "verify_absent_title": "এই নোড বিল্ড যাচাই করে না", + "verify_absent_body": "এই নোড রেজিস্ট্রি ধারণ করে না, তাই এটি বিল্ড পরীক্ষা করতে পারে না। অন্য একটি নোড পারে।", + "verify_unreachable_title": "এই নোডে পৌঁছানো যায়নি", + "verify_unreachable_body": "নোডটি সাড়া দেয়নি, তাই এটি বিল্ড যাচাই করতে পারে কি না তা আমরা জানি না। আপনি যে বিল্ডটি পরীক্ষা করছেন তার সমস্যা এটি নয়।", + "verify_status_registered": "নিবন্ধিত", + "verify_status_deprecated": "আর প্রস্তাবিত নয়", + "verify_status_revoked": "প্রত্যাহৃত", + "verify_status_unreadable": "অবস্থা সনাক্ত করা যায়নি", + "verify_revoked_warning": "এই বিল্ডটি প্রত্যাহার করা হয়েছে। এটি ব্যবহার করবেন না।", + "verify_not_found_title": "এই বিল্ডের কোনো রেকর্ড নেই", + "verify_not_found_body": "রেজিস্ট্রি সাড়া দিয়েছে এবং এই হ্যাশের জন্য কিছুই ধারণ করে না।", + "verify_unavailable_title": "পরীক্ষা করা যায়নি", + "verify_unavailable_body": "এটি ‘নিবন্ধিত নয়’-এর সমান নয় — রেজিস্ট্রি সাড়া দেয়নি।", + "verify_undetermined_title": "এই নোড নির্ধারণ করতে পারেনি যে এটি কী করতে পারে", + "verify_undetermined_body": "নোডটি সাড়া দিয়েছে, কিন্তু নিজের কী রেকর্ড পড়তে পারেনি। এটি সাধারণত সাময়িক — কিছুক্ষণ পরে আবার চেষ্টা করুন।", + "verify_retry": "আবার পরীক্ষা করুন", "attestation_actions_desc": "এই রেকর্ডের জন্য পদক্ষেপ", "chat_badge_message": "বার্তা", "chat_details": "ধরন {type} · পরিসর {scope} · অবস্থা {status}", diff --git a/client/androidApp/src/main/assets/localization/de.json b/client/androidApp/src/main/assets/localization/de.json index da1e0ac..6f85250 100644 --- a/client/androidApp/src/main/assets/localization/de.json +++ b/client/androidApp/src/main/assets/localization/de.json @@ -2862,6 +2862,18 @@ "users_status": "Status", "users_user_id": "Benutzer-ID", "users_wa_role": "WA:{role}", + "verify_unavailable_title": "Prüfung nicht möglich", + "verify_undetermined_title": "Dieser Knoten konnte nicht feststellen, was er kann", + "verify_undetermined_body": "Der Knoten hat geantwortet, konnte aber seinen eigenen Schlüsseldatensatz nicht lesen. Das ist meist vorübergehend — versuchen Sie es in Kürze erneut.", + "verify_retry": "Erneut prüfen", + "verify_unreachable_title": "Knoten nicht erreichbar", + "verify_unreachable_body": "Der Knoten hat nicht geantwortet, daher wissen wir nicht, ob er Builds verifizieren kann. Das liegt nicht an dem Build, den Sie prüfen.", + "verify_status_registered": "Registriert", + "verify_status_deprecated": "Nicht mehr empfohlen", + "verify_status_revoked": "Widerrufen", + "verify_status_unreadable": "Status nicht erkannt", + "verify_revoked_warning": "Dieser Build wurde widerrufen. Verwenden Sie ihn nicht.", + "verify_not_found_title": "Kein Eintrag für diesen Build", "wa_approve": "Genehmigen", "wa_avg_resolution": "Durchschnittl. Auflösung: {time} Min", "wa_bus_subscribers": "Bus-Abonnenten", @@ -2924,6 +2936,12 @@ "wallet_transfer_success": "Überweisung erfolgreich! TX: {tx}", "wallet_trust_degraded": "Hardware-Vertrauen herabgestuft", "wallet_warning": "Warnung", + "verify_title": "Build verifizieren", + "verify_hash_label": "Build-Hash", + "verify_button": "Prüfen", + "verify_undeclared_title": "Dieser Knoten kann nicht sagen, ob er Builds verifiziert", + "verify_undeclared_body": "Dieser Knoten ist älter als die Fähigkeitserklärung und kann daher keine Auskunft geben. Ein neuerer Knoten kann Builds verifizieren.", + "verify_absent_title": "Dieser Knoten verifiziert keine Builds", "attestation_actions_desc": "Aktionen für diesen Datensatz", "chat_badge_message": "NACHRICHT", "chat_details": "Typ {type} · Bereich {scope} · Status {status}", diff --git a/client/androidApp/src/main/assets/localization/es.json b/client/androidApp/src/main/assets/localization/es.json index fe02dbf..91b0f58 100644 --- a/client/androidApp/src/main/assets/localization/es.json +++ b/client/androidApp/src/main/assets/localization/es.json @@ -2924,6 +2924,27 @@ "wallet_transfer_success": "¡Transferencia exitosa! TX: {tx}", "wallet_trust_degraded": "Confianza de Hardware Degradada", "wallet_warning": "Advertencia", + "verify_title": "Verificar una compilación", + "verify_hash_label": "Hash de la compilación", + "verify_button": "Comprobar", + "verify_undeclared_title": "Este nodo no puede decir si verifica compilaciones", + "verify_undeclared_body": "Este nodo es anterior a la declaración de capacidades, así que no puede saberlo. Un nodo más reciente puede verificar compilaciones.", + "verify_absent_title": "Este nodo no verifica compilaciones", + "verify_absent_body": "Este nodo no aloja el registro, así que no puede comprobar compilaciones. Otro nodo sí puede.", + "verify_unreachable_title": "No se pudo contactar con este nodo", + "verify_unreachable_body": "El nodo no respondió, así que no sabemos si puede verificar compilaciones. Esto no es un problema de la compilación que estás comprobando.", + "verify_status_registered": "Registrada", + "verify_status_deprecated": "Ya no se recomienda", + "verify_status_revoked": "Revocada", + "verify_status_unreadable": "Estado no reconocido", + "verify_revoked_warning": "Esta compilación ha sido revocada. No la uses.", + "verify_not_found_title": "No hay registro de esta compilación", + "verify_not_found_body": "El registro respondió y no tiene nada para este hash.", + "verify_unavailable_title": "No se pudo comprobar", + "verify_unavailable_body": "Esto no es lo mismo que «no registrada» — el registro no respondió.", + "verify_undetermined_title": "Este nodo no pudo determinar qué puede hacer", + "verify_undetermined_body": "El nodo respondió, pero no pudo leer su propio registro de claves. Esto suele ser temporal — inténtalo de nuevo en breve.", + "verify_retry": "Comprobar de nuevo", "attestation_actions_desc": "Acciones para este registro", "chat_badge_message": "MENSAJE", "chat_details": "tipo {type} · ámbito {scope} · estado {status}", diff --git a/client/androidApp/src/main/assets/localization/fa.json b/client/androidApp/src/main/assets/localization/fa.json index 38b931c..41c206a 100644 --- a/client/androidApp/src/main/assets/localization/fa.json +++ b/client/androidApp/src/main/assets/localization/fa.json @@ -2930,6 +2930,27 @@ "wallet_transfer_success": "انتقال با موفقیت انجام شد! TX: {tx}", "wallet_trust_degraded": "افت اعتماد سخت‌افزاری", "wallet_warning": "هشدار", + "verify_title": "تأیید یک نسخه", + "verify_hash_label": "هش نسخه", + "verify_button": "بررسی", + "verify_undeclared_title": "این گره نمی‌تواند بگوید آیا نسخه‌ها را تأیید می‌کند یا نه", + "verify_undeclared_body": "این گره قدیمی‌تر از اعلامِ قابلیت است، پس نمی‌تواند بگوید. گرهی جدیدتر می‌تواند نسخه‌ها را تأیید کند.", + "verify_absent_title": "این گره نسخه‌ها را تأیید نمی‌کند", + "verify_absent_body": "این گره رجیستری را نگه نمی‌دارد، پس نمی‌تواند نسخه‌ها را بررسی کند. گرهی دیگر می‌تواند.", + "verify_unreachable_title": "دسترسی به این گره ممکن نشد", + "verify_unreachable_body": "گره پاسخ نداد، پس نمی‌دانیم آیا می‌تواند نسخه‌ها را تأیید کند یا نه. این مشکلی از نسخه‌ای که بررسی می‌کنید نیست.", + "verify_status_registered": "ثبت‌شده", + "verify_status_deprecated": "دیگر توصیه نمی‌شود", + "verify_status_revoked": "باطل‌شده", + "verify_status_unreadable": "وضعیت شناسایی نشد", + "verify_revoked_warning": "این نسخه باطل شده است. از آن استفاده نکنید.", + "verify_not_found_title": "رکوردی از این نسخه وجود ندارد", + "verify_not_found_body": "رجیستری پاسخ داد و چیزی برای این هش نگه نمی‌دارد.", + "verify_unavailable_title": "بررسی ممکن نشد", + "verify_unavailable_body": "این با «ثبت‌نشده» یکسان نیست — رجیستری پاسخ نداد.", + "verify_undetermined_title": "این گره نتوانست تشخیص دهد چه کاری از آن ساخته است", + "verify_undetermined_body": "گره پاسخ داد، اما نتوانست رکورد کلید خودش را بخواند. این معمولاً موقتی است — کمی بعد دوباره تلاش کنید.", + "verify_retry": "دوباره بررسی کن", "attestation_actions_desc": "اقدامات برای این رکورد", "chat_badge_message": "پیام", "chat_details": "نوع {type} · محدوده {scope} · وضعیت {status}", diff --git a/client/androidApp/src/main/assets/localization/fr.json b/client/androidApp/src/main/assets/localization/fr.json index fe1f844..4dda6cc 100644 --- a/client/androidApp/src/main/assets/localization/fr.json +++ b/client/androidApp/src/main/assets/localization/fr.json @@ -2924,6 +2924,27 @@ "wallet_transfer_success": "Transfert réussi ! TX: {tx}", "wallet_trust_degraded": "Confiance Matérielle Dégradée", "wallet_warning": "Avertissement", + "verify_title": "Vérifier un build", + "verify_hash_label": "Empreinte du build", + "verify_button": "Vérifier", + "verify_undeclared_title": "Ce nœud ne peut pas dire s'il vérifie les builds", + "verify_undeclared_body": "Ce nœud est antérieur à la déclaration de capacité : il ne peut donc pas se prononcer. Un nœud plus récent peut vérifier les builds.", + "verify_absent_title": "Ce nœud ne vérifie pas les builds", + "verify_absent_body": "Ce nœud ne détient pas le registre : il ne peut donc pas vérifier les builds. Un autre nœud le peut.", + "verify_unreachable_title": "Impossible de joindre ce nœud", + "verify_unreachable_body": "Le nœud n'a pas répondu : nous ne savons donc pas s'il peut vérifier les builds. Ceci n'est pas un problème lié au build que vous vérifiez.", + "verify_status_registered": "Enregistré", + "verify_status_deprecated": "N'est plus recommandé", + "verify_status_revoked": "Révoqué", + "verify_status_unreadable": "Statut non reconnu", + "verify_revoked_warning": "Ce build a été révoqué. Ne l'utilisez pas.", + "verify_not_found_title": "Aucun enregistrement pour ce build", + "verify_not_found_body": "Le registre a répondu et ne détient rien pour cette empreinte.", + "verify_unavailable_title": "Vérification impossible", + "verify_unavailable_body": "Ceci n'équivaut pas à « non enregistré » — le registre n'a pas répondu.", + "verify_undetermined_title": "Ce nœud n'a pas pu déterminer ce qu'il peut faire", + "verify_undetermined_body": "Le nœud a répondu, mais n'a pas pu lire son propre enregistrement de clé. C'est généralement temporaire — réessayez dans un instant.", + "verify_retry": "Vérifier à nouveau", "attestation_actions_desc": "Actions pour cet enregistrement", "chat_badge_message": "MESSAGE", "chat_details": "type {type} · portée {scope} · statut {status}", diff --git a/client/androidApp/src/main/assets/localization/ha.json b/client/androidApp/src/main/assets/localization/ha.json index f5f91af..e36d699 100644 --- a/client/androidApp/src/main/assets/localization/ha.json +++ b/client/androidApp/src/main/assets/localization/ha.json @@ -2924,6 +2924,27 @@ "wallet_transfer_success": "Aika ya yi nasara! TX: {tx}", "wallet_trust_degraded": "Tabbas Kayan Aiki Ya Rage", "wallet_warning": "Gargaɗi", + "verify_title": "Tabbatar da build", + "verify_hash_label": "Hash na build", + "verify_button": "Duba", + "verify_undeclared_title": "Wannan kumburi ba zai iya faɗi ko yana tabbatar da build ba", + "verify_undeclared_body": "Wannan kumburi ya girme sanarwar iyawa, don haka ba zai iya faɗi ba. Sabon kumburi na iya tabbatar da build.", + "verify_absent_title": "Wannan kumburi ba ya tabbatar da build ba", + "verify_absent_body": "Wannan kumburi ba ya riƙe rajista ba, don haka ba zai iya duba build ba. Wani kumburi na iya duba build.", + "verify_unreachable_title": "An kasa isa ga wannan kumburi", + "verify_unreachable_body": "Kumburin bai amsa ba, don haka ba mu san ko yana iya tabbatar da build ba. Wannan ba matsala ce ta build ɗin da kuke dubawa ba.", + "verify_status_registered": "An yi rajista", + "verify_status_deprecated": "Ba a ƙara shawarta ba", + "verify_status_revoked": "An soke", + "verify_status_unreadable": "Ba a gane matsayin ba", + "verify_revoked_warning": "An soke wannan build. Kada ku yi amfani da shi.", + "verify_not_found_title": "Babu rikodin wannan build", + "verify_not_found_body": "Rajistar ta amsa kuma ba ta riƙe komai ga wannan hash ba.", + "verify_unavailable_title": "An kasa duba", + "verify_unavailable_body": "Wannan bai zama daidai da 'ba a yi rajista ba' ba — rajistar ba ta amsa ba.", + "verify_undetermined_title": "Wannan kumburi bai iya tantance abin da yake iya yi ba", + "verify_undetermined_body": "Kumburin ya amsa, amma bai iya karanta rikodin maɓallinsa na kansa ba. Yawanci na ɗan lokaci ne — sake gwadawa nan da nan.", + "verify_retry": "Sake duba", "attestation_actions_desc": "Ayyuka don wannan rikodin", "chat_badge_message": "SAƘO", "chat_details": "nau'i {type} · iyaka {scope} · matsayi {status}", diff --git a/client/androidApp/src/main/assets/localization/hi.json b/client/androidApp/src/main/assets/localization/hi.json index 504fa17..a4e474c 100644 --- a/client/androidApp/src/main/assets/localization/hi.json +++ b/client/androidApp/src/main/assets/localization/hi.json @@ -2924,6 +2924,27 @@ "wallet_transfer_success": "स्थानांतरण सफल! TX: {tx}", "wallet_trust_degraded": "हार्डवेयर ट्रस्ट कम हुआ", "wallet_warning": "चेतावनी", + "verify_title": "बिल्ड सत्यापित करें", + "verify_hash_label": "बिल्ड हैश", + "verify_button": "जाँच करें", + "verify_undeclared_title": "यह नोड नहीं बता सकता कि यह बिल्ड सत्यापित करता है या नहीं", + "verify_undeclared_body": "यह नोड क्षमता घोषणा से पुराना है, इसलिए यह बता नहीं सकता। कोई नया नोड बिल्ड सत्यापित कर सकता है।", + "verify_absent_title": "यह नोड बिल्ड सत्यापित नहीं करता", + "verify_absent_body": "यह नोड रजिस्ट्री नहीं रखता, इसलिए यह बिल्ड की जाँच नहीं कर सकता। कोई अन्य नोड कर सकता है।", + "verify_unreachable_title": "इस नोड तक नहीं पहुँच सका", + "verify_unreachable_body": "नोड ने उत्तर नहीं दिया, इसलिए यह पता नहीं चलता कि यह बिल्ड सत्यापित कर सकता है या नहीं। यह उस बिल्ड की समस्या नहीं है जिसकी आप जाँच कर रहे हैं।", + "verify_status_registered": "पंजीकृत", + "verify_status_deprecated": "अब अनुशंसित नहीं", + "verify_status_revoked": "रद्द", + "verify_status_unreadable": "स्थिति पहचानी नहीं जा सकी", + "verify_revoked_warning": "इस बिल्ड को रद्द कर दिया गया है। इसका उपयोग न करें।", + "verify_not_found_title": "इस बिल्ड का कोई रिकॉर्ड नहीं", + "verify_not_found_body": "रजिस्ट्री ने उत्तर दिया और इस हैश के लिए उसके पास कुछ भी नहीं है।", + "verify_unavailable_title": "जाँच नहीं हो सकी", + "verify_unavailable_body": "यह 'पंजीकृत नहीं' जैसा नहीं है — रजिस्ट्री ने उत्तर नहीं दिया।", + "verify_undetermined_title": "यह नोड यह निर्धारित नहीं कर सका कि यह क्या कर सकता है", + "verify_undetermined_body": "नोड ने उत्तर दिया, पर अपना ही कुंजी रिकॉर्ड नहीं पढ़ सका। यह आमतौर पर अस्थायी होता है — थोड़ी देर में फिर से प्रयास करें।", + "verify_retry": "फिर से जाँच करें", "attestation_actions_desc": "इस रिकॉर्ड के लिए कार्रवाइयाँ", "chat_badge_message": "संदेश", "chat_details": "प्रकार {type} · दायरा {scope} · स्थिति {status}", diff --git a/client/androidApp/src/main/assets/localization/id.json b/client/androidApp/src/main/assets/localization/id.json index d51d506..8c7d4ad 100644 --- a/client/androidApp/src/main/assets/localization/id.json +++ b/client/androidApp/src/main/assets/localization/id.json @@ -2924,6 +2924,27 @@ "wallet_transfer_success": "Transfer berhasil! TX: {tx}", "wallet_trust_degraded": "Kepercayaan Perangkat Keras Menurun", "wallet_warning": "Peringatan", + "verify_title": "Verifikasi build", + "verify_hash_label": "Hash build", + "verify_button": "Periksa", + "verify_undeclared_title": "Node ini tidak dapat menyatakan apakah ia memverifikasi build", + "verify_undeclared_body": "Node ini lebih lama daripada deklarasi kapabilitas, sehingga tidak dapat menyatakannya. Node yang lebih baru dapat memverifikasi build.", + "verify_absent_title": "Node ini tidak memverifikasi build", + "verify_absent_body": "Node ini tidak menyimpan registry, sehingga tidak dapat memeriksa build. Node lain bisa.", + "verify_unreachable_title": "Tidak dapat menjangkau node ini", + "verify_unreachable_body": "Node tidak merespons, sehingga kami tidak tahu apakah ia dapat memverifikasi build. Ini bukan masalah pada build yang Anda periksa.", + "verify_status_registered": "Terdaftar", + "verify_status_deprecated": "Tidak lagi disarankan", + "verify_status_revoked": "Dicabut", + "verify_status_unreadable": "Status tidak dikenali", + "verify_revoked_warning": "Build ini telah dicabut. Jangan gunakan.", + "verify_not_found_title": "Tidak ada catatan untuk build ini", + "verify_not_found_body": "Registry merespons dan tidak menyimpan apa pun untuk hash ini.", + "verify_unavailable_title": "Tidak dapat memeriksa", + "verify_unavailable_body": "Ini tidak sama dengan 'tidak terdaftar' — registry tidak merespons.", + "verify_undetermined_title": "Node ini tidak dapat menentukan apa yang bisa dilakukannya", + "verify_undetermined_body": "Node merespons, tetapi tidak dapat membaca catatan kuncinya sendiri. Biasanya ini bersifat sementara — coba lagi sebentar lagi.", + "verify_retry": "Periksa lagi", "attestation_actions_desc": "Tindakan untuk catatan ini", "chat_badge_message": "PESAN", "chat_details": "jenis {type} · lingkup {scope} · status {status}", diff --git a/client/androidApp/src/main/assets/localization/it.json b/client/androidApp/src/main/assets/localization/it.json index 525dd69..95ab48d 100644 --- a/client/androidApp/src/main/assets/localization/it.json +++ b/client/androidApp/src/main/assets/localization/it.json @@ -2924,6 +2924,27 @@ "wallet_transfer_success": "Trasferimento riuscito! TX: {tx}", "wallet_trust_degraded": "Fiducia Hardware Degradata", "wallet_warning": "Avviso", + "verify_title": "Verifica una build", + "verify_hash_label": "Hash della build", + "verify_button": "Verifica", + "verify_undeclared_title": "Questo nodo non è in grado di dire se verifica le build", + "verify_undeclared_body": "Questo nodo è precedente alla dichiarazione delle funzionalità, quindi non è in grado di pronunciarsi. Un nodo più recente può verificare le build.", + "verify_absent_title": "Questo nodo non verifica le build", + "verify_absent_body": "Questo nodo non detiene il registro, quindi non può verificare le build. Un altro nodo può farlo.", + "verify_unreachable_title": "Impossibile raggiungere questo nodo", + "verify_unreachable_body": "Il nodo non ha risposto, quindi non sappiamo se sia in grado di verificare le build. Questo non è un problema della build che stai verificando.", + "verify_status_registered": "Registrata", + "verify_status_deprecated": "Non più consigliata", + "verify_status_revoked": "Revocata", + "verify_status_unreadable": "Stato non riconosciuto", + "verify_revoked_warning": "Questa build è stata revocata. Non utilizzarla.", + "verify_not_found_title": "Nessuna registrazione per questa build", + "verify_not_found_body": "Il registro ha risposto e non contiene nulla per questo hash.", + "verify_unavailable_title": "Verifica non riuscita", + "verify_unavailable_body": "Questo non equivale a «non registrata» — il registro non ha risposto.", + "verify_undetermined_title": "Questo nodo non è riuscito a determinare cosa può fare", + "verify_undetermined_body": "Il nodo ha risposto, ma non è riuscito a leggere il proprio record delle chiavi. Di solito è temporaneo — riprova a breve.", + "verify_retry": "Verifica di nuovo", "attestation_actions_desc": "Azioni per questo record", "chat_badge_message": "MESSAGGIO", "chat_details": "tipo {type} · ambito {scope} · stato {status}", diff --git a/client/androidApp/src/main/assets/localization/ja.json b/client/androidApp/src/main/assets/localization/ja.json index 371b63a..3123141 100644 --- a/client/androidApp/src/main/assets/localization/ja.json +++ b/client/androidApp/src/main/assets/localization/ja.json @@ -2924,6 +2924,27 @@ "wallet_transfer_success": "送金成功!TX: {tx}", "wallet_trust_degraded": "ハードウェア信頼が低下しました", "wallet_warning": "警告", + "verify_title": "ビルドを検証する", + "verify_hash_label": "ビルドハッシュ", + "verify_button": "確認", + "verify_undeclared_title": "このノードはビルドを検証できるかどうかを述べられません", + "verify_undeclared_body": "このノードは機能宣言より古いバージョンのため、判断できません。新しいノードであればビルドを検証できます。", + "verify_absent_title": "このノードはビルドを検証しません", + "verify_absent_body": "このノードはレジストリを保持していないため、ビルドを確認できません。他のノードであれば確認できます。", + "verify_unreachable_title": "このノードに接続できませんでした", + "verify_unreachable_body": "ノードが応答しなかったため、ビルドを検証できるかどうかは分かりません。これは、確認しようとしているビルド自体の問題ではありません。", + "verify_status_registered": "登録済み", + "verify_status_deprecated": "推奨されていません", + "verify_status_revoked": "失効済み", + "verify_status_unreadable": "ステータスを認識できません", + "verify_revoked_warning": "このビルドは失効しています。使用しないでください。", + "verify_not_found_title": "このビルドの記録はありません", + "verify_not_found_body": "レジストリは応答しましたが、このハッシュに対する記録を保持していません。", + "verify_unavailable_title": "確認できませんでした", + "verify_unavailable_body": "これは「未登録」と同じではありません — レジストリが応答しませんでした。", + "verify_undetermined_title": "このノードは自身にできることを判別できませんでした", + "verify_undetermined_body": "ノードは応答しましたが、自身の鍵の記録を読み取れませんでした。これは通常一時的なものです — しばらくしてから再試行してください。", + "verify_retry": "再確認", "attestation_actions_desc": "このレコードに対する操作", "chat_badge_message": "メッセージ", "chat_details": "種別 {type} · スコープ {scope} · 状態 {status}", diff --git a/client/androidApp/src/main/assets/localization/ko.json b/client/androidApp/src/main/assets/localization/ko.json index e46b77f..ce7f6a2 100644 --- a/client/androidApp/src/main/assets/localization/ko.json +++ b/client/androidApp/src/main/assets/localization/ko.json @@ -2924,6 +2924,27 @@ "wallet_transfer_success": "전송 성공! TX: {tx}", "wallet_trust_degraded": "하드웨어 신뢰 저하됨", "wallet_warning": "경고", + "verify_title": "빌드 검증", + "verify_hash_label": "빌드 해시", + "verify_button": "확인", + "verify_undeclared_title": "이 노드는 빌드를 검증하는지 여부를 알 수 없습니다", + "verify_undeclared_body": "이 노드는 기능 선언보다 오래되어 알 수 없습니다. 더 새로운 노드는 빌드를 검증할 수 있습니다.", + "verify_absent_title": "이 노드는 빌드를 검증하지 않습니다", + "verify_absent_body": "이 노드는 레지스트리를 보유하지 않아 빌드를 확인할 수 없습니다. 다른 노드는 확인할 수 있습니다.", + "verify_unreachable_title": "이 노드에 연결할 수 없음", + "verify_unreachable_body": "노드가 응답하지 않아 빌드를 검증할 수 있는지 알 수 없습니다. 이는 확인 중인 빌드의 문제가 아닙니다.", + "verify_status_registered": "등록됨", + "verify_status_deprecated": "더 이상 권장되지 않음", + "verify_status_revoked": "폐기됨", + "verify_status_unreadable": "상태를 인식할 수 없음", + "verify_revoked_warning": "이 빌드는 폐기되었습니다. 사용하지 마십시오.", + "verify_not_found_title": "이 빌드에 대한 기록 없음", + "verify_not_found_body": "레지스트리가 응답했지만 이 해시에 대한 기록이 없습니다.", + "verify_unavailable_title": "확인할 수 없음", + "verify_unavailable_body": "이는 '등록되지 않음'과 같지 않습니다 — 레지스트리가 응답하지 않았습니다.", + "verify_undetermined_title": "이 노드는 자신이 무엇을 할 수 있는지 판단할 수 없었습니다", + "verify_undetermined_body": "노드가 응답했지만 자체 키 레코드를 읽을 수 없었습니다. 이는 대개 일시적인 현상입니다 — 잠시 후 다시 시도하세요.", + "verify_retry": "다시 확인", "attestation_actions_desc": "이 레코드에 대한 작업", "chat_badge_message": "메시지", "chat_details": "유형 {type} · 범위 {scope} · 상태 {status}", diff --git a/client/androidApp/src/main/assets/localization/mr.json b/client/androidApp/src/main/assets/localization/mr.json index 35d3208..b4cb9d1 100644 --- a/client/androidApp/src/main/assets/localization/mr.json +++ b/client/androidApp/src/main/assets/localization/mr.json @@ -2924,6 +2924,27 @@ "wallet_transfer_success": "Transfer यशful! TX: {tx}", "wallet_trust_degraded": "हार्डवेअर विश्वास खालावला", "wallet_warning": "इशारा", + "verify_title": "बिल्ड सत्यापित करा", + "verify_hash_label": "बिल्ड हॅश", + "verify_button": "तपासा", + "verify_undeclared_title": "हा नोड बिल्ड सत्यापित करतो की नाही हे सांगू शकत नाही", + "verify_undeclared_body": "हा नोड क्षमता-घोषणेपेक्षा जुना आहे, त्यामुळे तो सांगू शकत नाही. नवीन नोड बिल्ड सत्यापित करू शकतो.", + "verify_absent_title": "हा नोड बिल्ड सत्यापित करत नाही", + "verify_absent_body": "या नोडकडे रजिस्ट्री नाही, त्यामुळे तो बिल्ड तपासू शकत नाही. दुसरा नोड हे करू शकतो.", + "verify_unreachable_title": "या नोडपर्यंत पोहोचता आले नाही", + "verify_unreachable_body": "नोडने उत्तर दिले नाही, त्यामुळे तो बिल्ड सत्यापित करू शकतो की नाही हे आम्हाला माहीत नाही. तुम्ही तपासत असलेल्या बिल्डमध्ये ही समस्या नाही.", + "verify_status_registered": "नोंदणीकृत", + "verify_status_deprecated": "आता शिफारस केलेले नाही", + "verify_status_revoked": "रद्द केलेले", + "verify_status_unreadable": "स्थिती ओळखता आली नाही", + "verify_revoked_warning": "हे बिल्ड रद्द करण्यात आले आहे. याचा वापर करू नका.", + "verify_not_found_title": "या बिल्डची कोणतीही नोंद नाही", + "verify_not_found_body": "रजिस्ट्रीने उत्तर दिले आणि या हॅशसाठी त्याकडे काहीही नाही.", + "verify_unavailable_title": "तपासता आले नाही", + "verify_unavailable_body": "हे 'नोंदणीकृत नाही' यासारखे नाही — रजिस्ट्रीने उत्तर दिले नाही.", + "verify_undetermined_title": "हा नोड काय करू शकतो हे ठरवता आले नाही", + "verify_undetermined_body": "नोडने उत्तर दिले, पण त्याला स्वतःची की-नोंद वाचता आली नाही. हे सहसा तात्पुरते असते — थोड्या वेळाने पुन्हा प्रयत्न करा.", + "verify_retry": "पुन्हा तपासा", "attestation_actions_desc": "या नोंदीसाठी क्रिया", "chat_badge_message": "संदेश", "chat_details": "प्रकार {type} · व्याप्ती {scope} · स्थिती {status}", diff --git a/client/androidApp/src/main/assets/localization/my.json b/client/androidApp/src/main/assets/localization/my.json index 37d756b..f956c52 100644 --- a/client/androidApp/src/main/assets/localization/my.json +++ b/client/androidApp/src/main/assets/localization/my.json @@ -2862,6 +2862,14 @@ "users_status": "အခြေအနေ", "users_user_id": "အသုံးပြုသူ ID", "users_wa_role": "WA:{role}", + "verify_revoked_warning": "ဤ build ကို ရုပ်သိမ်းထားပြီးဖြစ်သည်။ အသုံးမပြုပါနှင့်။", + "verify_not_found_title": "ဤ build ၏ မှတ်တမ်း မရှိပါ", + "verify_not_found_body": "registry က အဖြေ ပြန်ပေးခဲ့ပြီး ဤ hash အတွက် မည်သည့်အရာမျှ ကိုင်ဆောင်ထားခြင်း မရှိပါ။", + "verify_unavailable_title": "စစ်ဆေး၍ မရပါ", + "verify_unavailable_body": "ဤသည်မှာ 'မှတ်ပုံတင်ထားခြင်း မရှိပါ' ဟူသည်နှင့် မတူပါ — registry က အဖြေ ပြန်မပေးခဲ့ပါ။", + "verify_undetermined_title": "ဤ node သည် ၎င်း လုပ်နိုင်သည့်အရာကို သတ်မှတ်၍ မရခဲ့ပါ", + "verify_undetermined_body": "node က အဖြေ ပြန်ပေးခဲ့သော်လည်း ၎င်း၏ ကိုယ်ပိုင် key မှတ်တမ်းကို ဖတ်၍ မရခဲ့ပါ။ ဤသည် ယာယီသာ ဖြစ်လေ့ရှိသည် — မကြာမီ ထပ်ကြိုးစားပါ။", + "verify_retry": "ထပ်မံစစ်ဆေးပါ", "wa_approve": "အတည်ပြုပါ", "wa_avg_resolution": "ပျမ်းမျှ ဖြေရှင်းချိန်: {time} မိနစ်", "wa_bus_subscribers": "Bus Subscribers", @@ -2924,6 +2932,18 @@ "wallet_transfer_success": "Transfer အောင်မြင်ful! TX: {tx}", "wallet_trust_degraded": "Hardware ယုံကြည်မှု အားနည်းသွားပြီ", "wallet_warning": "သတိပေး", + "verify_title": "Build တစ်ခုကို အတည်ပြုပါ", + "verify_hash_label": "Build hash", + "verify_button": "စစ်ဆေးပါ", + "verify_undeclared_title": "ဤ node သည် build များကို အတည်ပြုနိုင်သည် မနိုင်သည်ကို ပြောနိုင်စွမ်း မရှိပါ", + "verify_undeclared_body": "ဤ node သည် capability declaration ထက် ပိုမိုဟောင်းနွမ်းသဖြင့် ပြောနိုင်စွမ်း မရှိပါ။ ပိုမို အသစ်သော node တစ်ခုက build များကို အတည်ပြုနိုင်ပါသည်။", + "verify_absent_title": "ဤ node သည် build များကို အတည်ပြု၍ မရပါ", + "verify_absent_body": "ဤ node သည် registry ကို ကိုင်ဆောင်ထားခြင်း မရှိသဖြင့် build များကို စစ်ဆေး၍ မရပါ။ အခြား node တစ်ခုက စစ်ဆေးနိုင်ပါသည်။", + "verify_unreachable_title": "ဤ node ကို ချိတ်ဆက်၍ မရပါ", + "verify_unreachable_body": "node က အဖြေ ပြန်မပေးခဲ့သဖြင့် ၎င်းသည် build များကို အတည်ပြုနိုင်သည် မနိုင်သည်ကို ကျွန်ုပ်တို့ မသိပါ။ ဤသည် သင် စစ်ဆေးနေသော build ၏ ပြဿနာ မဟုတ်ပါ။", + "verify_status_registered": "မှတ်ပုံတင်ထားသည်", + "verify_status_deprecated": "ထပ်မံ အသုံးပြုရန် အကြံမပြုတော့ပါ", + "verify_status_revoked": "ရုပ်သိမ်းထားသည်", "attestation_actions_desc": "ဤမှတ်တမ်းအတွက် လုပ်ဆောင်ချက်များ", "chat_badge_message": "မက်ဆေ့ချ်", "chat_details": "အမျိုးအစား {type} · scope {scope} · အခြေအနေ {status}", diff --git a/client/androidApp/src/main/assets/localization/pa.json b/client/androidApp/src/main/assets/localization/pa.json index b5d51c5..e50e1a8 100644 --- a/client/androidApp/src/main/assets/localization/pa.json +++ b/client/androidApp/src/main/assets/localization/pa.json @@ -2924,6 +2924,27 @@ "wallet_transfer_success": "ਟ੍ਰਾਂਸਫਰ ਸਫਲ! TX: {tx}", "wallet_trust_degraded": "ਹਾਰਡਵੇਅਰ ਭਰੋਸਾ ਘਟਿਆ", "wallet_warning": "ਚੇਤਾਵਨੀ", + "verify_title": "ਇੱਕ ਬਿਲਡ ਦੀ ਪੁਸ਼ਟੀ ਕਰੋ", + "verify_hash_label": "ਬਿਲਡ ਹੈਸ਼", + "verify_button": "ਜਾਂਚ ਕਰੋ", + "verify_undeclared_title": "ਇਹ ਨੋਡ ਨਹੀਂ ਕਹਿ ਸਕਦਾ ਕਿ ਇਹ ਬਿਲਡਾਂ ਦੀ ਪੁਸ਼ਟੀ ਕਰਦਾ ਹੈ ਜਾਂ ਨਹੀਂ", + "verify_undeclared_body": "ਇਹ ਨੋਡ ਸਮਰੱਥਾ ਐਲਾਨ ਤੋਂ ਪੁਰਾਣਾ ਹੈ, ਇਸ ਲਈ ਇਹ ਕੁਝ ਕਹਿ ਨਹੀਂ ਸਕਦਾ। ਇੱਕ ਨਵਾਂ ਨੋਡ ਬਿਲਡਾਂ ਦੀ ਪੁਸ਼ਟੀ ਕਰ ਸਕਦਾ ਹੈ।", + "verify_absent_title": "ਇਹ ਨੋਡ ਬਿਲਡਾਂ ਦੀ ਪੁਸ਼ਟੀ ਨਹੀਂ ਕਰਦਾ", + "verify_absent_body": "ਇਹ ਨੋਡ ਰਜਿਸਟਰੀ ਨਹੀਂ ਰੱਖਦਾ, ਇਸ ਲਈ ਇਹ ਬਿਲਡਾਂ ਦੀ ਜਾਂਚ ਨਹੀਂ ਕਰ ਸਕਦਾ। ਕੋਈ ਹੋਰ ਨੋਡ ਕਰ ਸਕਦਾ ਹੈ।", + "verify_unreachable_title": "ਇਸ ਨੋਡ ਤੱਕ ਨਹੀਂ ਪਹੁੰਚ ਸਕੇ", + "verify_unreachable_body": "ਨੋਡ ਨੇ ਜਵਾਬ ਨਹੀਂ ਦਿੱਤਾ, ਇਸ ਲਈ ਸਾਨੂੰ ਨਹੀਂ ਪਤਾ ਕਿ ਇਹ ਬਿਲਡਾਂ ਦੀ ਪੁਸ਼ਟੀ ਕਰ ਸਕਦਾ ਹੈ ਜਾਂ ਨਹੀਂ। ਇਹ ਉਸ ਬਿਲਡ ਦੀ ਸਮੱਸਿਆ ਨਹੀਂ ਹੈ ਜਿਸਦੀ ਤੁਸੀਂ ਜਾਂਚ ਕਰ ਰਹੇ ਹੋ।", + "verify_status_registered": "ਰਜਿਸਟਰਡ", + "verify_status_deprecated": "ਹੁਣ ਸਿਫ਼ਾਰਸ਼ੀ ਨਹੀਂ", + "verify_status_revoked": "ਰੱਦ ਕੀਤਾ", + "verify_status_unreadable": "ਹਾਲਤ ਪਛਾਣੀ ਨਹੀਂ ਗਈ", + "verify_revoked_warning": "ਇਹ ਬਿਲਡ ਰੱਦ ਕਰ ਦਿੱਤਾ ਗਿਆ ਹੈ। ਇਸਨੂੰ ਨਾ ਵਰਤੋ।", + "verify_not_found_title": "ਇਸ ਬਿਲਡ ਦਾ ਕੋਈ ਰਿਕਾਰਡ ਨਹੀਂ", + "verify_not_found_body": "ਰਜਿਸਟਰੀ ਨੇ ਜਵਾਬ ਦਿੱਤਾ ਅਤੇ ਇਸ ਹੈਸ਼ ਲਈ ਇਸ ਕੋਲ ਕੁਝ ਵੀ ਨਹੀਂ ਹੈ।", + "verify_unavailable_title": "ਜਾਂਚ ਨਹੀਂ ਹੋ ਸਕੀ", + "verify_unavailable_body": "ਇਹ 'ਰਜਿਸਟਰਡ ਨਹੀਂ' ਵਰਗੀ ਗੱਲ ਨਹੀਂ ਹੈ — ਰਜਿਸਟਰੀ ਨੇ ਜਵਾਬ ਨਹੀਂ ਦਿੱਤਾ।", + "verify_undetermined_title": "ਇਹ ਨੋਡ ਇਹ ਪਤਾ ਨਹੀਂ ਲਗਾ ਸਕਿਆ ਕਿ ਇਹ ਕੀ ਕਰ ਸਕਦਾ ਹੈ", + "verify_undetermined_body": "ਨੋਡ ਨੇ ਜਵਾਬ ਤਾਂ ਦਿੱਤਾ, ਪਰ ਆਪਣਾ ਕੁੰਜੀ ਰਿਕਾਰਡ ਨਹੀਂ ਪੜ੍ਹ ਸਕਿਆ। ਇਹ ਆਮ ਤੌਰ 'ਤੇ ਅਸਥਾਈ ਹੁੰਦਾ ਹੈ — ਥੋੜ੍ਹੀ ਦੇਰ ਵਿੱਚ ਦੁਬਾਰਾ ਕੋਸ਼ਿਸ਼ ਕਰੋ।", + "verify_retry": "ਦੁਬਾਰਾ ਜਾਂਚ ਕਰੋ", "attestation_actions_desc": "ਇਸ ਰਿਕਾਰਡ ਲਈ ਕਾਰਵਾਈਆਂ", "chat_badge_message": "ਸੁਨੇਹਾ", "chat_details": "ਕਿਸਮ {type} · ਦਾਇਰਾ {scope} · ਸਥਿਤੀ {status}", diff --git a/client/androidApp/src/main/assets/localization/pt.json b/client/androidApp/src/main/assets/localization/pt.json index d4d550e..4cd2723 100644 --- a/client/androidApp/src/main/assets/localization/pt.json +++ b/client/androidApp/src/main/assets/localization/pt.json @@ -2924,6 +2924,27 @@ "wallet_transfer_success": "Transferência bem-sucedida! TX: {tx}", "wallet_trust_degraded": "Confiança de Hardware Degradada", "wallet_warning": "Aviso", + "verify_title": "Verificar uma build", + "verify_hash_label": "Hash da build", + "verify_button": "Verificar", + "verify_undeclared_title": "Este nó não pode dizer se verifica builds", + "verify_undeclared_body": "Este nó é mais antigo do que a declaração de capacidades, portanto não pode dizer. Um nó mais recente pode verificar builds.", + "verify_absent_title": "Este nó não verifica builds", + "verify_absent_body": "Este nó não possui o registro, portanto não pode verificar builds. Outro nó pode.", + "verify_unreachable_title": "Não foi possível alcançar este nó", + "verify_unreachable_body": "O nó não respondeu, portanto não sabemos se ele pode verificar builds. Isto não é um problema com a build que você está verificando.", + "verify_status_registered": "Registrada", + "verify_status_deprecated": "Não mais recomendada", + "verify_status_revoked": "Revogada", + "verify_status_unreadable": "Status não reconhecido", + "verify_revoked_warning": "Esta build foi revogada. Não a use.", + "verify_not_found_title": "Nenhum registro desta build", + "verify_not_found_body": "O registro respondeu e não contém nada para este hash.", + "verify_unavailable_title": "Não foi possível verificar", + "verify_unavailable_body": "Isto não é o mesmo que 'não registrada' — o registro não respondeu.", + "verify_undetermined_title": "Este nó não conseguiu determinar o que pode fazer", + "verify_undetermined_body": "O nó respondeu, mas não conseguiu ler o próprio registro de chave. Isto costuma ser temporário — tente novamente em breve.", + "verify_retry": "Verificar novamente", "attestation_actions_desc": "Ações para este registo", "chat_badge_message": "MENSAGEM", "chat_details": "tipo {type} · âmbito {scope} · estado {status}", diff --git a/client/androidApp/src/main/assets/localization/ru.json b/client/androidApp/src/main/assets/localization/ru.json index db4bf61..14028b7 100644 --- a/client/androidApp/src/main/assets/localization/ru.json +++ b/client/androidApp/src/main/assets/localization/ru.json @@ -2924,6 +2924,27 @@ "wallet_transfer_success": "Перевод успешен! TX: {tx}", "wallet_trust_degraded": "Доверие к оборудованию ухудшено", "wallet_warning": "Предупреждение", + "verify_title": "Проверить сборку", + "verify_hash_label": "Хеш сборки", + "verify_button": "Проверить", + "verify_undeclared_title": "Этот узел не может сказать, проверяет ли он сборки", + "verify_undeclared_body": "Этот узел старше объявления возможностей, поэтому не может сказать. Более новый узел может проверять сборки.", + "verify_absent_title": "Этот узел не проверяет сборки", + "verify_absent_body": "Этот узел не хранит реестр, поэтому не может проверять сборки. Другой узел может.", + "verify_unreachable_title": "Не удалось связаться с этим узлом", + "verify_unreachable_body": "Узел не ответил, поэтому неизвестно, может ли он проверять сборки. Это не связано с проверяемой вами сборкой.", + "verify_status_registered": "Зарегистрирована", + "verify_status_deprecated": "Больше не рекомендуется", + "verify_status_revoked": "Отозвана", + "verify_status_unreadable": "Статус не распознан", + "verify_revoked_warning": "Эта сборка отозвана. Не используйте её.", + "verify_not_found_title": "Нет записи об этой сборке", + "verify_not_found_body": "Реестр ответил, но не содержит записи для этого хеша.", + "verify_unavailable_title": "Не удалось проверить", + "verify_unavailable_body": "Это не то же самое, что «не зарегистрирована» — реестр не ответил.", + "verify_undetermined_title": "Этот узел не смог определить, что он может делать", + "verify_undetermined_body": "Узел ответил, но не смог прочитать собственную запись ключа. Обычно это временно — повторите попытку через некоторое время.", + "verify_retry": "Проверить снова", "attestation_actions_desc": "Действия для этой записи", "chat_badge_message": "СООБЩЕНИЕ", "chat_details": "тип {type} · область {scope} · статус {status}", diff --git a/client/androidApp/src/main/assets/localization/sw.json b/client/androidApp/src/main/assets/localization/sw.json index 17baf50..2ebcdb1 100644 --- a/client/androidApp/src/main/assets/localization/sw.json +++ b/client/androidApp/src/main/assets/localization/sw.json @@ -2924,6 +2924,27 @@ "wallet_transfer_success": "Uhamisho umefanikiwa! TX: {tx}", "wallet_trust_degraded": "Kuaminika kwa Maunzi Kumedhoofika", "wallet_warning": "Onyo", + "verify_title": "Thibitisha toleo", + "verify_hash_label": "Hash ya toleo", + "verify_button": "Kagua", + "verify_undeclared_title": "Nodi hii haiwezi kusema kama inathibitisha matoleo", + "verify_undeclared_body": "Nodi hii ni ya zamani kuliko tamko la uwezo, kwa hivyo haiwezi kusema. Nodi mpya zaidi inaweza kuthibitisha matoleo.", + "verify_absent_title": "Nodi hii haithibitishi matoleo", + "verify_absent_body": "Nodi hii haibebi sajili, kwa hivyo haiwezi kukagua matoleo. Nodi nyingine inaweza.", + "verify_unreachable_title": "Imeshindwa kufikia nodi hii", + "verify_unreachable_body": "Nodi haikujibu, kwa hivyo hatujui kama inaweza kuthibitisha matoleo. Hili si tatizo la toleo unalolikagua.", + "verify_status_registered": "Limesajiliwa", + "verify_status_deprecated": "Halipendekezwi tena", + "verify_status_revoked": "Limebatilishwa", + "verify_status_unreadable": "Hali haitambuliki", + "verify_revoked_warning": "Toleo hili limebatilishwa. Usilitumie.", + "verify_not_found_title": "Hakuna rekodi ya toleo hili", + "verify_not_found_body": "Sajili ilijibu na haina kitu kwa hash hii.", + "verify_unavailable_title": "Imeshindwa kukagua", + "verify_unavailable_body": "Hii si sawa na 'halijasajiliwa' — sajili haikujibu.", + "verify_undetermined_title": "Nodi hii haikuweza kubaini kile inachoweza kufanya", + "verify_undetermined_body": "Nodi ilijibu, lakini haikuweza kusoma rekodi yake yenyewe ya ufunguo. Hii kwa kawaida ni ya muda tu — jaribu tena baada ya muda mfupi.", + "verify_retry": "Kagua tena", "attestation_actions_desc": "Vitendo vya rekodi hii", "chat_badge_message": "UJUMBE", "chat_details": "aina {type} · wigo {scope} · hali {status}", diff --git a/client/androidApp/src/main/assets/localization/ta.json b/client/androidApp/src/main/assets/localization/ta.json index f3a999a..166494d 100644 --- a/client/androidApp/src/main/assets/localization/ta.json +++ b/client/androidApp/src/main/assets/localization/ta.json @@ -2924,6 +2924,27 @@ "wallet_transfer_success": "பரிமாற்றம் வெற்றிகரம்! TX: {tx}", "wallet_trust_degraded": "Hardware நம்பகத்தன்மை Degraded", "wallet_warning": "எச்சரிக்கை", + "verify_title": "ஒரு பதிப்பைச் சரிபார்", + "verify_hash_label": "பதிப்பு ஹாஷ்", + "verify_button": "சரிபார்", + "verify_undeclared_title": "இந்த முனை பதிப்புகளைச் சரிபார்க்கிறதா என்று கூற முடியாது", + "verify_undeclared_body": "இந்த முனை திறன் அறிவிப்பைவிட பழையது; எனவே இதனால் கூற முடியாது. புதிய முனையால் பதிப்புகளைச் சரிபார்க்க முடியும்.", + "verify_absent_title": "இந்த முனை பதிப்புகளைச் சரிபார்க்காது", + "verify_absent_body": "இந்த முனையிடம் பதிவகம் இல்லை; எனவே இதனால் பதிப்புகளைச் சரிபார்க்க முடியாது. வேறொரு முனையால் முடியும்.", + "verify_unreachable_title": "இந்த முனையை அணுக முடியவில்லை", + "verify_unreachable_body": "முனை பதிலளிக்கவில்லை; எனவே அதனால் பதிப்புகளைச் சரிபார்க்க முடியுமா என்பது எங்களுக்குத் தெரியாது. இது நீங்கள் சரிபார்க்கும் பதிப்பின் சிக்கல் அல்ல.", + "verify_status_registered": "பதிவு செய்யப்பட்டது", + "verify_status_deprecated": "இனி பரிந்துரைக்கப்படவில்லை", + "verify_status_revoked": "திரும்பப் பெறப்பட்டது", + "verify_status_unreadable": "நிலை அறியப்படவில்லை", + "verify_revoked_warning": "இந்தப் பதிப்பு திரும்பப் பெறப்பட்டுள்ளது. இதைப் பயன்படுத்த வேண்டாம்.", + "verify_not_found_title": "இந்தப் பதிப்புக்கான பதிவு இல்லை", + "verify_not_found_body": "பதிவகம் பதிலளித்தது, இந்த ஹாஷுக்கு எதுவும் வைத்திருக்கவில்லை.", + "verify_unavailable_title": "சரிபார்க்க முடியவில்லை", + "verify_unavailable_body": "இது 'பதிவு செய்யப்படவில்லை' என்பதற்குச் சமமானதல்ல — பதிவகம் பதிலளிக்கவில்லை.", + "verify_undetermined_title": "இந்த முனை தன்னால் என்ன செய்ய முடியும் என்பதைத் தீர்மானிக்க முடியவில்லை", + "verify_undetermined_body": "முனை பதிலளித்தது, ஆனால் தன் சொந்த விசைப் பதிவை வாசிக்க முடியவில்லை. இது பொதுவாக தற்காலிகமானது — சிறிது நேரத்தில் மீண்டும் முயலவும்.", + "verify_retry": "மீண்டும் சரிபார்", "attestation_actions_desc": "இந்தப் பதிவுக்கான செயல்கள்", "chat_badge_message": "செய்தி", "chat_details": "வகை {type} · எல்லை {scope} · நிலை {status}", diff --git a/client/androidApp/src/main/assets/localization/te.json b/client/androidApp/src/main/assets/localization/te.json index 57f56c3..d5ae35d 100644 --- a/client/androidApp/src/main/assets/localization/te.json +++ b/client/androidApp/src/main/assets/localization/te.json @@ -2924,6 +2924,27 @@ "wallet_transfer_success": "బదిలీ విజయవంతమైంది! TX: {tx}", "wallet_trust_degraded": "హార్డ్‌వేర్ నమ్మకం తగ్గింది", "wallet_warning": "హెచ్చరిక", + "verify_title": "బిల్డ్‌ను ధృవీకరించండి", + "verify_hash_label": "బిల్డ్ హాష్", + "verify_button": "తనిఖీ చేయండి", + "verify_undeclared_title": "ఈ నోడ్ బిల్డ్‌లను ధృవీకరిస్తుందో లేదో చెప్పలేకపోతుంది", + "verify_undeclared_body": "ఈ నోడ్ కేపబిలిటీ ప్రకటన కంటే పాతది, కాబట్టి ఇది చెప్పలేకపోతుంది. కొత్త నోడ్ బిల్డ్‌లను ధృవీకరించగలదు.", + "verify_absent_title": "ఈ నోడ్ బిల్డ్‌లను ధృవీకరించదు", + "verify_absent_body": "ఈ నోడ్ వద్ద రిజిస్ట్రీ లేదు, కాబట్టి ఇది బిల్డ్‌లను తనిఖీ చేయలేకపోతుంది. మరో నోడ్ చేయగలదు.", + "verify_unreachable_title": "ఈ నోడ్‌ను చేరుకోలేకపోయాం", + "verify_unreachable_body": "నోడ్ స్పందించలేదు, కాబట్టి అది బిల్డ్‌లను ధృవీకరించగలదో లేదో మాకు తెలియదు. ఇది మీరు తనిఖీ చేస్తున్న బిల్డ్‌లో సమస్య కాదు.", + "verify_status_registered": "నమోదైంది", + "verify_status_deprecated": "ఇక సిఫార్సు చేయబడదు", + "verify_status_revoked": "రద్దు చేయబడింది", + "verify_status_unreadable": "స్థితి గుర్తించబడలేదు", + "verify_revoked_warning": "ఈ బిల్డ్ రద్దు చేయబడింది. దీన్ని ఉపయోగించవద్దు.", + "verify_not_found_title": "ఈ బిల్డ్ గురించి రికార్డు లేదు", + "verify_not_found_body": "రిజిస్ట్రీ స్పందించింది, కానీ ఈ హాష్ కోసం ఏమీ లేదు.", + "verify_unavailable_title": "తనిఖీ చేయలేకపోయాం", + "verify_unavailable_body": "ఇది 'నమోదు కాలేదు' అనే దానికి సమానం కాదు — రిజిస్ట్రీ స్పందించలేదు.", + "verify_undetermined_title": "ఈ నోడ్ తాను ఏమి చేయగలదో నిర్ధారించలేకపోయింది", + "verify_undetermined_body": "నోడ్ స్పందించింది, కానీ తన సొంత కీ రికార్డును చదవలేకపోయింది. ఇది సాధారణంగా తాత్కాలికం — కొద్ది సేపట్లో మళ్ళీ ప్రయత్నించండి.", + "verify_retry": "మళ్ళీ తనిఖీ చేయండి", "attestation_actions_desc": "ఈ రికార్డుకు చర్యలు", "chat_badge_message": "సందేశం", "chat_details": "రకం {type} · పరిధి {scope} · స్థితి {status}", diff --git a/client/androidApp/src/main/assets/localization/th.json b/client/androidApp/src/main/assets/localization/th.json index 079e23f..cba9e06 100644 --- a/client/androidApp/src/main/assets/localization/th.json +++ b/client/androidApp/src/main/assets/localization/th.json @@ -2924,6 +2924,27 @@ "wallet_transfer_success": "Transfer สำเร็จful! TX: {tx}", "wallet_trust_degraded": "ความน่าเชื่อถือของฮาร์ดแวร์ลดลง", "wallet_warning": "คำเตือน", + "verify_title": "ตรวจสอบ build", + "verify_hash_label": "Hash ของ build", + "verify_button": "ตรวจสอบ", + "verify_undeclared_title": "โหนดนี้บอกไม่ได้ว่าตนตรวจสอบ build หรือไม่", + "verify_undeclared_body": "โหนดนี้เก่ากว่าคำประกาศความสามารถ จึงบอกไม่ได้ โหนดที่ใหม่กว่าสามารถตรวจสอบ build ได้", + "verify_absent_title": "โหนดนี้ไม่ตรวจสอบ build", + "verify_absent_body": "โหนดนี้ไม่มีรีจิสทรี จึงไม่สามารถตรวจสอบ build ได้ โหนดอื่นสามารถทำได้", + "verify_unreachable_title": "ไม่สามารถติดต่อโหนดนี้ได้", + "verify_unreachable_body": "โหนดไม่ตอบสนอง เราจึงไม่ทราบว่าโหนดสามารถตรวจสอบ build ได้หรือไม่ นี่ไม่ใช่ปัญหาของ build ที่คุณกำลังตรวจสอบ", + "verify_status_registered": "ลงทะเบียนแล้ว", + "verify_status_deprecated": "ไม่แนะนำให้ใช้อีกต่อไป", + "verify_status_revoked": "ถูกเพิกถอน", + "verify_status_unreadable": "ไม่รู้จักสถานะ", + "verify_revoked_warning": "Build นี้ถูกเพิกถอนแล้ว อย่าใช้งาน", + "verify_not_found_title": "ไม่มีบันทึกสำหรับ build นี้", + "verify_not_found_body": "รีจิสทรีตอบกลับแล้ว และไม่มีข้อมูลสำหรับ hash นี้", + "verify_unavailable_title": "ไม่สามารถตรวจสอบได้", + "verify_unavailable_body": "นี่ไม่เหมือนกับ 'ไม่ได้ลงทะเบียน' — รีจิสทรีไม่ตอบสนอง", + "verify_undetermined_title": "โหนดนี้ไม่สามารถระบุได้ว่าตนทำสิ่งใดได้", + "verify_undetermined_body": "โหนดตอบแล้ว แต่อ่านบันทึกคีย์ของตนเองไม่ได้ โดยปกติแล้วนี่เป็นเพียงชั่วคราว — ลองอีกครั้งในไม่ช้า", + "verify_retry": "ตรวจสอบอีกครั้ง", "attestation_actions_desc": "การดำเนินการสำหรับระเบียนนี้", "chat_badge_message": "ข้อความ", "chat_details": "ประเภท {type} · ขอบเขต {scope} · สถานะ {status}", diff --git a/client/androidApp/src/main/assets/localization/tr.json b/client/androidApp/src/main/assets/localization/tr.json index 2bc1988..6729871 100644 --- a/client/androidApp/src/main/assets/localization/tr.json +++ b/client/androidApp/src/main/assets/localization/tr.json @@ -2924,6 +2924,27 @@ "wallet_transfer_success": "Transfer başarılı! TX: {tx}", "wallet_trust_degraded": "Donanım Güveni Düşmüş", "wallet_warning": "Uyarı", + "verify_title": "Bir derlemeyi doğrula", + "verify_hash_label": "Derleme hash'i", + "verify_button": "Kontrol Et", + "verify_undeclared_title": "Bu düğüm, derlemeleri doğrulayıp doğrulamadığını söyleyemez", + "verify_undeclared_body": "Bu düğüm, yetenek ilanından daha eski; dolayısıyla bunu söyleyemez. Daha yeni bir düğüm derlemeleri doğrulayabilir.", + "verify_absent_title": "Bu düğüm derlemeleri doğrulamıyor", + "verify_absent_body": "Bu düğüm sicili taşımıyor, dolayısıyla derlemeleri kontrol edemez. Başka bir düğüm kontrol edebilir.", + "verify_unreachable_title": "Bu düğüme erişilemedi", + "verify_unreachable_body": "Düğüm yanıt vermedi; dolayısıyla derlemeleri doğrulayıp doğrulayamayacağını bilmiyoruz. Bu, kontrol ettiğiniz derlemeyle ilgili bir sorun değildir.", + "verify_status_registered": "Kayıtlı", + "verify_status_deprecated": "Artık önerilmiyor", + "verify_status_revoked": "İptal Edildi", + "verify_status_unreadable": "Durum tanınmıyor", + "verify_revoked_warning": "Bu derleme iptal edilmiştir. Kullanmayın.", + "verify_not_found_title": "Bu derlemeye ait kayıt yok", + "verify_not_found_body": "Sicil yanıt verdi ve bu hash için hiçbir kayıt tutmuyor.", + "verify_unavailable_title": "Kontrol edilemedi", + "verify_unavailable_body": "Bu, 'kayıtlı değil' ile aynı şey değildir — sicil yanıt vermedi.", + "verify_undetermined_title": "Bu düğüm ne yapabileceğini belirleyemedi", + "verify_undetermined_body": "Düğüm yanıt verdi, ancak kendi anahtar kaydını okuyamadı. Bu genellikle geçicidir — kısa süre sonra tekrar deneyin.", + "verify_retry": "Yeniden kontrol et", "attestation_actions_desc": "Bu kayıt için eylemler", "chat_badge_message": "MESAJ", "chat_details": "tür {type} · kapsam {scope} · durum {status}", diff --git a/client/androidApp/src/main/assets/localization/uk.json b/client/androidApp/src/main/assets/localization/uk.json index 9de68ee..398a7c9 100644 --- a/client/androidApp/src/main/assets/localization/uk.json +++ b/client/androidApp/src/main/assets/localization/uk.json @@ -2924,6 +2924,27 @@ "wallet_transfer_success": "Переказ успішний! TX: {tx}", "wallet_trust_degraded": "Апаратну довіру знижено", "wallet_warning": "Попередження", + "verify_title": "Перевірити збірку", + "verify_hash_label": "Хеш збірки", + "verify_button": "Перевірити", + "verify_undeclared_title": "Цей вузол не може сказати, чи перевіряє він збірки", + "verify_undeclared_body": "Цей вузол старіший за декларацію можливостей, тож не може це сказати. Новіший вузол може перевіряти збірки.", + "verify_absent_title": "Цей вузол не перевіряє збірки", + "verify_absent_body": "Цей вузол не тримає реєстр, тож не може перевіряти збірки. Інший вузол може.", + "verify_unreachable_title": "Не вдалося зв'язатися з цим вузлом", + "verify_unreachable_body": "Вузол не відповів, тож ми не знаємо, чи може він перевіряти збірки. Це не проблема зі збіркою, яку ви перевіряєте.", + "verify_status_registered": "Зареєстровано", + "verify_status_deprecated": "Більше не рекомендується", + "verify_status_revoked": "Відкликано", + "verify_status_unreadable": "Статус не розпізнано", + "verify_revoked_warning": "Цю збірку відкликано. Не використовуйте її.", + "verify_not_found_title": "Немає запису про цю збірку", + "verify_not_found_body": "Реєстр відповів і не має нічого для цього хешу.", + "verify_unavailable_title": "Не вдалося перевірити", + "verify_unavailable_body": "Це не те саме, що «не зареєстровано» — реєстр не відповів.", + "verify_undetermined_title": "Цей вузол не зміг визначити, що він може робити", + "verify_undetermined_body": "Вузол відповів, але не зміг прочитати власний запис ключа. Зазвичай це тимчасово — спробуйте ще раз незабаром.", + "verify_retry": "Перевірити ще раз", "attestation_actions_desc": "Дії для цього запису", "chat_badge_message": "ПОВІДОМЛЕННЯ", "chat_details": "тип {type} · область {scope} · статус {status}", diff --git a/client/androidApp/src/main/assets/localization/ur.json b/client/androidApp/src/main/assets/localization/ur.json index cecd77f..462a656 100644 --- a/client/androidApp/src/main/assets/localization/ur.json +++ b/client/androidApp/src/main/assets/localization/ur.json @@ -2924,6 +2924,27 @@ "wallet_transfer_success": "ٹرانسفر کامیاب! TX: {tx}", "wallet_trust_degraded": "ہارڈ ویئر اعتماد کمزور پڑ گیا", "wallet_warning": "انتباہ", + "verify_title": "بلڈ کی تصدیق کریں", + "verify_hash_label": "بلڈ ہیش", + "verify_button": "جانچیں", + "verify_undeclared_title": "یہ نوڈ نہیں بتا سکتا کہ آیا وہ بلڈز کی تصدیق کرتا ہے", + "verify_undeclared_body": "یہ نوڈ صلاحیت کے اعلان سے پرانا ہے، اس لیے یہ نہیں بتا سکتا۔ ایک نیا نوڈ بلڈز کی تصدیق کر سکتا ہے۔", + "verify_absent_title": "یہ نوڈ بلڈز کی تصدیق نہیں کرتا", + "verify_absent_body": "یہ نوڈ رجسٹری نہیں رکھتا، اس لیے یہ بلڈز کی جانچ نہیں کر سکتا۔ کوئی دوسرا نوڈ کر سکتا ہے۔", + "verify_unreachable_title": "اس نوڈ تک رسائی نہیں ہو سکی", + "verify_unreachable_body": "نوڈ نے جواب نہیں دیا، اس لیے ہمیں معلوم نہیں کہ وہ بلڈز کی تصدیق کر سکتا ہے یا نہیں۔ یہ اس بلڈ کا مسئلہ نہیں جس کی آپ جانچ کر رہے ہیں۔", + "verify_status_registered": "رجسٹرڈ", + "verify_status_deprecated": "اب تجویز نہیں کیا جاتا", + "verify_status_revoked": "منسوخ شدہ", + "verify_status_unreadable": "حیثیت شناخت نہیں ہو سکی", + "verify_revoked_warning": "یہ بلڈ منسوخ کر دیا گیا ہے۔ اسے استعمال نہ کریں۔", + "verify_not_found_title": "اس بلڈ کا کوئی ریکارڈ نہیں", + "verify_not_found_body": "رجسٹری نے جواب دیا، اور اس کے پاس اس ہیش کے لیے کچھ نہیں ہے۔", + "verify_unavailable_title": "جانچ نہیں ہو سکی", + "verify_unavailable_body": "یہ 'رجسٹرڈ نہیں' کے برابر نہیں — رجسٹری نے جواب نہیں دیا۔", + "verify_undetermined_title": "یہ نوڈ طے نہیں کر سکا کہ وہ کیا کر سکتا ہے", + "verify_undetermined_body": "نوڈ نے جواب دیا، مگر اپنا کلیدی ریکارڈ نہ پڑھ سکا۔ یہ عام طور پر عارضی ہوتا ہے — تھوڑی دیر بعد دوبارہ کوشش کریں۔", + "verify_retry": "دوبارہ جانچیں", "attestation_actions_desc": "اس ریکارڈ کے لیے اقدامات", "chat_badge_message": "پیغام", "chat_details": "قسم {type} · دائرہ {scope} · حیثیت {status}", diff --git a/client/androidApp/src/main/assets/localization/vi.json b/client/androidApp/src/main/assets/localization/vi.json index 24135ce..6bc35d0 100644 --- a/client/androidApp/src/main/assets/localization/vi.json +++ b/client/androidApp/src/main/assets/localization/vi.json @@ -2924,6 +2924,27 @@ "wallet_transfer_success": "Chuyển khoản thành công! TX: {tx}", "wallet_trust_degraded": "Tin tưởng Suy giảm", "wallet_warning": "Cảnh báo", + "verify_title": "Xác minh một bản dựng", + "verify_hash_label": "Hash bản dựng", + "verify_button": "Kiểm tra", + "verify_undeclared_title": "Nút này không thể cho biết liệu nó có xác minh các bản dựng hay không", + "verify_undeclared_body": "Nút này cũ hơn bản khai năng lực, nên không thể trả lời. Một nút mới hơn có thể xác minh các bản dựng.", + "verify_absent_title": "Nút này không xác minh các bản dựng", + "verify_absent_body": "Nút này không giữ sổ đăng ký, nên không thể kiểm tra các bản dựng. Một nút khác có thể làm điều đó.", + "verify_unreachable_title": "Không thể kết nối với nút này", + "verify_unreachable_body": "Nút không phản hồi, nên chúng ta không biết liệu nó có thể xác minh các bản dựng hay không. Đây không phải là vấn đề của bản dựng bạn đang kiểm tra.", + "verify_status_registered": "Đã đăng ký", + "verify_status_deprecated": "Không còn được khuyến nghị", + "verify_status_revoked": "Đã bị thu hồi", + "verify_status_unreadable": "Không nhận dạng được trạng thái", + "verify_revoked_warning": "Bản dựng này đã bị thu hồi. Không sử dụng nó.", + "verify_not_found_title": "Không có bản ghi cho bản dựng này", + "verify_not_found_body": "Sổ đăng ký đã phản hồi và không có gì cho hash này.", + "verify_unavailable_title": "Không thể kiểm tra", + "verify_unavailable_body": "Điều này không giống với “chưa đăng ký” — sổ đăng ký không phản hồi.", + "verify_undetermined_title": "Nút này không thể xác định được nó có thể làm gì", + "verify_undetermined_body": "Nút đã trả lời, nhưng không đọc được bản ghi khóa của chính nó. Thông thường đây là tình trạng tạm thời — hãy thử lại sau.", + "verify_retry": "Kiểm tra lại", "attestation_actions_desc": "Các thao tác cho bản ghi này", "chat_badge_message": "TIN NHẮN", "chat_details": "loại {type} · phạm vi {scope} · trạng thái {status}", diff --git a/client/androidApp/src/main/assets/localization/yo.json b/client/androidApp/src/main/assets/localization/yo.json index c7c0a0f..f676e88 100644 --- a/client/androidApp/src/main/assets/localization/yo.json +++ b/client/androidApp/src/main/assets/localization/yo.json @@ -2924,6 +2924,27 @@ "wallet_transfer_success": "Gbígbé ṣe àṣeyọrí! TX: {tx}", "wallet_trust_degraded": "Ìgbẹ́kẹ̀lé Ohun Ẹ̀rọ Ti Dín Kù", "wallet_warning": "Ìkìlọ̀", + "verify_title": "Jẹ́rìísí build kan", + "verify_hash_label": "Hash build", + "verify_button": "Ṣàyẹ̀wò", + "verify_undeclared_title": "Nódù yìí kò lè sọ bóyá ó ń jẹ́rìísí àwọn build", + "verify_undeclared_body": "Nódù yìí dàgbà ju ìkéde agbára rẹ̀ lọ, nítorí náà kò lè sọ. Nódù tí ó ṣẹ̀ṣẹ̀ dé lè jẹ́rìísí àwọn build.", + "verify_absent_title": "Nódù yìí kì í jẹ́rìísí àwọn build", + "verify_absent_body": "Nódù yìí kò gbé àkójọ ìforúkọsílẹ̀, nítorí náà kò lè ṣàyẹ̀wò àwọn build. Nódù mìíràn lè ṣe é.", + "verify_unreachable_title": "A kò lè dé nódù yìí", + "verify_unreachable_body": "Nódù náà kò dáhùn, nítorí náà a kò mọ̀ bóyá ó lè jẹ́rìísí àwọn build. Èyí kì í ṣe ìṣòrò pẹ̀lú build tí o ń ṣàyẹ̀wò.", + "verify_status_registered": "Tí a forúkọsílẹ̀", + "verify_status_deprecated": "A kò gbà á nímọ̀ràn mọ́", + "verify_status_revoked": "Tí a fagilé", + "verify_status_unreadable": "Ipò tí a kò dá mọ̀", + "verify_revoked_warning": "A ti fagilé build yìí. Má lò ó.", + "verify_not_found_title": "Kò sí àkọsílẹ̀ fún build yìí", + "verify_not_found_body": "Àkójọ ìforúkọsílẹ̀ dáhùn, kò sì ní ohunkóhun fún hash yìí.", + "verify_unavailable_title": "A kò lè ṣàyẹ̀wò", + "verify_unavailable_body": "Èyí kò rí bákan náà pẹ̀lú 'a kò forúkọsílẹ̀' — àkójọ ìforúkọsílẹ̀ kò dáhùn.", + "verify_undetermined_title": "Nódù yìí kò lè pinnu ohun tí ó lè ṣe", + "verify_undetermined_body": "Nódù náà dáhùn, ṣùgbọ́n kò lè ka àkọsílẹ̀ kọ́kọ́rọ́ tirẹ̀. Èyí sábà máa ń jẹ́ fún ìgbà kékeré — gbìyànjú lẹ́ẹ̀kansi láìpẹ́.", + "verify_retry": "Ṣàyẹ̀wò lẹ́ẹ̀kansi", "attestation_actions_desc": "Àwọn ìgbésẹ̀ fún àkọsílẹ̀ yìí", "chat_badge_message": "ÌFIRÁNṢẸ́", "chat_details": "irú {type} · ààlà {scope} · ipò {status}", diff --git a/client/androidApp/src/main/assets/localization/zh.json b/client/androidApp/src/main/assets/localization/zh.json index 570ceda..c59f0cd 100644 --- a/client/androidApp/src/main/assets/localization/zh.json +++ b/client/androidApp/src/main/assets/localization/zh.json @@ -2924,6 +2924,27 @@ "wallet_transfer_success": "转账成功!TX: {tx}", "wallet_trust_degraded": "硬件信任降级", "wallet_warning": "警告", + "verify_title": "验证构建版本", + "verify_hash_label": "构建哈希", + "verify_button": "检查", + "verify_undeclared_title": "本节点无法说明自己是否验证构建版本", + "verify_undeclared_body": "本节点的版本早于能力声明机制,因此无法作答。更新版本的节点可以验证构建版本。", + "verify_absent_title": "本节点不验证构建版本", + "verify_absent_body": "本节点未持有注册表,因此无法检查构建版本。其他节点可以。", + "verify_unreachable_title": "无法连接到该节点", + "verify_unreachable_body": "该节点未作应答,因此我们不知道它是否能够验证构建版本。这不是您正在检查的构建版本本身的问题。", + "verify_status_registered": "已注册", + "verify_status_deprecated": "不再推荐", + "verify_status_revoked": "已撤销", + "verify_status_unreadable": "状态无法识别", + "verify_revoked_warning": "该构建版本已被撤销。请勿使用。", + "verify_not_found_title": "没有该构建版本的记录", + "verify_not_found_body": "注册表已应答,但未持有该哈希的任何记录。", + "verify_unavailable_title": "无法检查", + "verify_unavailable_body": "这与“未注册”并不相同——注册表未作应答。", + "verify_undetermined_title": "本节点无法确定自己能做什么", + "verify_undetermined_body": "该节点作出了应答,但无法读取自己的密钥记录。这通常是暂时性的——请稍后重试。", + "verify_retry": "重新检查", "attestation_actions_desc": "此记录的操作", "chat_badge_message": "消息", "chat_details": "类型 {type} · 范围 {scope} · 状态 {status}", diff --git a/client/desktopApp/src/main/resources/localization/am.json b/client/desktopApp/src/main/resources/localization/am.json index 6fc10f6..54741c5 100644 --- a/client/desktopApp/src/main/resources/localization/am.json +++ b/client/desktopApp/src/main/resources/localization/am.json @@ -2924,6 +2924,27 @@ "wallet_transfer_success": "ማስተላለፍ ተሳክቷል! TX: {tx}", "wallet_trust_degraded": "ስልክ ሥቅ ተዳክሞ ነበር", "wallet_warning": "ማስጠንቀቂያ", + "verify_title": "ግንባታ ማረጋገጥ", + "verify_hash_label": "የግንባታ ሃሽ", + "verify_button": "አረጋግጥ", + "verify_undeclared_title": "ይህ ኖድ ግንባታዎችን እንደሚያረጋግጥ ወይም እንደማያረጋግጥ መናገር አይችልም", + "verify_undeclared_body": "ይህ ኖድ ከችሎታ መግለጫው የቀደመ ነው፤ ስለዚህ መናገር አይችልም። አዲስ ኖድ ግንባታዎችን ማረጋገጥ ይችላል።", + "verify_absent_title": "ይህ ኖድ ግንባታዎችን አያረጋግጥም", + "verify_absent_body": "ይህ ኖድ መዝገቡን አልያዘም፤ ስለዚህ ግንባታዎችን ማረጋገጥ አይችልም። ሌላ ኖድ ግን ይችላል።", + "verify_unreachable_title": "ወደዚህ ኖድ መድረስ አልተቻለም", + "verify_unreachable_body": "ኖዱ መልስ አልሰጠም፤ ስለዚህ ግንባታዎችን ማረጋገጥ እንደሚችል ወይም እንደማይችል አናውቅም። ይህ እርስዎ የሚያረጋግጡት ግንባታ ችግር አይደለም።", + "verify_status_registered": "ተመዝግቧል", + "verify_status_deprecated": "ከዚህ በኋላ አይመከርም", + "verify_status_revoked": "ተሰርዟል", + "verify_status_unreadable": "ሁኔታው አልታወቀም", + "verify_revoked_warning": "ይህ ግንባታ ተሰርዟል። አይጠቀሙበት።", + "verify_not_found_title": "ለዚህ ግንባታ ምንም መዝገብ የለም", + "verify_not_found_body": "መዝገቡ መልስ ሰጥቷል፤ ለዚህ ሃሽ ምንም አልያዘም።", + "verify_unavailable_title": "ማረጋገጥ አልተቻለም", + "verify_unavailable_body": "ይህ ‘አልተመዘገበም’ ከመባል ጋር አንድ አይደለም — መዝገቡ መልስ አልሰጠም።", + "verify_undetermined_title": "ይህ ኖድ ምን ማድረግ እንደሚችል መወሰን አልቻለም", + "verify_undetermined_body": "ኖዱ መልስ ሰጥቷል፣ ሆኖም የራሱን የቁልፍ መዝገብ ማንበብ አልቻለም። ይህ በተለምዶ ጊዜያዊ ነው — ከጥቂት ጊዜ በኋላ እንደገና ይሞክሩ።", + "verify_retry": "እንደገና አረጋግጥ", "attestation_actions_desc": "ለዚህ መዝገብ ያሉ እርምጃዎች", "chat_badge_message": "መልዕክት", "chat_details": "ዓይነት {type} · ወሰን {scope} · ሁኔታ {status}", diff --git a/client/desktopApp/src/main/resources/localization/ar.json b/client/desktopApp/src/main/resources/localization/ar.json index 52541c6..48f9965 100644 --- a/client/desktopApp/src/main/resources/localization/ar.json +++ b/client/desktopApp/src/main/resources/localization/ar.json @@ -2924,6 +2924,27 @@ "wallet_transfer_success": "نجح التحويل! TX: {tx}", "wallet_trust_degraded": "تدهورت ثقة الأجهزة", "wallet_warning": "تحذير", + "verify_title": "التحقق من إصدار", + "verify_hash_label": "بصمة الإصدار", + "verify_button": "تحقّق", + "verify_undeclared_title": "لا تستطيع هذه العقدة الإفادة عن قدرتها على التحقق من الإصدارات", + "verify_undeclared_body": "هذه العقدة أقدم من إعلان القدرات، فلا يمكنها الإفادة. عقدة أحدث تستطيع التحقق من الإصدارات.", + "verify_absent_title": "هذه العقدة لا تتحقق من الإصدارات", + "verify_absent_body": "لا تحمل هذه العقدة السجل، فلا يمكنها التحقق من الإصدارات. عقدة أخرى تستطيع ذلك.", + "verify_unreachable_title": "تعذّر الوصول إلى هذه العقدة", + "verify_unreachable_body": "لم تُجب العقدة، فلا نعرف أتستطيع التحقق من الإصدارات أم لا. وهذا ليس عطلاً في الإصدار الذي تتحقق منه.", + "verify_status_registered": "مسجَّل", + "verify_status_deprecated": "لم يعد يُنصح به", + "verify_status_revoked": "مُلغى", + "verify_status_unreadable": "الحالة غير معروفة", + "verify_revoked_warning": "هذا الإصدار أُلغي. لا تستخدمه.", + "verify_not_found_title": "لا سجل لهذا الإصدار", + "verify_not_found_body": "أجاب السجل ولا يحمل شيئاً لهذه البصمة.", + "verify_unavailable_title": "تعذّر التحقق", + "verify_unavailable_body": "هذا ليس كـ«غير مسجَّل» — فالسجل لم يُجب.", + "verify_undetermined_title": "تعذّر على هذه العقدة تحديد ما تستطيع فعله", + "verify_undetermined_body": "أجابت العقدة، لكنها لم تستطع قراءة سجل مفتاحها الخاص. هذا عادةً مؤقت — حاول مجدداً بعد قليل.", + "verify_retry": "تحقّق مجدداً", "attestation_actions_desc": "إجراءات هذا السجل", "chat_badge_message": "رسالة", "chat_details": "النوع {type} · النطاق {scope} · الحالة {status}", diff --git a/client/desktopApp/src/main/resources/localization/bn.json b/client/desktopApp/src/main/resources/localization/bn.json index cbb52b3..203a77c 100644 --- a/client/desktopApp/src/main/resources/localization/bn.json +++ b/client/desktopApp/src/main/resources/localization/bn.json @@ -2925,6 +2925,27 @@ "wallet_transfer_success": "ট্রান্সফার সফল! TX: {tx}", "wallet_trust_degraded": "হার্ডওয়্যার বিশ্বাস হ্রাস পেয়েছে", "wallet_warning": "সতর্কতা", + "verify_title": "একটি বিল্ড যাচাই করুন", + "verify_hash_label": "বিল্ড হ্যাশ", + "verify_button": "পরীক্ষা করুন", + "verify_undeclared_title": "এই নোড বলতে পারে না যে এটি বিল্ড যাচাই করে কি না", + "verify_undeclared_body": "এই নোড সক্ষমতা ঘোষণার চেয়ে পুরনো, তাই এটি বলতে পারে না। নতুন কোনো নোড বিল্ড যাচাই করতে পারে।", + "verify_absent_title": "এই নোড বিল্ড যাচাই করে না", + "verify_absent_body": "এই নোড রেজিস্ট্রি ধারণ করে না, তাই এটি বিল্ড পরীক্ষা করতে পারে না। অন্য একটি নোড পারে।", + "verify_unreachable_title": "এই নোডে পৌঁছানো যায়নি", + "verify_unreachable_body": "নোডটি সাড়া দেয়নি, তাই এটি বিল্ড যাচাই করতে পারে কি না তা আমরা জানি না। আপনি যে বিল্ডটি পরীক্ষা করছেন তার সমস্যা এটি নয়।", + "verify_status_registered": "নিবন্ধিত", + "verify_status_deprecated": "আর প্রস্তাবিত নয়", + "verify_status_revoked": "প্রত্যাহৃত", + "verify_status_unreadable": "অবস্থা সনাক্ত করা যায়নি", + "verify_revoked_warning": "এই বিল্ডটি প্রত্যাহার করা হয়েছে। এটি ব্যবহার করবেন না।", + "verify_not_found_title": "এই বিল্ডের কোনো রেকর্ড নেই", + "verify_not_found_body": "রেজিস্ট্রি সাড়া দিয়েছে এবং এই হ্যাশের জন্য কিছুই ধারণ করে না।", + "verify_unavailable_title": "পরীক্ষা করা যায়নি", + "verify_unavailable_body": "এটি ‘নিবন্ধিত নয়’-এর সমান নয় — রেজিস্ট্রি সাড়া দেয়নি।", + "verify_undetermined_title": "এই নোড নির্ধারণ করতে পারেনি যে এটি কী করতে পারে", + "verify_undetermined_body": "নোডটি সাড়া দিয়েছে, কিন্তু নিজের কী রেকর্ড পড়তে পারেনি। এটি সাধারণত সাময়িক — কিছুক্ষণ পরে আবার চেষ্টা করুন।", + "verify_retry": "আবার পরীক্ষা করুন", "attestation_actions_desc": "এই রেকর্ডের জন্য পদক্ষেপ", "chat_badge_message": "বার্তা", "chat_details": "ধরন {type} · পরিসর {scope} · অবস্থা {status}", diff --git a/client/desktopApp/src/main/resources/localization/de.json b/client/desktopApp/src/main/resources/localization/de.json index da1e0ac..6f85250 100644 --- a/client/desktopApp/src/main/resources/localization/de.json +++ b/client/desktopApp/src/main/resources/localization/de.json @@ -2862,6 +2862,18 @@ "users_status": "Status", "users_user_id": "Benutzer-ID", "users_wa_role": "WA:{role}", + "verify_unavailable_title": "Prüfung nicht möglich", + "verify_undetermined_title": "Dieser Knoten konnte nicht feststellen, was er kann", + "verify_undetermined_body": "Der Knoten hat geantwortet, konnte aber seinen eigenen Schlüsseldatensatz nicht lesen. Das ist meist vorübergehend — versuchen Sie es in Kürze erneut.", + "verify_retry": "Erneut prüfen", + "verify_unreachable_title": "Knoten nicht erreichbar", + "verify_unreachable_body": "Der Knoten hat nicht geantwortet, daher wissen wir nicht, ob er Builds verifizieren kann. Das liegt nicht an dem Build, den Sie prüfen.", + "verify_status_registered": "Registriert", + "verify_status_deprecated": "Nicht mehr empfohlen", + "verify_status_revoked": "Widerrufen", + "verify_status_unreadable": "Status nicht erkannt", + "verify_revoked_warning": "Dieser Build wurde widerrufen. Verwenden Sie ihn nicht.", + "verify_not_found_title": "Kein Eintrag für diesen Build", "wa_approve": "Genehmigen", "wa_avg_resolution": "Durchschnittl. Auflösung: {time} Min", "wa_bus_subscribers": "Bus-Abonnenten", @@ -2924,6 +2936,12 @@ "wallet_transfer_success": "Überweisung erfolgreich! TX: {tx}", "wallet_trust_degraded": "Hardware-Vertrauen herabgestuft", "wallet_warning": "Warnung", + "verify_title": "Build verifizieren", + "verify_hash_label": "Build-Hash", + "verify_button": "Prüfen", + "verify_undeclared_title": "Dieser Knoten kann nicht sagen, ob er Builds verifiziert", + "verify_undeclared_body": "Dieser Knoten ist älter als die Fähigkeitserklärung und kann daher keine Auskunft geben. Ein neuerer Knoten kann Builds verifizieren.", + "verify_absent_title": "Dieser Knoten verifiziert keine Builds", "attestation_actions_desc": "Aktionen für diesen Datensatz", "chat_badge_message": "NACHRICHT", "chat_details": "Typ {type} · Bereich {scope} · Status {status}", diff --git a/client/desktopApp/src/main/resources/localization/es.json b/client/desktopApp/src/main/resources/localization/es.json index fe02dbf..91b0f58 100644 --- a/client/desktopApp/src/main/resources/localization/es.json +++ b/client/desktopApp/src/main/resources/localization/es.json @@ -2924,6 +2924,27 @@ "wallet_transfer_success": "¡Transferencia exitosa! TX: {tx}", "wallet_trust_degraded": "Confianza de Hardware Degradada", "wallet_warning": "Advertencia", + "verify_title": "Verificar una compilación", + "verify_hash_label": "Hash de la compilación", + "verify_button": "Comprobar", + "verify_undeclared_title": "Este nodo no puede decir si verifica compilaciones", + "verify_undeclared_body": "Este nodo es anterior a la declaración de capacidades, así que no puede saberlo. Un nodo más reciente puede verificar compilaciones.", + "verify_absent_title": "Este nodo no verifica compilaciones", + "verify_absent_body": "Este nodo no aloja el registro, así que no puede comprobar compilaciones. Otro nodo sí puede.", + "verify_unreachable_title": "No se pudo contactar con este nodo", + "verify_unreachable_body": "El nodo no respondió, así que no sabemos si puede verificar compilaciones. Esto no es un problema de la compilación que estás comprobando.", + "verify_status_registered": "Registrada", + "verify_status_deprecated": "Ya no se recomienda", + "verify_status_revoked": "Revocada", + "verify_status_unreadable": "Estado no reconocido", + "verify_revoked_warning": "Esta compilación ha sido revocada. No la uses.", + "verify_not_found_title": "No hay registro de esta compilación", + "verify_not_found_body": "El registro respondió y no tiene nada para este hash.", + "verify_unavailable_title": "No se pudo comprobar", + "verify_unavailable_body": "Esto no es lo mismo que «no registrada» — el registro no respondió.", + "verify_undetermined_title": "Este nodo no pudo determinar qué puede hacer", + "verify_undetermined_body": "El nodo respondió, pero no pudo leer su propio registro de claves. Esto suele ser temporal — inténtalo de nuevo en breve.", + "verify_retry": "Comprobar de nuevo", "attestation_actions_desc": "Acciones para este registro", "chat_badge_message": "MENSAJE", "chat_details": "tipo {type} · ámbito {scope} · estado {status}", diff --git a/client/desktopApp/src/main/resources/localization/fa.json b/client/desktopApp/src/main/resources/localization/fa.json index 38b931c..41c206a 100644 --- a/client/desktopApp/src/main/resources/localization/fa.json +++ b/client/desktopApp/src/main/resources/localization/fa.json @@ -2930,6 +2930,27 @@ "wallet_transfer_success": "انتقال با موفقیت انجام شد! TX: {tx}", "wallet_trust_degraded": "افت اعتماد سخت‌افزاری", "wallet_warning": "هشدار", + "verify_title": "تأیید یک نسخه", + "verify_hash_label": "هش نسخه", + "verify_button": "بررسی", + "verify_undeclared_title": "این گره نمی‌تواند بگوید آیا نسخه‌ها را تأیید می‌کند یا نه", + "verify_undeclared_body": "این گره قدیمی‌تر از اعلامِ قابلیت است، پس نمی‌تواند بگوید. گرهی جدیدتر می‌تواند نسخه‌ها را تأیید کند.", + "verify_absent_title": "این گره نسخه‌ها را تأیید نمی‌کند", + "verify_absent_body": "این گره رجیستری را نگه نمی‌دارد، پس نمی‌تواند نسخه‌ها را بررسی کند. گرهی دیگر می‌تواند.", + "verify_unreachable_title": "دسترسی به این گره ممکن نشد", + "verify_unreachable_body": "گره پاسخ نداد، پس نمی‌دانیم آیا می‌تواند نسخه‌ها را تأیید کند یا نه. این مشکلی از نسخه‌ای که بررسی می‌کنید نیست.", + "verify_status_registered": "ثبت‌شده", + "verify_status_deprecated": "دیگر توصیه نمی‌شود", + "verify_status_revoked": "باطل‌شده", + "verify_status_unreadable": "وضعیت شناسایی نشد", + "verify_revoked_warning": "این نسخه باطل شده است. از آن استفاده نکنید.", + "verify_not_found_title": "رکوردی از این نسخه وجود ندارد", + "verify_not_found_body": "رجیستری پاسخ داد و چیزی برای این هش نگه نمی‌دارد.", + "verify_unavailable_title": "بررسی ممکن نشد", + "verify_unavailable_body": "این با «ثبت‌نشده» یکسان نیست — رجیستری پاسخ نداد.", + "verify_undetermined_title": "این گره نتوانست تشخیص دهد چه کاری از آن ساخته است", + "verify_undetermined_body": "گره پاسخ داد، اما نتوانست رکورد کلید خودش را بخواند. این معمولاً موقتی است — کمی بعد دوباره تلاش کنید.", + "verify_retry": "دوباره بررسی کن", "attestation_actions_desc": "اقدامات برای این رکورد", "chat_badge_message": "پیام", "chat_details": "نوع {type} · محدوده {scope} · وضعیت {status}", diff --git a/client/desktopApp/src/main/resources/localization/fr.json b/client/desktopApp/src/main/resources/localization/fr.json index fe1f844..4dda6cc 100644 --- a/client/desktopApp/src/main/resources/localization/fr.json +++ b/client/desktopApp/src/main/resources/localization/fr.json @@ -2924,6 +2924,27 @@ "wallet_transfer_success": "Transfert réussi ! TX: {tx}", "wallet_trust_degraded": "Confiance Matérielle Dégradée", "wallet_warning": "Avertissement", + "verify_title": "Vérifier un build", + "verify_hash_label": "Empreinte du build", + "verify_button": "Vérifier", + "verify_undeclared_title": "Ce nœud ne peut pas dire s'il vérifie les builds", + "verify_undeclared_body": "Ce nœud est antérieur à la déclaration de capacité : il ne peut donc pas se prononcer. Un nœud plus récent peut vérifier les builds.", + "verify_absent_title": "Ce nœud ne vérifie pas les builds", + "verify_absent_body": "Ce nœud ne détient pas le registre : il ne peut donc pas vérifier les builds. Un autre nœud le peut.", + "verify_unreachable_title": "Impossible de joindre ce nœud", + "verify_unreachable_body": "Le nœud n'a pas répondu : nous ne savons donc pas s'il peut vérifier les builds. Ceci n'est pas un problème lié au build que vous vérifiez.", + "verify_status_registered": "Enregistré", + "verify_status_deprecated": "N'est plus recommandé", + "verify_status_revoked": "Révoqué", + "verify_status_unreadable": "Statut non reconnu", + "verify_revoked_warning": "Ce build a été révoqué. Ne l'utilisez pas.", + "verify_not_found_title": "Aucun enregistrement pour ce build", + "verify_not_found_body": "Le registre a répondu et ne détient rien pour cette empreinte.", + "verify_unavailable_title": "Vérification impossible", + "verify_unavailable_body": "Ceci n'équivaut pas à « non enregistré » — le registre n'a pas répondu.", + "verify_undetermined_title": "Ce nœud n'a pas pu déterminer ce qu'il peut faire", + "verify_undetermined_body": "Le nœud a répondu, mais n'a pas pu lire son propre enregistrement de clé. C'est généralement temporaire — réessayez dans un instant.", + "verify_retry": "Vérifier à nouveau", "attestation_actions_desc": "Actions pour cet enregistrement", "chat_badge_message": "MESSAGE", "chat_details": "type {type} · portée {scope} · statut {status}", diff --git a/client/desktopApp/src/main/resources/localization/ha.json b/client/desktopApp/src/main/resources/localization/ha.json index f5f91af..e36d699 100644 --- a/client/desktopApp/src/main/resources/localization/ha.json +++ b/client/desktopApp/src/main/resources/localization/ha.json @@ -2924,6 +2924,27 @@ "wallet_transfer_success": "Aika ya yi nasara! TX: {tx}", "wallet_trust_degraded": "Tabbas Kayan Aiki Ya Rage", "wallet_warning": "Gargaɗi", + "verify_title": "Tabbatar da build", + "verify_hash_label": "Hash na build", + "verify_button": "Duba", + "verify_undeclared_title": "Wannan kumburi ba zai iya faɗi ko yana tabbatar da build ba", + "verify_undeclared_body": "Wannan kumburi ya girme sanarwar iyawa, don haka ba zai iya faɗi ba. Sabon kumburi na iya tabbatar da build.", + "verify_absent_title": "Wannan kumburi ba ya tabbatar da build ba", + "verify_absent_body": "Wannan kumburi ba ya riƙe rajista ba, don haka ba zai iya duba build ba. Wani kumburi na iya duba build.", + "verify_unreachable_title": "An kasa isa ga wannan kumburi", + "verify_unreachable_body": "Kumburin bai amsa ba, don haka ba mu san ko yana iya tabbatar da build ba. Wannan ba matsala ce ta build ɗin da kuke dubawa ba.", + "verify_status_registered": "An yi rajista", + "verify_status_deprecated": "Ba a ƙara shawarta ba", + "verify_status_revoked": "An soke", + "verify_status_unreadable": "Ba a gane matsayin ba", + "verify_revoked_warning": "An soke wannan build. Kada ku yi amfani da shi.", + "verify_not_found_title": "Babu rikodin wannan build", + "verify_not_found_body": "Rajistar ta amsa kuma ba ta riƙe komai ga wannan hash ba.", + "verify_unavailable_title": "An kasa duba", + "verify_unavailable_body": "Wannan bai zama daidai da 'ba a yi rajista ba' ba — rajistar ba ta amsa ba.", + "verify_undetermined_title": "Wannan kumburi bai iya tantance abin da yake iya yi ba", + "verify_undetermined_body": "Kumburin ya amsa, amma bai iya karanta rikodin maɓallinsa na kansa ba. Yawanci na ɗan lokaci ne — sake gwadawa nan da nan.", + "verify_retry": "Sake duba", "attestation_actions_desc": "Ayyuka don wannan rikodin", "chat_badge_message": "SAƘO", "chat_details": "nau'i {type} · iyaka {scope} · matsayi {status}", diff --git a/client/desktopApp/src/main/resources/localization/hi.json b/client/desktopApp/src/main/resources/localization/hi.json index 504fa17..a4e474c 100644 --- a/client/desktopApp/src/main/resources/localization/hi.json +++ b/client/desktopApp/src/main/resources/localization/hi.json @@ -2924,6 +2924,27 @@ "wallet_transfer_success": "स्थानांतरण सफल! TX: {tx}", "wallet_trust_degraded": "हार्डवेयर ट्रस्ट कम हुआ", "wallet_warning": "चेतावनी", + "verify_title": "बिल्ड सत्यापित करें", + "verify_hash_label": "बिल्ड हैश", + "verify_button": "जाँच करें", + "verify_undeclared_title": "यह नोड नहीं बता सकता कि यह बिल्ड सत्यापित करता है या नहीं", + "verify_undeclared_body": "यह नोड क्षमता घोषणा से पुराना है, इसलिए यह बता नहीं सकता। कोई नया नोड बिल्ड सत्यापित कर सकता है।", + "verify_absent_title": "यह नोड बिल्ड सत्यापित नहीं करता", + "verify_absent_body": "यह नोड रजिस्ट्री नहीं रखता, इसलिए यह बिल्ड की जाँच नहीं कर सकता। कोई अन्य नोड कर सकता है।", + "verify_unreachable_title": "इस नोड तक नहीं पहुँच सका", + "verify_unreachable_body": "नोड ने उत्तर नहीं दिया, इसलिए यह पता नहीं चलता कि यह बिल्ड सत्यापित कर सकता है या नहीं। यह उस बिल्ड की समस्या नहीं है जिसकी आप जाँच कर रहे हैं।", + "verify_status_registered": "पंजीकृत", + "verify_status_deprecated": "अब अनुशंसित नहीं", + "verify_status_revoked": "रद्द", + "verify_status_unreadable": "स्थिति पहचानी नहीं जा सकी", + "verify_revoked_warning": "इस बिल्ड को रद्द कर दिया गया है। इसका उपयोग न करें।", + "verify_not_found_title": "इस बिल्ड का कोई रिकॉर्ड नहीं", + "verify_not_found_body": "रजिस्ट्री ने उत्तर दिया और इस हैश के लिए उसके पास कुछ भी नहीं है।", + "verify_unavailable_title": "जाँच नहीं हो सकी", + "verify_unavailable_body": "यह 'पंजीकृत नहीं' जैसा नहीं है — रजिस्ट्री ने उत्तर नहीं दिया।", + "verify_undetermined_title": "यह नोड यह निर्धारित नहीं कर सका कि यह क्या कर सकता है", + "verify_undetermined_body": "नोड ने उत्तर दिया, पर अपना ही कुंजी रिकॉर्ड नहीं पढ़ सका। यह आमतौर पर अस्थायी होता है — थोड़ी देर में फिर से प्रयास करें।", + "verify_retry": "फिर से जाँच करें", "attestation_actions_desc": "इस रिकॉर्ड के लिए कार्रवाइयाँ", "chat_badge_message": "संदेश", "chat_details": "प्रकार {type} · दायरा {scope} · स्थिति {status}", diff --git a/client/desktopApp/src/main/resources/localization/id.json b/client/desktopApp/src/main/resources/localization/id.json index d51d506..8c7d4ad 100644 --- a/client/desktopApp/src/main/resources/localization/id.json +++ b/client/desktopApp/src/main/resources/localization/id.json @@ -2924,6 +2924,27 @@ "wallet_transfer_success": "Transfer berhasil! TX: {tx}", "wallet_trust_degraded": "Kepercayaan Perangkat Keras Menurun", "wallet_warning": "Peringatan", + "verify_title": "Verifikasi build", + "verify_hash_label": "Hash build", + "verify_button": "Periksa", + "verify_undeclared_title": "Node ini tidak dapat menyatakan apakah ia memverifikasi build", + "verify_undeclared_body": "Node ini lebih lama daripada deklarasi kapabilitas, sehingga tidak dapat menyatakannya. Node yang lebih baru dapat memverifikasi build.", + "verify_absent_title": "Node ini tidak memverifikasi build", + "verify_absent_body": "Node ini tidak menyimpan registry, sehingga tidak dapat memeriksa build. Node lain bisa.", + "verify_unreachable_title": "Tidak dapat menjangkau node ini", + "verify_unreachable_body": "Node tidak merespons, sehingga kami tidak tahu apakah ia dapat memverifikasi build. Ini bukan masalah pada build yang Anda periksa.", + "verify_status_registered": "Terdaftar", + "verify_status_deprecated": "Tidak lagi disarankan", + "verify_status_revoked": "Dicabut", + "verify_status_unreadable": "Status tidak dikenali", + "verify_revoked_warning": "Build ini telah dicabut. Jangan gunakan.", + "verify_not_found_title": "Tidak ada catatan untuk build ini", + "verify_not_found_body": "Registry merespons dan tidak menyimpan apa pun untuk hash ini.", + "verify_unavailable_title": "Tidak dapat memeriksa", + "verify_unavailable_body": "Ini tidak sama dengan 'tidak terdaftar' — registry tidak merespons.", + "verify_undetermined_title": "Node ini tidak dapat menentukan apa yang bisa dilakukannya", + "verify_undetermined_body": "Node merespons, tetapi tidak dapat membaca catatan kuncinya sendiri. Biasanya ini bersifat sementara — coba lagi sebentar lagi.", + "verify_retry": "Periksa lagi", "attestation_actions_desc": "Tindakan untuk catatan ini", "chat_badge_message": "PESAN", "chat_details": "jenis {type} · lingkup {scope} · status {status}", diff --git a/client/desktopApp/src/main/resources/localization/it.json b/client/desktopApp/src/main/resources/localization/it.json index 525dd69..95ab48d 100644 --- a/client/desktopApp/src/main/resources/localization/it.json +++ b/client/desktopApp/src/main/resources/localization/it.json @@ -2924,6 +2924,27 @@ "wallet_transfer_success": "Trasferimento riuscito! TX: {tx}", "wallet_trust_degraded": "Fiducia Hardware Degradata", "wallet_warning": "Avviso", + "verify_title": "Verifica una build", + "verify_hash_label": "Hash della build", + "verify_button": "Verifica", + "verify_undeclared_title": "Questo nodo non è in grado di dire se verifica le build", + "verify_undeclared_body": "Questo nodo è precedente alla dichiarazione delle funzionalità, quindi non è in grado di pronunciarsi. Un nodo più recente può verificare le build.", + "verify_absent_title": "Questo nodo non verifica le build", + "verify_absent_body": "Questo nodo non detiene il registro, quindi non può verificare le build. Un altro nodo può farlo.", + "verify_unreachable_title": "Impossibile raggiungere questo nodo", + "verify_unreachable_body": "Il nodo non ha risposto, quindi non sappiamo se sia in grado di verificare le build. Questo non è un problema della build che stai verificando.", + "verify_status_registered": "Registrata", + "verify_status_deprecated": "Non più consigliata", + "verify_status_revoked": "Revocata", + "verify_status_unreadable": "Stato non riconosciuto", + "verify_revoked_warning": "Questa build è stata revocata. Non utilizzarla.", + "verify_not_found_title": "Nessuna registrazione per questa build", + "verify_not_found_body": "Il registro ha risposto e non contiene nulla per questo hash.", + "verify_unavailable_title": "Verifica non riuscita", + "verify_unavailable_body": "Questo non equivale a «non registrata» — il registro non ha risposto.", + "verify_undetermined_title": "Questo nodo non è riuscito a determinare cosa può fare", + "verify_undetermined_body": "Il nodo ha risposto, ma non è riuscito a leggere il proprio record delle chiavi. Di solito è temporaneo — riprova a breve.", + "verify_retry": "Verifica di nuovo", "attestation_actions_desc": "Azioni per questo record", "chat_badge_message": "MESSAGGIO", "chat_details": "tipo {type} · ambito {scope} · stato {status}", diff --git a/client/desktopApp/src/main/resources/localization/ja.json b/client/desktopApp/src/main/resources/localization/ja.json index 371b63a..3123141 100644 --- a/client/desktopApp/src/main/resources/localization/ja.json +++ b/client/desktopApp/src/main/resources/localization/ja.json @@ -2924,6 +2924,27 @@ "wallet_transfer_success": "送金成功!TX: {tx}", "wallet_trust_degraded": "ハードウェア信頼が低下しました", "wallet_warning": "警告", + "verify_title": "ビルドを検証する", + "verify_hash_label": "ビルドハッシュ", + "verify_button": "確認", + "verify_undeclared_title": "このノードはビルドを検証できるかどうかを述べられません", + "verify_undeclared_body": "このノードは機能宣言より古いバージョンのため、判断できません。新しいノードであればビルドを検証できます。", + "verify_absent_title": "このノードはビルドを検証しません", + "verify_absent_body": "このノードはレジストリを保持していないため、ビルドを確認できません。他のノードであれば確認できます。", + "verify_unreachable_title": "このノードに接続できませんでした", + "verify_unreachable_body": "ノードが応答しなかったため、ビルドを検証できるかどうかは分かりません。これは、確認しようとしているビルド自体の問題ではありません。", + "verify_status_registered": "登録済み", + "verify_status_deprecated": "推奨されていません", + "verify_status_revoked": "失効済み", + "verify_status_unreadable": "ステータスを認識できません", + "verify_revoked_warning": "このビルドは失効しています。使用しないでください。", + "verify_not_found_title": "このビルドの記録はありません", + "verify_not_found_body": "レジストリは応答しましたが、このハッシュに対する記録を保持していません。", + "verify_unavailable_title": "確認できませんでした", + "verify_unavailable_body": "これは「未登録」と同じではありません — レジストリが応答しませんでした。", + "verify_undetermined_title": "このノードは自身にできることを判別できませんでした", + "verify_undetermined_body": "ノードは応答しましたが、自身の鍵の記録を読み取れませんでした。これは通常一時的なものです — しばらくしてから再試行してください。", + "verify_retry": "再確認", "attestation_actions_desc": "このレコードに対する操作", "chat_badge_message": "メッセージ", "chat_details": "種別 {type} · スコープ {scope} · 状態 {status}", diff --git a/client/desktopApp/src/main/resources/localization/ko.json b/client/desktopApp/src/main/resources/localization/ko.json index e46b77f..ce7f6a2 100644 --- a/client/desktopApp/src/main/resources/localization/ko.json +++ b/client/desktopApp/src/main/resources/localization/ko.json @@ -2924,6 +2924,27 @@ "wallet_transfer_success": "전송 성공! TX: {tx}", "wallet_trust_degraded": "하드웨어 신뢰 저하됨", "wallet_warning": "경고", + "verify_title": "빌드 검증", + "verify_hash_label": "빌드 해시", + "verify_button": "확인", + "verify_undeclared_title": "이 노드는 빌드를 검증하는지 여부를 알 수 없습니다", + "verify_undeclared_body": "이 노드는 기능 선언보다 오래되어 알 수 없습니다. 더 새로운 노드는 빌드를 검증할 수 있습니다.", + "verify_absent_title": "이 노드는 빌드를 검증하지 않습니다", + "verify_absent_body": "이 노드는 레지스트리를 보유하지 않아 빌드를 확인할 수 없습니다. 다른 노드는 확인할 수 있습니다.", + "verify_unreachable_title": "이 노드에 연결할 수 없음", + "verify_unreachable_body": "노드가 응답하지 않아 빌드를 검증할 수 있는지 알 수 없습니다. 이는 확인 중인 빌드의 문제가 아닙니다.", + "verify_status_registered": "등록됨", + "verify_status_deprecated": "더 이상 권장되지 않음", + "verify_status_revoked": "폐기됨", + "verify_status_unreadable": "상태를 인식할 수 없음", + "verify_revoked_warning": "이 빌드는 폐기되었습니다. 사용하지 마십시오.", + "verify_not_found_title": "이 빌드에 대한 기록 없음", + "verify_not_found_body": "레지스트리가 응답했지만 이 해시에 대한 기록이 없습니다.", + "verify_unavailable_title": "확인할 수 없음", + "verify_unavailable_body": "이는 '등록되지 않음'과 같지 않습니다 — 레지스트리가 응답하지 않았습니다.", + "verify_undetermined_title": "이 노드는 자신이 무엇을 할 수 있는지 판단할 수 없었습니다", + "verify_undetermined_body": "노드가 응답했지만 자체 키 레코드를 읽을 수 없었습니다. 이는 대개 일시적인 현상입니다 — 잠시 후 다시 시도하세요.", + "verify_retry": "다시 확인", "attestation_actions_desc": "이 레코드에 대한 작업", "chat_badge_message": "메시지", "chat_details": "유형 {type} · 범위 {scope} · 상태 {status}", diff --git a/client/desktopApp/src/main/resources/localization/mr.json b/client/desktopApp/src/main/resources/localization/mr.json index 35d3208..b4cb9d1 100644 --- a/client/desktopApp/src/main/resources/localization/mr.json +++ b/client/desktopApp/src/main/resources/localization/mr.json @@ -2924,6 +2924,27 @@ "wallet_transfer_success": "Transfer यशful! TX: {tx}", "wallet_trust_degraded": "हार्डवेअर विश्वास खालावला", "wallet_warning": "इशारा", + "verify_title": "बिल्ड सत्यापित करा", + "verify_hash_label": "बिल्ड हॅश", + "verify_button": "तपासा", + "verify_undeclared_title": "हा नोड बिल्ड सत्यापित करतो की नाही हे सांगू शकत नाही", + "verify_undeclared_body": "हा नोड क्षमता-घोषणेपेक्षा जुना आहे, त्यामुळे तो सांगू शकत नाही. नवीन नोड बिल्ड सत्यापित करू शकतो.", + "verify_absent_title": "हा नोड बिल्ड सत्यापित करत नाही", + "verify_absent_body": "या नोडकडे रजिस्ट्री नाही, त्यामुळे तो बिल्ड तपासू शकत नाही. दुसरा नोड हे करू शकतो.", + "verify_unreachable_title": "या नोडपर्यंत पोहोचता आले नाही", + "verify_unreachable_body": "नोडने उत्तर दिले नाही, त्यामुळे तो बिल्ड सत्यापित करू शकतो की नाही हे आम्हाला माहीत नाही. तुम्ही तपासत असलेल्या बिल्डमध्ये ही समस्या नाही.", + "verify_status_registered": "नोंदणीकृत", + "verify_status_deprecated": "आता शिफारस केलेले नाही", + "verify_status_revoked": "रद्द केलेले", + "verify_status_unreadable": "स्थिती ओळखता आली नाही", + "verify_revoked_warning": "हे बिल्ड रद्द करण्यात आले आहे. याचा वापर करू नका.", + "verify_not_found_title": "या बिल्डची कोणतीही नोंद नाही", + "verify_not_found_body": "रजिस्ट्रीने उत्तर दिले आणि या हॅशसाठी त्याकडे काहीही नाही.", + "verify_unavailable_title": "तपासता आले नाही", + "verify_unavailable_body": "हे 'नोंदणीकृत नाही' यासारखे नाही — रजिस्ट्रीने उत्तर दिले नाही.", + "verify_undetermined_title": "हा नोड काय करू शकतो हे ठरवता आले नाही", + "verify_undetermined_body": "नोडने उत्तर दिले, पण त्याला स्वतःची की-नोंद वाचता आली नाही. हे सहसा तात्पुरते असते — थोड्या वेळाने पुन्हा प्रयत्न करा.", + "verify_retry": "पुन्हा तपासा", "attestation_actions_desc": "या नोंदीसाठी क्रिया", "chat_badge_message": "संदेश", "chat_details": "प्रकार {type} · व्याप्ती {scope} · स्थिती {status}", diff --git a/client/desktopApp/src/main/resources/localization/my.json b/client/desktopApp/src/main/resources/localization/my.json index 37d756b..f956c52 100644 --- a/client/desktopApp/src/main/resources/localization/my.json +++ b/client/desktopApp/src/main/resources/localization/my.json @@ -2862,6 +2862,14 @@ "users_status": "အခြေအနေ", "users_user_id": "အသုံးပြုသူ ID", "users_wa_role": "WA:{role}", + "verify_revoked_warning": "ဤ build ကို ရုပ်သိမ်းထားပြီးဖြစ်သည်။ အသုံးမပြုပါနှင့်။", + "verify_not_found_title": "ဤ build ၏ မှတ်တမ်း မရှိပါ", + "verify_not_found_body": "registry က အဖြေ ပြန်ပေးခဲ့ပြီး ဤ hash အတွက် မည်သည့်အရာမျှ ကိုင်ဆောင်ထားခြင်း မရှိပါ။", + "verify_unavailable_title": "စစ်ဆေး၍ မရပါ", + "verify_unavailable_body": "ဤသည်မှာ 'မှတ်ပုံတင်ထားခြင်း မရှိပါ' ဟူသည်နှင့် မတူပါ — registry က အဖြေ ပြန်မပေးခဲ့ပါ။", + "verify_undetermined_title": "ဤ node သည် ၎င်း လုပ်နိုင်သည့်အရာကို သတ်မှတ်၍ မရခဲ့ပါ", + "verify_undetermined_body": "node က အဖြေ ပြန်ပေးခဲ့သော်လည်း ၎င်း၏ ကိုယ်ပိုင် key မှတ်တမ်းကို ဖတ်၍ မရခဲ့ပါ။ ဤသည် ယာယီသာ ဖြစ်လေ့ရှိသည် — မကြာမီ ထပ်ကြိုးစားပါ။", + "verify_retry": "ထပ်မံစစ်ဆေးပါ", "wa_approve": "အတည်ပြုပါ", "wa_avg_resolution": "ပျမ်းမျှ ဖြေရှင်းချိန်: {time} မိနစ်", "wa_bus_subscribers": "Bus Subscribers", @@ -2924,6 +2932,18 @@ "wallet_transfer_success": "Transfer အောင်မြင်ful! TX: {tx}", "wallet_trust_degraded": "Hardware ယုံကြည်မှု အားနည်းသွားပြီ", "wallet_warning": "သတိပေး", + "verify_title": "Build တစ်ခုကို အတည်ပြုပါ", + "verify_hash_label": "Build hash", + "verify_button": "စစ်ဆေးပါ", + "verify_undeclared_title": "ဤ node သည် build များကို အတည်ပြုနိုင်သည် မနိုင်သည်ကို ပြောနိုင်စွမ်း မရှိပါ", + "verify_undeclared_body": "ဤ node သည် capability declaration ထက် ပိုမိုဟောင်းနွမ်းသဖြင့် ပြောနိုင်စွမ်း မရှိပါ။ ပိုမို အသစ်သော node တစ်ခုက build များကို အတည်ပြုနိုင်ပါသည်။", + "verify_absent_title": "ဤ node သည် build များကို အတည်ပြု၍ မရပါ", + "verify_absent_body": "ဤ node သည် registry ကို ကိုင်ဆောင်ထားခြင်း မရှိသဖြင့် build များကို စစ်ဆေး၍ မရပါ။ အခြား node တစ်ခုက စစ်ဆေးနိုင်ပါသည်။", + "verify_unreachable_title": "ဤ node ကို ချိတ်ဆက်၍ မရပါ", + "verify_unreachable_body": "node က အဖြေ ပြန်မပေးခဲ့သဖြင့် ၎င်းသည် build များကို အတည်ပြုနိုင်သည် မနိုင်သည်ကို ကျွန်ုပ်တို့ မသိပါ။ ဤသည် သင် စစ်ဆေးနေသော build ၏ ပြဿနာ မဟုတ်ပါ။", + "verify_status_registered": "မှတ်ပုံတင်ထားသည်", + "verify_status_deprecated": "ထပ်မံ အသုံးပြုရန် အကြံမပြုတော့ပါ", + "verify_status_revoked": "ရုပ်သိမ်းထားသည်", "attestation_actions_desc": "ဤမှတ်တမ်းအတွက် လုပ်ဆောင်ချက်များ", "chat_badge_message": "မက်ဆေ့ချ်", "chat_details": "အမျိုးအစား {type} · scope {scope} · အခြေအနေ {status}", diff --git a/client/desktopApp/src/main/resources/localization/pa.json b/client/desktopApp/src/main/resources/localization/pa.json index b5d51c5..e50e1a8 100644 --- a/client/desktopApp/src/main/resources/localization/pa.json +++ b/client/desktopApp/src/main/resources/localization/pa.json @@ -2924,6 +2924,27 @@ "wallet_transfer_success": "ਟ੍ਰਾਂਸਫਰ ਸਫਲ! TX: {tx}", "wallet_trust_degraded": "ਹਾਰਡਵੇਅਰ ਭਰੋਸਾ ਘਟਿਆ", "wallet_warning": "ਚੇਤਾਵਨੀ", + "verify_title": "ਇੱਕ ਬਿਲਡ ਦੀ ਪੁਸ਼ਟੀ ਕਰੋ", + "verify_hash_label": "ਬਿਲਡ ਹੈਸ਼", + "verify_button": "ਜਾਂਚ ਕਰੋ", + "verify_undeclared_title": "ਇਹ ਨੋਡ ਨਹੀਂ ਕਹਿ ਸਕਦਾ ਕਿ ਇਹ ਬਿਲਡਾਂ ਦੀ ਪੁਸ਼ਟੀ ਕਰਦਾ ਹੈ ਜਾਂ ਨਹੀਂ", + "verify_undeclared_body": "ਇਹ ਨੋਡ ਸਮਰੱਥਾ ਐਲਾਨ ਤੋਂ ਪੁਰਾਣਾ ਹੈ, ਇਸ ਲਈ ਇਹ ਕੁਝ ਕਹਿ ਨਹੀਂ ਸਕਦਾ। ਇੱਕ ਨਵਾਂ ਨੋਡ ਬਿਲਡਾਂ ਦੀ ਪੁਸ਼ਟੀ ਕਰ ਸਕਦਾ ਹੈ।", + "verify_absent_title": "ਇਹ ਨੋਡ ਬਿਲਡਾਂ ਦੀ ਪੁਸ਼ਟੀ ਨਹੀਂ ਕਰਦਾ", + "verify_absent_body": "ਇਹ ਨੋਡ ਰਜਿਸਟਰੀ ਨਹੀਂ ਰੱਖਦਾ, ਇਸ ਲਈ ਇਹ ਬਿਲਡਾਂ ਦੀ ਜਾਂਚ ਨਹੀਂ ਕਰ ਸਕਦਾ। ਕੋਈ ਹੋਰ ਨੋਡ ਕਰ ਸਕਦਾ ਹੈ।", + "verify_unreachable_title": "ਇਸ ਨੋਡ ਤੱਕ ਨਹੀਂ ਪਹੁੰਚ ਸਕੇ", + "verify_unreachable_body": "ਨੋਡ ਨੇ ਜਵਾਬ ਨਹੀਂ ਦਿੱਤਾ, ਇਸ ਲਈ ਸਾਨੂੰ ਨਹੀਂ ਪਤਾ ਕਿ ਇਹ ਬਿਲਡਾਂ ਦੀ ਪੁਸ਼ਟੀ ਕਰ ਸਕਦਾ ਹੈ ਜਾਂ ਨਹੀਂ। ਇਹ ਉਸ ਬਿਲਡ ਦੀ ਸਮੱਸਿਆ ਨਹੀਂ ਹੈ ਜਿਸਦੀ ਤੁਸੀਂ ਜਾਂਚ ਕਰ ਰਹੇ ਹੋ।", + "verify_status_registered": "ਰਜਿਸਟਰਡ", + "verify_status_deprecated": "ਹੁਣ ਸਿਫ਼ਾਰਸ਼ੀ ਨਹੀਂ", + "verify_status_revoked": "ਰੱਦ ਕੀਤਾ", + "verify_status_unreadable": "ਹਾਲਤ ਪਛਾਣੀ ਨਹੀਂ ਗਈ", + "verify_revoked_warning": "ਇਹ ਬਿਲਡ ਰੱਦ ਕਰ ਦਿੱਤਾ ਗਿਆ ਹੈ। ਇਸਨੂੰ ਨਾ ਵਰਤੋ।", + "verify_not_found_title": "ਇਸ ਬਿਲਡ ਦਾ ਕੋਈ ਰਿਕਾਰਡ ਨਹੀਂ", + "verify_not_found_body": "ਰਜਿਸਟਰੀ ਨੇ ਜਵਾਬ ਦਿੱਤਾ ਅਤੇ ਇਸ ਹੈਸ਼ ਲਈ ਇਸ ਕੋਲ ਕੁਝ ਵੀ ਨਹੀਂ ਹੈ।", + "verify_unavailable_title": "ਜਾਂਚ ਨਹੀਂ ਹੋ ਸਕੀ", + "verify_unavailable_body": "ਇਹ 'ਰਜਿਸਟਰਡ ਨਹੀਂ' ਵਰਗੀ ਗੱਲ ਨਹੀਂ ਹੈ — ਰਜਿਸਟਰੀ ਨੇ ਜਵਾਬ ਨਹੀਂ ਦਿੱਤਾ।", + "verify_undetermined_title": "ਇਹ ਨੋਡ ਇਹ ਪਤਾ ਨਹੀਂ ਲਗਾ ਸਕਿਆ ਕਿ ਇਹ ਕੀ ਕਰ ਸਕਦਾ ਹੈ", + "verify_undetermined_body": "ਨੋਡ ਨੇ ਜਵਾਬ ਤਾਂ ਦਿੱਤਾ, ਪਰ ਆਪਣਾ ਕੁੰਜੀ ਰਿਕਾਰਡ ਨਹੀਂ ਪੜ੍ਹ ਸਕਿਆ। ਇਹ ਆਮ ਤੌਰ 'ਤੇ ਅਸਥਾਈ ਹੁੰਦਾ ਹੈ — ਥੋੜ੍ਹੀ ਦੇਰ ਵਿੱਚ ਦੁਬਾਰਾ ਕੋਸ਼ਿਸ਼ ਕਰੋ।", + "verify_retry": "ਦੁਬਾਰਾ ਜਾਂਚ ਕਰੋ", "attestation_actions_desc": "ਇਸ ਰਿਕਾਰਡ ਲਈ ਕਾਰਵਾਈਆਂ", "chat_badge_message": "ਸੁਨੇਹਾ", "chat_details": "ਕਿਸਮ {type} · ਦਾਇਰਾ {scope} · ਸਥਿਤੀ {status}", diff --git a/client/desktopApp/src/main/resources/localization/pt.json b/client/desktopApp/src/main/resources/localization/pt.json index d4d550e..4cd2723 100644 --- a/client/desktopApp/src/main/resources/localization/pt.json +++ b/client/desktopApp/src/main/resources/localization/pt.json @@ -2924,6 +2924,27 @@ "wallet_transfer_success": "Transferência bem-sucedida! TX: {tx}", "wallet_trust_degraded": "Confiança de Hardware Degradada", "wallet_warning": "Aviso", + "verify_title": "Verificar uma build", + "verify_hash_label": "Hash da build", + "verify_button": "Verificar", + "verify_undeclared_title": "Este nó não pode dizer se verifica builds", + "verify_undeclared_body": "Este nó é mais antigo do que a declaração de capacidades, portanto não pode dizer. Um nó mais recente pode verificar builds.", + "verify_absent_title": "Este nó não verifica builds", + "verify_absent_body": "Este nó não possui o registro, portanto não pode verificar builds. Outro nó pode.", + "verify_unreachable_title": "Não foi possível alcançar este nó", + "verify_unreachable_body": "O nó não respondeu, portanto não sabemos se ele pode verificar builds. Isto não é um problema com a build que você está verificando.", + "verify_status_registered": "Registrada", + "verify_status_deprecated": "Não mais recomendada", + "verify_status_revoked": "Revogada", + "verify_status_unreadable": "Status não reconhecido", + "verify_revoked_warning": "Esta build foi revogada. Não a use.", + "verify_not_found_title": "Nenhum registro desta build", + "verify_not_found_body": "O registro respondeu e não contém nada para este hash.", + "verify_unavailable_title": "Não foi possível verificar", + "verify_unavailable_body": "Isto não é o mesmo que 'não registrada' — o registro não respondeu.", + "verify_undetermined_title": "Este nó não conseguiu determinar o que pode fazer", + "verify_undetermined_body": "O nó respondeu, mas não conseguiu ler o próprio registro de chave. Isto costuma ser temporário — tente novamente em breve.", + "verify_retry": "Verificar novamente", "attestation_actions_desc": "Ações para este registo", "chat_badge_message": "MENSAGEM", "chat_details": "tipo {type} · âmbito {scope} · estado {status}", diff --git a/client/desktopApp/src/main/resources/localization/ru.json b/client/desktopApp/src/main/resources/localization/ru.json index db4bf61..14028b7 100644 --- a/client/desktopApp/src/main/resources/localization/ru.json +++ b/client/desktopApp/src/main/resources/localization/ru.json @@ -2924,6 +2924,27 @@ "wallet_transfer_success": "Перевод успешен! TX: {tx}", "wallet_trust_degraded": "Доверие к оборудованию ухудшено", "wallet_warning": "Предупреждение", + "verify_title": "Проверить сборку", + "verify_hash_label": "Хеш сборки", + "verify_button": "Проверить", + "verify_undeclared_title": "Этот узел не может сказать, проверяет ли он сборки", + "verify_undeclared_body": "Этот узел старше объявления возможностей, поэтому не может сказать. Более новый узел может проверять сборки.", + "verify_absent_title": "Этот узел не проверяет сборки", + "verify_absent_body": "Этот узел не хранит реестр, поэтому не может проверять сборки. Другой узел может.", + "verify_unreachable_title": "Не удалось связаться с этим узлом", + "verify_unreachable_body": "Узел не ответил, поэтому неизвестно, может ли он проверять сборки. Это не связано с проверяемой вами сборкой.", + "verify_status_registered": "Зарегистрирована", + "verify_status_deprecated": "Больше не рекомендуется", + "verify_status_revoked": "Отозвана", + "verify_status_unreadable": "Статус не распознан", + "verify_revoked_warning": "Эта сборка отозвана. Не используйте её.", + "verify_not_found_title": "Нет записи об этой сборке", + "verify_not_found_body": "Реестр ответил, но не содержит записи для этого хеша.", + "verify_unavailable_title": "Не удалось проверить", + "verify_unavailable_body": "Это не то же самое, что «не зарегистрирована» — реестр не ответил.", + "verify_undetermined_title": "Этот узел не смог определить, что он может делать", + "verify_undetermined_body": "Узел ответил, но не смог прочитать собственную запись ключа. Обычно это временно — повторите попытку через некоторое время.", + "verify_retry": "Проверить снова", "attestation_actions_desc": "Действия для этой записи", "chat_badge_message": "СООБЩЕНИЕ", "chat_details": "тип {type} · область {scope} · статус {status}", diff --git a/client/desktopApp/src/main/resources/localization/sw.json b/client/desktopApp/src/main/resources/localization/sw.json index 17baf50..2ebcdb1 100644 --- a/client/desktopApp/src/main/resources/localization/sw.json +++ b/client/desktopApp/src/main/resources/localization/sw.json @@ -2924,6 +2924,27 @@ "wallet_transfer_success": "Uhamisho umefanikiwa! TX: {tx}", "wallet_trust_degraded": "Kuaminika kwa Maunzi Kumedhoofika", "wallet_warning": "Onyo", + "verify_title": "Thibitisha toleo", + "verify_hash_label": "Hash ya toleo", + "verify_button": "Kagua", + "verify_undeclared_title": "Nodi hii haiwezi kusema kama inathibitisha matoleo", + "verify_undeclared_body": "Nodi hii ni ya zamani kuliko tamko la uwezo, kwa hivyo haiwezi kusema. Nodi mpya zaidi inaweza kuthibitisha matoleo.", + "verify_absent_title": "Nodi hii haithibitishi matoleo", + "verify_absent_body": "Nodi hii haibebi sajili, kwa hivyo haiwezi kukagua matoleo. Nodi nyingine inaweza.", + "verify_unreachable_title": "Imeshindwa kufikia nodi hii", + "verify_unreachable_body": "Nodi haikujibu, kwa hivyo hatujui kama inaweza kuthibitisha matoleo. Hili si tatizo la toleo unalolikagua.", + "verify_status_registered": "Limesajiliwa", + "verify_status_deprecated": "Halipendekezwi tena", + "verify_status_revoked": "Limebatilishwa", + "verify_status_unreadable": "Hali haitambuliki", + "verify_revoked_warning": "Toleo hili limebatilishwa. Usilitumie.", + "verify_not_found_title": "Hakuna rekodi ya toleo hili", + "verify_not_found_body": "Sajili ilijibu na haina kitu kwa hash hii.", + "verify_unavailable_title": "Imeshindwa kukagua", + "verify_unavailable_body": "Hii si sawa na 'halijasajiliwa' — sajili haikujibu.", + "verify_undetermined_title": "Nodi hii haikuweza kubaini kile inachoweza kufanya", + "verify_undetermined_body": "Nodi ilijibu, lakini haikuweza kusoma rekodi yake yenyewe ya ufunguo. Hii kwa kawaida ni ya muda tu — jaribu tena baada ya muda mfupi.", + "verify_retry": "Kagua tena", "attestation_actions_desc": "Vitendo vya rekodi hii", "chat_badge_message": "UJUMBE", "chat_details": "aina {type} · wigo {scope} · hali {status}", diff --git a/client/desktopApp/src/main/resources/localization/ta.json b/client/desktopApp/src/main/resources/localization/ta.json index f3a999a..166494d 100644 --- a/client/desktopApp/src/main/resources/localization/ta.json +++ b/client/desktopApp/src/main/resources/localization/ta.json @@ -2924,6 +2924,27 @@ "wallet_transfer_success": "பரிமாற்றம் வெற்றிகரம்! TX: {tx}", "wallet_trust_degraded": "Hardware நம்பகத்தன்மை Degraded", "wallet_warning": "எச்சரிக்கை", + "verify_title": "ஒரு பதிப்பைச் சரிபார்", + "verify_hash_label": "பதிப்பு ஹாஷ்", + "verify_button": "சரிபார்", + "verify_undeclared_title": "இந்த முனை பதிப்புகளைச் சரிபார்க்கிறதா என்று கூற முடியாது", + "verify_undeclared_body": "இந்த முனை திறன் அறிவிப்பைவிட பழையது; எனவே இதனால் கூற முடியாது. புதிய முனையால் பதிப்புகளைச் சரிபார்க்க முடியும்.", + "verify_absent_title": "இந்த முனை பதிப்புகளைச் சரிபார்க்காது", + "verify_absent_body": "இந்த முனையிடம் பதிவகம் இல்லை; எனவே இதனால் பதிப்புகளைச் சரிபார்க்க முடியாது. வேறொரு முனையால் முடியும்.", + "verify_unreachable_title": "இந்த முனையை அணுக முடியவில்லை", + "verify_unreachable_body": "முனை பதிலளிக்கவில்லை; எனவே அதனால் பதிப்புகளைச் சரிபார்க்க முடியுமா என்பது எங்களுக்குத் தெரியாது. இது நீங்கள் சரிபார்க்கும் பதிப்பின் சிக்கல் அல்ல.", + "verify_status_registered": "பதிவு செய்யப்பட்டது", + "verify_status_deprecated": "இனி பரிந்துரைக்கப்படவில்லை", + "verify_status_revoked": "திரும்பப் பெறப்பட்டது", + "verify_status_unreadable": "நிலை அறியப்படவில்லை", + "verify_revoked_warning": "இந்தப் பதிப்பு திரும்பப் பெறப்பட்டுள்ளது. இதைப் பயன்படுத்த வேண்டாம்.", + "verify_not_found_title": "இந்தப் பதிப்புக்கான பதிவு இல்லை", + "verify_not_found_body": "பதிவகம் பதிலளித்தது, இந்த ஹாஷுக்கு எதுவும் வைத்திருக்கவில்லை.", + "verify_unavailable_title": "சரிபார்க்க முடியவில்லை", + "verify_unavailable_body": "இது 'பதிவு செய்யப்படவில்லை' என்பதற்குச் சமமானதல்ல — பதிவகம் பதிலளிக்கவில்லை.", + "verify_undetermined_title": "இந்த முனை தன்னால் என்ன செய்ய முடியும் என்பதைத் தீர்மானிக்க முடியவில்லை", + "verify_undetermined_body": "முனை பதிலளித்தது, ஆனால் தன் சொந்த விசைப் பதிவை வாசிக்க முடியவில்லை. இது பொதுவாக தற்காலிகமானது — சிறிது நேரத்தில் மீண்டும் முயலவும்.", + "verify_retry": "மீண்டும் சரிபார்", "attestation_actions_desc": "இந்தப் பதிவுக்கான செயல்கள்", "chat_badge_message": "செய்தி", "chat_details": "வகை {type} · எல்லை {scope} · நிலை {status}", diff --git a/client/desktopApp/src/main/resources/localization/te.json b/client/desktopApp/src/main/resources/localization/te.json index 57f56c3..d5ae35d 100644 --- a/client/desktopApp/src/main/resources/localization/te.json +++ b/client/desktopApp/src/main/resources/localization/te.json @@ -2924,6 +2924,27 @@ "wallet_transfer_success": "బదిలీ విజయవంతమైంది! TX: {tx}", "wallet_trust_degraded": "హార్డ్‌వేర్ నమ్మకం తగ్గింది", "wallet_warning": "హెచ్చరిక", + "verify_title": "బిల్డ్‌ను ధృవీకరించండి", + "verify_hash_label": "బిల్డ్ హాష్", + "verify_button": "తనిఖీ చేయండి", + "verify_undeclared_title": "ఈ నోడ్ బిల్డ్‌లను ధృవీకరిస్తుందో లేదో చెప్పలేకపోతుంది", + "verify_undeclared_body": "ఈ నోడ్ కేపబిలిటీ ప్రకటన కంటే పాతది, కాబట్టి ఇది చెప్పలేకపోతుంది. కొత్త నోడ్ బిల్డ్‌లను ధృవీకరించగలదు.", + "verify_absent_title": "ఈ నోడ్ బిల్డ్‌లను ధృవీకరించదు", + "verify_absent_body": "ఈ నోడ్ వద్ద రిజిస్ట్రీ లేదు, కాబట్టి ఇది బిల్డ్‌లను తనిఖీ చేయలేకపోతుంది. మరో నోడ్ చేయగలదు.", + "verify_unreachable_title": "ఈ నోడ్‌ను చేరుకోలేకపోయాం", + "verify_unreachable_body": "నోడ్ స్పందించలేదు, కాబట్టి అది బిల్డ్‌లను ధృవీకరించగలదో లేదో మాకు తెలియదు. ఇది మీరు తనిఖీ చేస్తున్న బిల్డ్‌లో సమస్య కాదు.", + "verify_status_registered": "నమోదైంది", + "verify_status_deprecated": "ఇక సిఫార్సు చేయబడదు", + "verify_status_revoked": "రద్దు చేయబడింది", + "verify_status_unreadable": "స్థితి గుర్తించబడలేదు", + "verify_revoked_warning": "ఈ బిల్డ్ రద్దు చేయబడింది. దీన్ని ఉపయోగించవద్దు.", + "verify_not_found_title": "ఈ బిల్డ్ గురించి రికార్డు లేదు", + "verify_not_found_body": "రిజిస్ట్రీ స్పందించింది, కానీ ఈ హాష్ కోసం ఏమీ లేదు.", + "verify_unavailable_title": "తనిఖీ చేయలేకపోయాం", + "verify_unavailable_body": "ఇది 'నమోదు కాలేదు' అనే దానికి సమానం కాదు — రిజిస్ట్రీ స్పందించలేదు.", + "verify_undetermined_title": "ఈ నోడ్ తాను ఏమి చేయగలదో నిర్ధారించలేకపోయింది", + "verify_undetermined_body": "నోడ్ స్పందించింది, కానీ తన సొంత కీ రికార్డును చదవలేకపోయింది. ఇది సాధారణంగా తాత్కాలికం — కొద్ది సేపట్లో మళ్ళీ ప్రయత్నించండి.", + "verify_retry": "మళ్ళీ తనిఖీ చేయండి", "attestation_actions_desc": "ఈ రికార్డుకు చర్యలు", "chat_badge_message": "సందేశం", "chat_details": "రకం {type} · పరిధి {scope} · స్థితి {status}", diff --git a/client/desktopApp/src/main/resources/localization/th.json b/client/desktopApp/src/main/resources/localization/th.json index 079e23f..cba9e06 100644 --- a/client/desktopApp/src/main/resources/localization/th.json +++ b/client/desktopApp/src/main/resources/localization/th.json @@ -2924,6 +2924,27 @@ "wallet_transfer_success": "Transfer สำเร็จful! TX: {tx}", "wallet_trust_degraded": "ความน่าเชื่อถือของฮาร์ดแวร์ลดลง", "wallet_warning": "คำเตือน", + "verify_title": "ตรวจสอบ build", + "verify_hash_label": "Hash ของ build", + "verify_button": "ตรวจสอบ", + "verify_undeclared_title": "โหนดนี้บอกไม่ได้ว่าตนตรวจสอบ build หรือไม่", + "verify_undeclared_body": "โหนดนี้เก่ากว่าคำประกาศความสามารถ จึงบอกไม่ได้ โหนดที่ใหม่กว่าสามารถตรวจสอบ build ได้", + "verify_absent_title": "โหนดนี้ไม่ตรวจสอบ build", + "verify_absent_body": "โหนดนี้ไม่มีรีจิสทรี จึงไม่สามารถตรวจสอบ build ได้ โหนดอื่นสามารถทำได้", + "verify_unreachable_title": "ไม่สามารถติดต่อโหนดนี้ได้", + "verify_unreachable_body": "โหนดไม่ตอบสนอง เราจึงไม่ทราบว่าโหนดสามารถตรวจสอบ build ได้หรือไม่ นี่ไม่ใช่ปัญหาของ build ที่คุณกำลังตรวจสอบ", + "verify_status_registered": "ลงทะเบียนแล้ว", + "verify_status_deprecated": "ไม่แนะนำให้ใช้อีกต่อไป", + "verify_status_revoked": "ถูกเพิกถอน", + "verify_status_unreadable": "ไม่รู้จักสถานะ", + "verify_revoked_warning": "Build นี้ถูกเพิกถอนแล้ว อย่าใช้งาน", + "verify_not_found_title": "ไม่มีบันทึกสำหรับ build นี้", + "verify_not_found_body": "รีจิสทรีตอบกลับแล้ว และไม่มีข้อมูลสำหรับ hash นี้", + "verify_unavailable_title": "ไม่สามารถตรวจสอบได้", + "verify_unavailable_body": "นี่ไม่เหมือนกับ 'ไม่ได้ลงทะเบียน' — รีจิสทรีไม่ตอบสนอง", + "verify_undetermined_title": "โหนดนี้ไม่สามารถระบุได้ว่าตนทำสิ่งใดได้", + "verify_undetermined_body": "โหนดตอบแล้ว แต่อ่านบันทึกคีย์ของตนเองไม่ได้ โดยปกติแล้วนี่เป็นเพียงชั่วคราว — ลองอีกครั้งในไม่ช้า", + "verify_retry": "ตรวจสอบอีกครั้ง", "attestation_actions_desc": "การดำเนินการสำหรับระเบียนนี้", "chat_badge_message": "ข้อความ", "chat_details": "ประเภท {type} · ขอบเขต {scope} · สถานะ {status}", diff --git a/client/desktopApp/src/main/resources/localization/tr.json b/client/desktopApp/src/main/resources/localization/tr.json index 2bc1988..6729871 100644 --- a/client/desktopApp/src/main/resources/localization/tr.json +++ b/client/desktopApp/src/main/resources/localization/tr.json @@ -2924,6 +2924,27 @@ "wallet_transfer_success": "Transfer başarılı! TX: {tx}", "wallet_trust_degraded": "Donanım Güveni Düşmüş", "wallet_warning": "Uyarı", + "verify_title": "Bir derlemeyi doğrula", + "verify_hash_label": "Derleme hash'i", + "verify_button": "Kontrol Et", + "verify_undeclared_title": "Bu düğüm, derlemeleri doğrulayıp doğrulamadığını söyleyemez", + "verify_undeclared_body": "Bu düğüm, yetenek ilanından daha eski; dolayısıyla bunu söyleyemez. Daha yeni bir düğüm derlemeleri doğrulayabilir.", + "verify_absent_title": "Bu düğüm derlemeleri doğrulamıyor", + "verify_absent_body": "Bu düğüm sicili taşımıyor, dolayısıyla derlemeleri kontrol edemez. Başka bir düğüm kontrol edebilir.", + "verify_unreachable_title": "Bu düğüme erişilemedi", + "verify_unreachable_body": "Düğüm yanıt vermedi; dolayısıyla derlemeleri doğrulayıp doğrulayamayacağını bilmiyoruz. Bu, kontrol ettiğiniz derlemeyle ilgili bir sorun değildir.", + "verify_status_registered": "Kayıtlı", + "verify_status_deprecated": "Artık önerilmiyor", + "verify_status_revoked": "İptal Edildi", + "verify_status_unreadable": "Durum tanınmıyor", + "verify_revoked_warning": "Bu derleme iptal edilmiştir. Kullanmayın.", + "verify_not_found_title": "Bu derlemeye ait kayıt yok", + "verify_not_found_body": "Sicil yanıt verdi ve bu hash için hiçbir kayıt tutmuyor.", + "verify_unavailable_title": "Kontrol edilemedi", + "verify_unavailable_body": "Bu, 'kayıtlı değil' ile aynı şey değildir — sicil yanıt vermedi.", + "verify_undetermined_title": "Bu düğüm ne yapabileceğini belirleyemedi", + "verify_undetermined_body": "Düğüm yanıt verdi, ancak kendi anahtar kaydını okuyamadı. Bu genellikle geçicidir — kısa süre sonra tekrar deneyin.", + "verify_retry": "Yeniden kontrol et", "attestation_actions_desc": "Bu kayıt için eylemler", "chat_badge_message": "MESAJ", "chat_details": "tür {type} · kapsam {scope} · durum {status}", diff --git a/client/desktopApp/src/main/resources/localization/uk.json b/client/desktopApp/src/main/resources/localization/uk.json index 9de68ee..398a7c9 100644 --- a/client/desktopApp/src/main/resources/localization/uk.json +++ b/client/desktopApp/src/main/resources/localization/uk.json @@ -2924,6 +2924,27 @@ "wallet_transfer_success": "Переказ успішний! TX: {tx}", "wallet_trust_degraded": "Апаратну довіру знижено", "wallet_warning": "Попередження", + "verify_title": "Перевірити збірку", + "verify_hash_label": "Хеш збірки", + "verify_button": "Перевірити", + "verify_undeclared_title": "Цей вузол не може сказати, чи перевіряє він збірки", + "verify_undeclared_body": "Цей вузол старіший за декларацію можливостей, тож не може це сказати. Новіший вузол може перевіряти збірки.", + "verify_absent_title": "Цей вузол не перевіряє збірки", + "verify_absent_body": "Цей вузол не тримає реєстр, тож не може перевіряти збірки. Інший вузол може.", + "verify_unreachable_title": "Не вдалося зв'язатися з цим вузлом", + "verify_unreachable_body": "Вузол не відповів, тож ми не знаємо, чи може він перевіряти збірки. Це не проблема зі збіркою, яку ви перевіряєте.", + "verify_status_registered": "Зареєстровано", + "verify_status_deprecated": "Більше не рекомендується", + "verify_status_revoked": "Відкликано", + "verify_status_unreadable": "Статус не розпізнано", + "verify_revoked_warning": "Цю збірку відкликано. Не використовуйте її.", + "verify_not_found_title": "Немає запису про цю збірку", + "verify_not_found_body": "Реєстр відповів і не має нічого для цього хешу.", + "verify_unavailable_title": "Не вдалося перевірити", + "verify_unavailable_body": "Це не те саме, що «не зареєстровано» — реєстр не відповів.", + "verify_undetermined_title": "Цей вузол не зміг визначити, що він може робити", + "verify_undetermined_body": "Вузол відповів, але не зміг прочитати власний запис ключа. Зазвичай це тимчасово — спробуйте ще раз незабаром.", + "verify_retry": "Перевірити ще раз", "attestation_actions_desc": "Дії для цього запису", "chat_badge_message": "ПОВІДОМЛЕННЯ", "chat_details": "тип {type} · область {scope} · статус {status}", diff --git a/client/desktopApp/src/main/resources/localization/ur.json b/client/desktopApp/src/main/resources/localization/ur.json index cecd77f..462a656 100644 --- a/client/desktopApp/src/main/resources/localization/ur.json +++ b/client/desktopApp/src/main/resources/localization/ur.json @@ -2924,6 +2924,27 @@ "wallet_transfer_success": "ٹرانسفر کامیاب! TX: {tx}", "wallet_trust_degraded": "ہارڈ ویئر اعتماد کمزور پڑ گیا", "wallet_warning": "انتباہ", + "verify_title": "بلڈ کی تصدیق کریں", + "verify_hash_label": "بلڈ ہیش", + "verify_button": "جانچیں", + "verify_undeclared_title": "یہ نوڈ نہیں بتا سکتا کہ آیا وہ بلڈز کی تصدیق کرتا ہے", + "verify_undeclared_body": "یہ نوڈ صلاحیت کے اعلان سے پرانا ہے، اس لیے یہ نہیں بتا سکتا۔ ایک نیا نوڈ بلڈز کی تصدیق کر سکتا ہے۔", + "verify_absent_title": "یہ نوڈ بلڈز کی تصدیق نہیں کرتا", + "verify_absent_body": "یہ نوڈ رجسٹری نہیں رکھتا، اس لیے یہ بلڈز کی جانچ نہیں کر سکتا۔ کوئی دوسرا نوڈ کر سکتا ہے۔", + "verify_unreachable_title": "اس نوڈ تک رسائی نہیں ہو سکی", + "verify_unreachable_body": "نوڈ نے جواب نہیں دیا، اس لیے ہمیں معلوم نہیں کہ وہ بلڈز کی تصدیق کر سکتا ہے یا نہیں۔ یہ اس بلڈ کا مسئلہ نہیں جس کی آپ جانچ کر رہے ہیں۔", + "verify_status_registered": "رجسٹرڈ", + "verify_status_deprecated": "اب تجویز نہیں کیا جاتا", + "verify_status_revoked": "منسوخ شدہ", + "verify_status_unreadable": "حیثیت شناخت نہیں ہو سکی", + "verify_revoked_warning": "یہ بلڈ منسوخ کر دیا گیا ہے۔ اسے استعمال نہ کریں۔", + "verify_not_found_title": "اس بلڈ کا کوئی ریکارڈ نہیں", + "verify_not_found_body": "رجسٹری نے جواب دیا، اور اس کے پاس اس ہیش کے لیے کچھ نہیں ہے۔", + "verify_unavailable_title": "جانچ نہیں ہو سکی", + "verify_unavailable_body": "یہ 'رجسٹرڈ نہیں' کے برابر نہیں — رجسٹری نے جواب نہیں دیا۔", + "verify_undetermined_title": "یہ نوڈ طے نہیں کر سکا کہ وہ کیا کر سکتا ہے", + "verify_undetermined_body": "نوڈ نے جواب دیا، مگر اپنا کلیدی ریکارڈ نہ پڑھ سکا۔ یہ عام طور پر عارضی ہوتا ہے — تھوڑی دیر بعد دوبارہ کوشش کریں۔", + "verify_retry": "دوبارہ جانچیں", "attestation_actions_desc": "اس ریکارڈ کے لیے اقدامات", "chat_badge_message": "پیغام", "chat_details": "قسم {type} · دائرہ {scope} · حیثیت {status}", diff --git a/client/desktopApp/src/main/resources/localization/vi.json b/client/desktopApp/src/main/resources/localization/vi.json index 24135ce..6bc35d0 100644 --- a/client/desktopApp/src/main/resources/localization/vi.json +++ b/client/desktopApp/src/main/resources/localization/vi.json @@ -2924,6 +2924,27 @@ "wallet_transfer_success": "Chuyển khoản thành công! TX: {tx}", "wallet_trust_degraded": "Tin tưởng Suy giảm", "wallet_warning": "Cảnh báo", + "verify_title": "Xác minh một bản dựng", + "verify_hash_label": "Hash bản dựng", + "verify_button": "Kiểm tra", + "verify_undeclared_title": "Nút này không thể cho biết liệu nó có xác minh các bản dựng hay không", + "verify_undeclared_body": "Nút này cũ hơn bản khai năng lực, nên không thể trả lời. Một nút mới hơn có thể xác minh các bản dựng.", + "verify_absent_title": "Nút này không xác minh các bản dựng", + "verify_absent_body": "Nút này không giữ sổ đăng ký, nên không thể kiểm tra các bản dựng. Một nút khác có thể làm điều đó.", + "verify_unreachable_title": "Không thể kết nối với nút này", + "verify_unreachable_body": "Nút không phản hồi, nên chúng ta không biết liệu nó có thể xác minh các bản dựng hay không. Đây không phải là vấn đề của bản dựng bạn đang kiểm tra.", + "verify_status_registered": "Đã đăng ký", + "verify_status_deprecated": "Không còn được khuyến nghị", + "verify_status_revoked": "Đã bị thu hồi", + "verify_status_unreadable": "Không nhận dạng được trạng thái", + "verify_revoked_warning": "Bản dựng này đã bị thu hồi. Không sử dụng nó.", + "verify_not_found_title": "Không có bản ghi cho bản dựng này", + "verify_not_found_body": "Sổ đăng ký đã phản hồi và không có gì cho hash này.", + "verify_unavailable_title": "Không thể kiểm tra", + "verify_unavailable_body": "Điều này không giống với “chưa đăng ký” — sổ đăng ký không phản hồi.", + "verify_undetermined_title": "Nút này không thể xác định được nó có thể làm gì", + "verify_undetermined_body": "Nút đã trả lời, nhưng không đọc được bản ghi khóa của chính nó. Thông thường đây là tình trạng tạm thời — hãy thử lại sau.", + "verify_retry": "Kiểm tra lại", "attestation_actions_desc": "Các thao tác cho bản ghi này", "chat_badge_message": "TIN NHẮN", "chat_details": "loại {type} · phạm vi {scope} · trạng thái {status}", diff --git a/client/desktopApp/src/main/resources/localization/yo.json b/client/desktopApp/src/main/resources/localization/yo.json index c7c0a0f..f676e88 100644 --- a/client/desktopApp/src/main/resources/localization/yo.json +++ b/client/desktopApp/src/main/resources/localization/yo.json @@ -2924,6 +2924,27 @@ "wallet_transfer_success": "Gbígbé ṣe àṣeyọrí! TX: {tx}", "wallet_trust_degraded": "Ìgbẹ́kẹ̀lé Ohun Ẹ̀rọ Ti Dín Kù", "wallet_warning": "Ìkìlọ̀", + "verify_title": "Jẹ́rìísí build kan", + "verify_hash_label": "Hash build", + "verify_button": "Ṣàyẹ̀wò", + "verify_undeclared_title": "Nódù yìí kò lè sọ bóyá ó ń jẹ́rìísí àwọn build", + "verify_undeclared_body": "Nódù yìí dàgbà ju ìkéde agbára rẹ̀ lọ, nítorí náà kò lè sọ. Nódù tí ó ṣẹ̀ṣẹ̀ dé lè jẹ́rìísí àwọn build.", + "verify_absent_title": "Nódù yìí kì í jẹ́rìísí àwọn build", + "verify_absent_body": "Nódù yìí kò gbé àkójọ ìforúkọsílẹ̀, nítorí náà kò lè ṣàyẹ̀wò àwọn build. Nódù mìíràn lè ṣe é.", + "verify_unreachable_title": "A kò lè dé nódù yìí", + "verify_unreachable_body": "Nódù náà kò dáhùn, nítorí náà a kò mọ̀ bóyá ó lè jẹ́rìísí àwọn build. Èyí kì í ṣe ìṣòrò pẹ̀lú build tí o ń ṣàyẹ̀wò.", + "verify_status_registered": "Tí a forúkọsílẹ̀", + "verify_status_deprecated": "A kò gbà á nímọ̀ràn mọ́", + "verify_status_revoked": "Tí a fagilé", + "verify_status_unreadable": "Ipò tí a kò dá mọ̀", + "verify_revoked_warning": "A ti fagilé build yìí. Má lò ó.", + "verify_not_found_title": "Kò sí àkọsílẹ̀ fún build yìí", + "verify_not_found_body": "Àkójọ ìforúkọsílẹ̀ dáhùn, kò sì ní ohunkóhun fún hash yìí.", + "verify_unavailable_title": "A kò lè ṣàyẹ̀wò", + "verify_unavailable_body": "Èyí kò rí bákan náà pẹ̀lú 'a kò forúkọsílẹ̀' — àkójọ ìforúkọsílẹ̀ kò dáhùn.", + "verify_undetermined_title": "Nódù yìí kò lè pinnu ohun tí ó lè ṣe", + "verify_undetermined_body": "Nódù náà dáhùn, ṣùgbọ́n kò lè ka àkọsílẹ̀ kọ́kọ́rọ́ tirẹ̀. Èyí sábà máa ń jẹ́ fún ìgbà kékeré — gbìyànjú lẹ́ẹ̀kansi láìpẹ́.", + "verify_retry": "Ṣàyẹ̀wò lẹ́ẹ̀kansi", "attestation_actions_desc": "Àwọn ìgbésẹ̀ fún àkọsílẹ̀ yìí", "chat_badge_message": "ÌFIRÁNṢẸ́", "chat_details": "irú {type} · ààlà {scope} · ipò {status}", diff --git a/client/desktopApp/src/main/resources/localization/zh.json b/client/desktopApp/src/main/resources/localization/zh.json index 570ceda..c59f0cd 100644 --- a/client/desktopApp/src/main/resources/localization/zh.json +++ b/client/desktopApp/src/main/resources/localization/zh.json @@ -2924,6 +2924,27 @@ "wallet_transfer_success": "转账成功!TX: {tx}", "wallet_trust_degraded": "硬件信任降级", "wallet_warning": "警告", + "verify_title": "验证构建版本", + "verify_hash_label": "构建哈希", + "verify_button": "检查", + "verify_undeclared_title": "本节点无法说明自己是否验证构建版本", + "verify_undeclared_body": "本节点的版本早于能力声明机制,因此无法作答。更新版本的节点可以验证构建版本。", + "verify_absent_title": "本节点不验证构建版本", + "verify_absent_body": "本节点未持有注册表,因此无法检查构建版本。其他节点可以。", + "verify_unreachable_title": "无法连接到该节点", + "verify_unreachable_body": "该节点未作应答,因此我们不知道它是否能够验证构建版本。这不是您正在检查的构建版本本身的问题。", + "verify_status_registered": "已注册", + "verify_status_deprecated": "不再推荐", + "verify_status_revoked": "已撤销", + "verify_status_unreadable": "状态无法识别", + "verify_revoked_warning": "该构建版本已被撤销。请勿使用。", + "verify_not_found_title": "没有该构建版本的记录", + "verify_not_found_body": "注册表已应答,但未持有该哈希的任何记录。", + "verify_unavailable_title": "无法检查", + "verify_unavailable_body": "这与“未注册”并不相同——注册表未作应答。", + "verify_undetermined_title": "本节点无法确定自己能做什么", + "verify_undetermined_body": "该节点作出了应答,但无法读取自己的密钥记录。这通常是暂时性的——请稍后重试。", + "verify_retry": "重新检查", "attestation_actions_desc": "此记录的操作", "chat_badge_message": "消息", "chat_details": "类型 {type} · 范围 {scope} · 状态 {status}", diff --git a/client/iosApp/iosApp/localization/am.json b/client/iosApp/iosApp/localization/am.json index 6fc10f6..54741c5 100644 --- a/client/iosApp/iosApp/localization/am.json +++ b/client/iosApp/iosApp/localization/am.json @@ -2924,6 +2924,27 @@ "wallet_transfer_success": "ማስተላለፍ ተሳክቷል! TX: {tx}", "wallet_trust_degraded": "ስልክ ሥቅ ተዳክሞ ነበር", "wallet_warning": "ማስጠንቀቂያ", + "verify_title": "ግንባታ ማረጋገጥ", + "verify_hash_label": "የግንባታ ሃሽ", + "verify_button": "አረጋግጥ", + "verify_undeclared_title": "ይህ ኖድ ግንባታዎችን እንደሚያረጋግጥ ወይም እንደማያረጋግጥ መናገር አይችልም", + "verify_undeclared_body": "ይህ ኖድ ከችሎታ መግለጫው የቀደመ ነው፤ ስለዚህ መናገር አይችልም። አዲስ ኖድ ግንባታዎችን ማረጋገጥ ይችላል።", + "verify_absent_title": "ይህ ኖድ ግንባታዎችን አያረጋግጥም", + "verify_absent_body": "ይህ ኖድ መዝገቡን አልያዘም፤ ስለዚህ ግንባታዎችን ማረጋገጥ አይችልም። ሌላ ኖድ ግን ይችላል።", + "verify_unreachable_title": "ወደዚህ ኖድ መድረስ አልተቻለም", + "verify_unreachable_body": "ኖዱ መልስ አልሰጠም፤ ስለዚህ ግንባታዎችን ማረጋገጥ እንደሚችል ወይም እንደማይችል አናውቅም። ይህ እርስዎ የሚያረጋግጡት ግንባታ ችግር አይደለም።", + "verify_status_registered": "ተመዝግቧል", + "verify_status_deprecated": "ከዚህ በኋላ አይመከርም", + "verify_status_revoked": "ተሰርዟል", + "verify_status_unreadable": "ሁኔታው አልታወቀም", + "verify_revoked_warning": "ይህ ግንባታ ተሰርዟል። አይጠቀሙበት።", + "verify_not_found_title": "ለዚህ ግንባታ ምንም መዝገብ የለም", + "verify_not_found_body": "መዝገቡ መልስ ሰጥቷል፤ ለዚህ ሃሽ ምንም አልያዘም።", + "verify_unavailable_title": "ማረጋገጥ አልተቻለም", + "verify_unavailable_body": "ይህ ‘አልተመዘገበም’ ከመባል ጋር አንድ አይደለም — መዝገቡ መልስ አልሰጠም።", + "verify_undetermined_title": "ይህ ኖድ ምን ማድረግ እንደሚችል መወሰን አልቻለም", + "verify_undetermined_body": "ኖዱ መልስ ሰጥቷል፣ ሆኖም የራሱን የቁልፍ መዝገብ ማንበብ አልቻለም። ይህ በተለምዶ ጊዜያዊ ነው — ከጥቂት ጊዜ በኋላ እንደገና ይሞክሩ።", + "verify_retry": "እንደገና አረጋግጥ", "attestation_actions_desc": "ለዚህ መዝገብ ያሉ እርምጃዎች", "chat_badge_message": "መልዕክት", "chat_details": "ዓይነት {type} · ወሰን {scope} · ሁኔታ {status}", diff --git a/client/iosApp/iosApp/localization/ar.json b/client/iosApp/iosApp/localization/ar.json index 52541c6..48f9965 100644 --- a/client/iosApp/iosApp/localization/ar.json +++ b/client/iosApp/iosApp/localization/ar.json @@ -2924,6 +2924,27 @@ "wallet_transfer_success": "نجح التحويل! TX: {tx}", "wallet_trust_degraded": "تدهورت ثقة الأجهزة", "wallet_warning": "تحذير", + "verify_title": "التحقق من إصدار", + "verify_hash_label": "بصمة الإصدار", + "verify_button": "تحقّق", + "verify_undeclared_title": "لا تستطيع هذه العقدة الإفادة عن قدرتها على التحقق من الإصدارات", + "verify_undeclared_body": "هذه العقدة أقدم من إعلان القدرات، فلا يمكنها الإفادة. عقدة أحدث تستطيع التحقق من الإصدارات.", + "verify_absent_title": "هذه العقدة لا تتحقق من الإصدارات", + "verify_absent_body": "لا تحمل هذه العقدة السجل، فلا يمكنها التحقق من الإصدارات. عقدة أخرى تستطيع ذلك.", + "verify_unreachable_title": "تعذّر الوصول إلى هذه العقدة", + "verify_unreachable_body": "لم تُجب العقدة، فلا نعرف أتستطيع التحقق من الإصدارات أم لا. وهذا ليس عطلاً في الإصدار الذي تتحقق منه.", + "verify_status_registered": "مسجَّل", + "verify_status_deprecated": "لم يعد يُنصح به", + "verify_status_revoked": "مُلغى", + "verify_status_unreadable": "الحالة غير معروفة", + "verify_revoked_warning": "هذا الإصدار أُلغي. لا تستخدمه.", + "verify_not_found_title": "لا سجل لهذا الإصدار", + "verify_not_found_body": "أجاب السجل ولا يحمل شيئاً لهذه البصمة.", + "verify_unavailable_title": "تعذّر التحقق", + "verify_unavailable_body": "هذا ليس كـ«غير مسجَّل» — فالسجل لم يُجب.", + "verify_undetermined_title": "تعذّر على هذه العقدة تحديد ما تستطيع فعله", + "verify_undetermined_body": "أجابت العقدة، لكنها لم تستطع قراءة سجل مفتاحها الخاص. هذا عادةً مؤقت — حاول مجدداً بعد قليل.", + "verify_retry": "تحقّق مجدداً", "attestation_actions_desc": "إجراءات هذا السجل", "chat_badge_message": "رسالة", "chat_details": "النوع {type} · النطاق {scope} · الحالة {status}", diff --git a/client/iosApp/iosApp/localization/bn.json b/client/iosApp/iosApp/localization/bn.json index cbb52b3..203a77c 100644 --- a/client/iosApp/iosApp/localization/bn.json +++ b/client/iosApp/iosApp/localization/bn.json @@ -2925,6 +2925,27 @@ "wallet_transfer_success": "ট্রান্সফার সফল! TX: {tx}", "wallet_trust_degraded": "হার্ডওয়্যার বিশ্বাস হ্রাস পেয়েছে", "wallet_warning": "সতর্কতা", + "verify_title": "একটি বিল্ড যাচাই করুন", + "verify_hash_label": "বিল্ড হ্যাশ", + "verify_button": "পরীক্ষা করুন", + "verify_undeclared_title": "এই নোড বলতে পারে না যে এটি বিল্ড যাচাই করে কি না", + "verify_undeclared_body": "এই নোড সক্ষমতা ঘোষণার চেয়ে পুরনো, তাই এটি বলতে পারে না। নতুন কোনো নোড বিল্ড যাচাই করতে পারে।", + "verify_absent_title": "এই নোড বিল্ড যাচাই করে না", + "verify_absent_body": "এই নোড রেজিস্ট্রি ধারণ করে না, তাই এটি বিল্ড পরীক্ষা করতে পারে না। অন্য একটি নোড পারে।", + "verify_unreachable_title": "এই নোডে পৌঁছানো যায়নি", + "verify_unreachable_body": "নোডটি সাড়া দেয়নি, তাই এটি বিল্ড যাচাই করতে পারে কি না তা আমরা জানি না। আপনি যে বিল্ডটি পরীক্ষা করছেন তার সমস্যা এটি নয়।", + "verify_status_registered": "নিবন্ধিত", + "verify_status_deprecated": "আর প্রস্তাবিত নয়", + "verify_status_revoked": "প্রত্যাহৃত", + "verify_status_unreadable": "অবস্থা সনাক্ত করা যায়নি", + "verify_revoked_warning": "এই বিল্ডটি প্রত্যাহার করা হয়েছে। এটি ব্যবহার করবেন না।", + "verify_not_found_title": "এই বিল্ডের কোনো রেকর্ড নেই", + "verify_not_found_body": "রেজিস্ট্রি সাড়া দিয়েছে এবং এই হ্যাশের জন্য কিছুই ধারণ করে না।", + "verify_unavailable_title": "পরীক্ষা করা যায়নি", + "verify_unavailable_body": "এটি ‘নিবন্ধিত নয়’-এর সমান নয় — রেজিস্ট্রি সাড়া দেয়নি।", + "verify_undetermined_title": "এই নোড নির্ধারণ করতে পারেনি যে এটি কী করতে পারে", + "verify_undetermined_body": "নোডটি সাড়া দিয়েছে, কিন্তু নিজের কী রেকর্ড পড়তে পারেনি। এটি সাধারণত সাময়িক — কিছুক্ষণ পরে আবার চেষ্টা করুন।", + "verify_retry": "আবার পরীক্ষা করুন", "attestation_actions_desc": "এই রেকর্ডের জন্য পদক্ষেপ", "chat_badge_message": "বার্তা", "chat_details": "ধরন {type} · পরিসর {scope} · অবস্থা {status}", diff --git a/client/iosApp/iosApp/localization/de.json b/client/iosApp/iosApp/localization/de.json index da1e0ac..6f85250 100644 --- a/client/iosApp/iosApp/localization/de.json +++ b/client/iosApp/iosApp/localization/de.json @@ -2862,6 +2862,18 @@ "users_status": "Status", "users_user_id": "Benutzer-ID", "users_wa_role": "WA:{role}", + "verify_unavailable_title": "Prüfung nicht möglich", + "verify_undetermined_title": "Dieser Knoten konnte nicht feststellen, was er kann", + "verify_undetermined_body": "Der Knoten hat geantwortet, konnte aber seinen eigenen Schlüsseldatensatz nicht lesen. Das ist meist vorübergehend — versuchen Sie es in Kürze erneut.", + "verify_retry": "Erneut prüfen", + "verify_unreachable_title": "Knoten nicht erreichbar", + "verify_unreachable_body": "Der Knoten hat nicht geantwortet, daher wissen wir nicht, ob er Builds verifizieren kann. Das liegt nicht an dem Build, den Sie prüfen.", + "verify_status_registered": "Registriert", + "verify_status_deprecated": "Nicht mehr empfohlen", + "verify_status_revoked": "Widerrufen", + "verify_status_unreadable": "Status nicht erkannt", + "verify_revoked_warning": "Dieser Build wurde widerrufen. Verwenden Sie ihn nicht.", + "verify_not_found_title": "Kein Eintrag für diesen Build", "wa_approve": "Genehmigen", "wa_avg_resolution": "Durchschnittl. Auflösung: {time} Min", "wa_bus_subscribers": "Bus-Abonnenten", @@ -2924,6 +2936,12 @@ "wallet_transfer_success": "Überweisung erfolgreich! TX: {tx}", "wallet_trust_degraded": "Hardware-Vertrauen herabgestuft", "wallet_warning": "Warnung", + "verify_title": "Build verifizieren", + "verify_hash_label": "Build-Hash", + "verify_button": "Prüfen", + "verify_undeclared_title": "Dieser Knoten kann nicht sagen, ob er Builds verifiziert", + "verify_undeclared_body": "Dieser Knoten ist älter als die Fähigkeitserklärung und kann daher keine Auskunft geben. Ein neuerer Knoten kann Builds verifizieren.", + "verify_absent_title": "Dieser Knoten verifiziert keine Builds", "attestation_actions_desc": "Aktionen für diesen Datensatz", "chat_badge_message": "NACHRICHT", "chat_details": "Typ {type} · Bereich {scope} · Status {status}", diff --git a/client/iosApp/iosApp/localization/es.json b/client/iosApp/iosApp/localization/es.json index fe02dbf..91b0f58 100644 --- a/client/iosApp/iosApp/localization/es.json +++ b/client/iosApp/iosApp/localization/es.json @@ -2924,6 +2924,27 @@ "wallet_transfer_success": "¡Transferencia exitosa! TX: {tx}", "wallet_trust_degraded": "Confianza de Hardware Degradada", "wallet_warning": "Advertencia", + "verify_title": "Verificar una compilación", + "verify_hash_label": "Hash de la compilación", + "verify_button": "Comprobar", + "verify_undeclared_title": "Este nodo no puede decir si verifica compilaciones", + "verify_undeclared_body": "Este nodo es anterior a la declaración de capacidades, así que no puede saberlo. Un nodo más reciente puede verificar compilaciones.", + "verify_absent_title": "Este nodo no verifica compilaciones", + "verify_absent_body": "Este nodo no aloja el registro, así que no puede comprobar compilaciones. Otro nodo sí puede.", + "verify_unreachable_title": "No se pudo contactar con este nodo", + "verify_unreachable_body": "El nodo no respondió, así que no sabemos si puede verificar compilaciones. Esto no es un problema de la compilación que estás comprobando.", + "verify_status_registered": "Registrada", + "verify_status_deprecated": "Ya no se recomienda", + "verify_status_revoked": "Revocada", + "verify_status_unreadable": "Estado no reconocido", + "verify_revoked_warning": "Esta compilación ha sido revocada. No la uses.", + "verify_not_found_title": "No hay registro de esta compilación", + "verify_not_found_body": "El registro respondió y no tiene nada para este hash.", + "verify_unavailable_title": "No se pudo comprobar", + "verify_unavailable_body": "Esto no es lo mismo que «no registrada» — el registro no respondió.", + "verify_undetermined_title": "Este nodo no pudo determinar qué puede hacer", + "verify_undetermined_body": "El nodo respondió, pero no pudo leer su propio registro de claves. Esto suele ser temporal — inténtalo de nuevo en breve.", + "verify_retry": "Comprobar de nuevo", "attestation_actions_desc": "Acciones para este registro", "chat_badge_message": "MENSAJE", "chat_details": "tipo {type} · ámbito {scope} · estado {status}", diff --git a/client/iosApp/iosApp/localization/fa.json b/client/iosApp/iosApp/localization/fa.json index 38b931c..41c206a 100644 --- a/client/iosApp/iosApp/localization/fa.json +++ b/client/iosApp/iosApp/localization/fa.json @@ -2930,6 +2930,27 @@ "wallet_transfer_success": "انتقال با موفقیت انجام شد! TX: {tx}", "wallet_trust_degraded": "افت اعتماد سخت‌افزاری", "wallet_warning": "هشدار", + "verify_title": "تأیید یک نسخه", + "verify_hash_label": "هش نسخه", + "verify_button": "بررسی", + "verify_undeclared_title": "این گره نمی‌تواند بگوید آیا نسخه‌ها را تأیید می‌کند یا نه", + "verify_undeclared_body": "این گره قدیمی‌تر از اعلامِ قابلیت است، پس نمی‌تواند بگوید. گرهی جدیدتر می‌تواند نسخه‌ها را تأیید کند.", + "verify_absent_title": "این گره نسخه‌ها را تأیید نمی‌کند", + "verify_absent_body": "این گره رجیستری را نگه نمی‌دارد، پس نمی‌تواند نسخه‌ها را بررسی کند. گرهی دیگر می‌تواند.", + "verify_unreachable_title": "دسترسی به این گره ممکن نشد", + "verify_unreachable_body": "گره پاسخ نداد، پس نمی‌دانیم آیا می‌تواند نسخه‌ها را تأیید کند یا نه. این مشکلی از نسخه‌ای که بررسی می‌کنید نیست.", + "verify_status_registered": "ثبت‌شده", + "verify_status_deprecated": "دیگر توصیه نمی‌شود", + "verify_status_revoked": "باطل‌شده", + "verify_status_unreadable": "وضعیت شناسایی نشد", + "verify_revoked_warning": "این نسخه باطل شده است. از آن استفاده نکنید.", + "verify_not_found_title": "رکوردی از این نسخه وجود ندارد", + "verify_not_found_body": "رجیستری پاسخ داد و چیزی برای این هش نگه نمی‌دارد.", + "verify_unavailable_title": "بررسی ممکن نشد", + "verify_unavailable_body": "این با «ثبت‌نشده» یکسان نیست — رجیستری پاسخ نداد.", + "verify_undetermined_title": "این گره نتوانست تشخیص دهد چه کاری از آن ساخته است", + "verify_undetermined_body": "گره پاسخ داد، اما نتوانست رکورد کلید خودش را بخواند. این معمولاً موقتی است — کمی بعد دوباره تلاش کنید.", + "verify_retry": "دوباره بررسی کن", "attestation_actions_desc": "اقدامات برای این رکورد", "chat_badge_message": "پیام", "chat_details": "نوع {type} · محدوده {scope} · وضعیت {status}", diff --git a/client/iosApp/iosApp/localization/fr.json b/client/iosApp/iosApp/localization/fr.json index fe1f844..4dda6cc 100644 --- a/client/iosApp/iosApp/localization/fr.json +++ b/client/iosApp/iosApp/localization/fr.json @@ -2924,6 +2924,27 @@ "wallet_transfer_success": "Transfert réussi ! TX: {tx}", "wallet_trust_degraded": "Confiance Matérielle Dégradée", "wallet_warning": "Avertissement", + "verify_title": "Vérifier un build", + "verify_hash_label": "Empreinte du build", + "verify_button": "Vérifier", + "verify_undeclared_title": "Ce nœud ne peut pas dire s'il vérifie les builds", + "verify_undeclared_body": "Ce nœud est antérieur à la déclaration de capacité : il ne peut donc pas se prononcer. Un nœud plus récent peut vérifier les builds.", + "verify_absent_title": "Ce nœud ne vérifie pas les builds", + "verify_absent_body": "Ce nœud ne détient pas le registre : il ne peut donc pas vérifier les builds. Un autre nœud le peut.", + "verify_unreachable_title": "Impossible de joindre ce nœud", + "verify_unreachable_body": "Le nœud n'a pas répondu : nous ne savons donc pas s'il peut vérifier les builds. Ceci n'est pas un problème lié au build que vous vérifiez.", + "verify_status_registered": "Enregistré", + "verify_status_deprecated": "N'est plus recommandé", + "verify_status_revoked": "Révoqué", + "verify_status_unreadable": "Statut non reconnu", + "verify_revoked_warning": "Ce build a été révoqué. Ne l'utilisez pas.", + "verify_not_found_title": "Aucun enregistrement pour ce build", + "verify_not_found_body": "Le registre a répondu et ne détient rien pour cette empreinte.", + "verify_unavailable_title": "Vérification impossible", + "verify_unavailable_body": "Ceci n'équivaut pas à « non enregistré » — le registre n'a pas répondu.", + "verify_undetermined_title": "Ce nœud n'a pas pu déterminer ce qu'il peut faire", + "verify_undetermined_body": "Le nœud a répondu, mais n'a pas pu lire son propre enregistrement de clé. C'est généralement temporaire — réessayez dans un instant.", + "verify_retry": "Vérifier à nouveau", "attestation_actions_desc": "Actions pour cet enregistrement", "chat_badge_message": "MESSAGE", "chat_details": "type {type} · portée {scope} · statut {status}", diff --git a/client/iosApp/iosApp/localization/ha.json b/client/iosApp/iosApp/localization/ha.json index f5f91af..e36d699 100644 --- a/client/iosApp/iosApp/localization/ha.json +++ b/client/iosApp/iosApp/localization/ha.json @@ -2924,6 +2924,27 @@ "wallet_transfer_success": "Aika ya yi nasara! TX: {tx}", "wallet_trust_degraded": "Tabbas Kayan Aiki Ya Rage", "wallet_warning": "Gargaɗi", + "verify_title": "Tabbatar da build", + "verify_hash_label": "Hash na build", + "verify_button": "Duba", + "verify_undeclared_title": "Wannan kumburi ba zai iya faɗi ko yana tabbatar da build ba", + "verify_undeclared_body": "Wannan kumburi ya girme sanarwar iyawa, don haka ba zai iya faɗi ba. Sabon kumburi na iya tabbatar da build.", + "verify_absent_title": "Wannan kumburi ba ya tabbatar da build ba", + "verify_absent_body": "Wannan kumburi ba ya riƙe rajista ba, don haka ba zai iya duba build ba. Wani kumburi na iya duba build.", + "verify_unreachable_title": "An kasa isa ga wannan kumburi", + "verify_unreachable_body": "Kumburin bai amsa ba, don haka ba mu san ko yana iya tabbatar da build ba. Wannan ba matsala ce ta build ɗin da kuke dubawa ba.", + "verify_status_registered": "An yi rajista", + "verify_status_deprecated": "Ba a ƙara shawarta ba", + "verify_status_revoked": "An soke", + "verify_status_unreadable": "Ba a gane matsayin ba", + "verify_revoked_warning": "An soke wannan build. Kada ku yi amfani da shi.", + "verify_not_found_title": "Babu rikodin wannan build", + "verify_not_found_body": "Rajistar ta amsa kuma ba ta riƙe komai ga wannan hash ba.", + "verify_unavailable_title": "An kasa duba", + "verify_unavailable_body": "Wannan bai zama daidai da 'ba a yi rajista ba' ba — rajistar ba ta amsa ba.", + "verify_undetermined_title": "Wannan kumburi bai iya tantance abin da yake iya yi ba", + "verify_undetermined_body": "Kumburin ya amsa, amma bai iya karanta rikodin maɓallinsa na kansa ba. Yawanci na ɗan lokaci ne — sake gwadawa nan da nan.", + "verify_retry": "Sake duba", "attestation_actions_desc": "Ayyuka don wannan rikodin", "chat_badge_message": "SAƘO", "chat_details": "nau'i {type} · iyaka {scope} · matsayi {status}", diff --git a/client/iosApp/iosApp/localization/hi.json b/client/iosApp/iosApp/localization/hi.json index 504fa17..a4e474c 100644 --- a/client/iosApp/iosApp/localization/hi.json +++ b/client/iosApp/iosApp/localization/hi.json @@ -2924,6 +2924,27 @@ "wallet_transfer_success": "स्थानांतरण सफल! TX: {tx}", "wallet_trust_degraded": "हार्डवेयर ट्रस्ट कम हुआ", "wallet_warning": "चेतावनी", + "verify_title": "बिल्ड सत्यापित करें", + "verify_hash_label": "बिल्ड हैश", + "verify_button": "जाँच करें", + "verify_undeclared_title": "यह नोड नहीं बता सकता कि यह बिल्ड सत्यापित करता है या नहीं", + "verify_undeclared_body": "यह नोड क्षमता घोषणा से पुराना है, इसलिए यह बता नहीं सकता। कोई नया नोड बिल्ड सत्यापित कर सकता है।", + "verify_absent_title": "यह नोड बिल्ड सत्यापित नहीं करता", + "verify_absent_body": "यह नोड रजिस्ट्री नहीं रखता, इसलिए यह बिल्ड की जाँच नहीं कर सकता। कोई अन्य नोड कर सकता है।", + "verify_unreachable_title": "इस नोड तक नहीं पहुँच सका", + "verify_unreachable_body": "नोड ने उत्तर नहीं दिया, इसलिए यह पता नहीं चलता कि यह बिल्ड सत्यापित कर सकता है या नहीं। यह उस बिल्ड की समस्या नहीं है जिसकी आप जाँच कर रहे हैं।", + "verify_status_registered": "पंजीकृत", + "verify_status_deprecated": "अब अनुशंसित नहीं", + "verify_status_revoked": "रद्द", + "verify_status_unreadable": "स्थिति पहचानी नहीं जा सकी", + "verify_revoked_warning": "इस बिल्ड को रद्द कर दिया गया है। इसका उपयोग न करें।", + "verify_not_found_title": "इस बिल्ड का कोई रिकॉर्ड नहीं", + "verify_not_found_body": "रजिस्ट्री ने उत्तर दिया और इस हैश के लिए उसके पास कुछ भी नहीं है।", + "verify_unavailable_title": "जाँच नहीं हो सकी", + "verify_unavailable_body": "यह 'पंजीकृत नहीं' जैसा नहीं है — रजिस्ट्री ने उत्तर नहीं दिया।", + "verify_undetermined_title": "यह नोड यह निर्धारित नहीं कर सका कि यह क्या कर सकता है", + "verify_undetermined_body": "नोड ने उत्तर दिया, पर अपना ही कुंजी रिकॉर्ड नहीं पढ़ सका। यह आमतौर पर अस्थायी होता है — थोड़ी देर में फिर से प्रयास करें।", + "verify_retry": "फिर से जाँच करें", "attestation_actions_desc": "इस रिकॉर्ड के लिए कार्रवाइयाँ", "chat_badge_message": "संदेश", "chat_details": "प्रकार {type} · दायरा {scope} · स्थिति {status}", diff --git a/client/iosApp/iosApp/localization/id.json b/client/iosApp/iosApp/localization/id.json index d51d506..8c7d4ad 100644 --- a/client/iosApp/iosApp/localization/id.json +++ b/client/iosApp/iosApp/localization/id.json @@ -2924,6 +2924,27 @@ "wallet_transfer_success": "Transfer berhasil! TX: {tx}", "wallet_trust_degraded": "Kepercayaan Perangkat Keras Menurun", "wallet_warning": "Peringatan", + "verify_title": "Verifikasi build", + "verify_hash_label": "Hash build", + "verify_button": "Periksa", + "verify_undeclared_title": "Node ini tidak dapat menyatakan apakah ia memverifikasi build", + "verify_undeclared_body": "Node ini lebih lama daripada deklarasi kapabilitas, sehingga tidak dapat menyatakannya. Node yang lebih baru dapat memverifikasi build.", + "verify_absent_title": "Node ini tidak memverifikasi build", + "verify_absent_body": "Node ini tidak menyimpan registry, sehingga tidak dapat memeriksa build. Node lain bisa.", + "verify_unreachable_title": "Tidak dapat menjangkau node ini", + "verify_unreachable_body": "Node tidak merespons, sehingga kami tidak tahu apakah ia dapat memverifikasi build. Ini bukan masalah pada build yang Anda periksa.", + "verify_status_registered": "Terdaftar", + "verify_status_deprecated": "Tidak lagi disarankan", + "verify_status_revoked": "Dicabut", + "verify_status_unreadable": "Status tidak dikenali", + "verify_revoked_warning": "Build ini telah dicabut. Jangan gunakan.", + "verify_not_found_title": "Tidak ada catatan untuk build ini", + "verify_not_found_body": "Registry merespons dan tidak menyimpan apa pun untuk hash ini.", + "verify_unavailable_title": "Tidak dapat memeriksa", + "verify_unavailable_body": "Ini tidak sama dengan 'tidak terdaftar' — registry tidak merespons.", + "verify_undetermined_title": "Node ini tidak dapat menentukan apa yang bisa dilakukannya", + "verify_undetermined_body": "Node merespons, tetapi tidak dapat membaca catatan kuncinya sendiri. Biasanya ini bersifat sementara — coba lagi sebentar lagi.", + "verify_retry": "Periksa lagi", "attestation_actions_desc": "Tindakan untuk catatan ini", "chat_badge_message": "PESAN", "chat_details": "jenis {type} · lingkup {scope} · status {status}", diff --git a/client/iosApp/iosApp/localization/it.json b/client/iosApp/iosApp/localization/it.json index 525dd69..95ab48d 100644 --- a/client/iosApp/iosApp/localization/it.json +++ b/client/iosApp/iosApp/localization/it.json @@ -2924,6 +2924,27 @@ "wallet_transfer_success": "Trasferimento riuscito! TX: {tx}", "wallet_trust_degraded": "Fiducia Hardware Degradata", "wallet_warning": "Avviso", + "verify_title": "Verifica una build", + "verify_hash_label": "Hash della build", + "verify_button": "Verifica", + "verify_undeclared_title": "Questo nodo non è in grado di dire se verifica le build", + "verify_undeclared_body": "Questo nodo è precedente alla dichiarazione delle funzionalità, quindi non è in grado di pronunciarsi. Un nodo più recente può verificare le build.", + "verify_absent_title": "Questo nodo non verifica le build", + "verify_absent_body": "Questo nodo non detiene il registro, quindi non può verificare le build. Un altro nodo può farlo.", + "verify_unreachable_title": "Impossibile raggiungere questo nodo", + "verify_unreachable_body": "Il nodo non ha risposto, quindi non sappiamo se sia in grado di verificare le build. Questo non è un problema della build che stai verificando.", + "verify_status_registered": "Registrata", + "verify_status_deprecated": "Non più consigliata", + "verify_status_revoked": "Revocata", + "verify_status_unreadable": "Stato non riconosciuto", + "verify_revoked_warning": "Questa build è stata revocata. Non utilizzarla.", + "verify_not_found_title": "Nessuna registrazione per questa build", + "verify_not_found_body": "Il registro ha risposto e non contiene nulla per questo hash.", + "verify_unavailable_title": "Verifica non riuscita", + "verify_unavailable_body": "Questo non equivale a «non registrata» — il registro non ha risposto.", + "verify_undetermined_title": "Questo nodo non è riuscito a determinare cosa può fare", + "verify_undetermined_body": "Il nodo ha risposto, ma non è riuscito a leggere il proprio record delle chiavi. Di solito è temporaneo — riprova a breve.", + "verify_retry": "Verifica di nuovo", "attestation_actions_desc": "Azioni per questo record", "chat_badge_message": "MESSAGGIO", "chat_details": "tipo {type} · ambito {scope} · stato {status}", diff --git a/client/iosApp/iosApp/localization/ja.json b/client/iosApp/iosApp/localization/ja.json index 371b63a..3123141 100644 --- a/client/iosApp/iosApp/localization/ja.json +++ b/client/iosApp/iosApp/localization/ja.json @@ -2924,6 +2924,27 @@ "wallet_transfer_success": "送金成功!TX: {tx}", "wallet_trust_degraded": "ハードウェア信頼が低下しました", "wallet_warning": "警告", + "verify_title": "ビルドを検証する", + "verify_hash_label": "ビルドハッシュ", + "verify_button": "確認", + "verify_undeclared_title": "このノードはビルドを検証できるかどうかを述べられません", + "verify_undeclared_body": "このノードは機能宣言より古いバージョンのため、判断できません。新しいノードであればビルドを検証できます。", + "verify_absent_title": "このノードはビルドを検証しません", + "verify_absent_body": "このノードはレジストリを保持していないため、ビルドを確認できません。他のノードであれば確認できます。", + "verify_unreachable_title": "このノードに接続できませんでした", + "verify_unreachable_body": "ノードが応答しなかったため、ビルドを検証できるかどうかは分かりません。これは、確認しようとしているビルド自体の問題ではありません。", + "verify_status_registered": "登録済み", + "verify_status_deprecated": "推奨されていません", + "verify_status_revoked": "失効済み", + "verify_status_unreadable": "ステータスを認識できません", + "verify_revoked_warning": "このビルドは失効しています。使用しないでください。", + "verify_not_found_title": "このビルドの記録はありません", + "verify_not_found_body": "レジストリは応答しましたが、このハッシュに対する記録を保持していません。", + "verify_unavailable_title": "確認できませんでした", + "verify_unavailable_body": "これは「未登録」と同じではありません — レジストリが応答しませんでした。", + "verify_undetermined_title": "このノードは自身にできることを判別できませんでした", + "verify_undetermined_body": "ノードは応答しましたが、自身の鍵の記録を読み取れませんでした。これは通常一時的なものです — しばらくしてから再試行してください。", + "verify_retry": "再確認", "attestation_actions_desc": "このレコードに対する操作", "chat_badge_message": "メッセージ", "chat_details": "種別 {type} · スコープ {scope} · 状態 {status}", diff --git a/client/iosApp/iosApp/localization/ko.json b/client/iosApp/iosApp/localization/ko.json index e46b77f..ce7f6a2 100644 --- a/client/iosApp/iosApp/localization/ko.json +++ b/client/iosApp/iosApp/localization/ko.json @@ -2924,6 +2924,27 @@ "wallet_transfer_success": "전송 성공! TX: {tx}", "wallet_trust_degraded": "하드웨어 신뢰 저하됨", "wallet_warning": "경고", + "verify_title": "빌드 검증", + "verify_hash_label": "빌드 해시", + "verify_button": "확인", + "verify_undeclared_title": "이 노드는 빌드를 검증하는지 여부를 알 수 없습니다", + "verify_undeclared_body": "이 노드는 기능 선언보다 오래되어 알 수 없습니다. 더 새로운 노드는 빌드를 검증할 수 있습니다.", + "verify_absent_title": "이 노드는 빌드를 검증하지 않습니다", + "verify_absent_body": "이 노드는 레지스트리를 보유하지 않아 빌드를 확인할 수 없습니다. 다른 노드는 확인할 수 있습니다.", + "verify_unreachable_title": "이 노드에 연결할 수 없음", + "verify_unreachable_body": "노드가 응답하지 않아 빌드를 검증할 수 있는지 알 수 없습니다. 이는 확인 중인 빌드의 문제가 아닙니다.", + "verify_status_registered": "등록됨", + "verify_status_deprecated": "더 이상 권장되지 않음", + "verify_status_revoked": "폐기됨", + "verify_status_unreadable": "상태를 인식할 수 없음", + "verify_revoked_warning": "이 빌드는 폐기되었습니다. 사용하지 마십시오.", + "verify_not_found_title": "이 빌드에 대한 기록 없음", + "verify_not_found_body": "레지스트리가 응답했지만 이 해시에 대한 기록이 없습니다.", + "verify_unavailable_title": "확인할 수 없음", + "verify_unavailable_body": "이는 '등록되지 않음'과 같지 않습니다 — 레지스트리가 응답하지 않았습니다.", + "verify_undetermined_title": "이 노드는 자신이 무엇을 할 수 있는지 판단할 수 없었습니다", + "verify_undetermined_body": "노드가 응답했지만 자체 키 레코드를 읽을 수 없었습니다. 이는 대개 일시적인 현상입니다 — 잠시 후 다시 시도하세요.", + "verify_retry": "다시 확인", "attestation_actions_desc": "이 레코드에 대한 작업", "chat_badge_message": "메시지", "chat_details": "유형 {type} · 범위 {scope} · 상태 {status}", diff --git a/client/iosApp/iosApp/localization/mr.json b/client/iosApp/iosApp/localization/mr.json index 35d3208..b4cb9d1 100644 --- a/client/iosApp/iosApp/localization/mr.json +++ b/client/iosApp/iosApp/localization/mr.json @@ -2924,6 +2924,27 @@ "wallet_transfer_success": "Transfer यशful! TX: {tx}", "wallet_trust_degraded": "हार्डवेअर विश्वास खालावला", "wallet_warning": "इशारा", + "verify_title": "बिल्ड सत्यापित करा", + "verify_hash_label": "बिल्ड हॅश", + "verify_button": "तपासा", + "verify_undeclared_title": "हा नोड बिल्ड सत्यापित करतो की नाही हे सांगू शकत नाही", + "verify_undeclared_body": "हा नोड क्षमता-घोषणेपेक्षा जुना आहे, त्यामुळे तो सांगू शकत नाही. नवीन नोड बिल्ड सत्यापित करू शकतो.", + "verify_absent_title": "हा नोड बिल्ड सत्यापित करत नाही", + "verify_absent_body": "या नोडकडे रजिस्ट्री नाही, त्यामुळे तो बिल्ड तपासू शकत नाही. दुसरा नोड हे करू शकतो.", + "verify_unreachable_title": "या नोडपर्यंत पोहोचता आले नाही", + "verify_unreachable_body": "नोडने उत्तर दिले नाही, त्यामुळे तो बिल्ड सत्यापित करू शकतो की नाही हे आम्हाला माहीत नाही. तुम्ही तपासत असलेल्या बिल्डमध्ये ही समस्या नाही.", + "verify_status_registered": "नोंदणीकृत", + "verify_status_deprecated": "आता शिफारस केलेले नाही", + "verify_status_revoked": "रद्द केलेले", + "verify_status_unreadable": "स्थिती ओळखता आली नाही", + "verify_revoked_warning": "हे बिल्ड रद्द करण्यात आले आहे. याचा वापर करू नका.", + "verify_not_found_title": "या बिल्डची कोणतीही नोंद नाही", + "verify_not_found_body": "रजिस्ट्रीने उत्तर दिले आणि या हॅशसाठी त्याकडे काहीही नाही.", + "verify_unavailable_title": "तपासता आले नाही", + "verify_unavailable_body": "हे 'नोंदणीकृत नाही' यासारखे नाही — रजिस्ट्रीने उत्तर दिले नाही.", + "verify_undetermined_title": "हा नोड काय करू शकतो हे ठरवता आले नाही", + "verify_undetermined_body": "नोडने उत्तर दिले, पण त्याला स्वतःची की-नोंद वाचता आली नाही. हे सहसा तात्पुरते असते — थोड्या वेळाने पुन्हा प्रयत्न करा.", + "verify_retry": "पुन्हा तपासा", "attestation_actions_desc": "या नोंदीसाठी क्रिया", "chat_badge_message": "संदेश", "chat_details": "प्रकार {type} · व्याप्ती {scope} · स्थिती {status}", diff --git a/client/iosApp/iosApp/localization/my.json b/client/iosApp/iosApp/localization/my.json index 37d756b..f956c52 100644 --- a/client/iosApp/iosApp/localization/my.json +++ b/client/iosApp/iosApp/localization/my.json @@ -2862,6 +2862,14 @@ "users_status": "အခြေအနေ", "users_user_id": "အသုံးပြုသူ ID", "users_wa_role": "WA:{role}", + "verify_revoked_warning": "ဤ build ကို ရုပ်သိမ်းထားပြီးဖြစ်သည်။ အသုံးမပြုပါနှင့်။", + "verify_not_found_title": "ဤ build ၏ မှတ်တမ်း မရှိပါ", + "verify_not_found_body": "registry က အဖြေ ပြန်ပေးခဲ့ပြီး ဤ hash အတွက် မည်သည့်အရာမျှ ကိုင်ဆောင်ထားခြင်း မရှိပါ။", + "verify_unavailable_title": "စစ်ဆေး၍ မရပါ", + "verify_unavailable_body": "ဤသည်မှာ 'မှတ်ပုံတင်ထားခြင်း မရှိပါ' ဟူသည်နှင့် မတူပါ — registry က အဖြေ ပြန်မပေးခဲ့ပါ။", + "verify_undetermined_title": "ဤ node သည် ၎င်း လုပ်နိုင်သည့်အရာကို သတ်မှတ်၍ မရခဲ့ပါ", + "verify_undetermined_body": "node က အဖြေ ပြန်ပေးခဲ့သော်လည်း ၎င်း၏ ကိုယ်ပိုင် key မှတ်တမ်းကို ဖတ်၍ မရခဲ့ပါ။ ဤသည် ယာယီသာ ဖြစ်လေ့ရှိသည် — မကြာမီ ထပ်ကြိုးစားပါ။", + "verify_retry": "ထပ်မံစစ်ဆေးပါ", "wa_approve": "အတည်ပြုပါ", "wa_avg_resolution": "ပျမ်းမျှ ဖြေရှင်းချိန်: {time} မိနစ်", "wa_bus_subscribers": "Bus Subscribers", @@ -2924,6 +2932,18 @@ "wallet_transfer_success": "Transfer အောင်မြင်ful! TX: {tx}", "wallet_trust_degraded": "Hardware ယုံကြည်မှု အားနည်းသွားပြီ", "wallet_warning": "သတိပေး", + "verify_title": "Build တစ်ခုကို အတည်ပြုပါ", + "verify_hash_label": "Build hash", + "verify_button": "စစ်ဆေးပါ", + "verify_undeclared_title": "ဤ node သည် build များကို အတည်ပြုနိုင်သည် မနိုင်သည်ကို ပြောနိုင်စွမ်း မရှိပါ", + "verify_undeclared_body": "ဤ node သည် capability declaration ထက် ပိုမိုဟောင်းနွမ်းသဖြင့် ပြောနိုင်စွမ်း မရှိပါ။ ပိုမို အသစ်သော node တစ်ခုက build များကို အတည်ပြုနိုင်ပါသည်။", + "verify_absent_title": "ဤ node သည် build များကို အတည်ပြု၍ မရပါ", + "verify_absent_body": "ဤ node သည် registry ကို ကိုင်ဆောင်ထားခြင်း မရှိသဖြင့် build များကို စစ်ဆေး၍ မရပါ။ အခြား node တစ်ခုက စစ်ဆေးနိုင်ပါသည်။", + "verify_unreachable_title": "ဤ node ကို ချိတ်ဆက်၍ မရပါ", + "verify_unreachable_body": "node က အဖြေ ပြန်မပေးခဲ့သဖြင့် ၎င်းသည် build များကို အတည်ပြုနိုင်သည် မနိုင်သည်ကို ကျွန်ုပ်တို့ မသိပါ။ ဤသည် သင် စစ်ဆေးနေသော build ၏ ပြဿနာ မဟုတ်ပါ။", + "verify_status_registered": "မှတ်ပုံတင်ထားသည်", + "verify_status_deprecated": "ထပ်မံ အသုံးပြုရန် အကြံမပြုတော့ပါ", + "verify_status_revoked": "ရုပ်သိမ်းထားသည်", "attestation_actions_desc": "ဤမှတ်တမ်းအတွက် လုပ်ဆောင်ချက်များ", "chat_badge_message": "မက်ဆေ့ချ်", "chat_details": "အမျိုးအစား {type} · scope {scope} · အခြေအနေ {status}", diff --git a/client/iosApp/iosApp/localization/pa.json b/client/iosApp/iosApp/localization/pa.json index b5d51c5..e50e1a8 100644 --- a/client/iosApp/iosApp/localization/pa.json +++ b/client/iosApp/iosApp/localization/pa.json @@ -2924,6 +2924,27 @@ "wallet_transfer_success": "ਟ੍ਰਾਂਸਫਰ ਸਫਲ! TX: {tx}", "wallet_trust_degraded": "ਹਾਰਡਵੇਅਰ ਭਰੋਸਾ ਘਟਿਆ", "wallet_warning": "ਚੇਤਾਵਨੀ", + "verify_title": "ਇੱਕ ਬਿਲਡ ਦੀ ਪੁਸ਼ਟੀ ਕਰੋ", + "verify_hash_label": "ਬਿਲਡ ਹੈਸ਼", + "verify_button": "ਜਾਂਚ ਕਰੋ", + "verify_undeclared_title": "ਇਹ ਨੋਡ ਨਹੀਂ ਕਹਿ ਸਕਦਾ ਕਿ ਇਹ ਬਿਲਡਾਂ ਦੀ ਪੁਸ਼ਟੀ ਕਰਦਾ ਹੈ ਜਾਂ ਨਹੀਂ", + "verify_undeclared_body": "ਇਹ ਨੋਡ ਸਮਰੱਥਾ ਐਲਾਨ ਤੋਂ ਪੁਰਾਣਾ ਹੈ, ਇਸ ਲਈ ਇਹ ਕੁਝ ਕਹਿ ਨਹੀਂ ਸਕਦਾ। ਇੱਕ ਨਵਾਂ ਨੋਡ ਬਿਲਡਾਂ ਦੀ ਪੁਸ਼ਟੀ ਕਰ ਸਕਦਾ ਹੈ।", + "verify_absent_title": "ਇਹ ਨੋਡ ਬਿਲਡਾਂ ਦੀ ਪੁਸ਼ਟੀ ਨਹੀਂ ਕਰਦਾ", + "verify_absent_body": "ਇਹ ਨੋਡ ਰਜਿਸਟਰੀ ਨਹੀਂ ਰੱਖਦਾ, ਇਸ ਲਈ ਇਹ ਬਿਲਡਾਂ ਦੀ ਜਾਂਚ ਨਹੀਂ ਕਰ ਸਕਦਾ। ਕੋਈ ਹੋਰ ਨੋਡ ਕਰ ਸਕਦਾ ਹੈ।", + "verify_unreachable_title": "ਇਸ ਨੋਡ ਤੱਕ ਨਹੀਂ ਪਹੁੰਚ ਸਕੇ", + "verify_unreachable_body": "ਨੋਡ ਨੇ ਜਵਾਬ ਨਹੀਂ ਦਿੱਤਾ, ਇਸ ਲਈ ਸਾਨੂੰ ਨਹੀਂ ਪਤਾ ਕਿ ਇਹ ਬਿਲਡਾਂ ਦੀ ਪੁਸ਼ਟੀ ਕਰ ਸਕਦਾ ਹੈ ਜਾਂ ਨਹੀਂ। ਇਹ ਉਸ ਬਿਲਡ ਦੀ ਸਮੱਸਿਆ ਨਹੀਂ ਹੈ ਜਿਸਦੀ ਤੁਸੀਂ ਜਾਂਚ ਕਰ ਰਹੇ ਹੋ।", + "verify_status_registered": "ਰਜਿਸਟਰਡ", + "verify_status_deprecated": "ਹੁਣ ਸਿਫ਼ਾਰਸ਼ੀ ਨਹੀਂ", + "verify_status_revoked": "ਰੱਦ ਕੀਤਾ", + "verify_status_unreadable": "ਹਾਲਤ ਪਛਾਣੀ ਨਹੀਂ ਗਈ", + "verify_revoked_warning": "ਇਹ ਬਿਲਡ ਰੱਦ ਕਰ ਦਿੱਤਾ ਗਿਆ ਹੈ। ਇਸਨੂੰ ਨਾ ਵਰਤੋ।", + "verify_not_found_title": "ਇਸ ਬਿਲਡ ਦਾ ਕੋਈ ਰਿਕਾਰਡ ਨਹੀਂ", + "verify_not_found_body": "ਰਜਿਸਟਰੀ ਨੇ ਜਵਾਬ ਦਿੱਤਾ ਅਤੇ ਇਸ ਹੈਸ਼ ਲਈ ਇਸ ਕੋਲ ਕੁਝ ਵੀ ਨਹੀਂ ਹੈ।", + "verify_unavailable_title": "ਜਾਂਚ ਨਹੀਂ ਹੋ ਸਕੀ", + "verify_unavailable_body": "ਇਹ 'ਰਜਿਸਟਰਡ ਨਹੀਂ' ਵਰਗੀ ਗੱਲ ਨਹੀਂ ਹੈ — ਰਜਿਸਟਰੀ ਨੇ ਜਵਾਬ ਨਹੀਂ ਦਿੱਤਾ।", + "verify_undetermined_title": "ਇਹ ਨੋਡ ਇਹ ਪਤਾ ਨਹੀਂ ਲਗਾ ਸਕਿਆ ਕਿ ਇਹ ਕੀ ਕਰ ਸਕਦਾ ਹੈ", + "verify_undetermined_body": "ਨੋਡ ਨੇ ਜਵਾਬ ਤਾਂ ਦਿੱਤਾ, ਪਰ ਆਪਣਾ ਕੁੰਜੀ ਰਿਕਾਰਡ ਨਹੀਂ ਪੜ੍ਹ ਸਕਿਆ। ਇਹ ਆਮ ਤੌਰ 'ਤੇ ਅਸਥਾਈ ਹੁੰਦਾ ਹੈ — ਥੋੜ੍ਹੀ ਦੇਰ ਵਿੱਚ ਦੁਬਾਰਾ ਕੋਸ਼ਿਸ਼ ਕਰੋ।", + "verify_retry": "ਦੁਬਾਰਾ ਜਾਂਚ ਕਰੋ", "attestation_actions_desc": "ਇਸ ਰਿਕਾਰਡ ਲਈ ਕਾਰਵਾਈਆਂ", "chat_badge_message": "ਸੁਨੇਹਾ", "chat_details": "ਕਿਸਮ {type} · ਦਾਇਰਾ {scope} · ਸਥਿਤੀ {status}", diff --git a/client/iosApp/iosApp/localization/pt.json b/client/iosApp/iosApp/localization/pt.json index d4d550e..4cd2723 100644 --- a/client/iosApp/iosApp/localization/pt.json +++ b/client/iosApp/iosApp/localization/pt.json @@ -2924,6 +2924,27 @@ "wallet_transfer_success": "Transferência bem-sucedida! TX: {tx}", "wallet_trust_degraded": "Confiança de Hardware Degradada", "wallet_warning": "Aviso", + "verify_title": "Verificar uma build", + "verify_hash_label": "Hash da build", + "verify_button": "Verificar", + "verify_undeclared_title": "Este nó não pode dizer se verifica builds", + "verify_undeclared_body": "Este nó é mais antigo do que a declaração de capacidades, portanto não pode dizer. Um nó mais recente pode verificar builds.", + "verify_absent_title": "Este nó não verifica builds", + "verify_absent_body": "Este nó não possui o registro, portanto não pode verificar builds. Outro nó pode.", + "verify_unreachable_title": "Não foi possível alcançar este nó", + "verify_unreachable_body": "O nó não respondeu, portanto não sabemos se ele pode verificar builds. Isto não é um problema com a build que você está verificando.", + "verify_status_registered": "Registrada", + "verify_status_deprecated": "Não mais recomendada", + "verify_status_revoked": "Revogada", + "verify_status_unreadable": "Status não reconhecido", + "verify_revoked_warning": "Esta build foi revogada. Não a use.", + "verify_not_found_title": "Nenhum registro desta build", + "verify_not_found_body": "O registro respondeu e não contém nada para este hash.", + "verify_unavailable_title": "Não foi possível verificar", + "verify_unavailable_body": "Isto não é o mesmo que 'não registrada' — o registro não respondeu.", + "verify_undetermined_title": "Este nó não conseguiu determinar o que pode fazer", + "verify_undetermined_body": "O nó respondeu, mas não conseguiu ler o próprio registro de chave. Isto costuma ser temporário — tente novamente em breve.", + "verify_retry": "Verificar novamente", "attestation_actions_desc": "Ações para este registo", "chat_badge_message": "MENSAGEM", "chat_details": "tipo {type} · âmbito {scope} · estado {status}", diff --git a/client/iosApp/iosApp/localization/ru.json b/client/iosApp/iosApp/localization/ru.json index db4bf61..14028b7 100644 --- a/client/iosApp/iosApp/localization/ru.json +++ b/client/iosApp/iosApp/localization/ru.json @@ -2924,6 +2924,27 @@ "wallet_transfer_success": "Перевод успешен! TX: {tx}", "wallet_trust_degraded": "Доверие к оборудованию ухудшено", "wallet_warning": "Предупреждение", + "verify_title": "Проверить сборку", + "verify_hash_label": "Хеш сборки", + "verify_button": "Проверить", + "verify_undeclared_title": "Этот узел не может сказать, проверяет ли он сборки", + "verify_undeclared_body": "Этот узел старше объявления возможностей, поэтому не может сказать. Более новый узел может проверять сборки.", + "verify_absent_title": "Этот узел не проверяет сборки", + "verify_absent_body": "Этот узел не хранит реестр, поэтому не может проверять сборки. Другой узел может.", + "verify_unreachable_title": "Не удалось связаться с этим узлом", + "verify_unreachable_body": "Узел не ответил, поэтому неизвестно, может ли он проверять сборки. Это не связано с проверяемой вами сборкой.", + "verify_status_registered": "Зарегистрирована", + "verify_status_deprecated": "Больше не рекомендуется", + "verify_status_revoked": "Отозвана", + "verify_status_unreadable": "Статус не распознан", + "verify_revoked_warning": "Эта сборка отозвана. Не используйте её.", + "verify_not_found_title": "Нет записи об этой сборке", + "verify_not_found_body": "Реестр ответил, но не содержит записи для этого хеша.", + "verify_unavailable_title": "Не удалось проверить", + "verify_unavailable_body": "Это не то же самое, что «не зарегистрирована» — реестр не ответил.", + "verify_undetermined_title": "Этот узел не смог определить, что он может делать", + "verify_undetermined_body": "Узел ответил, но не смог прочитать собственную запись ключа. Обычно это временно — повторите попытку через некоторое время.", + "verify_retry": "Проверить снова", "attestation_actions_desc": "Действия для этой записи", "chat_badge_message": "СООБЩЕНИЕ", "chat_details": "тип {type} · область {scope} · статус {status}", diff --git a/client/iosApp/iosApp/localization/sw.json b/client/iosApp/iosApp/localization/sw.json index 17baf50..2ebcdb1 100644 --- a/client/iosApp/iosApp/localization/sw.json +++ b/client/iosApp/iosApp/localization/sw.json @@ -2924,6 +2924,27 @@ "wallet_transfer_success": "Uhamisho umefanikiwa! TX: {tx}", "wallet_trust_degraded": "Kuaminika kwa Maunzi Kumedhoofika", "wallet_warning": "Onyo", + "verify_title": "Thibitisha toleo", + "verify_hash_label": "Hash ya toleo", + "verify_button": "Kagua", + "verify_undeclared_title": "Nodi hii haiwezi kusema kama inathibitisha matoleo", + "verify_undeclared_body": "Nodi hii ni ya zamani kuliko tamko la uwezo, kwa hivyo haiwezi kusema. Nodi mpya zaidi inaweza kuthibitisha matoleo.", + "verify_absent_title": "Nodi hii haithibitishi matoleo", + "verify_absent_body": "Nodi hii haibebi sajili, kwa hivyo haiwezi kukagua matoleo. Nodi nyingine inaweza.", + "verify_unreachable_title": "Imeshindwa kufikia nodi hii", + "verify_unreachable_body": "Nodi haikujibu, kwa hivyo hatujui kama inaweza kuthibitisha matoleo. Hili si tatizo la toleo unalolikagua.", + "verify_status_registered": "Limesajiliwa", + "verify_status_deprecated": "Halipendekezwi tena", + "verify_status_revoked": "Limebatilishwa", + "verify_status_unreadable": "Hali haitambuliki", + "verify_revoked_warning": "Toleo hili limebatilishwa. Usilitumie.", + "verify_not_found_title": "Hakuna rekodi ya toleo hili", + "verify_not_found_body": "Sajili ilijibu na haina kitu kwa hash hii.", + "verify_unavailable_title": "Imeshindwa kukagua", + "verify_unavailable_body": "Hii si sawa na 'halijasajiliwa' — sajili haikujibu.", + "verify_undetermined_title": "Nodi hii haikuweza kubaini kile inachoweza kufanya", + "verify_undetermined_body": "Nodi ilijibu, lakini haikuweza kusoma rekodi yake yenyewe ya ufunguo. Hii kwa kawaida ni ya muda tu — jaribu tena baada ya muda mfupi.", + "verify_retry": "Kagua tena", "attestation_actions_desc": "Vitendo vya rekodi hii", "chat_badge_message": "UJUMBE", "chat_details": "aina {type} · wigo {scope} · hali {status}", diff --git a/client/iosApp/iosApp/localization/ta.json b/client/iosApp/iosApp/localization/ta.json index f3a999a..166494d 100644 --- a/client/iosApp/iosApp/localization/ta.json +++ b/client/iosApp/iosApp/localization/ta.json @@ -2924,6 +2924,27 @@ "wallet_transfer_success": "பரிமாற்றம் வெற்றிகரம்! TX: {tx}", "wallet_trust_degraded": "Hardware நம்பகத்தன்மை Degraded", "wallet_warning": "எச்சரிக்கை", + "verify_title": "ஒரு பதிப்பைச் சரிபார்", + "verify_hash_label": "பதிப்பு ஹாஷ்", + "verify_button": "சரிபார்", + "verify_undeclared_title": "இந்த முனை பதிப்புகளைச் சரிபார்க்கிறதா என்று கூற முடியாது", + "verify_undeclared_body": "இந்த முனை திறன் அறிவிப்பைவிட பழையது; எனவே இதனால் கூற முடியாது. புதிய முனையால் பதிப்புகளைச் சரிபார்க்க முடியும்.", + "verify_absent_title": "இந்த முனை பதிப்புகளைச் சரிபார்க்காது", + "verify_absent_body": "இந்த முனையிடம் பதிவகம் இல்லை; எனவே இதனால் பதிப்புகளைச் சரிபார்க்க முடியாது. வேறொரு முனையால் முடியும்.", + "verify_unreachable_title": "இந்த முனையை அணுக முடியவில்லை", + "verify_unreachable_body": "முனை பதிலளிக்கவில்லை; எனவே அதனால் பதிப்புகளைச் சரிபார்க்க முடியுமா என்பது எங்களுக்குத் தெரியாது. இது நீங்கள் சரிபார்க்கும் பதிப்பின் சிக்கல் அல்ல.", + "verify_status_registered": "பதிவு செய்யப்பட்டது", + "verify_status_deprecated": "இனி பரிந்துரைக்கப்படவில்லை", + "verify_status_revoked": "திரும்பப் பெறப்பட்டது", + "verify_status_unreadable": "நிலை அறியப்படவில்லை", + "verify_revoked_warning": "இந்தப் பதிப்பு திரும்பப் பெறப்பட்டுள்ளது. இதைப் பயன்படுத்த வேண்டாம்.", + "verify_not_found_title": "இந்தப் பதிப்புக்கான பதிவு இல்லை", + "verify_not_found_body": "பதிவகம் பதிலளித்தது, இந்த ஹாஷுக்கு எதுவும் வைத்திருக்கவில்லை.", + "verify_unavailable_title": "சரிபார்க்க முடியவில்லை", + "verify_unavailable_body": "இது 'பதிவு செய்யப்படவில்லை' என்பதற்குச் சமமானதல்ல — பதிவகம் பதிலளிக்கவில்லை.", + "verify_undetermined_title": "இந்த முனை தன்னால் என்ன செய்ய முடியும் என்பதைத் தீர்மானிக்க முடியவில்லை", + "verify_undetermined_body": "முனை பதிலளித்தது, ஆனால் தன் சொந்த விசைப் பதிவை வாசிக்க முடியவில்லை. இது பொதுவாக தற்காலிகமானது — சிறிது நேரத்தில் மீண்டும் முயலவும்.", + "verify_retry": "மீண்டும் சரிபார்", "attestation_actions_desc": "இந்தப் பதிவுக்கான செயல்கள்", "chat_badge_message": "செய்தி", "chat_details": "வகை {type} · எல்லை {scope} · நிலை {status}", diff --git a/client/iosApp/iosApp/localization/te.json b/client/iosApp/iosApp/localization/te.json index 57f56c3..d5ae35d 100644 --- a/client/iosApp/iosApp/localization/te.json +++ b/client/iosApp/iosApp/localization/te.json @@ -2924,6 +2924,27 @@ "wallet_transfer_success": "బదిలీ విజయవంతమైంది! TX: {tx}", "wallet_trust_degraded": "హార్డ్‌వేర్ నమ్మకం తగ్గింది", "wallet_warning": "హెచ్చరిక", + "verify_title": "బిల్డ్‌ను ధృవీకరించండి", + "verify_hash_label": "బిల్డ్ హాష్", + "verify_button": "తనిఖీ చేయండి", + "verify_undeclared_title": "ఈ నోడ్ బిల్డ్‌లను ధృవీకరిస్తుందో లేదో చెప్పలేకపోతుంది", + "verify_undeclared_body": "ఈ నోడ్ కేపబిలిటీ ప్రకటన కంటే పాతది, కాబట్టి ఇది చెప్పలేకపోతుంది. కొత్త నోడ్ బిల్డ్‌లను ధృవీకరించగలదు.", + "verify_absent_title": "ఈ నోడ్ బిల్డ్‌లను ధృవీకరించదు", + "verify_absent_body": "ఈ నోడ్ వద్ద రిజిస్ట్రీ లేదు, కాబట్టి ఇది బిల్డ్‌లను తనిఖీ చేయలేకపోతుంది. మరో నోడ్ చేయగలదు.", + "verify_unreachable_title": "ఈ నోడ్‌ను చేరుకోలేకపోయాం", + "verify_unreachable_body": "నోడ్ స్పందించలేదు, కాబట్టి అది బిల్డ్‌లను ధృవీకరించగలదో లేదో మాకు తెలియదు. ఇది మీరు తనిఖీ చేస్తున్న బిల్డ్‌లో సమస్య కాదు.", + "verify_status_registered": "నమోదైంది", + "verify_status_deprecated": "ఇక సిఫార్సు చేయబడదు", + "verify_status_revoked": "రద్దు చేయబడింది", + "verify_status_unreadable": "స్థితి గుర్తించబడలేదు", + "verify_revoked_warning": "ఈ బిల్డ్ రద్దు చేయబడింది. దీన్ని ఉపయోగించవద్దు.", + "verify_not_found_title": "ఈ బిల్డ్ గురించి రికార్డు లేదు", + "verify_not_found_body": "రిజిస్ట్రీ స్పందించింది, కానీ ఈ హాష్ కోసం ఏమీ లేదు.", + "verify_unavailable_title": "తనిఖీ చేయలేకపోయాం", + "verify_unavailable_body": "ఇది 'నమోదు కాలేదు' అనే దానికి సమానం కాదు — రిజిస్ట్రీ స్పందించలేదు.", + "verify_undetermined_title": "ఈ నోడ్ తాను ఏమి చేయగలదో నిర్ధారించలేకపోయింది", + "verify_undetermined_body": "నోడ్ స్పందించింది, కానీ తన సొంత కీ రికార్డును చదవలేకపోయింది. ఇది సాధారణంగా తాత్కాలికం — కొద్ది సేపట్లో మళ్ళీ ప్రయత్నించండి.", + "verify_retry": "మళ్ళీ తనిఖీ చేయండి", "attestation_actions_desc": "ఈ రికార్డుకు చర్యలు", "chat_badge_message": "సందేశం", "chat_details": "రకం {type} · పరిధి {scope} · స్థితి {status}", diff --git a/client/iosApp/iosApp/localization/th.json b/client/iosApp/iosApp/localization/th.json index 079e23f..cba9e06 100644 --- a/client/iosApp/iosApp/localization/th.json +++ b/client/iosApp/iosApp/localization/th.json @@ -2924,6 +2924,27 @@ "wallet_transfer_success": "Transfer สำเร็จful! TX: {tx}", "wallet_trust_degraded": "ความน่าเชื่อถือของฮาร์ดแวร์ลดลง", "wallet_warning": "คำเตือน", + "verify_title": "ตรวจสอบ build", + "verify_hash_label": "Hash ของ build", + "verify_button": "ตรวจสอบ", + "verify_undeclared_title": "โหนดนี้บอกไม่ได้ว่าตนตรวจสอบ build หรือไม่", + "verify_undeclared_body": "โหนดนี้เก่ากว่าคำประกาศความสามารถ จึงบอกไม่ได้ โหนดที่ใหม่กว่าสามารถตรวจสอบ build ได้", + "verify_absent_title": "โหนดนี้ไม่ตรวจสอบ build", + "verify_absent_body": "โหนดนี้ไม่มีรีจิสทรี จึงไม่สามารถตรวจสอบ build ได้ โหนดอื่นสามารถทำได้", + "verify_unreachable_title": "ไม่สามารถติดต่อโหนดนี้ได้", + "verify_unreachable_body": "โหนดไม่ตอบสนอง เราจึงไม่ทราบว่าโหนดสามารถตรวจสอบ build ได้หรือไม่ นี่ไม่ใช่ปัญหาของ build ที่คุณกำลังตรวจสอบ", + "verify_status_registered": "ลงทะเบียนแล้ว", + "verify_status_deprecated": "ไม่แนะนำให้ใช้อีกต่อไป", + "verify_status_revoked": "ถูกเพิกถอน", + "verify_status_unreadable": "ไม่รู้จักสถานะ", + "verify_revoked_warning": "Build นี้ถูกเพิกถอนแล้ว อย่าใช้งาน", + "verify_not_found_title": "ไม่มีบันทึกสำหรับ build นี้", + "verify_not_found_body": "รีจิสทรีตอบกลับแล้ว และไม่มีข้อมูลสำหรับ hash นี้", + "verify_unavailable_title": "ไม่สามารถตรวจสอบได้", + "verify_unavailable_body": "นี่ไม่เหมือนกับ 'ไม่ได้ลงทะเบียน' — รีจิสทรีไม่ตอบสนอง", + "verify_undetermined_title": "โหนดนี้ไม่สามารถระบุได้ว่าตนทำสิ่งใดได้", + "verify_undetermined_body": "โหนดตอบแล้ว แต่อ่านบันทึกคีย์ของตนเองไม่ได้ โดยปกติแล้วนี่เป็นเพียงชั่วคราว — ลองอีกครั้งในไม่ช้า", + "verify_retry": "ตรวจสอบอีกครั้ง", "attestation_actions_desc": "การดำเนินการสำหรับระเบียนนี้", "chat_badge_message": "ข้อความ", "chat_details": "ประเภท {type} · ขอบเขต {scope} · สถานะ {status}", diff --git a/client/iosApp/iosApp/localization/tr.json b/client/iosApp/iosApp/localization/tr.json index 2bc1988..6729871 100644 --- a/client/iosApp/iosApp/localization/tr.json +++ b/client/iosApp/iosApp/localization/tr.json @@ -2924,6 +2924,27 @@ "wallet_transfer_success": "Transfer başarılı! TX: {tx}", "wallet_trust_degraded": "Donanım Güveni Düşmüş", "wallet_warning": "Uyarı", + "verify_title": "Bir derlemeyi doğrula", + "verify_hash_label": "Derleme hash'i", + "verify_button": "Kontrol Et", + "verify_undeclared_title": "Bu düğüm, derlemeleri doğrulayıp doğrulamadığını söyleyemez", + "verify_undeclared_body": "Bu düğüm, yetenek ilanından daha eski; dolayısıyla bunu söyleyemez. Daha yeni bir düğüm derlemeleri doğrulayabilir.", + "verify_absent_title": "Bu düğüm derlemeleri doğrulamıyor", + "verify_absent_body": "Bu düğüm sicili taşımıyor, dolayısıyla derlemeleri kontrol edemez. Başka bir düğüm kontrol edebilir.", + "verify_unreachable_title": "Bu düğüme erişilemedi", + "verify_unreachable_body": "Düğüm yanıt vermedi; dolayısıyla derlemeleri doğrulayıp doğrulayamayacağını bilmiyoruz. Bu, kontrol ettiğiniz derlemeyle ilgili bir sorun değildir.", + "verify_status_registered": "Kayıtlı", + "verify_status_deprecated": "Artık önerilmiyor", + "verify_status_revoked": "İptal Edildi", + "verify_status_unreadable": "Durum tanınmıyor", + "verify_revoked_warning": "Bu derleme iptal edilmiştir. Kullanmayın.", + "verify_not_found_title": "Bu derlemeye ait kayıt yok", + "verify_not_found_body": "Sicil yanıt verdi ve bu hash için hiçbir kayıt tutmuyor.", + "verify_unavailable_title": "Kontrol edilemedi", + "verify_unavailable_body": "Bu, 'kayıtlı değil' ile aynı şey değildir — sicil yanıt vermedi.", + "verify_undetermined_title": "Bu düğüm ne yapabileceğini belirleyemedi", + "verify_undetermined_body": "Düğüm yanıt verdi, ancak kendi anahtar kaydını okuyamadı. Bu genellikle geçicidir — kısa süre sonra tekrar deneyin.", + "verify_retry": "Yeniden kontrol et", "attestation_actions_desc": "Bu kayıt için eylemler", "chat_badge_message": "MESAJ", "chat_details": "tür {type} · kapsam {scope} · durum {status}", diff --git a/client/iosApp/iosApp/localization/uk.json b/client/iosApp/iosApp/localization/uk.json index 9de68ee..398a7c9 100644 --- a/client/iosApp/iosApp/localization/uk.json +++ b/client/iosApp/iosApp/localization/uk.json @@ -2924,6 +2924,27 @@ "wallet_transfer_success": "Переказ успішний! TX: {tx}", "wallet_trust_degraded": "Апаратну довіру знижено", "wallet_warning": "Попередження", + "verify_title": "Перевірити збірку", + "verify_hash_label": "Хеш збірки", + "verify_button": "Перевірити", + "verify_undeclared_title": "Цей вузол не може сказати, чи перевіряє він збірки", + "verify_undeclared_body": "Цей вузол старіший за декларацію можливостей, тож не може це сказати. Новіший вузол може перевіряти збірки.", + "verify_absent_title": "Цей вузол не перевіряє збірки", + "verify_absent_body": "Цей вузол не тримає реєстр, тож не може перевіряти збірки. Інший вузол може.", + "verify_unreachable_title": "Не вдалося зв'язатися з цим вузлом", + "verify_unreachable_body": "Вузол не відповів, тож ми не знаємо, чи може він перевіряти збірки. Це не проблема зі збіркою, яку ви перевіряєте.", + "verify_status_registered": "Зареєстровано", + "verify_status_deprecated": "Більше не рекомендується", + "verify_status_revoked": "Відкликано", + "verify_status_unreadable": "Статус не розпізнано", + "verify_revoked_warning": "Цю збірку відкликано. Не використовуйте її.", + "verify_not_found_title": "Немає запису про цю збірку", + "verify_not_found_body": "Реєстр відповів і не має нічого для цього хешу.", + "verify_unavailable_title": "Не вдалося перевірити", + "verify_unavailable_body": "Це не те саме, що «не зареєстровано» — реєстр не відповів.", + "verify_undetermined_title": "Цей вузол не зміг визначити, що він може робити", + "verify_undetermined_body": "Вузол відповів, але не зміг прочитати власний запис ключа. Зазвичай це тимчасово — спробуйте ще раз незабаром.", + "verify_retry": "Перевірити ще раз", "attestation_actions_desc": "Дії для цього запису", "chat_badge_message": "ПОВІДОМЛЕННЯ", "chat_details": "тип {type} · область {scope} · статус {status}", diff --git a/client/iosApp/iosApp/localization/ur.json b/client/iosApp/iosApp/localization/ur.json index cecd77f..462a656 100644 --- a/client/iosApp/iosApp/localization/ur.json +++ b/client/iosApp/iosApp/localization/ur.json @@ -2924,6 +2924,27 @@ "wallet_transfer_success": "ٹرانسفر کامیاب! TX: {tx}", "wallet_trust_degraded": "ہارڈ ویئر اعتماد کمزور پڑ گیا", "wallet_warning": "انتباہ", + "verify_title": "بلڈ کی تصدیق کریں", + "verify_hash_label": "بلڈ ہیش", + "verify_button": "جانچیں", + "verify_undeclared_title": "یہ نوڈ نہیں بتا سکتا کہ آیا وہ بلڈز کی تصدیق کرتا ہے", + "verify_undeclared_body": "یہ نوڈ صلاحیت کے اعلان سے پرانا ہے، اس لیے یہ نہیں بتا سکتا۔ ایک نیا نوڈ بلڈز کی تصدیق کر سکتا ہے۔", + "verify_absent_title": "یہ نوڈ بلڈز کی تصدیق نہیں کرتا", + "verify_absent_body": "یہ نوڈ رجسٹری نہیں رکھتا، اس لیے یہ بلڈز کی جانچ نہیں کر سکتا۔ کوئی دوسرا نوڈ کر سکتا ہے۔", + "verify_unreachable_title": "اس نوڈ تک رسائی نہیں ہو سکی", + "verify_unreachable_body": "نوڈ نے جواب نہیں دیا، اس لیے ہمیں معلوم نہیں کہ وہ بلڈز کی تصدیق کر سکتا ہے یا نہیں۔ یہ اس بلڈ کا مسئلہ نہیں جس کی آپ جانچ کر رہے ہیں۔", + "verify_status_registered": "رجسٹرڈ", + "verify_status_deprecated": "اب تجویز نہیں کیا جاتا", + "verify_status_revoked": "منسوخ شدہ", + "verify_status_unreadable": "حیثیت شناخت نہیں ہو سکی", + "verify_revoked_warning": "یہ بلڈ منسوخ کر دیا گیا ہے۔ اسے استعمال نہ کریں۔", + "verify_not_found_title": "اس بلڈ کا کوئی ریکارڈ نہیں", + "verify_not_found_body": "رجسٹری نے جواب دیا، اور اس کے پاس اس ہیش کے لیے کچھ نہیں ہے۔", + "verify_unavailable_title": "جانچ نہیں ہو سکی", + "verify_unavailable_body": "یہ 'رجسٹرڈ نہیں' کے برابر نہیں — رجسٹری نے جواب نہیں دیا۔", + "verify_undetermined_title": "یہ نوڈ طے نہیں کر سکا کہ وہ کیا کر سکتا ہے", + "verify_undetermined_body": "نوڈ نے جواب دیا، مگر اپنا کلیدی ریکارڈ نہ پڑھ سکا۔ یہ عام طور پر عارضی ہوتا ہے — تھوڑی دیر بعد دوبارہ کوشش کریں۔", + "verify_retry": "دوبارہ جانچیں", "attestation_actions_desc": "اس ریکارڈ کے لیے اقدامات", "chat_badge_message": "پیغام", "chat_details": "قسم {type} · دائرہ {scope} · حیثیت {status}", diff --git a/client/iosApp/iosApp/localization/vi.json b/client/iosApp/iosApp/localization/vi.json index 24135ce..6bc35d0 100644 --- a/client/iosApp/iosApp/localization/vi.json +++ b/client/iosApp/iosApp/localization/vi.json @@ -2924,6 +2924,27 @@ "wallet_transfer_success": "Chuyển khoản thành công! TX: {tx}", "wallet_trust_degraded": "Tin tưởng Suy giảm", "wallet_warning": "Cảnh báo", + "verify_title": "Xác minh một bản dựng", + "verify_hash_label": "Hash bản dựng", + "verify_button": "Kiểm tra", + "verify_undeclared_title": "Nút này không thể cho biết liệu nó có xác minh các bản dựng hay không", + "verify_undeclared_body": "Nút này cũ hơn bản khai năng lực, nên không thể trả lời. Một nút mới hơn có thể xác minh các bản dựng.", + "verify_absent_title": "Nút này không xác minh các bản dựng", + "verify_absent_body": "Nút này không giữ sổ đăng ký, nên không thể kiểm tra các bản dựng. Một nút khác có thể làm điều đó.", + "verify_unreachable_title": "Không thể kết nối với nút này", + "verify_unreachable_body": "Nút không phản hồi, nên chúng ta không biết liệu nó có thể xác minh các bản dựng hay không. Đây không phải là vấn đề của bản dựng bạn đang kiểm tra.", + "verify_status_registered": "Đã đăng ký", + "verify_status_deprecated": "Không còn được khuyến nghị", + "verify_status_revoked": "Đã bị thu hồi", + "verify_status_unreadable": "Không nhận dạng được trạng thái", + "verify_revoked_warning": "Bản dựng này đã bị thu hồi. Không sử dụng nó.", + "verify_not_found_title": "Không có bản ghi cho bản dựng này", + "verify_not_found_body": "Sổ đăng ký đã phản hồi và không có gì cho hash này.", + "verify_unavailable_title": "Không thể kiểm tra", + "verify_unavailable_body": "Điều này không giống với “chưa đăng ký” — sổ đăng ký không phản hồi.", + "verify_undetermined_title": "Nút này không thể xác định được nó có thể làm gì", + "verify_undetermined_body": "Nút đã trả lời, nhưng không đọc được bản ghi khóa của chính nó. Thông thường đây là tình trạng tạm thời — hãy thử lại sau.", + "verify_retry": "Kiểm tra lại", "attestation_actions_desc": "Các thao tác cho bản ghi này", "chat_badge_message": "TIN NHẮN", "chat_details": "loại {type} · phạm vi {scope} · trạng thái {status}", diff --git a/client/iosApp/iosApp/localization/yo.json b/client/iosApp/iosApp/localization/yo.json index c7c0a0f..f676e88 100644 --- a/client/iosApp/iosApp/localization/yo.json +++ b/client/iosApp/iosApp/localization/yo.json @@ -2924,6 +2924,27 @@ "wallet_transfer_success": "Gbígbé ṣe àṣeyọrí! TX: {tx}", "wallet_trust_degraded": "Ìgbẹ́kẹ̀lé Ohun Ẹ̀rọ Ti Dín Kù", "wallet_warning": "Ìkìlọ̀", + "verify_title": "Jẹ́rìísí build kan", + "verify_hash_label": "Hash build", + "verify_button": "Ṣàyẹ̀wò", + "verify_undeclared_title": "Nódù yìí kò lè sọ bóyá ó ń jẹ́rìísí àwọn build", + "verify_undeclared_body": "Nódù yìí dàgbà ju ìkéde agbára rẹ̀ lọ, nítorí náà kò lè sọ. Nódù tí ó ṣẹ̀ṣẹ̀ dé lè jẹ́rìísí àwọn build.", + "verify_absent_title": "Nódù yìí kì í jẹ́rìísí àwọn build", + "verify_absent_body": "Nódù yìí kò gbé àkójọ ìforúkọsílẹ̀, nítorí náà kò lè ṣàyẹ̀wò àwọn build. Nódù mìíràn lè ṣe é.", + "verify_unreachable_title": "A kò lè dé nódù yìí", + "verify_unreachable_body": "Nódù náà kò dáhùn, nítorí náà a kò mọ̀ bóyá ó lè jẹ́rìísí àwọn build. Èyí kì í ṣe ìṣòrò pẹ̀lú build tí o ń ṣàyẹ̀wò.", + "verify_status_registered": "Tí a forúkọsílẹ̀", + "verify_status_deprecated": "A kò gbà á nímọ̀ràn mọ́", + "verify_status_revoked": "Tí a fagilé", + "verify_status_unreadable": "Ipò tí a kò dá mọ̀", + "verify_revoked_warning": "A ti fagilé build yìí. Má lò ó.", + "verify_not_found_title": "Kò sí àkọsílẹ̀ fún build yìí", + "verify_not_found_body": "Àkójọ ìforúkọsílẹ̀ dáhùn, kò sì ní ohunkóhun fún hash yìí.", + "verify_unavailable_title": "A kò lè ṣàyẹ̀wò", + "verify_unavailable_body": "Èyí kò rí bákan náà pẹ̀lú 'a kò forúkọsílẹ̀' — àkójọ ìforúkọsílẹ̀ kò dáhùn.", + "verify_undetermined_title": "Nódù yìí kò lè pinnu ohun tí ó lè ṣe", + "verify_undetermined_body": "Nódù náà dáhùn, ṣùgbọ́n kò lè ka àkọsílẹ̀ kọ́kọ́rọ́ tirẹ̀. Èyí sábà máa ń jẹ́ fún ìgbà kékeré — gbìyànjú lẹ́ẹ̀kansi láìpẹ́.", + "verify_retry": "Ṣàyẹ̀wò lẹ́ẹ̀kansi", "attestation_actions_desc": "Àwọn ìgbésẹ̀ fún àkọsílẹ̀ yìí", "chat_badge_message": "ÌFIRÁNṢẸ́", "chat_details": "irú {type} · ààlà {scope} · ipò {status}", diff --git a/client/iosApp/iosApp/localization/zh.json b/client/iosApp/iosApp/localization/zh.json index 570ceda..c59f0cd 100644 --- a/client/iosApp/iosApp/localization/zh.json +++ b/client/iosApp/iosApp/localization/zh.json @@ -2924,6 +2924,27 @@ "wallet_transfer_success": "转账成功!TX: {tx}", "wallet_trust_degraded": "硬件信任降级", "wallet_warning": "警告", + "verify_title": "验证构建版本", + "verify_hash_label": "构建哈希", + "verify_button": "检查", + "verify_undeclared_title": "本节点无法说明自己是否验证构建版本", + "verify_undeclared_body": "本节点的版本早于能力声明机制,因此无法作答。更新版本的节点可以验证构建版本。", + "verify_absent_title": "本节点不验证构建版本", + "verify_absent_body": "本节点未持有注册表,因此无法检查构建版本。其他节点可以。", + "verify_unreachable_title": "无法连接到该节点", + "verify_unreachable_body": "该节点未作应答,因此我们不知道它是否能够验证构建版本。这不是您正在检查的构建版本本身的问题。", + "verify_status_registered": "已注册", + "verify_status_deprecated": "不再推荐", + "verify_status_revoked": "已撤销", + "verify_status_unreadable": "状态无法识别", + "verify_revoked_warning": "该构建版本已被撤销。请勿使用。", + "verify_not_found_title": "没有该构建版本的记录", + "verify_not_found_body": "注册表已应答,但未持有该哈希的任何记录。", + "verify_unavailable_title": "无法检查", + "verify_unavailable_body": "这与“未注册”并不相同——注册表未作应答。", + "verify_undetermined_title": "本节点无法确定自己能做什么", + "verify_undetermined_body": "该节点作出了应答,但无法读取自己的密钥记录。这通常是暂时性的——请稍后重试。", + "verify_retry": "重新检查", "attestation_actions_desc": "此记录的操作", "chat_badge_message": "消息", "chat_details": "类型 {type} · 范围 {scope} · 状态 {status}", diff --git a/client/shared/src/desktopMain/resources/localization/am.json b/client/shared/src/desktopMain/resources/localization/am.json index 6fc10f6..54741c5 100644 --- a/client/shared/src/desktopMain/resources/localization/am.json +++ b/client/shared/src/desktopMain/resources/localization/am.json @@ -2924,6 +2924,27 @@ "wallet_transfer_success": "ማስተላለፍ ተሳክቷል! TX: {tx}", "wallet_trust_degraded": "ስልክ ሥቅ ተዳክሞ ነበር", "wallet_warning": "ማስጠንቀቂያ", + "verify_title": "ግንባታ ማረጋገጥ", + "verify_hash_label": "የግንባታ ሃሽ", + "verify_button": "አረጋግጥ", + "verify_undeclared_title": "ይህ ኖድ ግንባታዎችን እንደሚያረጋግጥ ወይም እንደማያረጋግጥ መናገር አይችልም", + "verify_undeclared_body": "ይህ ኖድ ከችሎታ መግለጫው የቀደመ ነው፤ ስለዚህ መናገር አይችልም። አዲስ ኖድ ግንባታዎችን ማረጋገጥ ይችላል።", + "verify_absent_title": "ይህ ኖድ ግንባታዎችን አያረጋግጥም", + "verify_absent_body": "ይህ ኖድ መዝገቡን አልያዘም፤ ስለዚህ ግንባታዎችን ማረጋገጥ አይችልም። ሌላ ኖድ ግን ይችላል።", + "verify_unreachable_title": "ወደዚህ ኖድ መድረስ አልተቻለም", + "verify_unreachable_body": "ኖዱ መልስ አልሰጠም፤ ስለዚህ ግንባታዎችን ማረጋገጥ እንደሚችል ወይም እንደማይችል አናውቅም። ይህ እርስዎ የሚያረጋግጡት ግንባታ ችግር አይደለም።", + "verify_status_registered": "ተመዝግቧል", + "verify_status_deprecated": "ከዚህ በኋላ አይመከርም", + "verify_status_revoked": "ተሰርዟል", + "verify_status_unreadable": "ሁኔታው አልታወቀም", + "verify_revoked_warning": "ይህ ግንባታ ተሰርዟል። አይጠቀሙበት።", + "verify_not_found_title": "ለዚህ ግንባታ ምንም መዝገብ የለም", + "verify_not_found_body": "መዝገቡ መልስ ሰጥቷል፤ ለዚህ ሃሽ ምንም አልያዘም።", + "verify_unavailable_title": "ማረጋገጥ አልተቻለም", + "verify_unavailable_body": "ይህ ‘አልተመዘገበም’ ከመባል ጋር አንድ አይደለም — መዝገቡ መልስ አልሰጠም።", + "verify_undetermined_title": "ይህ ኖድ ምን ማድረግ እንደሚችል መወሰን አልቻለም", + "verify_undetermined_body": "ኖዱ መልስ ሰጥቷል፣ ሆኖም የራሱን የቁልፍ መዝገብ ማንበብ አልቻለም። ይህ በተለምዶ ጊዜያዊ ነው — ከጥቂት ጊዜ በኋላ እንደገና ይሞክሩ።", + "verify_retry": "እንደገና አረጋግጥ", "attestation_actions_desc": "ለዚህ መዝገብ ያሉ እርምጃዎች", "chat_badge_message": "መልዕክት", "chat_details": "ዓይነት {type} · ወሰን {scope} · ሁኔታ {status}", diff --git a/client/shared/src/desktopMain/resources/localization/ar.json b/client/shared/src/desktopMain/resources/localization/ar.json index 52541c6..48f9965 100644 --- a/client/shared/src/desktopMain/resources/localization/ar.json +++ b/client/shared/src/desktopMain/resources/localization/ar.json @@ -2924,6 +2924,27 @@ "wallet_transfer_success": "نجح التحويل! TX: {tx}", "wallet_trust_degraded": "تدهورت ثقة الأجهزة", "wallet_warning": "تحذير", + "verify_title": "التحقق من إصدار", + "verify_hash_label": "بصمة الإصدار", + "verify_button": "تحقّق", + "verify_undeclared_title": "لا تستطيع هذه العقدة الإفادة عن قدرتها على التحقق من الإصدارات", + "verify_undeclared_body": "هذه العقدة أقدم من إعلان القدرات، فلا يمكنها الإفادة. عقدة أحدث تستطيع التحقق من الإصدارات.", + "verify_absent_title": "هذه العقدة لا تتحقق من الإصدارات", + "verify_absent_body": "لا تحمل هذه العقدة السجل، فلا يمكنها التحقق من الإصدارات. عقدة أخرى تستطيع ذلك.", + "verify_unreachable_title": "تعذّر الوصول إلى هذه العقدة", + "verify_unreachable_body": "لم تُجب العقدة، فلا نعرف أتستطيع التحقق من الإصدارات أم لا. وهذا ليس عطلاً في الإصدار الذي تتحقق منه.", + "verify_status_registered": "مسجَّل", + "verify_status_deprecated": "لم يعد يُنصح به", + "verify_status_revoked": "مُلغى", + "verify_status_unreadable": "الحالة غير معروفة", + "verify_revoked_warning": "هذا الإصدار أُلغي. لا تستخدمه.", + "verify_not_found_title": "لا سجل لهذا الإصدار", + "verify_not_found_body": "أجاب السجل ولا يحمل شيئاً لهذه البصمة.", + "verify_unavailable_title": "تعذّر التحقق", + "verify_unavailable_body": "هذا ليس كـ«غير مسجَّل» — فالسجل لم يُجب.", + "verify_undetermined_title": "تعذّر على هذه العقدة تحديد ما تستطيع فعله", + "verify_undetermined_body": "أجابت العقدة، لكنها لم تستطع قراءة سجل مفتاحها الخاص. هذا عادةً مؤقت — حاول مجدداً بعد قليل.", + "verify_retry": "تحقّق مجدداً", "attestation_actions_desc": "إجراءات هذا السجل", "chat_badge_message": "رسالة", "chat_details": "النوع {type} · النطاق {scope} · الحالة {status}", diff --git a/client/shared/src/desktopMain/resources/localization/bn.json b/client/shared/src/desktopMain/resources/localization/bn.json index cbb52b3..203a77c 100644 --- a/client/shared/src/desktopMain/resources/localization/bn.json +++ b/client/shared/src/desktopMain/resources/localization/bn.json @@ -2925,6 +2925,27 @@ "wallet_transfer_success": "ট্রান্সফার সফল! TX: {tx}", "wallet_trust_degraded": "হার্ডওয়্যার বিশ্বাস হ্রাস পেয়েছে", "wallet_warning": "সতর্কতা", + "verify_title": "একটি বিল্ড যাচাই করুন", + "verify_hash_label": "বিল্ড হ্যাশ", + "verify_button": "পরীক্ষা করুন", + "verify_undeclared_title": "এই নোড বলতে পারে না যে এটি বিল্ড যাচাই করে কি না", + "verify_undeclared_body": "এই নোড সক্ষমতা ঘোষণার চেয়ে পুরনো, তাই এটি বলতে পারে না। নতুন কোনো নোড বিল্ড যাচাই করতে পারে।", + "verify_absent_title": "এই নোড বিল্ড যাচাই করে না", + "verify_absent_body": "এই নোড রেজিস্ট্রি ধারণ করে না, তাই এটি বিল্ড পরীক্ষা করতে পারে না। অন্য একটি নোড পারে।", + "verify_unreachable_title": "এই নোডে পৌঁছানো যায়নি", + "verify_unreachable_body": "নোডটি সাড়া দেয়নি, তাই এটি বিল্ড যাচাই করতে পারে কি না তা আমরা জানি না। আপনি যে বিল্ডটি পরীক্ষা করছেন তার সমস্যা এটি নয়।", + "verify_status_registered": "নিবন্ধিত", + "verify_status_deprecated": "আর প্রস্তাবিত নয়", + "verify_status_revoked": "প্রত্যাহৃত", + "verify_status_unreadable": "অবস্থা সনাক্ত করা যায়নি", + "verify_revoked_warning": "এই বিল্ডটি প্রত্যাহার করা হয়েছে। এটি ব্যবহার করবেন না।", + "verify_not_found_title": "এই বিল্ডের কোনো রেকর্ড নেই", + "verify_not_found_body": "রেজিস্ট্রি সাড়া দিয়েছে এবং এই হ্যাশের জন্য কিছুই ধারণ করে না।", + "verify_unavailable_title": "পরীক্ষা করা যায়নি", + "verify_unavailable_body": "এটি ‘নিবন্ধিত নয়’-এর সমান নয় — রেজিস্ট্রি সাড়া দেয়নি।", + "verify_undetermined_title": "এই নোড নির্ধারণ করতে পারেনি যে এটি কী করতে পারে", + "verify_undetermined_body": "নোডটি সাড়া দিয়েছে, কিন্তু নিজের কী রেকর্ড পড়তে পারেনি। এটি সাধারণত সাময়িক — কিছুক্ষণ পরে আবার চেষ্টা করুন।", + "verify_retry": "আবার পরীক্ষা করুন", "attestation_actions_desc": "এই রেকর্ডের জন্য পদক্ষেপ", "chat_badge_message": "বার্তা", "chat_details": "ধরন {type} · পরিসর {scope} · অবস্থা {status}", diff --git a/client/shared/src/desktopMain/resources/localization/de.json b/client/shared/src/desktopMain/resources/localization/de.json index da1e0ac..6f85250 100644 --- a/client/shared/src/desktopMain/resources/localization/de.json +++ b/client/shared/src/desktopMain/resources/localization/de.json @@ -2862,6 +2862,18 @@ "users_status": "Status", "users_user_id": "Benutzer-ID", "users_wa_role": "WA:{role}", + "verify_unavailable_title": "Prüfung nicht möglich", + "verify_undetermined_title": "Dieser Knoten konnte nicht feststellen, was er kann", + "verify_undetermined_body": "Der Knoten hat geantwortet, konnte aber seinen eigenen Schlüsseldatensatz nicht lesen. Das ist meist vorübergehend — versuchen Sie es in Kürze erneut.", + "verify_retry": "Erneut prüfen", + "verify_unreachable_title": "Knoten nicht erreichbar", + "verify_unreachable_body": "Der Knoten hat nicht geantwortet, daher wissen wir nicht, ob er Builds verifizieren kann. Das liegt nicht an dem Build, den Sie prüfen.", + "verify_status_registered": "Registriert", + "verify_status_deprecated": "Nicht mehr empfohlen", + "verify_status_revoked": "Widerrufen", + "verify_status_unreadable": "Status nicht erkannt", + "verify_revoked_warning": "Dieser Build wurde widerrufen. Verwenden Sie ihn nicht.", + "verify_not_found_title": "Kein Eintrag für diesen Build", "wa_approve": "Genehmigen", "wa_avg_resolution": "Durchschnittl. Auflösung: {time} Min", "wa_bus_subscribers": "Bus-Abonnenten", @@ -2924,6 +2936,12 @@ "wallet_transfer_success": "Überweisung erfolgreich! TX: {tx}", "wallet_trust_degraded": "Hardware-Vertrauen herabgestuft", "wallet_warning": "Warnung", + "verify_title": "Build verifizieren", + "verify_hash_label": "Build-Hash", + "verify_button": "Prüfen", + "verify_undeclared_title": "Dieser Knoten kann nicht sagen, ob er Builds verifiziert", + "verify_undeclared_body": "Dieser Knoten ist älter als die Fähigkeitserklärung und kann daher keine Auskunft geben. Ein neuerer Knoten kann Builds verifizieren.", + "verify_absent_title": "Dieser Knoten verifiziert keine Builds", "attestation_actions_desc": "Aktionen für diesen Datensatz", "chat_badge_message": "NACHRICHT", "chat_details": "Typ {type} · Bereich {scope} · Status {status}", diff --git a/client/shared/src/desktopMain/resources/localization/es.json b/client/shared/src/desktopMain/resources/localization/es.json index fe02dbf..91b0f58 100644 --- a/client/shared/src/desktopMain/resources/localization/es.json +++ b/client/shared/src/desktopMain/resources/localization/es.json @@ -2924,6 +2924,27 @@ "wallet_transfer_success": "¡Transferencia exitosa! TX: {tx}", "wallet_trust_degraded": "Confianza de Hardware Degradada", "wallet_warning": "Advertencia", + "verify_title": "Verificar una compilación", + "verify_hash_label": "Hash de la compilación", + "verify_button": "Comprobar", + "verify_undeclared_title": "Este nodo no puede decir si verifica compilaciones", + "verify_undeclared_body": "Este nodo es anterior a la declaración de capacidades, así que no puede saberlo. Un nodo más reciente puede verificar compilaciones.", + "verify_absent_title": "Este nodo no verifica compilaciones", + "verify_absent_body": "Este nodo no aloja el registro, así que no puede comprobar compilaciones. Otro nodo sí puede.", + "verify_unreachable_title": "No se pudo contactar con este nodo", + "verify_unreachable_body": "El nodo no respondió, así que no sabemos si puede verificar compilaciones. Esto no es un problema de la compilación que estás comprobando.", + "verify_status_registered": "Registrada", + "verify_status_deprecated": "Ya no se recomienda", + "verify_status_revoked": "Revocada", + "verify_status_unreadable": "Estado no reconocido", + "verify_revoked_warning": "Esta compilación ha sido revocada. No la uses.", + "verify_not_found_title": "No hay registro de esta compilación", + "verify_not_found_body": "El registro respondió y no tiene nada para este hash.", + "verify_unavailable_title": "No se pudo comprobar", + "verify_unavailable_body": "Esto no es lo mismo que «no registrada» — el registro no respondió.", + "verify_undetermined_title": "Este nodo no pudo determinar qué puede hacer", + "verify_undetermined_body": "El nodo respondió, pero no pudo leer su propio registro de claves. Esto suele ser temporal — inténtalo de nuevo en breve.", + "verify_retry": "Comprobar de nuevo", "attestation_actions_desc": "Acciones para este registro", "chat_badge_message": "MENSAJE", "chat_details": "tipo {type} · ámbito {scope} · estado {status}", diff --git a/client/shared/src/desktopMain/resources/localization/fa.json b/client/shared/src/desktopMain/resources/localization/fa.json index 38b931c..41c206a 100644 --- a/client/shared/src/desktopMain/resources/localization/fa.json +++ b/client/shared/src/desktopMain/resources/localization/fa.json @@ -2930,6 +2930,27 @@ "wallet_transfer_success": "انتقال با موفقیت انجام شد! TX: {tx}", "wallet_trust_degraded": "افت اعتماد سخت‌افزاری", "wallet_warning": "هشدار", + "verify_title": "تأیید یک نسخه", + "verify_hash_label": "هش نسخه", + "verify_button": "بررسی", + "verify_undeclared_title": "این گره نمی‌تواند بگوید آیا نسخه‌ها را تأیید می‌کند یا نه", + "verify_undeclared_body": "این گره قدیمی‌تر از اعلامِ قابلیت است، پس نمی‌تواند بگوید. گرهی جدیدتر می‌تواند نسخه‌ها را تأیید کند.", + "verify_absent_title": "این گره نسخه‌ها را تأیید نمی‌کند", + "verify_absent_body": "این گره رجیستری را نگه نمی‌دارد، پس نمی‌تواند نسخه‌ها را بررسی کند. گرهی دیگر می‌تواند.", + "verify_unreachable_title": "دسترسی به این گره ممکن نشد", + "verify_unreachable_body": "گره پاسخ نداد، پس نمی‌دانیم آیا می‌تواند نسخه‌ها را تأیید کند یا نه. این مشکلی از نسخه‌ای که بررسی می‌کنید نیست.", + "verify_status_registered": "ثبت‌شده", + "verify_status_deprecated": "دیگر توصیه نمی‌شود", + "verify_status_revoked": "باطل‌شده", + "verify_status_unreadable": "وضعیت شناسایی نشد", + "verify_revoked_warning": "این نسخه باطل شده است. از آن استفاده نکنید.", + "verify_not_found_title": "رکوردی از این نسخه وجود ندارد", + "verify_not_found_body": "رجیستری پاسخ داد و چیزی برای این هش نگه نمی‌دارد.", + "verify_unavailable_title": "بررسی ممکن نشد", + "verify_unavailable_body": "این با «ثبت‌نشده» یکسان نیست — رجیستری پاسخ نداد.", + "verify_undetermined_title": "این گره نتوانست تشخیص دهد چه کاری از آن ساخته است", + "verify_undetermined_body": "گره پاسخ داد، اما نتوانست رکورد کلید خودش را بخواند. این معمولاً موقتی است — کمی بعد دوباره تلاش کنید.", + "verify_retry": "دوباره بررسی کن", "attestation_actions_desc": "اقدامات برای این رکورد", "chat_badge_message": "پیام", "chat_details": "نوع {type} · محدوده {scope} · وضعیت {status}", diff --git a/client/shared/src/desktopMain/resources/localization/fr.json b/client/shared/src/desktopMain/resources/localization/fr.json index fe1f844..4dda6cc 100644 --- a/client/shared/src/desktopMain/resources/localization/fr.json +++ b/client/shared/src/desktopMain/resources/localization/fr.json @@ -2924,6 +2924,27 @@ "wallet_transfer_success": "Transfert réussi ! TX: {tx}", "wallet_trust_degraded": "Confiance Matérielle Dégradée", "wallet_warning": "Avertissement", + "verify_title": "Vérifier un build", + "verify_hash_label": "Empreinte du build", + "verify_button": "Vérifier", + "verify_undeclared_title": "Ce nœud ne peut pas dire s'il vérifie les builds", + "verify_undeclared_body": "Ce nœud est antérieur à la déclaration de capacité : il ne peut donc pas se prononcer. Un nœud plus récent peut vérifier les builds.", + "verify_absent_title": "Ce nœud ne vérifie pas les builds", + "verify_absent_body": "Ce nœud ne détient pas le registre : il ne peut donc pas vérifier les builds. Un autre nœud le peut.", + "verify_unreachable_title": "Impossible de joindre ce nœud", + "verify_unreachable_body": "Le nœud n'a pas répondu : nous ne savons donc pas s'il peut vérifier les builds. Ceci n'est pas un problème lié au build que vous vérifiez.", + "verify_status_registered": "Enregistré", + "verify_status_deprecated": "N'est plus recommandé", + "verify_status_revoked": "Révoqué", + "verify_status_unreadable": "Statut non reconnu", + "verify_revoked_warning": "Ce build a été révoqué. Ne l'utilisez pas.", + "verify_not_found_title": "Aucun enregistrement pour ce build", + "verify_not_found_body": "Le registre a répondu et ne détient rien pour cette empreinte.", + "verify_unavailable_title": "Vérification impossible", + "verify_unavailable_body": "Ceci n'équivaut pas à « non enregistré » — le registre n'a pas répondu.", + "verify_undetermined_title": "Ce nœud n'a pas pu déterminer ce qu'il peut faire", + "verify_undetermined_body": "Le nœud a répondu, mais n'a pas pu lire son propre enregistrement de clé. C'est généralement temporaire — réessayez dans un instant.", + "verify_retry": "Vérifier à nouveau", "attestation_actions_desc": "Actions pour cet enregistrement", "chat_badge_message": "MESSAGE", "chat_details": "type {type} · portée {scope} · statut {status}", diff --git a/client/shared/src/desktopMain/resources/localization/ha.json b/client/shared/src/desktopMain/resources/localization/ha.json index f5f91af..e36d699 100644 --- a/client/shared/src/desktopMain/resources/localization/ha.json +++ b/client/shared/src/desktopMain/resources/localization/ha.json @@ -2924,6 +2924,27 @@ "wallet_transfer_success": "Aika ya yi nasara! TX: {tx}", "wallet_trust_degraded": "Tabbas Kayan Aiki Ya Rage", "wallet_warning": "Gargaɗi", + "verify_title": "Tabbatar da build", + "verify_hash_label": "Hash na build", + "verify_button": "Duba", + "verify_undeclared_title": "Wannan kumburi ba zai iya faɗi ko yana tabbatar da build ba", + "verify_undeclared_body": "Wannan kumburi ya girme sanarwar iyawa, don haka ba zai iya faɗi ba. Sabon kumburi na iya tabbatar da build.", + "verify_absent_title": "Wannan kumburi ba ya tabbatar da build ba", + "verify_absent_body": "Wannan kumburi ba ya riƙe rajista ba, don haka ba zai iya duba build ba. Wani kumburi na iya duba build.", + "verify_unreachable_title": "An kasa isa ga wannan kumburi", + "verify_unreachable_body": "Kumburin bai amsa ba, don haka ba mu san ko yana iya tabbatar da build ba. Wannan ba matsala ce ta build ɗin da kuke dubawa ba.", + "verify_status_registered": "An yi rajista", + "verify_status_deprecated": "Ba a ƙara shawarta ba", + "verify_status_revoked": "An soke", + "verify_status_unreadable": "Ba a gane matsayin ba", + "verify_revoked_warning": "An soke wannan build. Kada ku yi amfani da shi.", + "verify_not_found_title": "Babu rikodin wannan build", + "verify_not_found_body": "Rajistar ta amsa kuma ba ta riƙe komai ga wannan hash ba.", + "verify_unavailable_title": "An kasa duba", + "verify_unavailable_body": "Wannan bai zama daidai da 'ba a yi rajista ba' ba — rajistar ba ta amsa ba.", + "verify_undetermined_title": "Wannan kumburi bai iya tantance abin da yake iya yi ba", + "verify_undetermined_body": "Kumburin ya amsa, amma bai iya karanta rikodin maɓallinsa na kansa ba. Yawanci na ɗan lokaci ne — sake gwadawa nan da nan.", + "verify_retry": "Sake duba", "attestation_actions_desc": "Ayyuka don wannan rikodin", "chat_badge_message": "SAƘO", "chat_details": "nau'i {type} · iyaka {scope} · matsayi {status}", diff --git a/client/shared/src/desktopMain/resources/localization/hi.json b/client/shared/src/desktopMain/resources/localization/hi.json index 504fa17..a4e474c 100644 --- a/client/shared/src/desktopMain/resources/localization/hi.json +++ b/client/shared/src/desktopMain/resources/localization/hi.json @@ -2924,6 +2924,27 @@ "wallet_transfer_success": "स्थानांतरण सफल! TX: {tx}", "wallet_trust_degraded": "हार्डवेयर ट्रस्ट कम हुआ", "wallet_warning": "चेतावनी", + "verify_title": "बिल्ड सत्यापित करें", + "verify_hash_label": "बिल्ड हैश", + "verify_button": "जाँच करें", + "verify_undeclared_title": "यह नोड नहीं बता सकता कि यह बिल्ड सत्यापित करता है या नहीं", + "verify_undeclared_body": "यह नोड क्षमता घोषणा से पुराना है, इसलिए यह बता नहीं सकता। कोई नया नोड बिल्ड सत्यापित कर सकता है।", + "verify_absent_title": "यह नोड बिल्ड सत्यापित नहीं करता", + "verify_absent_body": "यह नोड रजिस्ट्री नहीं रखता, इसलिए यह बिल्ड की जाँच नहीं कर सकता। कोई अन्य नोड कर सकता है।", + "verify_unreachable_title": "इस नोड तक नहीं पहुँच सका", + "verify_unreachable_body": "नोड ने उत्तर नहीं दिया, इसलिए यह पता नहीं चलता कि यह बिल्ड सत्यापित कर सकता है या नहीं। यह उस बिल्ड की समस्या नहीं है जिसकी आप जाँच कर रहे हैं।", + "verify_status_registered": "पंजीकृत", + "verify_status_deprecated": "अब अनुशंसित नहीं", + "verify_status_revoked": "रद्द", + "verify_status_unreadable": "स्थिति पहचानी नहीं जा सकी", + "verify_revoked_warning": "इस बिल्ड को रद्द कर दिया गया है। इसका उपयोग न करें।", + "verify_not_found_title": "इस बिल्ड का कोई रिकॉर्ड नहीं", + "verify_not_found_body": "रजिस्ट्री ने उत्तर दिया और इस हैश के लिए उसके पास कुछ भी नहीं है।", + "verify_unavailable_title": "जाँच नहीं हो सकी", + "verify_unavailable_body": "यह 'पंजीकृत नहीं' जैसा नहीं है — रजिस्ट्री ने उत्तर नहीं दिया।", + "verify_undetermined_title": "यह नोड यह निर्धारित नहीं कर सका कि यह क्या कर सकता है", + "verify_undetermined_body": "नोड ने उत्तर दिया, पर अपना ही कुंजी रिकॉर्ड नहीं पढ़ सका। यह आमतौर पर अस्थायी होता है — थोड़ी देर में फिर से प्रयास करें।", + "verify_retry": "फिर से जाँच करें", "attestation_actions_desc": "इस रिकॉर्ड के लिए कार्रवाइयाँ", "chat_badge_message": "संदेश", "chat_details": "प्रकार {type} · दायरा {scope} · स्थिति {status}", diff --git a/client/shared/src/desktopMain/resources/localization/id.json b/client/shared/src/desktopMain/resources/localization/id.json index d51d506..8c7d4ad 100644 --- a/client/shared/src/desktopMain/resources/localization/id.json +++ b/client/shared/src/desktopMain/resources/localization/id.json @@ -2924,6 +2924,27 @@ "wallet_transfer_success": "Transfer berhasil! TX: {tx}", "wallet_trust_degraded": "Kepercayaan Perangkat Keras Menurun", "wallet_warning": "Peringatan", + "verify_title": "Verifikasi build", + "verify_hash_label": "Hash build", + "verify_button": "Periksa", + "verify_undeclared_title": "Node ini tidak dapat menyatakan apakah ia memverifikasi build", + "verify_undeclared_body": "Node ini lebih lama daripada deklarasi kapabilitas, sehingga tidak dapat menyatakannya. Node yang lebih baru dapat memverifikasi build.", + "verify_absent_title": "Node ini tidak memverifikasi build", + "verify_absent_body": "Node ini tidak menyimpan registry, sehingga tidak dapat memeriksa build. Node lain bisa.", + "verify_unreachable_title": "Tidak dapat menjangkau node ini", + "verify_unreachable_body": "Node tidak merespons, sehingga kami tidak tahu apakah ia dapat memverifikasi build. Ini bukan masalah pada build yang Anda periksa.", + "verify_status_registered": "Terdaftar", + "verify_status_deprecated": "Tidak lagi disarankan", + "verify_status_revoked": "Dicabut", + "verify_status_unreadable": "Status tidak dikenali", + "verify_revoked_warning": "Build ini telah dicabut. Jangan gunakan.", + "verify_not_found_title": "Tidak ada catatan untuk build ini", + "verify_not_found_body": "Registry merespons dan tidak menyimpan apa pun untuk hash ini.", + "verify_unavailable_title": "Tidak dapat memeriksa", + "verify_unavailable_body": "Ini tidak sama dengan 'tidak terdaftar' — registry tidak merespons.", + "verify_undetermined_title": "Node ini tidak dapat menentukan apa yang bisa dilakukannya", + "verify_undetermined_body": "Node merespons, tetapi tidak dapat membaca catatan kuncinya sendiri. Biasanya ini bersifat sementara — coba lagi sebentar lagi.", + "verify_retry": "Periksa lagi", "attestation_actions_desc": "Tindakan untuk catatan ini", "chat_badge_message": "PESAN", "chat_details": "jenis {type} · lingkup {scope} · status {status}", diff --git a/client/shared/src/desktopMain/resources/localization/it.json b/client/shared/src/desktopMain/resources/localization/it.json index 525dd69..95ab48d 100644 --- a/client/shared/src/desktopMain/resources/localization/it.json +++ b/client/shared/src/desktopMain/resources/localization/it.json @@ -2924,6 +2924,27 @@ "wallet_transfer_success": "Trasferimento riuscito! TX: {tx}", "wallet_trust_degraded": "Fiducia Hardware Degradata", "wallet_warning": "Avviso", + "verify_title": "Verifica una build", + "verify_hash_label": "Hash della build", + "verify_button": "Verifica", + "verify_undeclared_title": "Questo nodo non è in grado di dire se verifica le build", + "verify_undeclared_body": "Questo nodo è precedente alla dichiarazione delle funzionalità, quindi non è in grado di pronunciarsi. Un nodo più recente può verificare le build.", + "verify_absent_title": "Questo nodo non verifica le build", + "verify_absent_body": "Questo nodo non detiene il registro, quindi non può verificare le build. Un altro nodo può farlo.", + "verify_unreachable_title": "Impossibile raggiungere questo nodo", + "verify_unreachable_body": "Il nodo non ha risposto, quindi non sappiamo se sia in grado di verificare le build. Questo non è un problema della build che stai verificando.", + "verify_status_registered": "Registrata", + "verify_status_deprecated": "Non più consigliata", + "verify_status_revoked": "Revocata", + "verify_status_unreadable": "Stato non riconosciuto", + "verify_revoked_warning": "Questa build è stata revocata. Non utilizzarla.", + "verify_not_found_title": "Nessuna registrazione per questa build", + "verify_not_found_body": "Il registro ha risposto e non contiene nulla per questo hash.", + "verify_unavailable_title": "Verifica non riuscita", + "verify_unavailable_body": "Questo non equivale a «non registrata» — il registro non ha risposto.", + "verify_undetermined_title": "Questo nodo non è riuscito a determinare cosa può fare", + "verify_undetermined_body": "Il nodo ha risposto, ma non è riuscito a leggere il proprio record delle chiavi. Di solito è temporaneo — riprova a breve.", + "verify_retry": "Verifica di nuovo", "attestation_actions_desc": "Azioni per questo record", "chat_badge_message": "MESSAGGIO", "chat_details": "tipo {type} · ambito {scope} · stato {status}", diff --git a/client/shared/src/desktopMain/resources/localization/ja.json b/client/shared/src/desktopMain/resources/localization/ja.json index 371b63a..3123141 100644 --- a/client/shared/src/desktopMain/resources/localization/ja.json +++ b/client/shared/src/desktopMain/resources/localization/ja.json @@ -2924,6 +2924,27 @@ "wallet_transfer_success": "送金成功!TX: {tx}", "wallet_trust_degraded": "ハードウェア信頼が低下しました", "wallet_warning": "警告", + "verify_title": "ビルドを検証する", + "verify_hash_label": "ビルドハッシュ", + "verify_button": "確認", + "verify_undeclared_title": "このノードはビルドを検証できるかどうかを述べられません", + "verify_undeclared_body": "このノードは機能宣言より古いバージョンのため、判断できません。新しいノードであればビルドを検証できます。", + "verify_absent_title": "このノードはビルドを検証しません", + "verify_absent_body": "このノードはレジストリを保持していないため、ビルドを確認できません。他のノードであれば確認できます。", + "verify_unreachable_title": "このノードに接続できませんでした", + "verify_unreachable_body": "ノードが応答しなかったため、ビルドを検証できるかどうかは分かりません。これは、確認しようとしているビルド自体の問題ではありません。", + "verify_status_registered": "登録済み", + "verify_status_deprecated": "推奨されていません", + "verify_status_revoked": "失効済み", + "verify_status_unreadable": "ステータスを認識できません", + "verify_revoked_warning": "このビルドは失効しています。使用しないでください。", + "verify_not_found_title": "このビルドの記録はありません", + "verify_not_found_body": "レジストリは応答しましたが、このハッシュに対する記録を保持していません。", + "verify_unavailable_title": "確認できませんでした", + "verify_unavailable_body": "これは「未登録」と同じではありません — レジストリが応答しませんでした。", + "verify_undetermined_title": "このノードは自身にできることを判別できませんでした", + "verify_undetermined_body": "ノードは応答しましたが、自身の鍵の記録を読み取れませんでした。これは通常一時的なものです — しばらくしてから再試行してください。", + "verify_retry": "再確認", "attestation_actions_desc": "このレコードに対する操作", "chat_badge_message": "メッセージ", "chat_details": "種別 {type} · スコープ {scope} · 状態 {status}", diff --git a/client/shared/src/desktopMain/resources/localization/ko.json b/client/shared/src/desktopMain/resources/localization/ko.json index e46b77f..ce7f6a2 100644 --- a/client/shared/src/desktopMain/resources/localization/ko.json +++ b/client/shared/src/desktopMain/resources/localization/ko.json @@ -2924,6 +2924,27 @@ "wallet_transfer_success": "전송 성공! TX: {tx}", "wallet_trust_degraded": "하드웨어 신뢰 저하됨", "wallet_warning": "경고", + "verify_title": "빌드 검증", + "verify_hash_label": "빌드 해시", + "verify_button": "확인", + "verify_undeclared_title": "이 노드는 빌드를 검증하는지 여부를 알 수 없습니다", + "verify_undeclared_body": "이 노드는 기능 선언보다 오래되어 알 수 없습니다. 더 새로운 노드는 빌드를 검증할 수 있습니다.", + "verify_absent_title": "이 노드는 빌드를 검증하지 않습니다", + "verify_absent_body": "이 노드는 레지스트리를 보유하지 않아 빌드를 확인할 수 없습니다. 다른 노드는 확인할 수 있습니다.", + "verify_unreachable_title": "이 노드에 연결할 수 없음", + "verify_unreachable_body": "노드가 응답하지 않아 빌드를 검증할 수 있는지 알 수 없습니다. 이는 확인 중인 빌드의 문제가 아닙니다.", + "verify_status_registered": "등록됨", + "verify_status_deprecated": "더 이상 권장되지 않음", + "verify_status_revoked": "폐기됨", + "verify_status_unreadable": "상태를 인식할 수 없음", + "verify_revoked_warning": "이 빌드는 폐기되었습니다. 사용하지 마십시오.", + "verify_not_found_title": "이 빌드에 대한 기록 없음", + "verify_not_found_body": "레지스트리가 응답했지만 이 해시에 대한 기록이 없습니다.", + "verify_unavailable_title": "확인할 수 없음", + "verify_unavailable_body": "이는 '등록되지 않음'과 같지 않습니다 — 레지스트리가 응답하지 않았습니다.", + "verify_undetermined_title": "이 노드는 자신이 무엇을 할 수 있는지 판단할 수 없었습니다", + "verify_undetermined_body": "노드가 응답했지만 자체 키 레코드를 읽을 수 없었습니다. 이는 대개 일시적인 현상입니다 — 잠시 후 다시 시도하세요.", + "verify_retry": "다시 확인", "attestation_actions_desc": "이 레코드에 대한 작업", "chat_badge_message": "메시지", "chat_details": "유형 {type} · 범위 {scope} · 상태 {status}", diff --git a/client/shared/src/desktopMain/resources/localization/mr.json b/client/shared/src/desktopMain/resources/localization/mr.json index 35d3208..b4cb9d1 100644 --- a/client/shared/src/desktopMain/resources/localization/mr.json +++ b/client/shared/src/desktopMain/resources/localization/mr.json @@ -2924,6 +2924,27 @@ "wallet_transfer_success": "Transfer यशful! TX: {tx}", "wallet_trust_degraded": "हार्डवेअर विश्वास खालावला", "wallet_warning": "इशारा", + "verify_title": "बिल्ड सत्यापित करा", + "verify_hash_label": "बिल्ड हॅश", + "verify_button": "तपासा", + "verify_undeclared_title": "हा नोड बिल्ड सत्यापित करतो की नाही हे सांगू शकत नाही", + "verify_undeclared_body": "हा नोड क्षमता-घोषणेपेक्षा जुना आहे, त्यामुळे तो सांगू शकत नाही. नवीन नोड बिल्ड सत्यापित करू शकतो.", + "verify_absent_title": "हा नोड बिल्ड सत्यापित करत नाही", + "verify_absent_body": "या नोडकडे रजिस्ट्री नाही, त्यामुळे तो बिल्ड तपासू शकत नाही. दुसरा नोड हे करू शकतो.", + "verify_unreachable_title": "या नोडपर्यंत पोहोचता आले नाही", + "verify_unreachable_body": "नोडने उत्तर दिले नाही, त्यामुळे तो बिल्ड सत्यापित करू शकतो की नाही हे आम्हाला माहीत नाही. तुम्ही तपासत असलेल्या बिल्डमध्ये ही समस्या नाही.", + "verify_status_registered": "नोंदणीकृत", + "verify_status_deprecated": "आता शिफारस केलेले नाही", + "verify_status_revoked": "रद्द केलेले", + "verify_status_unreadable": "स्थिती ओळखता आली नाही", + "verify_revoked_warning": "हे बिल्ड रद्द करण्यात आले आहे. याचा वापर करू नका.", + "verify_not_found_title": "या बिल्डची कोणतीही नोंद नाही", + "verify_not_found_body": "रजिस्ट्रीने उत्तर दिले आणि या हॅशसाठी त्याकडे काहीही नाही.", + "verify_unavailable_title": "तपासता आले नाही", + "verify_unavailable_body": "हे 'नोंदणीकृत नाही' यासारखे नाही — रजिस्ट्रीने उत्तर दिले नाही.", + "verify_undetermined_title": "हा नोड काय करू शकतो हे ठरवता आले नाही", + "verify_undetermined_body": "नोडने उत्तर दिले, पण त्याला स्वतःची की-नोंद वाचता आली नाही. हे सहसा तात्पुरते असते — थोड्या वेळाने पुन्हा प्रयत्न करा.", + "verify_retry": "पुन्हा तपासा", "attestation_actions_desc": "या नोंदीसाठी क्रिया", "chat_badge_message": "संदेश", "chat_details": "प्रकार {type} · व्याप्ती {scope} · स्थिती {status}", diff --git a/client/shared/src/desktopMain/resources/localization/my.json b/client/shared/src/desktopMain/resources/localization/my.json index 37d756b..f956c52 100644 --- a/client/shared/src/desktopMain/resources/localization/my.json +++ b/client/shared/src/desktopMain/resources/localization/my.json @@ -2862,6 +2862,14 @@ "users_status": "အခြေအနေ", "users_user_id": "အသုံးပြုသူ ID", "users_wa_role": "WA:{role}", + "verify_revoked_warning": "ဤ build ကို ရုပ်သိမ်းထားပြီးဖြစ်သည်။ အသုံးမပြုပါနှင့်။", + "verify_not_found_title": "ဤ build ၏ မှတ်တမ်း မရှိပါ", + "verify_not_found_body": "registry က အဖြေ ပြန်ပေးခဲ့ပြီး ဤ hash အတွက် မည်သည့်အရာမျှ ကိုင်ဆောင်ထားခြင်း မရှိပါ။", + "verify_unavailable_title": "စစ်ဆေး၍ မရပါ", + "verify_unavailable_body": "ဤသည်မှာ 'မှတ်ပုံတင်ထားခြင်း မရှိပါ' ဟူသည်နှင့် မတူပါ — registry က အဖြေ ပြန်မပေးခဲ့ပါ။", + "verify_undetermined_title": "ဤ node သည် ၎င်း လုပ်နိုင်သည့်အရာကို သတ်မှတ်၍ မရခဲ့ပါ", + "verify_undetermined_body": "node က အဖြေ ပြန်ပေးခဲ့သော်လည်း ၎င်း၏ ကိုယ်ပိုင် key မှတ်တမ်းကို ဖတ်၍ မရခဲ့ပါ။ ဤသည် ယာယီသာ ဖြစ်လေ့ရှိသည် — မကြာမီ ထပ်ကြိုးစားပါ။", + "verify_retry": "ထပ်မံစစ်ဆေးပါ", "wa_approve": "အတည်ပြုပါ", "wa_avg_resolution": "ပျမ်းမျှ ဖြေရှင်းချိန်: {time} မိနစ်", "wa_bus_subscribers": "Bus Subscribers", @@ -2924,6 +2932,18 @@ "wallet_transfer_success": "Transfer အောင်မြင်ful! TX: {tx}", "wallet_trust_degraded": "Hardware ယုံကြည်မှု အားနည်းသွားပြီ", "wallet_warning": "သတိပေး", + "verify_title": "Build တစ်ခုကို အတည်ပြုပါ", + "verify_hash_label": "Build hash", + "verify_button": "စစ်ဆေးပါ", + "verify_undeclared_title": "ဤ node သည် build များကို အတည်ပြုနိုင်သည် မနိုင်သည်ကို ပြောနိုင်စွမ်း မရှိပါ", + "verify_undeclared_body": "ဤ node သည် capability declaration ထက် ပိုမိုဟောင်းနွမ်းသဖြင့် ပြောနိုင်စွမ်း မရှိပါ။ ပိုမို အသစ်သော node တစ်ခုက build များကို အတည်ပြုနိုင်ပါသည်။", + "verify_absent_title": "ဤ node သည် build များကို အတည်ပြု၍ မရပါ", + "verify_absent_body": "ဤ node သည် registry ကို ကိုင်ဆောင်ထားခြင်း မရှိသဖြင့် build များကို စစ်ဆေး၍ မရပါ။ အခြား node တစ်ခုက စစ်ဆေးနိုင်ပါသည်။", + "verify_unreachable_title": "ဤ node ကို ချိတ်ဆက်၍ မရပါ", + "verify_unreachable_body": "node က အဖြေ ပြန်မပေးခဲ့သဖြင့် ၎င်းသည် build များကို အတည်ပြုနိုင်သည် မနိုင်သည်ကို ကျွန်ုပ်တို့ မသိပါ။ ဤသည် သင် စစ်ဆေးနေသော build ၏ ပြဿနာ မဟုတ်ပါ။", + "verify_status_registered": "မှတ်ပုံတင်ထားသည်", + "verify_status_deprecated": "ထပ်မံ အသုံးပြုရန် အကြံမပြုတော့ပါ", + "verify_status_revoked": "ရုပ်သိမ်းထားသည်", "attestation_actions_desc": "ဤမှတ်တမ်းအတွက် လုပ်ဆောင်ချက်များ", "chat_badge_message": "မက်ဆေ့ချ်", "chat_details": "အမျိုးအစား {type} · scope {scope} · အခြေအနေ {status}", diff --git a/client/shared/src/desktopMain/resources/localization/pa.json b/client/shared/src/desktopMain/resources/localization/pa.json index b5d51c5..e50e1a8 100644 --- a/client/shared/src/desktopMain/resources/localization/pa.json +++ b/client/shared/src/desktopMain/resources/localization/pa.json @@ -2924,6 +2924,27 @@ "wallet_transfer_success": "ਟ੍ਰਾਂਸਫਰ ਸਫਲ! TX: {tx}", "wallet_trust_degraded": "ਹਾਰਡਵੇਅਰ ਭਰੋਸਾ ਘਟਿਆ", "wallet_warning": "ਚੇਤਾਵਨੀ", + "verify_title": "ਇੱਕ ਬਿਲਡ ਦੀ ਪੁਸ਼ਟੀ ਕਰੋ", + "verify_hash_label": "ਬਿਲਡ ਹੈਸ਼", + "verify_button": "ਜਾਂਚ ਕਰੋ", + "verify_undeclared_title": "ਇਹ ਨੋਡ ਨਹੀਂ ਕਹਿ ਸਕਦਾ ਕਿ ਇਹ ਬਿਲਡਾਂ ਦੀ ਪੁਸ਼ਟੀ ਕਰਦਾ ਹੈ ਜਾਂ ਨਹੀਂ", + "verify_undeclared_body": "ਇਹ ਨੋਡ ਸਮਰੱਥਾ ਐਲਾਨ ਤੋਂ ਪੁਰਾਣਾ ਹੈ, ਇਸ ਲਈ ਇਹ ਕੁਝ ਕਹਿ ਨਹੀਂ ਸਕਦਾ। ਇੱਕ ਨਵਾਂ ਨੋਡ ਬਿਲਡਾਂ ਦੀ ਪੁਸ਼ਟੀ ਕਰ ਸਕਦਾ ਹੈ।", + "verify_absent_title": "ਇਹ ਨੋਡ ਬਿਲਡਾਂ ਦੀ ਪੁਸ਼ਟੀ ਨਹੀਂ ਕਰਦਾ", + "verify_absent_body": "ਇਹ ਨੋਡ ਰਜਿਸਟਰੀ ਨਹੀਂ ਰੱਖਦਾ, ਇਸ ਲਈ ਇਹ ਬਿਲਡਾਂ ਦੀ ਜਾਂਚ ਨਹੀਂ ਕਰ ਸਕਦਾ। ਕੋਈ ਹੋਰ ਨੋਡ ਕਰ ਸਕਦਾ ਹੈ।", + "verify_unreachable_title": "ਇਸ ਨੋਡ ਤੱਕ ਨਹੀਂ ਪਹੁੰਚ ਸਕੇ", + "verify_unreachable_body": "ਨੋਡ ਨੇ ਜਵਾਬ ਨਹੀਂ ਦਿੱਤਾ, ਇਸ ਲਈ ਸਾਨੂੰ ਨਹੀਂ ਪਤਾ ਕਿ ਇਹ ਬਿਲਡਾਂ ਦੀ ਪੁਸ਼ਟੀ ਕਰ ਸਕਦਾ ਹੈ ਜਾਂ ਨਹੀਂ। ਇਹ ਉਸ ਬਿਲਡ ਦੀ ਸਮੱਸਿਆ ਨਹੀਂ ਹੈ ਜਿਸਦੀ ਤੁਸੀਂ ਜਾਂਚ ਕਰ ਰਹੇ ਹੋ।", + "verify_status_registered": "ਰਜਿਸਟਰਡ", + "verify_status_deprecated": "ਹੁਣ ਸਿਫ਼ਾਰਸ਼ੀ ਨਹੀਂ", + "verify_status_revoked": "ਰੱਦ ਕੀਤਾ", + "verify_status_unreadable": "ਹਾਲਤ ਪਛਾਣੀ ਨਹੀਂ ਗਈ", + "verify_revoked_warning": "ਇਹ ਬਿਲਡ ਰੱਦ ਕਰ ਦਿੱਤਾ ਗਿਆ ਹੈ। ਇਸਨੂੰ ਨਾ ਵਰਤੋ।", + "verify_not_found_title": "ਇਸ ਬਿਲਡ ਦਾ ਕੋਈ ਰਿਕਾਰਡ ਨਹੀਂ", + "verify_not_found_body": "ਰਜਿਸਟਰੀ ਨੇ ਜਵਾਬ ਦਿੱਤਾ ਅਤੇ ਇਸ ਹੈਸ਼ ਲਈ ਇਸ ਕੋਲ ਕੁਝ ਵੀ ਨਹੀਂ ਹੈ।", + "verify_unavailable_title": "ਜਾਂਚ ਨਹੀਂ ਹੋ ਸਕੀ", + "verify_unavailable_body": "ਇਹ 'ਰਜਿਸਟਰਡ ਨਹੀਂ' ਵਰਗੀ ਗੱਲ ਨਹੀਂ ਹੈ — ਰਜਿਸਟਰੀ ਨੇ ਜਵਾਬ ਨਹੀਂ ਦਿੱਤਾ।", + "verify_undetermined_title": "ਇਹ ਨੋਡ ਇਹ ਪਤਾ ਨਹੀਂ ਲਗਾ ਸਕਿਆ ਕਿ ਇਹ ਕੀ ਕਰ ਸਕਦਾ ਹੈ", + "verify_undetermined_body": "ਨੋਡ ਨੇ ਜਵਾਬ ਤਾਂ ਦਿੱਤਾ, ਪਰ ਆਪਣਾ ਕੁੰਜੀ ਰਿਕਾਰਡ ਨਹੀਂ ਪੜ੍ਹ ਸਕਿਆ। ਇਹ ਆਮ ਤੌਰ 'ਤੇ ਅਸਥਾਈ ਹੁੰਦਾ ਹੈ — ਥੋੜ੍ਹੀ ਦੇਰ ਵਿੱਚ ਦੁਬਾਰਾ ਕੋਸ਼ਿਸ਼ ਕਰੋ।", + "verify_retry": "ਦੁਬਾਰਾ ਜਾਂਚ ਕਰੋ", "attestation_actions_desc": "ਇਸ ਰਿਕਾਰਡ ਲਈ ਕਾਰਵਾਈਆਂ", "chat_badge_message": "ਸੁਨੇਹਾ", "chat_details": "ਕਿਸਮ {type} · ਦਾਇਰਾ {scope} · ਸਥਿਤੀ {status}", diff --git a/client/shared/src/desktopMain/resources/localization/pt.json b/client/shared/src/desktopMain/resources/localization/pt.json index d4d550e..4cd2723 100644 --- a/client/shared/src/desktopMain/resources/localization/pt.json +++ b/client/shared/src/desktopMain/resources/localization/pt.json @@ -2924,6 +2924,27 @@ "wallet_transfer_success": "Transferência bem-sucedida! TX: {tx}", "wallet_trust_degraded": "Confiança de Hardware Degradada", "wallet_warning": "Aviso", + "verify_title": "Verificar uma build", + "verify_hash_label": "Hash da build", + "verify_button": "Verificar", + "verify_undeclared_title": "Este nó não pode dizer se verifica builds", + "verify_undeclared_body": "Este nó é mais antigo do que a declaração de capacidades, portanto não pode dizer. Um nó mais recente pode verificar builds.", + "verify_absent_title": "Este nó não verifica builds", + "verify_absent_body": "Este nó não possui o registro, portanto não pode verificar builds. Outro nó pode.", + "verify_unreachable_title": "Não foi possível alcançar este nó", + "verify_unreachable_body": "O nó não respondeu, portanto não sabemos se ele pode verificar builds. Isto não é um problema com a build que você está verificando.", + "verify_status_registered": "Registrada", + "verify_status_deprecated": "Não mais recomendada", + "verify_status_revoked": "Revogada", + "verify_status_unreadable": "Status não reconhecido", + "verify_revoked_warning": "Esta build foi revogada. Não a use.", + "verify_not_found_title": "Nenhum registro desta build", + "verify_not_found_body": "O registro respondeu e não contém nada para este hash.", + "verify_unavailable_title": "Não foi possível verificar", + "verify_unavailable_body": "Isto não é o mesmo que 'não registrada' — o registro não respondeu.", + "verify_undetermined_title": "Este nó não conseguiu determinar o que pode fazer", + "verify_undetermined_body": "O nó respondeu, mas não conseguiu ler o próprio registro de chave. Isto costuma ser temporário — tente novamente em breve.", + "verify_retry": "Verificar novamente", "attestation_actions_desc": "Ações para este registo", "chat_badge_message": "MENSAGEM", "chat_details": "tipo {type} · âmbito {scope} · estado {status}", diff --git a/client/shared/src/desktopMain/resources/localization/ru.json b/client/shared/src/desktopMain/resources/localization/ru.json index db4bf61..14028b7 100644 --- a/client/shared/src/desktopMain/resources/localization/ru.json +++ b/client/shared/src/desktopMain/resources/localization/ru.json @@ -2924,6 +2924,27 @@ "wallet_transfer_success": "Перевод успешен! TX: {tx}", "wallet_trust_degraded": "Доверие к оборудованию ухудшено", "wallet_warning": "Предупреждение", + "verify_title": "Проверить сборку", + "verify_hash_label": "Хеш сборки", + "verify_button": "Проверить", + "verify_undeclared_title": "Этот узел не может сказать, проверяет ли он сборки", + "verify_undeclared_body": "Этот узел старше объявления возможностей, поэтому не может сказать. Более новый узел может проверять сборки.", + "verify_absent_title": "Этот узел не проверяет сборки", + "verify_absent_body": "Этот узел не хранит реестр, поэтому не может проверять сборки. Другой узел может.", + "verify_unreachable_title": "Не удалось связаться с этим узлом", + "verify_unreachable_body": "Узел не ответил, поэтому неизвестно, может ли он проверять сборки. Это не связано с проверяемой вами сборкой.", + "verify_status_registered": "Зарегистрирована", + "verify_status_deprecated": "Больше не рекомендуется", + "verify_status_revoked": "Отозвана", + "verify_status_unreadable": "Статус не распознан", + "verify_revoked_warning": "Эта сборка отозвана. Не используйте её.", + "verify_not_found_title": "Нет записи об этой сборке", + "verify_not_found_body": "Реестр ответил, но не содержит записи для этого хеша.", + "verify_unavailable_title": "Не удалось проверить", + "verify_unavailable_body": "Это не то же самое, что «не зарегистрирована» — реестр не ответил.", + "verify_undetermined_title": "Этот узел не смог определить, что он может делать", + "verify_undetermined_body": "Узел ответил, но не смог прочитать собственную запись ключа. Обычно это временно — повторите попытку через некоторое время.", + "verify_retry": "Проверить снова", "attestation_actions_desc": "Действия для этой записи", "chat_badge_message": "СООБЩЕНИЕ", "chat_details": "тип {type} · область {scope} · статус {status}", diff --git a/client/shared/src/desktopMain/resources/localization/sw.json b/client/shared/src/desktopMain/resources/localization/sw.json index 17baf50..2ebcdb1 100644 --- a/client/shared/src/desktopMain/resources/localization/sw.json +++ b/client/shared/src/desktopMain/resources/localization/sw.json @@ -2924,6 +2924,27 @@ "wallet_transfer_success": "Uhamisho umefanikiwa! TX: {tx}", "wallet_trust_degraded": "Kuaminika kwa Maunzi Kumedhoofika", "wallet_warning": "Onyo", + "verify_title": "Thibitisha toleo", + "verify_hash_label": "Hash ya toleo", + "verify_button": "Kagua", + "verify_undeclared_title": "Nodi hii haiwezi kusema kama inathibitisha matoleo", + "verify_undeclared_body": "Nodi hii ni ya zamani kuliko tamko la uwezo, kwa hivyo haiwezi kusema. Nodi mpya zaidi inaweza kuthibitisha matoleo.", + "verify_absent_title": "Nodi hii haithibitishi matoleo", + "verify_absent_body": "Nodi hii haibebi sajili, kwa hivyo haiwezi kukagua matoleo. Nodi nyingine inaweza.", + "verify_unreachable_title": "Imeshindwa kufikia nodi hii", + "verify_unreachable_body": "Nodi haikujibu, kwa hivyo hatujui kama inaweza kuthibitisha matoleo. Hili si tatizo la toleo unalolikagua.", + "verify_status_registered": "Limesajiliwa", + "verify_status_deprecated": "Halipendekezwi tena", + "verify_status_revoked": "Limebatilishwa", + "verify_status_unreadable": "Hali haitambuliki", + "verify_revoked_warning": "Toleo hili limebatilishwa. Usilitumie.", + "verify_not_found_title": "Hakuna rekodi ya toleo hili", + "verify_not_found_body": "Sajili ilijibu na haina kitu kwa hash hii.", + "verify_unavailable_title": "Imeshindwa kukagua", + "verify_unavailable_body": "Hii si sawa na 'halijasajiliwa' — sajili haikujibu.", + "verify_undetermined_title": "Nodi hii haikuweza kubaini kile inachoweza kufanya", + "verify_undetermined_body": "Nodi ilijibu, lakini haikuweza kusoma rekodi yake yenyewe ya ufunguo. Hii kwa kawaida ni ya muda tu — jaribu tena baada ya muda mfupi.", + "verify_retry": "Kagua tena", "attestation_actions_desc": "Vitendo vya rekodi hii", "chat_badge_message": "UJUMBE", "chat_details": "aina {type} · wigo {scope} · hali {status}", diff --git a/client/shared/src/desktopMain/resources/localization/ta.json b/client/shared/src/desktopMain/resources/localization/ta.json index f3a999a..166494d 100644 --- a/client/shared/src/desktopMain/resources/localization/ta.json +++ b/client/shared/src/desktopMain/resources/localization/ta.json @@ -2924,6 +2924,27 @@ "wallet_transfer_success": "பரிமாற்றம் வெற்றிகரம்! TX: {tx}", "wallet_trust_degraded": "Hardware நம்பகத்தன்மை Degraded", "wallet_warning": "எச்சரிக்கை", + "verify_title": "ஒரு பதிப்பைச் சரிபார்", + "verify_hash_label": "பதிப்பு ஹாஷ்", + "verify_button": "சரிபார்", + "verify_undeclared_title": "இந்த முனை பதிப்புகளைச் சரிபார்க்கிறதா என்று கூற முடியாது", + "verify_undeclared_body": "இந்த முனை திறன் அறிவிப்பைவிட பழையது; எனவே இதனால் கூற முடியாது. புதிய முனையால் பதிப்புகளைச் சரிபார்க்க முடியும்.", + "verify_absent_title": "இந்த முனை பதிப்புகளைச் சரிபார்க்காது", + "verify_absent_body": "இந்த முனையிடம் பதிவகம் இல்லை; எனவே இதனால் பதிப்புகளைச் சரிபார்க்க முடியாது. வேறொரு முனையால் முடியும்.", + "verify_unreachable_title": "இந்த முனையை அணுக முடியவில்லை", + "verify_unreachable_body": "முனை பதிலளிக்கவில்லை; எனவே அதனால் பதிப்புகளைச் சரிபார்க்க முடியுமா என்பது எங்களுக்குத் தெரியாது. இது நீங்கள் சரிபார்க்கும் பதிப்பின் சிக்கல் அல்ல.", + "verify_status_registered": "பதிவு செய்யப்பட்டது", + "verify_status_deprecated": "இனி பரிந்துரைக்கப்படவில்லை", + "verify_status_revoked": "திரும்பப் பெறப்பட்டது", + "verify_status_unreadable": "நிலை அறியப்படவில்லை", + "verify_revoked_warning": "இந்தப் பதிப்பு திரும்பப் பெறப்பட்டுள்ளது. இதைப் பயன்படுத்த வேண்டாம்.", + "verify_not_found_title": "இந்தப் பதிப்புக்கான பதிவு இல்லை", + "verify_not_found_body": "பதிவகம் பதிலளித்தது, இந்த ஹாஷுக்கு எதுவும் வைத்திருக்கவில்லை.", + "verify_unavailable_title": "சரிபார்க்க முடியவில்லை", + "verify_unavailable_body": "இது 'பதிவு செய்யப்படவில்லை' என்பதற்குச் சமமானதல்ல — பதிவகம் பதிலளிக்கவில்லை.", + "verify_undetermined_title": "இந்த முனை தன்னால் என்ன செய்ய முடியும் என்பதைத் தீர்மானிக்க முடியவில்லை", + "verify_undetermined_body": "முனை பதிலளித்தது, ஆனால் தன் சொந்த விசைப் பதிவை வாசிக்க முடியவில்லை. இது பொதுவாக தற்காலிகமானது — சிறிது நேரத்தில் மீண்டும் முயலவும்.", + "verify_retry": "மீண்டும் சரிபார்", "attestation_actions_desc": "இந்தப் பதிவுக்கான செயல்கள்", "chat_badge_message": "செய்தி", "chat_details": "வகை {type} · எல்லை {scope} · நிலை {status}", diff --git a/client/shared/src/desktopMain/resources/localization/te.json b/client/shared/src/desktopMain/resources/localization/te.json index 57f56c3..d5ae35d 100644 --- a/client/shared/src/desktopMain/resources/localization/te.json +++ b/client/shared/src/desktopMain/resources/localization/te.json @@ -2924,6 +2924,27 @@ "wallet_transfer_success": "బదిలీ విజయవంతమైంది! TX: {tx}", "wallet_trust_degraded": "హార్డ్‌వేర్ నమ్మకం తగ్గింది", "wallet_warning": "హెచ్చరిక", + "verify_title": "బిల్డ్‌ను ధృవీకరించండి", + "verify_hash_label": "బిల్డ్ హాష్", + "verify_button": "తనిఖీ చేయండి", + "verify_undeclared_title": "ఈ నోడ్ బిల్డ్‌లను ధృవీకరిస్తుందో లేదో చెప్పలేకపోతుంది", + "verify_undeclared_body": "ఈ నోడ్ కేపబిలిటీ ప్రకటన కంటే పాతది, కాబట్టి ఇది చెప్పలేకపోతుంది. కొత్త నోడ్ బిల్డ్‌లను ధృవీకరించగలదు.", + "verify_absent_title": "ఈ నోడ్ బిల్డ్‌లను ధృవీకరించదు", + "verify_absent_body": "ఈ నోడ్ వద్ద రిజిస్ట్రీ లేదు, కాబట్టి ఇది బిల్డ్‌లను తనిఖీ చేయలేకపోతుంది. మరో నోడ్ చేయగలదు.", + "verify_unreachable_title": "ఈ నోడ్‌ను చేరుకోలేకపోయాం", + "verify_unreachable_body": "నోడ్ స్పందించలేదు, కాబట్టి అది బిల్డ్‌లను ధృవీకరించగలదో లేదో మాకు తెలియదు. ఇది మీరు తనిఖీ చేస్తున్న బిల్డ్‌లో సమస్య కాదు.", + "verify_status_registered": "నమోదైంది", + "verify_status_deprecated": "ఇక సిఫార్సు చేయబడదు", + "verify_status_revoked": "రద్దు చేయబడింది", + "verify_status_unreadable": "స్థితి గుర్తించబడలేదు", + "verify_revoked_warning": "ఈ బిల్డ్ రద్దు చేయబడింది. దీన్ని ఉపయోగించవద్దు.", + "verify_not_found_title": "ఈ బిల్డ్ గురించి రికార్డు లేదు", + "verify_not_found_body": "రిజిస్ట్రీ స్పందించింది, కానీ ఈ హాష్ కోసం ఏమీ లేదు.", + "verify_unavailable_title": "తనిఖీ చేయలేకపోయాం", + "verify_unavailable_body": "ఇది 'నమోదు కాలేదు' అనే దానికి సమానం కాదు — రిజిస్ట్రీ స్పందించలేదు.", + "verify_undetermined_title": "ఈ నోడ్ తాను ఏమి చేయగలదో నిర్ధారించలేకపోయింది", + "verify_undetermined_body": "నోడ్ స్పందించింది, కానీ తన సొంత కీ రికార్డును చదవలేకపోయింది. ఇది సాధారణంగా తాత్కాలికం — కొద్ది సేపట్లో మళ్ళీ ప్రయత్నించండి.", + "verify_retry": "మళ్ళీ తనిఖీ చేయండి", "attestation_actions_desc": "ఈ రికార్డుకు చర్యలు", "chat_badge_message": "సందేశం", "chat_details": "రకం {type} · పరిధి {scope} · స్థితి {status}", diff --git a/client/shared/src/desktopMain/resources/localization/th.json b/client/shared/src/desktopMain/resources/localization/th.json index 079e23f..cba9e06 100644 --- a/client/shared/src/desktopMain/resources/localization/th.json +++ b/client/shared/src/desktopMain/resources/localization/th.json @@ -2924,6 +2924,27 @@ "wallet_transfer_success": "Transfer สำเร็จful! TX: {tx}", "wallet_trust_degraded": "ความน่าเชื่อถือของฮาร์ดแวร์ลดลง", "wallet_warning": "คำเตือน", + "verify_title": "ตรวจสอบ build", + "verify_hash_label": "Hash ของ build", + "verify_button": "ตรวจสอบ", + "verify_undeclared_title": "โหนดนี้บอกไม่ได้ว่าตนตรวจสอบ build หรือไม่", + "verify_undeclared_body": "โหนดนี้เก่ากว่าคำประกาศความสามารถ จึงบอกไม่ได้ โหนดที่ใหม่กว่าสามารถตรวจสอบ build ได้", + "verify_absent_title": "โหนดนี้ไม่ตรวจสอบ build", + "verify_absent_body": "โหนดนี้ไม่มีรีจิสทรี จึงไม่สามารถตรวจสอบ build ได้ โหนดอื่นสามารถทำได้", + "verify_unreachable_title": "ไม่สามารถติดต่อโหนดนี้ได้", + "verify_unreachable_body": "โหนดไม่ตอบสนอง เราจึงไม่ทราบว่าโหนดสามารถตรวจสอบ build ได้หรือไม่ นี่ไม่ใช่ปัญหาของ build ที่คุณกำลังตรวจสอบ", + "verify_status_registered": "ลงทะเบียนแล้ว", + "verify_status_deprecated": "ไม่แนะนำให้ใช้อีกต่อไป", + "verify_status_revoked": "ถูกเพิกถอน", + "verify_status_unreadable": "ไม่รู้จักสถานะ", + "verify_revoked_warning": "Build นี้ถูกเพิกถอนแล้ว อย่าใช้งาน", + "verify_not_found_title": "ไม่มีบันทึกสำหรับ build นี้", + "verify_not_found_body": "รีจิสทรีตอบกลับแล้ว และไม่มีข้อมูลสำหรับ hash นี้", + "verify_unavailable_title": "ไม่สามารถตรวจสอบได้", + "verify_unavailable_body": "นี่ไม่เหมือนกับ 'ไม่ได้ลงทะเบียน' — รีจิสทรีไม่ตอบสนอง", + "verify_undetermined_title": "โหนดนี้ไม่สามารถระบุได้ว่าตนทำสิ่งใดได้", + "verify_undetermined_body": "โหนดตอบแล้ว แต่อ่านบันทึกคีย์ของตนเองไม่ได้ โดยปกติแล้วนี่เป็นเพียงชั่วคราว — ลองอีกครั้งในไม่ช้า", + "verify_retry": "ตรวจสอบอีกครั้ง", "attestation_actions_desc": "การดำเนินการสำหรับระเบียนนี้", "chat_badge_message": "ข้อความ", "chat_details": "ประเภท {type} · ขอบเขต {scope} · สถานะ {status}", diff --git a/client/shared/src/desktopMain/resources/localization/tr.json b/client/shared/src/desktopMain/resources/localization/tr.json index 2bc1988..6729871 100644 --- a/client/shared/src/desktopMain/resources/localization/tr.json +++ b/client/shared/src/desktopMain/resources/localization/tr.json @@ -2924,6 +2924,27 @@ "wallet_transfer_success": "Transfer başarılı! TX: {tx}", "wallet_trust_degraded": "Donanım Güveni Düşmüş", "wallet_warning": "Uyarı", + "verify_title": "Bir derlemeyi doğrula", + "verify_hash_label": "Derleme hash'i", + "verify_button": "Kontrol Et", + "verify_undeclared_title": "Bu düğüm, derlemeleri doğrulayıp doğrulamadığını söyleyemez", + "verify_undeclared_body": "Bu düğüm, yetenek ilanından daha eski; dolayısıyla bunu söyleyemez. Daha yeni bir düğüm derlemeleri doğrulayabilir.", + "verify_absent_title": "Bu düğüm derlemeleri doğrulamıyor", + "verify_absent_body": "Bu düğüm sicili taşımıyor, dolayısıyla derlemeleri kontrol edemez. Başka bir düğüm kontrol edebilir.", + "verify_unreachable_title": "Bu düğüme erişilemedi", + "verify_unreachable_body": "Düğüm yanıt vermedi; dolayısıyla derlemeleri doğrulayıp doğrulayamayacağını bilmiyoruz. Bu, kontrol ettiğiniz derlemeyle ilgili bir sorun değildir.", + "verify_status_registered": "Kayıtlı", + "verify_status_deprecated": "Artık önerilmiyor", + "verify_status_revoked": "İptal Edildi", + "verify_status_unreadable": "Durum tanınmıyor", + "verify_revoked_warning": "Bu derleme iptal edilmiştir. Kullanmayın.", + "verify_not_found_title": "Bu derlemeye ait kayıt yok", + "verify_not_found_body": "Sicil yanıt verdi ve bu hash için hiçbir kayıt tutmuyor.", + "verify_unavailable_title": "Kontrol edilemedi", + "verify_unavailable_body": "Bu, 'kayıtlı değil' ile aynı şey değildir — sicil yanıt vermedi.", + "verify_undetermined_title": "Bu düğüm ne yapabileceğini belirleyemedi", + "verify_undetermined_body": "Düğüm yanıt verdi, ancak kendi anahtar kaydını okuyamadı. Bu genellikle geçicidir — kısa süre sonra tekrar deneyin.", + "verify_retry": "Yeniden kontrol et", "attestation_actions_desc": "Bu kayıt için eylemler", "chat_badge_message": "MESAJ", "chat_details": "tür {type} · kapsam {scope} · durum {status}", diff --git a/client/shared/src/desktopMain/resources/localization/uk.json b/client/shared/src/desktopMain/resources/localization/uk.json index 9de68ee..398a7c9 100644 --- a/client/shared/src/desktopMain/resources/localization/uk.json +++ b/client/shared/src/desktopMain/resources/localization/uk.json @@ -2924,6 +2924,27 @@ "wallet_transfer_success": "Переказ успішний! TX: {tx}", "wallet_trust_degraded": "Апаратну довіру знижено", "wallet_warning": "Попередження", + "verify_title": "Перевірити збірку", + "verify_hash_label": "Хеш збірки", + "verify_button": "Перевірити", + "verify_undeclared_title": "Цей вузол не може сказати, чи перевіряє він збірки", + "verify_undeclared_body": "Цей вузол старіший за декларацію можливостей, тож не може це сказати. Новіший вузол може перевіряти збірки.", + "verify_absent_title": "Цей вузол не перевіряє збірки", + "verify_absent_body": "Цей вузол не тримає реєстр, тож не може перевіряти збірки. Інший вузол може.", + "verify_unreachable_title": "Не вдалося зв'язатися з цим вузлом", + "verify_unreachable_body": "Вузол не відповів, тож ми не знаємо, чи може він перевіряти збірки. Це не проблема зі збіркою, яку ви перевіряєте.", + "verify_status_registered": "Зареєстровано", + "verify_status_deprecated": "Більше не рекомендується", + "verify_status_revoked": "Відкликано", + "verify_status_unreadable": "Статус не розпізнано", + "verify_revoked_warning": "Цю збірку відкликано. Не використовуйте її.", + "verify_not_found_title": "Немає запису про цю збірку", + "verify_not_found_body": "Реєстр відповів і не має нічого для цього хешу.", + "verify_unavailable_title": "Не вдалося перевірити", + "verify_unavailable_body": "Це не те саме, що «не зареєстровано» — реєстр не відповів.", + "verify_undetermined_title": "Цей вузол не зміг визначити, що він може робити", + "verify_undetermined_body": "Вузол відповів, але не зміг прочитати власний запис ключа. Зазвичай це тимчасово — спробуйте ще раз незабаром.", + "verify_retry": "Перевірити ще раз", "attestation_actions_desc": "Дії для цього запису", "chat_badge_message": "ПОВІДОМЛЕННЯ", "chat_details": "тип {type} · область {scope} · статус {status}", diff --git a/client/shared/src/desktopMain/resources/localization/ur.json b/client/shared/src/desktopMain/resources/localization/ur.json index cecd77f..462a656 100644 --- a/client/shared/src/desktopMain/resources/localization/ur.json +++ b/client/shared/src/desktopMain/resources/localization/ur.json @@ -2924,6 +2924,27 @@ "wallet_transfer_success": "ٹرانسفر کامیاب! TX: {tx}", "wallet_trust_degraded": "ہارڈ ویئر اعتماد کمزور پڑ گیا", "wallet_warning": "انتباہ", + "verify_title": "بلڈ کی تصدیق کریں", + "verify_hash_label": "بلڈ ہیش", + "verify_button": "جانچیں", + "verify_undeclared_title": "یہ نوڈ نہیں بتا سکتا کہ آیا وہ بلڈز کی تصدیق کرتا ہے", + "verify_undeclared_body": "یہ نوڈ صلاحیت کے اعلان سے پرانا ہے، اس لیے یہ نہیں بتا سکتا۔ ایک نیا نوڈ بلڈز کی تصدیق کر سکتا ہے۔", + "verify_absent_title": "یہ نوڈ بلڈز کی تصدیق نہیں کرتا", + "verify_absent_body": "یہ نوڈ رجسٹری نہیں رکھتا، اس لیے یہ بلڈز کی جانچ نہیں کر سکتا۔ کوئی دوسرا نوڈ کر سکتا ہے۔", + "verify_unreachable_title": "اس نوڈ تک رسائی نہیں ہو سکی", + "verify_unreachable_body": "نوڈ نے جواب نہیں دیا، اس لیے ہمیں معلوم نہیں کہ وہ بلڈز کی تصدیق کر سکتا ہے یا نہیں۔ یہ اس بلڈ کا مسئلہ نہیں جس کی آپ جانچ کر رہے ہیں۔", + "verify_status_registered": "رجسٹرڈ", + "verify_status_deprecated": "اب تجویز نہیں کیا جاتا", + "verify_status_revoked": "منسوخ شدہ", + "verify_status_unreadable": "حیثیت شناخت نہیں ہو سکی", + "verify_revoked_warning": "یہ بلڈ منسوخ کر دیا گیا ہے۔ اسے استعمال نہ کریں۔", + "verify_not_found_title": "اس بلڈ کا کوئی ریکارڈ نہیں", + "verify_not_found_body": "رجسٹری نے جواب دیا، اور اس کے پاس اس ہیش کے لیے کچھ نہیں ہے۔", + "verify_unavailable_title": "جانچ نہیں ہو سکی", + "verify_unavailable_body": "یہ 'رجسٹرڈ نہیں' کے برابر نہیں — رجسٹری نے جواب نہیں دیا۔", + "verify_undetermined_title": "یہ نوڈ طے نہیں کر سکا کہ وہ کیا کر سکتا ہے", + "verify_undetermined_body": "نوڈ نے جواب دیا، مگر اپنا کلیدی ریکارڈ نہ پڑھ سکا۔ یہ عام طور پر عارضی ہوتا ہے — تھوڑی دیر بعد دوبارہ کوشش کریں۔", + "verify_retry": "دوبارہ جانچیں", "attestation_actions_desc": "اس ریکارڈ کے لیے اقدامات", "chat_badge_message": "پیغام", "chat_details": "قسم {type} · دائرہ {scope} · حیثیت {status}", diff --git a/client/shared/src/desktopMain/resources/localization/vi.json b/client/shared/src/desktopMain/resources/localization/vi.json index 24135ce..6bc35d0 100644 --- a/client/shared/src/desktopMain/resources/localization/vi.json +++ b/client/shared/src/desktopMain/resources/localization/vi.json @@ -2924,6 +2924,27 @@ "wallet_transfer_success": "Chuyển khoản thành công! TX: {tx}", "wallet_trust_degraded": "Tin tưởng Suy giảm", "wallet_warning": "Cảnh báo", + "verify_title": "Xác minh một bản dựng", + "verify_hash_label": "Hash bản dựng", + "verify_button": "Kiểm tra", + "verify_undeclared_title": "Nút này không thể cho biết liệu nó có xác minh các bản dựng hay không", + "verify_undeclared_body": "Nút này cũ hơn bản khai năng lực, nên không thể trả lời. Một nút mới hơn có thể xác minh các bản dựng.", + "verify_absent_title": "Nút này không xác minh các bản dựng", + "verify_absent_body": "Nút này không giữ sổ đăng ký, nên không thể kiểm tra các bản dựng. Một nút khác có thể làm điều đó.", + "verify_unreachable_title": "Không thể kết nối với nút này", + "verify_unreachable_body": "Nút không phản hồi, nên chúng ta không biết liệu nó có thể xác minh các bản dựng hay không. Đây không phải là vấn đề của bản dựng bạn đang kiểm tra.", + "verify_status_registered": "Đã đăng ký", + "verify_status_deprecated": "Không còn được khuyến nghị", + "verify_status_revoked": "Đã bị thu hồi", + "verify_status_unreadable": "Không nhận dạng được trạng thái", + "verify_revoked_warning": "Bản dựng này đã bị thu hồi. Không sử dụng nó.", + "verify_not_found_title": "Không có bản ghi cho bản dựng này", + "verify_not_found_body": "Sổ đăng ký đã phản hồi và không có gì cho hash này.", + "verify_unavailable_title": "Không thể kiểm tra", + "verify_unavailable_body": "Điều này không giống với “chưa đăng ký” — sổ đăng ký không phản hồi.", + "verify_undetermined_title": "Nút này không thể xác định được nó có thể làm gì", + "verify_undetermined_body": "Nút đã trả lời, nhưng không đọc được bản ghi khóa của chính nó. Thông thường đây là tình trạng tạm thời — hãy thử lại sau.", + "verify_retry": "Kiểm tra lại", "attestation_actions_desc": "Các thao tác cho bản ghi này", "chat_badge_message": "TIN NHẮN", "chat_details": "loại {type} · phạm vi {scope} · trạng thái {status}", diff --git a/client/shared/src/desktopMain/resources/localization/yo.json b/client/shared/src/desktopMain/resources/localization/yo.json index c7c0a0f..f676e88 100644 --- a/client/shared/src/desktopMain/resources/localization/yo.json +++ b/client/shared/src/desktopMain/resources/localization/yo.json @@ -2924,6 +2924,27 @@ "wallet_transfer_success": "Gbígbé ṣe àṣeyọrí! TX: {tx}", "wallet_trust_degraded": "Ìgbẹ́kẹ̀lé Ohun Ẹ̀rọ Ti Dín Kù", "wallet_warning": "Ìkìlọ̀", + "verify_title": "Jẹ́rìísí build kan", + "verify_hash_label": "Hash build", + "verify_button": "Ṣàyẹ̀wò", + "verify_undeclared_title": "Nódù yìí kò lè sọ bóyá ó ń jẹ́rìísí àwọn build", + "verify_undeclared_body": "Nódù yìí dàgbà ju ìkéde agbára rẹ̀ lọ, nítorí náà kò lè sọ. Nódù tí ó ṣẹ̀ṣẹ̀ dé lè jẹ́rìísí àwọn build.", + "verify_absent_title": "Nódù yìí kì í jẹ́rìísí àwọn build", + "verify_absent_body": "Nódù yìí kò gbé àkójọ ìforúkọsílẹ̀, nítorí náà kò lè ṣàyẹ̀wò àwọn build. Nódù mìíràn lè ṣe é.", + "verify_unreachable_title": "A kò lè dé nódù yìí", + "verify_unreachable_body": "Nódù náà kò dáhùn, nítorí náà a kò mọ̀ bóyá ó lè jẹ́rìísí àwọn build. Èyí kì í ṣe ìṣòrò pẹ̀lú build tí o ń ṣàyẹ̀wò.", + "verify_status_registered": "Tí a forúkọsílẹ̀", + "verify_status_deprecated": "A kò gbà á nímọ̀ràn mọ́", + "verify_status_revoked": "Tí a fagilé", + "verify_status_unreadable": "Ipò tí a kò dá mọ̀", + "verify_revoked_warning": "A ti fagilé build yìí. Má lò ó.", + "verify_not_found_title": "Kò sí àkọsílẹ̀ fún build yìí", + "verify_not_found_body": "Àkójọ ìforúkọsílẹ̀ dáhùn, kò sì ní ohunkóhun fún hash yìí.", + "verify_unavailable_title": "A kò lè ṣàyẹ̀wò", + "verify_unavailable_body": "Èyí kò rí bákan náà pẹ̀lú 'a kò forúkọsílẹ̀' — àkójọ ìforúkọsílẹ̀ kò dáhùn.", + "verify_undetermined_title": "Nódù yìí kò lè pinnu ohun tí ó lè ṣe", + "verify_undetermined_body": "Nódù náà dáhùn, ṣùgbọ́n kò lè ka àkọsílẹ̀ kọ́kọ́rọ́ tirẹ̀. Èyí sábà máa ń jẹ́ fún ìgbà kékeré — gbìyànjú lẹ́ẹ̀kansi láìpẹ́.", + "verify_retry": "Ṣàyẹ̀wò lẹ́ẹ̀kansi", "attestation_actions_desc": "Àwọn ìgbésẹ̀ fún àkọsílẹ̀ yìí", "chat_badge_message": "ÌFIRÁNṢẸ́", "chat_details": "irú {type} · ààlà {scope} · ipò {status}", diff --git a/client/shared/src/desktopMain/resources/localization/zh.json b/client/shared/src/desktopMain/resources/localization/zh.json index 570ceda..c59f0cd 100644 --- a/client/shared/src/desktopMain/resources/localization/zh.json +++ b/client/shared/src/desktopMain/resources/localization/zh.json @@ -2924,6 +2924,27 @@ "wallet_transfer_success": "转账成功!TX: {tx}", "wallet_trust_degraded": "硬件信任降级", "wallet_warning": "警告", + "verify_title": "验证构建版本", + "verify_hash_label": "构建哈希", + "verify_button": "检查", + "verify_undeclared_title": "本节点无法说明自己是否验证构建版本", + "verify_undeclared_body": "本节点的版本早于能力声明机制,因此无法作答。更新版本的节点可以验证构建版本。", + "verify_absent_title": "本节点不验证构建版本", + "verify_absent_body": "本节点未持有注册表,因此无法检查构建版本。其他节点可以。", + "verify_unreachable_title": "无法连接到该节点", + "verify_unreachable_body": "该节点未作应答,因此我们不知道它是否能够验证构建版本。这不是您正在检查的构建版本本身的问题。", + "verify_status_registered": "已注册", + "verify_status_deprecated": "不再推荐", + "verify_status_revoked": "已撤销", + "verify_status_unreadable": "状态无法识别", + "verify_revoked_warning": "该构建版本已被撤销。请勿使用。", + "verify_not_found_title": "没有该构建版本的记录", + "verify_not_found_body": "注册表已应答,但未持有该哈希的任何记录。", + "verify_unavailable_title": "无法检查", + "verify_unavailable_body": "这与“未注册”并不相同——注册表未作应答。", + "verify_undetermined_title": "本节点无法确定自己能做什么", + "verify_undetermined_body": "该节点作出了应答,但无法读取自己的密钥记录。这通常是暂时性的——请稍后重试。", + "verify_retry": "重新检查", "attestation_actions_desc": "此记录的操作", "chat_badge_message": "消息", "chat_details": "类型 {type} · 范围 {scope} · 状态 {status}", From ea331df619838fd557f6f23538afa9237d6dc68c Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Sat, 29 Aug 2026 01:40:50 +0000 Subject: [PATCH 15/18] i18n: translate lane (translate -> evaluate -> repair) Machine translation, independently reviewed against MQM, and repaired where the review found a critical, major or terminology error. Every value here is status=draft / review_status=needs_native_review: this pipeline guarantees terminology, structure and meaning, and does not guarantee native fluency. Validated by check_localization_sync.py --strict in this same run. The MQM findings are attached to the run as i18n-report.json. Review like any other diff. --- client/VENDORING.md | 2 +- client/androidApp/src/main/assets/localization/de.json | 3 +++ client/desktopApp/src/main/resources/localization/de.json | 3 +++ client/iosApp/iosApp/localization/de.json | 3 +++ client/shared/src/desktopMain/resources/localization/de.json | 3 +++ 5 files changed, 13 insertions(+), 1 deletion(-) diff --git a/client/VENDORING.md b/client/VENDORING.md index 58c2f8c..4090bbd 100644 --- a/client/VENDORING.md +++ b/client/VENDORING.md @@ -40,7 +40,7 @@ source is the pair a bisect wants: The tree's current recorded state — sha256-of-sha256s over every git-tracked file under `client/` except this one: -**state digest:** `65b64d2ae6d83307dc17d1832a54ec4df2eca07531ddb282444f6ec5b7d366d9` +**state digest:** `60fc8c1265ebc6c438aac0da4db06f0b6ce4f3e3f095c6dec353aeb006b7564c` `packaging/check_vendoring.py` asserts it on every push, and refuses any tracked file matching a §2 never-vendor class. **Any commit that touches diff --git a/client/androidApp/src/main/assets/localization/de.json b/client/androidApp/src/main/assets/localization/de.json index 6f85250..a86708e 100644 --- a/client/androidApp/src/main/assets/localization/de.json +++ b/client/androidApp/src/main/assets/localization/de.json @@ -2863,6 +2863,7 @@ "users_user_id": "Benutzer-ID", "users_wa_role": "WA:{role}", "verify_unavailable_title": "Prüfung nicht möglich", + "verify_unavailable_body": "Das ist nicht dasselbe wie „nicht registriert“ — das Register hat nicht geantwortet.", "verify_undetermined_title": "Dieser Knoten konnte nicht feststellen, was er kann", "verify_undetermined_body": "Der Knoten hat geantwortet, konnte aber seinen eigenen Schlüsseldatensatz nicht lesen. Das ist meist vorübergehend — versuchen Sie es in Kürze erneut.", "verify_retry": "Erneut prüfen", @@ -2874,6 +2875,7 @@ "verify_status_unreadable": "Status nicht erkannt", "verify_revoked_warning": "Dieser Build wurde widerrufen. Verwenden Sie ihn nicht.", "verify_not_found_title": "Kein Eintrag für diesen Build", + "verify_not_found_body": "Das Register hat geantwortet und enthält nichts zu diesem Hash.", "wa_approve": "Genehmigen", "wa_avg_resolution": "Durchschnittl. Auflösung: {time} Min", "wa_bus_subscribers": "Bus-Abonnenten", @@ -2942,6 +2944,7 @@ "verify_undeclared_title": "Dieser Knoten kann nicht sagen, ob er Builds verifiziert", "verify_undeclared_body": "Dieser Knoten ist älter als die Fähigkeitserklärung und kann daher keine Auskunft geben. Ein neuerer Knoten kann Builds verifizieren.", "verify_absent_title": "Dieser Knoten verifiziert keine Builds", + "verify_absent_body": "Dieser Knoten verwaltet das Register nicht und kann daher keine Builds prüfen. Ein anderer Knoten kann das.", "attestation_actions_desc": "Aktionen für diesen Datensatz", "chat_badge_message": "NACHRICHT", "chat_details": "Typ {type} · Bereich {scope} · Status {status}", diff --git a/client/desktopApp/src/main/resources/localization/de.json b/client/desktopApp/src/main/resources/localization/de.json index 6f85250..a86708e 100644 --- a/client/desktopApp/src/main/resources/localization/de.json +++ b/client/desktopApp/src/main/resources/localization/de.json @@ -2863,6 +2863,7 @@ "users_user_id": "Benutzer-ID", "users_wa_role": "WA:{role}", "verify_unavailable_title": "Prüfung nicht möglich", + "verify_unavailable_body": "Das ist nicht dasselbe wie „nicht registriert“ — das Register hat nicht geantwortet.", "verify_undetermined_title": "Dieser Knoten konnte nicht feststellen, was er kann", "verify_undetermined_body": "Der Knoten hat geantwortet, konnte aber seinen eigenen Schlüsseldatensatz nicht lesen. Das ist meist vorübergehend — versuchen Sie es in Kürze erneut.", "verify_retry": "Erneut prüfen", @@ -2874,6 +2875,7 @@ "verify_status_unreadable": "Status nicht erkannt", "verify_revoked_warning": "Dieser Build wurde widerrufen. Verwenden Sie ihn nicht.", "verify_not_found_title": "Kein Eintrag für diesen Build", + "verify_not_found_body": "Das Register hat geantwortet und enthält nichts zu diesem Hash.", "wa_approve": "Genehmigen", "wa_avg_resolution": "Durchschnittl. Auflösung: {time} Min", "wa_bus_subscribers": "Bus-Abonnenten", @@ -2942,6 +2944,7 @@ "verify_undeclared_title": "Dieser Knoten kann nicht sagen, ob er Builds verifiziert", "verify_undeclared_body": "Dieser Knoten ist älter als die Fähigkeitserklärung und kann daher keine Auskunft geben. Ein neuerer Knoten kann Builds verifizieren.", "verify_absent_title": "Dieser Knoten verifiziert keine Builds", + "verify_absent_body": "Dieser Knoten verwaltet das Register nicht und kann daher keine Builds prüfen. Ein anderer Knoten kann das.", "attestation_actions_desc": "Aktionen für diesen Datensatz", "chat_badge_message": "NACHRICHT", "chat_details": "Typ {type} · Bereich {scope} · Status {status}", diff --git a/client/iosApp/iosApp/localization/de.json b/client/iosApp/iosApp/localization/de.json index 6f85250..a86708e 100644 --- a/client/iosApp/iosApp/localization/de.json +++ b/client/iosApp/iosApp/localization/de.json @@ -2863,6 +2863,7 @@ "users_user_id": "Benutzer-ID", "users_wa_role": "WA:{role}", "verify_unavailable_title": "Prüfung nicht möglich", + "verify_unavailable_body": "Das ist nicht dasselbe wie „nicht registriert“ — das Register hat nicht geantwortet.", "verify_undetermined_title": "Dieser Knoten konnte nicht feststellen, was er kann", "verify_undetermined_body": "Der Knoten hat geantwortet, konnte aber seinen eigenen Schlüsseldatensatz nicht lesen. Das ist meist vorübergehend — versuchen Sie es in Kürze erneut.", "verify_retry": "Erneut prüfen", @@ -2874,6 +2875,7 @@ "verify_status_unreadable": "Status nicht erkannt", "verify_revoked_warning": "Dieser Build wurde widerrufen. Verwenden Sie ihn nicht.", "verify_not_found_title": "Kein Eintrag für diesen Build", + "verify_not_found_body": "Das Register hat geantwortet und enthält nichts zu diesem Hash.", "wa_approve": "Genehmigen", "wa_avg_resolution": "Durchschnittl. Auflösung: {time} Min", "wa_bus_subscribers": "Bus-Abonnenten", @@ -2942,6 +2944,7 @@ "verify_undeclared_title": "Dieser Knoten kann nicht sagen, ob er Builds verifiziert", "verify_undeclared_body": "Dieser Knoten ist älter als die Fähigkeitserklärung und kann daher keine Auskunft geben. Ein neuerer Knoten kann Builds verifizieren.", "verify_absent_title": "Dieser Knoten verifiziert keine Builds", + "verify_absent_body": "Dieser Knoten verwaltet das Register nicht und kann daher keine Builds prüfen. Ein anderer Knoten kann das.", "attestation_actions_desc": "Aktionen für diesen Datensatz", "chat_badge_message": "NACHRICHT", "chat_details": "Typ {type} · Bereich {scope} · Status {status}", diff --git a/client/shared/src/desktopMain/resources/localization/de.json b/client/shared/src/desktopMain/resources/localization/de.json index 6f85250..a86708e 100644 --- a/client/shared/src/desktopMain/resources/localization/de.json +++ b/client/shared/src/desktopMain/resources/localization/de.json @@ -2863,6 +2863,7 @@ "users_user_id": "Benutzer-ID", "users_wa_role": "WA:{role}", "verify_unavailable_title": "Prüfung nicht möglich", + "verify_unavailable_body": "Das ist nicht dasselbe wie „nicht registriert“ — das Register hat nicht geantwortet.", "verify_undetermined_title": "Dieser Knoten konnte nicht feststellen, was er kann", "verify_undetermined_body": "Der Knoten hat geantwortet, konnte aber seinen eigenen Schlüsseldatensatz nicht lesen. Das ist meist vorübergehend — versuchen Sie es in Kürze erneut.", "verify_retry": "Erneut prüfen", @@ -2874,6 +2875,7 @@ "verify_status_unreadable": "Status nicht erkannt", "verify_revoked_warning": "Dieser Build wurde widerrufen. Verwenden Sie ihn nicht.", "verify_not_found_title": "Kein Eintrag für diesen Build", + "verify_not_found_body": "Das Register hat geantwortet und enthält nichts zu diesem Hash.", "wa_approve": "Genehmigen", "wa_avg_resolution": "Durchschnittl. Auflösung: {time} Min", "wa_bus_subscribers": "Bus-Abonnenten", @@ -2942,6 +2944,7 @@ "verify_undeclared_title": "Dieser Knoten kann nicht sagen, ob er Builds verifiziert", "verify_undeclared_body": "Dieser Knoten ist älter als die Fähigkeitserklärung und kann daher keine Auskunft geben. Ein neuerer Knoten kann Builds verifizieren.", "verify_absent_title": "Dieser Knoten verifiziert keine Builds", + "verify_absent_body": "Dieser Knoten verwaltet das Register nicht und kann daher keine Builds prüfen. Ein anderer Knoten kann das.", "attestation_actions_desc": "Aktionen für diesen Datensatz", "chat_badge_message": "NACHRICHT", "chat_details": "Typ {type} · Bereich {scope} · Status {status}", From 53ca3a377570902fca2d13575a7bdf3f13b11c00 Mon Sep 17 00:00:00 2001 From: Eric Moore Date: Fri, 28 Aug 2026 20:43:23 -0500 Subject: [PATCH 16/18] fix(i18n): one name held two different things, and the lane crashed on the last language MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit unresolved[lang] = could_not line 1012 accumulator, lang -> keys fixes, unresolved = repair_until_clean(...) line 1038 REBOUND per language for lang, keys in sorted(unresolved.items()) line 1108 AttributeError The per-language result shadowed the accumulator, so after the loop `unresolved` was whatever the LAST language returned. When that was empty the final report worked by accident; when it was not, the run died with `'list' object has no attribute 'items'` — and because it died there, the accumulator's contents were never reported at all. Pre-existing, and it survived because full-set runs happened to end on a language with nothing outstanding. Scoping a run to `de my` put a failing language last and it fell straight over. The banking change is what made scoped runs worth doing, so it did not cause this — it made it reachable. The per-language binding is `unrepaired` now, and the guard above it tests the same thing its body reports; it was testing the accumulator and printing the per-language count, which would have printed a rejection line for a language that had none. Verified by AST: `unresolved` is bound once in `run`, `unrepaired` is the tuple-unpacked per-language value. Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_01EGE52kPzjGFiPzGcs63ZC1 --- localization/localize.py | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/localization/localize.py b/localization/localize.py index 3602c0b..2ecf778 100644 --- a/localization/localize.py +++ b/localization/localize.py @@ -1035,28 +1035,28 @@ def run(lane: str, patterns: Sequence[str], langs: Sequence[str], *, max_keys: i # each rung, so a rung that returns well-formed but rejected text is # escalated rather than accepted. What survives every rung is what no # model this pipeline can reach was able to render acceptably. - fixes, unresolved = repair_until_clean(lang, values, findings, en_flat, spend) + fixes, unrepaired = repair_until_clean(lang, values, findings, en_flat, spend) values.update(fixes) for k in fixes: findings[k] = [] scores[k] = 100 - for k, errs in unresolved.items(): + for k, errs in unrepaired.items(): findings[k] = errs scores[k] = mqm_score(errs) - if unresolved: + if unrepaired: # Rejected text is still rejected text. Writing it and exiting 0 # would put a semantic defect through a structural gate that cannot # see it — which is the entire reason the review lane exists. - print(f"[repair] {lang}: {len(unresolved)} key(s) rejected by every rung " - f"— {', '.join(sorted(unresolved)[:5])}" - f"{' …' if len(unresolved) > 5 else ''}") + print(f"[repair] {lang}: {len(unrepaired)} key(s) rejected by every rung " + f"— {', '.join(sorted(unrepaired)[:5])}" + f"{' …' if len(unrepaired) > 5 else ''}") rc = 1 rejected[lang] = { k: "; ".join( f"{e.get('severity')}/{e.get('category')}: {e.get('note', '')}" for e in errs if needs_repair([e]) - ) for k, errs in unresolved.items() + ) for k, errs in unrepaired.items() } report[lang] = { @@ -1086,7 +1086,7 @@ def run(lane: str, patterns: Sequence[str], langs: Sequence[str], *, max_keys: i # 1, the key stays missing, and the strict guard still blocks the merge # until it is filled. The only thing that changes is that the accepted # values survive, so the next run has one key to do instead of 588. - withheld = set(rejected.get(lang, {})) | set(unresolved) + withheld = set(rejected.get(lang, {})) | set(unrepaired) writable = {k: v for k, v in values.items() if k not in withheld} if writable: insert(lang, writable, en, overwrite=(lane != "translate")) From 55b5c91fc2db7c79442d9d94d3789a9d981bdc3b Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Sat, 29 Aug 2026 01:46:59 +0000 Subject: [PATCH 17/18] i18n: translate lane (translate -> evaluate -> repair) Machine translation, independently reviewed against MQM, and repaired where the review found a critical, major or terminology error. Every value here is status=draft / review_status=needs_native_review: this pipeline guarantees terminology, structure and meaning, and does not guarantee native fluency. Validated by check_localization_sync.py --strict in this same run. The MQM findings are attached to the run as i18n-report.json. Review like any other diff. --- client/VENDORING.md | 2 +- client/androidApp/src/main/assets/localization/my.json | 1 + client/desktopApp/src/main/resources/localization/my.json | 1 + client/iosApp/iosApp/localization/my.json | 1 + client/shared/src/desktopMain/resources/localization/my.json | 1 + 5 files changed, 5 insertions(+), 1 deletion(-) diff --git a/client/VENDORING.md b/client/VENDORING.md index 4090bbd..4f1f59c 100644 --- a/client/VENDORING.md +++ b/client/VENDORING.md @@ -40,7 +40,7 @@ source is the pair a bisect wants: The tree's current recorded state — sha256-of-sha256s over every git-tracked file under `client/` except this one: -**state digest:** `60fc8c1265ebc6c438aac0da4db06f0b6ce4f3e3f095c6dec353aeb006b7564c` +**state digest:** `c6c17a6c3a83b6d110a3b94fc6ac3aaf74ceb0c567000ad251048d1c82cf79a4` `packaging/check_vendoring.py` asserts it on every push, and refuses any tracked file matching a §2 never-vendor class. **Any commit that touches diff --git a/client/androidApp/src/main/assets/localization/my.json b/client/androidApp/src/main/assets/localization/my.json index f956c52..d2f3419 100644 --- a/client/androidApp/src/main/assets/localization/my.json +++ b/client/androidApp/src/main/assets/localization/my.json @@ -2944,6 +2944,7 @@ "verify_status_registered": "မှတ်ပုံတင်ထားသည်", "verify_status_deprecated": "ထပ်မံ အသုံးပြုရန် အကြံမပြုတော့ပါ", "verify_status_revoked": "ရုပ်သိမ်းထားသည်", + "verify_status_unreadable": "အခြေအနေကို အသိအမှတ်မပြုနိုင်ပါ", "attestation_actions_desc": "ဤမှတ်တမ်းအတွက် လုပ်ဆောင်ချက်များ", "chat_badge_message": "မက်ဆေ့ချ်", "chat_details": "အမျိုးအစား {type} · scope {scope} · အခြေအနေ {status}", diff --git a/client/desktopApp/src/main/resources/localization/my.json b/client/desktopApp/src/main/resources/localization/my.json index f956c52..d2f3419 100644 --- a/client/desktopApp/src/main/resources/localization/my.json +++ b/client/desktopApp/src/main/resources/localization/my.json @@ -2944,6 +2944,7 @@ "verify_status_registered": "မှတ်ပုံတင်ထားသည်", "verify_status_deprecated": "ထပ်မံ အသုံးပြုရန် အကြံမပြုတော့ပါ", "verify_status_revoked": "ရုပ်သိမ်းထားသည်", + "verify_status_unreadable": "အခြေအနေကို အသိအမှတ်မပြုနိုင်ပါ", "attestation_actions_desc": "ဤမှတ်တမ်းအတွက် လုပ်ဆောင်ချက်များ", "chat_badge_message": "မက်ဆေ့ချ်", "chat_details": "အမျိုးအစား {type} · scope {scope} · အခြေအနေ {status}", diff --git a/client/iosApp/iosApp/localization/my.json b/client/iosApp/iosApp/localization/my.json index f956c52..d2f3419 100644 --- a/client/iosApp/iosApp/localization/my.json +++ b/client/iosApp/iosApp/localization/my.json @@ -2944,6 +2944,7 @@ "verify_status_registered": "မှတ်ပုံတင်ထားသည်", "verify_status_deprecated": "ထပ်မံ အသုံးပြုရန် အကြံမပြုတော့ပါ", "verify_status_revoked": "ရုပ်သိမ်းထားသည်", + "verify_status_unreadable": "အခြေအနေကို အသိအမှတ်မပြုနိုင်ပါ", "attestation_actions_desc": "ဤမှတ်တမ်းအတွက် လုပ်ဆောင်ချက်များ", "chat_badge_message": "မက်ဆေ့ချ်", "chat_details": "အမျိုးအစား {type} · scope {scope} · အခြေအနေ {status}", diff --git a/client/shared/src/desktopMain/resources/localization/my.json b/client/shared/src/desktopMain/resources/localization/my.json index f956c52..d2f3419 100644 --- a/client/shared/src/desktopMain/resources/localization/my.json +++ b/client/shared/src/desktopMain/resources/localization/my.json @@ -2944,6 +2944,7 @@ "verify_status_registered": "မှတ်ပုံတင်ထားသည်", "verify_status_deprecated": "ထပ်မံ အသုံးပြုရန် အကြံမပြုတော့ပါ", "verify_status_revoked": "ရုပ်သိမ်းထားသည်", + "verify_status_unreadable": "အခြေအနေကို အသိအမှတ်မပြုနိုင်ပါ", "attestation_actions_desc": "ဤမှတ်တမ်းအတွက် လုပ်ဆောင်ချက်များ", "chat_badge_message": "မက်ဆေ့ချ်", "chat_details": "အမျိုးအစား {type} · scope {scope} · အခြေအနေ {status}", From 9e1885398baae8135d8517b4956969727c975aa0 Mon Sep 17 00:00:00 2001 From: Eric Moore Date: Fri, 28 Aug 2026 20:51:43 -0500 Subject: [PATCH 18/18] fix(i18n): the lane's push has to survive the branch moving under it MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The last run did all its work and then failed: ! [rejected] feat/portal-capability-gate (fetch first) error: failed to push some refs A lane takes minutes, and a human can land a commit on the same branch while it runs — which is precisely what happened: I pushed a fix mid-run, the runner finished, committed the last translation, and could not push it. Everything before that step succeeded, so the run reported failure for a race rather than a defect, and the work was only safe because a previous run had already landed it. Rebase and retry, three times. A conflict is left to fail loudly: the bundles are regenerated deterministically from en.json, so a real conflict means someone edited the same keys and resolving it blind would silently pick a winner. Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_01EGE52kPzjGFiPzGcs63ZC1 --- .github/workflows/i18n-lane.yml | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/.github/workflows/i18n-lane.yml b/.github/workflows/i18n-lane.yml index 95fb3b5..2f26876 100644 --- a/.github/workflows/i18n-lane.yml +++ b/.github/workflows/i18n-lane.yml @@ -165,6 +165,8 @@ jobs: python3 packaging/check_vendoring.py - name: Commit + env: + BRANCH: ${{ github.ref_name }} # ALWAYS, even when the lane exited 1. The lane writes only ACCEPTED # values now, so committing on failure banks the good work and leaves # the rejected keys missing — which the strict guard then blocks on, @@ -196,5 +198,21 @@ jobs: The MQM findings are attached to the run as i18n-report.json. Review like any other diff. MSG - git push + # REBASE BEFORE PUSHING. The lane takes minutes and a human can + # land a commit on the same branch while it runs — which is exactly + # what happened: the runner committed the last translation, the push + # was rejected "fetch first", and the step failed AFTER doing all the + # work. Retry a few times because the race can recur. + for attempt in 1 2 3; do + if git push; then + exit 0 + fi + echo "push rejected (attempt $attempt) — rebasing onto the branch and retrying" + git pull --rebase --autostash origin "$BRANCH" || true + # The bundles are regenerated deterministically from en.json, so a + # rebase conflict here means someone edited the same keys; let it + # fail loudly rather than resolving it blind. + done + echo "::error::could not push the translations after 3 attempts — the branch moved under the lane each time" + exit 1 fi