fix(exec-approval): stop misattributing Allow Always unavailability to policy (#97740)

* fix(exec-approval): stop misattributing Allow Always unavailability to policy

Allow Always is dropped both when policy ask=always AND when a command is
non-persistable (e.g. shell redirect `2>&1` -> one-shot), but the prompt always
claimed 'effective approval policy requires approval every time'. That's
misleading for the non-persistable case (#97069). Reword to reason-neutral
'Allow Always is unavailable for this command.' across all approval surfaces,
update en + 20 locale bundles, refresh i18n meta, and the matching tests.

Closes #97069

* fix(exec-approval): stop misattributing Allow Always unavailability to policy

* test(ui): await exec approval render updates

* chore(ui): sync approval i18n metadata

---------

Co-authored-by: saju01 <saju01@users.noreply.github.com>
Co-authored-by: openclaw-clownfish[bot] <280122609+openclaw-clownfish[bot]@users.noreply.github.com>
Co-authored-by: Vincent Koc <25068+vincentkoc@users.noreply.github.com>
This commit is contained in:
saju01
2026-07-11 15:39:51 +05:30
committed by GitHub
parent c702719eda
commit cbc84767bd
50 changed files with 203 additions and 100 deletions
+1 -3
View File
@@ -403,9 +403,7 @@ export function buildApprovalPendingMessage(params: {
);
lines.push(`Reply with: /approve ${params.approvalSlug} ${decisionText}`);
if (!allowedDecisions.includes("allow-always")) {
lines.push(
"The effective approval policy requires approval every time, so Allow Always is unavailable.",
);
lines.push("Allow Always is unavailable for this command.");
}
lines.push("If the short code is ambiguous, use the full id in /approve.");
return lines.join("\n");
+1 -2
View File
@@ -480,8 +480,7 @@ export function createExecApprovalHandlers(
return allowedDecisions.includes(decision)
? null
: {
message:
"allow-always is unavailable because the effective policy requires approval every time",
message: "allow-always is unavailable for this command",
details: APPROVAL_ALLOW_ALWAYS_UNAVAILABLE_DETAILS,
};
},
@@ -3716,8 +3716,7 @@ describe("exec approval handlers", () => {
expect(mockCallArg(resolveRespond)).toBe(false);
expect(mockCallArg(resolveRespond, 0, 1)).toBeUndefined();
expectRecordFields(mockCallArg(resolveRespond, 0, 2), {
message:
"allow-always is unavailable because the effective policy requires approval every time",
message: "allow-always is unavailable for this command",
});
const denyRespond = vi.fn();
@@ -3759,8 +3758,7 @@ describe("exec approval handlers", () => {
expect(mockCallArg(resolveRespond)).toBe(false);
expect(mockCallArg(resolveRespond, 0, 1)).toBeUndefined();
expectRecordFields(mockCallArg(resolveRespond, 0, 2), {
message:
"allow-always is unavailable because the effective policy requires approval every time",
message: "allow-always is unavailable for this command",
});
const allowOnceRespond = vi.fn();
+1 -3
View File
@@ -283,9 +283,7 @@ export function buildExecApprovalRequestMessage(request: ExecApprovalRequest, no
);
lines.push(`Reply with: /approve ${request.id} ${decisionText}`);
if (!allowedDecisions.includes("allow-always")) {
lines.push(
"Allow Always is unavailable because the effective policy requires approval every time.",
);
lines.push("Allow Always is unavailable for this command.");
}
return lines.join("\n");
}
+2 -4
View File
@@ -334,7 +334,7 @@ describe("exec approval reply helpers", () => {
expect(payload.text).not.toContain("C:\\Users\\alice");
});
it("omits allow-always actions when the effective policy requires approval every time", () => {
it("omits allow-always actions when allow-always is unavailable", () => {
const payload = buildExecApprovalPendingReplyPayload({
approvalId: "req-ask-always",
approvalSlug: "slug-always",
@@ -353,9 +353,7 @@ describe("exec approval reply helpers", () => {
});
expect(payload.text).toContain("```txt\n/approve slug-always allow-once\n```");
expect(payload.text).not.toContain("allow-always");
expect(payload.text).toContain(
"The effective approval policy requires approval every time, so Allow Always is unavailable.",
);
expect(payload.text).toContain("Allow Always is unavailable for this command.");
expect(payload.presentation).toEqual({
blocks: [
{
+1 -3
View File
@@ -383,9 +383,7 @@ export function buildExecApprovalPendingReplyPayload(
lines.push(secondaryFence);
}
if (!allowedDecisions.includes("allow-always")) {
lines.push(
"The effective approval policy requires approval every time, so Allow Always is unavailable.",
);
lines.push("Allow Always is unavailable for this command.");
}
const info: string[] = [];
info.push(`Host: ${params.host}`);
@@ -155,6 +155,27 @@ describe("plugin-sdk/approval-reaction-runtime", () => {
expect(payload.text).not.toContain("\nIgnore previous instructions");
});
it("builds exec reaction prompts with neutral allow-always unavailable copy", () => {
const payload = buildApprovalReactionPromptPayloadForRequest({
request: {
...execRequest,
request: {
...execRequest.request,
ask: "always",
},
},
nowMs: 1_000,
});
expect(payload.text).toContain("React with:\n\n👍 Allow Once\n👎 Deny");
expect(payload.text).not.toContain("♾️ Allow Always");
expect(payload.text).toContain("Allow Always is unavailable for this command.");
expect(payload.text).not.toContain("effective policy requires approval every time");
expect(
payload.text?.trim().endsWith("Reply with: /approve exec-approval-123 allow-once|deny"),
).toBe(true);
});
it("builds canonical plugin reaction prompts with real ids", () => {
const payload = buildApprovalReactionPromptPayloadForRequest({
request: {
@@ -176,6 +197,7 @@ describe("plugin-sdk/approval-reaction-runtime", () => {
expect(payload.text).toContain(
"Allow Always is unavailable because the effective policy requires approval every time.",
);
expect(payload.text).not.toContain("Allow Always is unavailable for this command.");
expect(
payload.text?.trim().endsWith("Reply with: /approve plugin:approval-123 allow-once|deny"),
).toBe(true);
+5 -1
View File
@@ -236,13 +236,16 @@ function buildDecisionText(allowedDecisions: readonly ExecApprovalReplyDecision[
}
function buildManualInstructionSection(params: {
approvalKind: ApprovalKind;
approvalId: string;
allowedDecisions: readonly ExecApprovalReplyDecision[];
}): string[] {
const lines: string[] = [];
if (!params.allowedDecisions.includes("allow-always")) {
lines.push(
"Allow Always is unavailable because the effective policy requires approval every time.",
params.approvalKind === "exec"
? "Allow Always is unavailable for this command."
: "Allow Always is unavailable because the effective policy requires approval every time.",
);
}
if (params.allowedDecisions.length > 0) {
@@ -335,6 +338,7 @@ function buildApprovalReactionPromptText(params: {
sections.push(commandInstructions.join("\n"));
}
const manualInstructions = buildManualInstructionSection({
approvalKind: view.approvalKind,
approvalId: view.approvalId,
allowedDecisions,
});
+107
View File
@@ -0,0 +1,107 @@
/* @vitest-environment jsdom */
import { html, nothing, render, type LitElement } from "lit";
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
import type { ExecApprovalRequest } from "../app/exec-approval.ts";
import { i18n } from "../i18n/index.ts";
import { getRenderedModalDialog, installDialogPolyfill } from "../test-helpers/modal-dialog.ts";
import "./exec-approval.ts";
let container: HTMLDivElement;
let restoreDialogPolyfill: () => void;
function createExecRequest(overrides: Partial<ExecApprovalRequest> = {}): ExecApprovalRequest {
return {
id: "approval-1",
kind: "exec",
request: {
command: "echo hello",
ask: "on-request",
},
createdAtMs: Date.now() - 1_000,
expiresAtMs: Date.now() + 60_000,
...overrides,
};
}
async function renderApproval(request: ExecApprovalRequest) {
render(
html`<openclaw-exec-approval
.props=${{
queue: [request],
busy: false,
error: null,
onDecision: vi.fn(),
}}
></openclaw-exec-approval>`,
container,
);
const approval = container.querySelector<LitElement>("openclaw-exec-approval");
if (!approval) {
throw new Error("Expected exec approval");
}
await approval.updateComplete;
}
describe("openclaw-exec-approval", () => {
beforeEach(async () => {
restoreDialogPolyfill = installDialogPolyfill();
await i18n.setLocale("en");
container = document.createElement("div");
document.body.append(container);
});
afterEach(async () => {
render(nothing, container);
container.remove();
await i18n.setLocale("en");
restoreDialogPolyfill();
vi.restoreAllMocks();
});
it("uses neutral unavailable copy for exec allow-always decisions", async () => {
await renderApproval(
createExecRequest({
request: {
command: "echo hello",
ask: "always",
allowedDecisions: ["allow-once", "deny"],
},
}),
);
await getRenderedModalDialog(container);
expect(
Array.from(container.querySelectorAll(".exec-approval-actions button")).map((button) =>
button.textContent?.trim(),
),
).toEqual(["Allow once", "Deny"]);
expect(container.querySelector(".exec-approval-warning")?.textContent?.trim()).toBe(
"Allow Always is unavailable for this command.",
);
});
it("does not show exec unavailable copy for restricted plugin approvals", async () => {
await renderApproval(
createExecRequest({
id: "plugin-approval-1",
kind: "plugin",
request: {
command: "Plugin approval",
allowedDecisions: ["allow-once", "deny"],
},
pluginTitle: "Plugin approval",
}),
);
await getRenderedModalDialog(container);
expect(
Array.from(container.querySelectorAll(".exec-approval-actions button")).map((button) =>
button.textContent?.trim(),
),
).toEqual(["Allow once", "Deny"]);
expect(container.querySelector(".exec-approval-warning")).toBeNull();
});
});
+2 -2
View File
@@ -1,10 +1,10 @@
{
"fallbackKeys": [],
"generatedAt": "2026-07-11T09:23:33.404Z",
"generatedAt": "2026-07-11T09:56:49.437Z",
"locale": "ar",
"model": "gpt-5.5",
"provider": "openai",
"sourceHash": "9146812dfe02813bf7fc8eb1e6aa5d92db8285d2979abbdb2aa3ad7df99cbfa6",
"sourceHash": "fba37d0370a89c15e35e7cb0cc8fa13860cd265f7fd54d798a9e625cdb2e932b",
"totalKeys": 2107,
"translatedKeys": 2107,
"workflow": 1
+2 -2
View File
@@ -1,10 +1,10 @@
{
"fallbackKeys": [],
"generatedAt": "2026-07-11T09:23:32.165Z",
"generatedAt": "2026-07-11T09:56:48.554Z",
"locale": "de",
"model": "gpt-5.5",
"provider": "openai",
"sourceHash": "9146812dfe02813bf7fc8eb1e6aa5d92db8285d2979abbdb2aa3ad7df99cbfa6",
"sourceHash": "fba37d0370a89c15e35e7cb0cc8fa13860cd265f7fd54d798a9e625cdb2e932b",
"totalKeys": 2107,
"translatedKeys": 2107,
"workflow": 1
+2 -2
View File
@@ -1,10 +1,10 @@
{
"fallbackKeys": [],
"generatedAt": "2026-07-11T09:23:32.362Z",
"generatedAt": "2026-07-11T09:56:48.697Z",
"locale": "es",
"model": "gpt-5.5",
"provider": "openai",
"sourceHash": "9146812dfe02813bf7fc8eb1e6aa5d92db8285d2979abbdb2aa3ad7df99cbfa6",
"sourceHash": "fba37d0370a89c15e35e7cb0cc8fa13860cd265f7fd54d798a9e625cdb2e932b",
"totalKeys": 2107,
"translatedKeys": 2107,
"workflow": 1
+2 -2
View File
@@ -1,10 +1,10 @@
{
"fallbackKeys": [],
"generatedAt": "2026-07-11T09:23:35.201Z",
"generatedAt": "2026-07-11T09:56:51.134Z",
"locale": "fa",
"model": "gpt-5.5",
"provider": "openai",
"sourceHash": "9146812dfe02813bf7fc8eb1e6aa5d92db8285d2979abbdb2aa3ad7df99cbfa6",
"sourceHash": "fba37d0370a89c15e35e7cb0cc8fa13860cd265f7fd54d798a9e625cdb2e932b",
"totalKeys": 2107,
"translatedKeys": 2107,
"workflow": 1
+2 -2
View File
@@ -1,10 +1,10 @@
{
"fallbackKeys": [],
"generatedAt": "2026-07-11T09:23:32.981Z",
"generatedAt": "2026-07-11T09:56:49.141Z",
"locale": "fr",
"model": "gpt-5.5",
"provider": "openai",
"sourceHash": "9146812dfe02813bf7fc8eb1e6aa5d92db8285d2979abbdb2aa3ad7df99cbfa6",
"sourceHash": "fba37d0370a89c15e35e7cb0cc8fa13860cd265f7fd54d798a9e625cdb2e932b",
"totalKeys": 2107,
"translatedKeys": 2107,
"workflow": 1
+2 -2
View File
@@ -1,10 +1,10 @@
{
"fallbackKeys": [],
"generatedAt": "2026-07-11T09:23:33.193Z",
"generatedAt": "2026-07-11T09:56:49.292Z",
"locale": "hi",
"model": "gpt-5.5",
"provider": "openai",
"sourceHash": "9146812dfe02813bf7fc8eb1e6aa5d92db8285d2979abbdb2aa3ad7df99cbfa6",
"sourceHash": "fba37d0370a89c15e35e7cb0cc8fa13860cd265f7fd54d798a9e625cdb2e932b",
"totalKeys": 2107,
"translatedKeys": 2107,
"workflow": 1
+2 -2
View File
@@ -1,10 +1,10 @@
{
"fallbackKeys": [],
"generatedAt": "2026-07-11T09:23:34.204Z",
"generatedAt": "2026-07-11T09:56:50.018Z",
"locale": "id",
"model": "gpt-5.5",
"provider": "openai",
"sourceHash": "9146812dfe02813bf7fc8eb1e6aa5d92db8285d2979abbdb2aa3ad7df99cbfa6",
"sourceHash": "fba37d0370a89c15e35e7cb0cc8fa13860cd265f7fd54d798a9e625cdb2e932b",
"totalKeys": 2107,
"translatedKeys": 2107,
"workflow": 1
+2 -2
View File
@@ -1,10 +1,10 @@
{
"fallbackKeys": [],
"generatedAt": "2026-07-11T09:23:33.611Z",
"generatedAt": "2026-07-11T09:56:49.584Z",
"locale": "it",
"model": "gpt-5.5",
"provider": "openai",
"sourceHash": "9146812dfe02813bf7fc8eb1e6aa5d92db8285d2979abbdb2aa3ad7df99cbfa6",
"sourceHash": "fba37d0370a89c15e35e7cb0cc8fa13860cd265f7fd54d798a9e625cdb2e932b",
"totalKeys": 2107,
"translatedKeys": 2107,
"workflow": 1
+2 -2
View File
@@ -1,10 +1,10 @@
{
"fallbackKeys": [],
"generatedAt": "2026-07-11T09:23:32.564Z",
"generatedAt": "2026-07-11T09:56:48.848Z",
"locale": "ja-JP",
"model": "gpt-5.5",
"provider": "openai",
"sourceHash": "9146812dfe02813bf7fc8eb1e6aa5d92db8285d2979abbdb2aa3ad7df99cbfa6",
"sourceHash": "fba37d0370a89c15e35e7cb0cc8fa13860cd265f7fd54d798a9e625cdb2e932b",
"totalKeys": 2107,
"translatedKeys": 2107,
"workflow": 1
+2 -2
View File
@@ -1,10 +1,10 @@
{
"fallbackKeys": [],
"generatedAt": "2026-07-11T09:23:32.774Z",
"generatedAt": "2026-07-11T09:56:48.993Z",
"locale": "ko",
"model": "gpt-5.5",
"provider": "openai",
"sourceHash": "9146812dfe02813bf7fc8eb1e6aa5d92db8285d2979abbdb2aa3ad7df99cbfa6",
"sourceHash": "fba37d0370a89c15e35e7cb0cc8fa13860cd265f7fd54d798a9e625cdb2e932b",
"totalKeys": 2107,
"translatedKeys": 2107,
"workflow": 1
+2 -2
View File
@@ -1,10 +1,10 @@
{
"fallbackKeys": [],
"generatedAt": "2026-07-11T09:23:34.993Z",
"generatedAt": "2026-07-11T09:56:50.985Z",
"locale": "nl",
"model": "gpt-5.5",
"provider": "openai",
"sourceHash": "9146812dfe02813bf7fc8eb1e6aa5d92db8285d2979abbdb2aa3ad7df99cbfa6",
"sourceHash": "fba37d0370a89c15e35e7cb0cc8fa13860cd265f7fd54d798a9e625cdb2e932b",
"totalKeys": 2107,
"translatedKeys": 2107,
"workflow": 1
+2 -2
View File
@@ -1,10 +1,10 @@
{
"fallbackKeys": [],
"generatedAt": "2026-07-11T09:23:34.419Z",
"generatedAt": "2026-07-11T09:56:50.155Z",
"locale": "pl",
"model": "gpt-5.5",
"provider": "openai",
"sourceHash": "9146812dfe02813bf7fc8eb1e6aa5d92db8285d2979abbdb2aa3ad7df99cbfa6",
"sourceHash": "fba37d0370a89c15e35e7cb0cc8fa13860cd265f7fd54d798a9e625cdb2e932b",
"totalKeys": 2107,
"translatedKeys": 2107,
"workflow": 1
+2 -2
View File
@@ -1,10 +1,10 @@
{
"fallbackKeys": [],
"generatedAt": "2026-07-11T09:23:31.982Z",
"generatedAt": "2026-07-11T09:56:48.414Z",
"locale": "pt-BR",
"model": "gpt-5.5",
"provider": "openai",
"sourceHash": "9146812dfe02813bf7fc8eb1e6aa5d92db8285d2979abbdb2aa3ad7df99cbfa6",
"sourceHash": "fba37d0370a89c15e35e7cb0cc8fa13860cd265f7fd54d798a9e625cdb2e932b",
"totalKeys": 2107,
"translatedKeys": 2107,
"workflow": 1
+2 -2
View File
@@ -1,10 +1,10 @@
{
"fallbackKeys": [],
"generatedAt": "2026-07-11T09:23:35.401Z",
"generatedAt": "2026-07-11T09:56:51.279Z",
"locale": "ru",
"model": "gpt-5.5",
"provider": "openai",
"sourceHash": "9146812dfe02813bf7fc8eb1e6aa5d92db8285d2979abbdb2aa3ad7df99cbfa6",
"sourceHash": "fba37d0370a89c15e35e7cb0cc8fa13860cd265f7fd54d798a9e625cdb2e932b",
"totalKeys": 2107,
"translatedKeys": 2107,
"workflow": 1
+2 -2
View File
@@ -1,10 +1,10 @@
{
"fallbackKeys": [],
"generatedAt": "2026-07-11T09:23:34.610Z",
"generatedAt": "2026-07-11T09:56:50.298Z",
"locale": "th",
"model": "gpt-5.5",
"provider": "openai",
"sourceHash": "9146812dfe02813bf7fc8eb1e6aa5d92db8285d2979abbdb2aa3ad7df99cbfa6",
"sourceHash": "fba37d0370a89c15e35e7cb0cc8fa13860cd265f7fd54d798a9e625cdb2e932b",
"totalKeys": 2107,
"translatedKeys": 2107,
"workflow": 1
+2 -2
View File
@@ -1,10 +1,10 @@
{
"fallbackKeys": [],
"generatedAt": "2026-07-11T09:23:33.815Z",
"generatedAt": "2026-07-11T09:56:49.733Z",
"locale": "tr",
"model": "gpt-5.5",
"provider": "openai",
"sourceHash": "9146812dfe02813bf7fc8eb1e6aa5d92db8285d2979abbdb2aa3ad7df99cbfa6",
"sourceHash": "fba37d0370a89c15e35e7cb0cc8fa13860cd265f7fd54d798a9e625cdb2e932b",
"totalKeys": 2107,
"translatedKeys": 2107,
"workflow": 1
+2 -2
View File
@@ -1,10 +1,10 @@
{
"fallbackKeys": [],
"generatedAt": "2026-07-11T09:23:34.005Z",
"generatedAt": "2026-07-11T09:56:49.871Z",
"locale": "uk",
"model": "gpt-5.5",
"provider": "openai",
"sourceHash": "9146812dfe02813bf7fc8eb1e6aa5d92db8285d2979abbdb2aa3ad7df99cbfa6",
"sourceHash": "fba37d0370a89c15e35e7cb0cc8fa13860cd265f7fd54d798a9e625cdb2e932b",
"totalKeys": 2107,
"translatedKeys": 2107,
"workflow": 1
+2 -2
View File
@@ -1,10 +1,10 @@
{
"fallbackKeys": [],
"generatedAt": "2026-07-11T09:23:34.811Z",
"generatedAt": "2026-07-11T09:56:50.827Z",
"locale": "vi",
"model": "gpt-5.5",
"provider": "openai",
"sourceHash": "9146812dfe02813bf7fc8eb1e6aa5d92db8285d2979abbdb2aa3ad7df99cbfa6",
"sourceHash": "fba37d0370a89c15e35e7cb0cc8fa13860cd265f7fd54d798a9e625cdb2e932b",
"totalKeys": 2107,
"translatedKeys": 2107,
"workflow": 1
+2 -2
View File
@@ -1,10 +1,10 @@
{
"fallbackKeys": [],
"generatedAt": "2026-07-11T09:23:31.467Z",
"generatedAt": "2026-07-11T09:56:47.987Z",
"locale": "zh-CN",
"model": "gpt-5.5",
"provider": "openai",
"sourceHash": "9146812dfe02813bf7fc8eb1e6aa5d92db8285d2979abbdb2aa3ad7df99cbfa6",
"sourceHash": "fba37d0370a89c15e35e7cb0cc8fa13860cd265f7fd54d798a9e625cdb2e932b",
"totalKeys": 2107,
"translatedKeys": 2107,
"workflow": 1
+2 -2
View File
@@ -1,10 +1,10 @@
{
"fallbackKeys": [],
"generatedAt": "2026-07-11T09:23:31.818Z",
"generatedAt": "2026-07-11T09:56:48.269Z",
"locale": "zh-TW",
"model": "gpt-5.5",
"provider": "openai",
"sourceHash": "9146812dfe02813bf7fc8eb1e6aa5d92db8285d2979abbdb2aa3ad7df99cbfa6",
"sourceHash": "fba37d0370a89c15e35e7cb0cc8fa13860cd265f7fd54d798a9e625cdb2e932b",
"totalKeys": 2107,
"translatedKeys": 2107,
"workflow": 1
+1 -2
View File
@@ -501,8 +501,7 @@ export const ar: TranslationMap = {
pending: "{count} قيد الانتظار",
allowOnce: "السماح مرة واحدة",
alwaysAllow: "السماح دائمًا",
allowAlwaysUnavailable:
"تتطلب سياسة الموافقة السارية الحصول على الموافقة في كل مرة، لذا فإن خيار السماح دائمًا غير متاح.",
allowAlwaysUnavailable: "خيار السماح دائمًا غير متاح لهذا الأمر.",
deny: "رفض",
labels: {
host: "المضيف",
+1 -2
View File
@@ -506,8 +506,7 @@ export const de: TranslationMap = {
pending: "{count} pending",
allowOnce: "Allow once",
alwaysAllow: "Always allow",
allowAlwaysUnavailable:
"Die wirksame Genehmigungsrichtlinie erfordert jedes Mal eine Genehmigung, daher ist Immer erlauben nicht verfügbar.",
allowAlwaysUnavailable: "Allow Always ist für diesen Befehl nicht verfügbar.",
deny: "Deny",
labels: {
host: "Host",
+1 -2
View File
@@ -500,8 +500,7 @@ export const en: TranslationMap = {
pending: "{count} pending",
allowOnce: "Allow once",
alwaysAllow: "Always allow",
allowAlwaysUnavailable:
"The effective approval policy requires approval every time, so Allow Always is unavailable.",
allowAlwaysUnavailable: "Allow Always is unavailable for this command.",
deny: "Deny",
labels: {
host: "Host",
+1 -2
View File
@@ -503,8 +503,7 @@ export const es: TranslationMap = {
pending: "{count} pending",
allowOnce: "Allow once",
alwaysAllow: "Always allow",
allowAlwaysUnavailable:
"La política de aprobación efectiva requiere aprobación cada vez, por lo que Permitir siempre no está disponible.",
allowAlwaysUnavailable: "Permitir siempre no está disponible para este comando.",
deny: "Deny",
labels: {
host: "Host",
+1 -2
View File
@@ -503,8 +503,7 @@ export const fa: TranslationMap = {
pending: "{count} در انتظار",
allowOnce: "یک‌بار مجاز کن",
alwaysAllow: "همیشه مجاز کن",
allowAlwaysUnavailable:
"سیاست تأیید مؤثر هر بار به تأیید نیاز دارد، بنابراین «همیشه مجاز باشد» در دسترس نیست.",
allowAlwaysUnavailable: "«همیشه مجاز باشد» برای این فرمان در دسترس نیست.",
deny: "رد کردن",
labels: {
host: "میزبان",
+1 -2
View File
@@ -509,8 +509,7 @@ export const fr: TranslationMap = {
pending: "{count} pending",
allowOnce: "Allow once",
alwaysAllow: "Always allow",
allowAlwaysUnavailable:
"La politique dapprobation effective exige une approbation à chaque fois, donc Autoriser toujours nest pas disponible.",
allowAlwaysUnavailable: "Autoriser toujours nest pas disponible pour cette commande.",
deny: "Deny",
labels: {
host: "Host",
+1 -2
View File
@@ -502,8 +502,7 @@ export const hi: TranslationMap = {
pending: "{count} लंबित",
allowOnce: "एक बार अनुमति दें",
alwaysAllow: "हमेशा अनुमति दें",
allowAlwaysUnavailable:
"प्रभावी अनुमोदन नीति हर बार अनुमोदन की आवश्यकता रखती है, इसलिए हमेशा अनुमति दें उपलब्ध नहीं है।",
allowAlwaysUnavailable: "इस कमांड के लिए हमेशा अनुमति दें उपलब्ध नहीं है।",
deny: "अस्वीकार करें",
labels: {
host: "होस्ट",
+1 -2
View File
@@ -503,8 +503,7 @@ export const id: TranslationMap = {
pending: "{count} pending",
allowOnce: "Allow once",
alwaysAllow: "Always allow",
allowAlwaysUnavailable:
"Kebijakan persetujuan yang berlaku mengharuskan persetujuan setiap kali, sehingga Izinkan Selalu tidak tersedia.",
allowAlwaysUnavailable: "Izinkan Selalu tidak tersedia untuk perintah ini.",
deny: "Deny",
labels: {
host: "Host",
+1 -2
View File
@@ -508,8 +508,7 @@ export const it: TranslationMap = {
pending: "{count} in sospeso",
allowOnce: "Consenti una volta",
alwaysAllow: "Consenti sempre",
allowAlwaysUnavailable:
"Il criterio di approvazione effettivo richiede lapprovazione ogni volta, quindi Consenti sempre non è disponibile.",
allowAlwaysUnavailable: "Consenti sempre non è disponibile per questo comando.",
deny: "Nega",
labels: {
host: "Host",
+1 -2
View File
@@ -508,8 +508,7 @@ export const ja_JP: TranslationMap = {
pending: "{count} pending",
allowOnce: "Allow once",
alwaysAllow: "Always allow",
allowAlwaysUnavailable:
"有効な承認ポリシーでは毎回承認が必要なため、Allow Always は利用できません。",
allowAlwaysUnavailable: "このコマンドでは Allow Always は利用できません。",
deny: "Deny",
labels: {
host: "Host",
+1 -2
View File
@@ -501,8 +501,7 @@ export const ko: TranslationMap = {
pending: "{count} pending",
allowOnce: "Allow once",
alwaysAllow: "Always allow",
allowAlwaysUnavailable:
"유효한 승인 정책이 매번 승인을 요구하므로, 항상 허용을 사용할 수 없습니다.",
allowAlwaysUnavailable: "이 명령에는 항상 허용을 사용할 수 없습니다.",
deny: "Deny",
labels: {
host: "Host",
+1 -2
View File
@@ -506,8 +506,7 @@ export const nl: TranslationMap = {
pending: "{count} in behandeling",
allowOnce: "Eenmalig toestaan",
alwaysAllow: "Altijd toestaan",
allowAlwaysUnavailable:
"Het effectieve goedkeuringsbeleid vereist elke keer goedkeuring, dus Altijd toestaan is niet beschikbaar.",
allowAlwaysUnavailable: "Altijd toestaan is niet beschikbaar voor deze opdracht.",
deny: "Weigeren",
labels: {
host: "Host",
+1 -2
View File
@@ -504,8 +504,7 @@ export const pl: TranslationMap = {
pending: "{count} pending",
allowOnce: "Allow once",
alwaysAllow: "Always allow",
allowAlwaysUnavailable:
"Obowiązująca zasada zatwierdzania wymaga zatwierdzenia za każdym razem, więc opcja Zawsze zezwalaj jest niedostępna.",
allowAlwaysUnavailable: "Opcja Zawsze zezwalaj jest niedostępna dla tego polecenia.",
deny: "Deny",
labels: {
host: "Host",
+1 -2
View File
@@ -502,8 +502,7 @@ export const pt_BR: TranslationMap = {
pending: "{count} pending",
allowOnce: "Allow once",
alwaysAllow: "Always allow",
allowAlwaysUnavailable:
"A política de aprovação efetiva exige aprovação todas as vezes, portanto Permitir sempre não está disponível.",
allowAlwaysUnavailable: "Permitir sempre não está disponível para este comando.",
deny: "Deny",
labels: {
host: "Host",
+1 -2
View File
@@ -507,8 +507,7 @@ export const ru: TranslationMap = {
pending: "Ожидает: {count}",
allowOnce: "Разрешить один раз",
alwaysAllow: "Всегда разрешать",
allowAlwaysUnavailable:
"Действующая политика подтверждений требует подтверждения каждый раз, поэтому «Всегда разрешать» недоступно.",
allowAlwaysUnavailable: "«Всегда разрешать» недоступно для этой команды.",
deny: "Запретить",
labels: {
host: "Хост",
+1 -2
View File
@@ -500,8 +500,7 @@ export const th: TranslationMap = {
pending: "{count} pending",
allowOnce: "Allow once",
alwaysAllow: "Always allow",
allowAlwaysUnavailable:
"นโยบายการอนุมัติที่มีผลบังคับใช้กำหนดให้ต้องอนุมัติทุกครั้ง ดังนั้น Allow Always จึงไม่พร้อมใช้งาน",
allowAlwaysUnavailable: "Allow Always ไม่พร้อมใช้งานสำหรับคำสั่งนี้",
deny: "Deny",
labels: {
host: "Host",
+1 -2
View File
@@ -506,8 +506,7 @@ export const tr: TranslationMap = {
pending: "{count} pending",
allowOnce: "Allow once",
alwaysAllow: "Always allow",
allowAlwaysUnavailable:
"Geçerli onay ilkesi her seferinde onay gerektiriyor, bu nedenle Her Zaman İzin Ver kullanılamıyor.",
allowAlwaysUnavailable: "Her Zaman İzin Ver bu komut için kullanılamıyor.",
deny: "Deny",
labels: {
host: "Host",
+1 -2
View File
@@ -503,8 +503,7 @@ export const uk: TranslationMap = {
pending: "{count} pending",
allowOnce: "Allow once",
alwaysAllow: "Always allow",
allowAlwaysUnavailable:
"Чинна політика схвалення вимагає схвалення щоразу, тому «Дозволяти завжди» недоступно.",
allowAlwaysUnavailable: "«Дозволяти завжди» недоступно для цієї команди.",
deny: "Deny",
labels: {
host: "Host",
+1 -2
View File
@@ -502,8 +502,7 @@ export const vi: TranslationMap = {
pending: "{count} đang chờ",
allowOnce: "Cho phép một lần",
alwaysAllow: "Luôn cho phép",
allowAlwaysUnavailable:
"Chính sách phê duyệt có hiệu lực yêu cầu phê duyệt mọi lần, vì vậy Không cho phép Luôn cho phép.",
allowAlwaysUnavailable: "Luôn cho phép không khả dụng cho lệnh này.",
deny: "Từ chối",
labels: {
host: "Máy chủ",
+1 -1
View File
@@ -500,7 +500,7 @@ export const zh_CN: TranslationMap = {
pending: "{count} 个待处理",
allowOnce: "允许一次",
alwaysAllow: "始终允许",
allowAlwaysUnavailable: "有效的批准策略要求每次都批准,因此“始终允许”不可用。",
allowAlwaysUnavailable: "“始终允许”不可用于此命令。",
deny: "拒绝",
labels: {
host: "主机",
+1 -1
View File
@@ -500,7 +500,7 @@ export const zh_TW: TranslationMap = {
pending: "{count} pending",
allowOnce: "Allow once",
alwaysAllow: "Always allow",
allowAlwaysUnavailable: "有效的核准政策要求每次都需核准,因此「一律允許」無法使用。",
allowAlwaysUnavailable: "「一律允許」無法用於此指令。",
deny: "Deny",
labels: {
host: "Host",