Prechádzať zdrojové kódy

feat: Bring back a way to temporarily and globally pause auto-approve without losing your toggle state (#8024)

* Visual improvements and code cleanup (removes duplication)

* Brings back an 'enabled' toggle for auto-approve
Bruno Bergher 5 mesiacov pred
rodič
commit
3d45d4aa13

+ 74 - 78
webview-ui/src/components/chat/AutoApproveDropdown.tsx

@@ -1,14 +1,15 @@
 import React from "react"
-import { ListChecks, LayoutList, Settings, CheckCheck } from "lucide-react"
+import { ListChecks, LayoutList, Settings, CheckCheck, X } from "lucide-react"
 
 import { vscode } from "@/utils/vscode"
 import { cn } from "@/lib/utils"
 import { useExtensionState } from "@/context/ExtensionStateContext"
 import { useAppTranslation } from "@/i18n/TranslationContext"
 import { useRooPortal } from "@/components/ui/hooks/useRooPortal"
-import { Popover, PopoverContent, PopoverTrigger, StandardTooltip } from "@/components/ui"
+import { Popover, PopoverContent, PopoverTrigger, StandardTooltip, ToggleSwitch } from "@/components/ui"
 import { AutoApproveSetting, autoApproveSettingsConfig } from "../settings/AutoApproveToggle"
 import { useAutoApprovalToggles } from "@/hooks/useAutoApprovalToggles"
+import { useAutoApprovalState } from "@/hooks/useAutoApprovalState"
 
 interface AutoApproveDropdownProps {
 	disabled?: boolean
@@ -124,12 +125,7 @@ export const AutoApproveDropdown = ({ disabled = false, triggerClassName = "" }:
 		Object.keys(autoApproveSettingsConfig).forEach((key) => {
 			onAutoApproveToggle(key as AutoApproveSetting, false)
 		})
-		// Disable master auto-approval
-		if (autoApprovalEnabled) {
-			setAutoApprovalEnabled(false)
-			vscode.postMessage({ type: "autoApprovalEnabled", bool: false })
-		}
-	}, [onAutoApproveToggle, autoApprovalEnabled, setAutoApprovalEnabled])
+	}, [onAutoApproveToggle])
 
 	const handleOpenSettings = React.useCallback(
 		() =>
@@ -137,7 +133,16 @@ export const AutoApproveDropdown = ({ disabled = false, triggerClassName = "" }:
 		[],
 	)
 
+	// Handle the main auto-approval toggle
+	const handleAutoApprovalToggle = React.useCallback(() => {
+		const newValue = !(autoApprovalEnabled ?? false)
+		setAutoApprovalEnabled(newValue)
+		vscode.postMessage({ type: "autoApprovalEnabled", bool: newValue })
+	}, [autoApprovalEnabled, setAutoApprovalEnabled])
+
 	// Calculate enabled and total counts as separate properties
+	const settingsArray = Object.values(autoApproveSettingsConfig)
+
 	const enabledCount = React.useMemo(() => {
 		return Object.values(toggles).filter((value) => !!value).length
 	}, [toggles])
@@ -146,11 +151,7 @@ export const AutoApproveDropdown = ({ disabled = false, triggerClassName = "" }:
 		return Object.keys(toggles).length
 	}, [toggles])
 
-	// Split settings into two columns
-	const settingsArray = Object.values(autoApproveSettingsConfig)
-	const halfLength = Math.ceil(settingsArray.length / 2)
-	const firstColumn = settingsArray.slice(0, halfLength)
-	const secondColumn = settingsArray.slice(halfLength)
+	const { effectiveAutoApprovalEnabled } = useAutoApprovalState(toggles, autoApprovalEnabled)
 
 	return (
 		<Popover open={open} onOpenChange={setOpen} data-testid="auto-approve-dropdown-root">
@@ -167,11 +168,18 @@ export const AutoApproveDropdown = ({ disabled = false, triggerClassName = "" }:
 							: "opacity-90 hover:opacity-100 hover:bg-[rgba(255,255,255,0.03)] hover:border-[rgba(255,255,255,0.15)] cursor-pointer",
 						triggerClassName,
 					)}>
-					<CheckCheck className="size-3 flex-shrink-0" />
+					{!effectiveAutoApprovalEnabled ? (
+						<X className="size-3 flex-shrink-0" />
+					) : (
+						<CheckCheck className="size-3 flex-shrink-0" />
+					)}
+
 					<span className="truncate min-w-0">
-						{enabledCount === totalCount
-							? t("chat:autoApprove.triggerLabelAll")
-							: t("chat:autoApprove.triggerLabel", { count: enabledCount })}
+						{!effectiveAutoApprovalEnabled
+							? t("chat:autoApprove.triggerLabelOff")
+							: enabledCount === totalCount
+								? t("chat:autoApprove.triggerLabelAll")
+								: t("chat:autoApprove.triggerLabel", { count: enabledCount })}
 					</span>
 				</PopoverTrigger>
 			</StandardTooltip>
@@ -179,7 +187,7 @@ export const AutoApproveDropdown = ({ disabled = false, triggerClassName = "" }:
 				align="start"
 				sideOffset={4}
 				container={portalContainer}
-				className="p-0 overflow-hidden min-w-96 max-w-9/10"
+				className="p-0 overflow-hidden min-w-90 max-w-9/10"
 				onOpenAutoFocus={(e) => e.preventDefault()}>
 				<div className="flex flex-col w-full">
 					{/* Header with description */}
@@ -197,66 +205,32 @@ export const AutoApproveDropdown = ({ disabled = false, triggerClassName = "" }:
 							{t("chat:autoApprove.description")}
 						</p>
 					</div>
-
-					{/* Two-column layout for approval options */}
-					<div className="p-3">
-						<div className="grid grid-cols-2 gap-x-4 gap-y-2">
-							{/* First Column */}
-							<div className="space-y-2">
-								{firstColumn.map(({ key, labelKey, descriptionKey, icon }) => {
-									const isEnabled = toggles[key]
-									return (
-										<StandardTooltip key={key} content={t(descriptionKey)}>
-											<button
-												onClick={() => onAutoApproveToggle(key, !isEnabled)}
-												className={cn(
-													"w-full flex items-center gap-2 px-2 py-1.5 rounded text-xs text-left",
-													"transition-all duration-150",
-													"hover:bg-vscode-list-hoverBackground",
-													isEnabled
-														? "bg-vscode-button-background text-vscode-button-foreground"
-														: "bg-transparent text-vscode-foreground opacity-70 hover:opacity-100",
-												)}
-												data-testid={`auto-approve-${key}`}>
-												<span className={`codicon codicon-${icon} text-sm flex-shrink-0`} />
-												<span className="flex-1 truncate">{t(labelKey)}</span>
-												{isEnabled && (
-													<span className="codicon codicon-check text-xs flex-shrink-0" />
-												)}
-											</button>
-										</StandardTooltip>
-									)
-								})}
-							</div>
-
-							{/* Second Column */}
-							<div className="space-y-2">
-								{secondColumn.map(({ key, labelKey, descriptionKey, icon }) => {
-									const isEnabled = toggles[key]
-									return (
-										<StandardTooltip key={key} content={t(descriptionKey)}>
-											<button
-												onClick={() => onAutoApproveToggle(key, !isEnabled)}
-												className={cn(
-													"w-full flex items-center gap-2 px-2 py-1.5 rounded text-xs text-left",
-													"transition-all duration-150",
-													"hover:bg-vscode-list-hoverBackground",
-													isEnabled
-														? "bg-vscode-button-background text-vscode-button-foreground"
-														: "bg-transparent text-vscode-foreground opacity-70 hover:opacity-100",
-												)}
-												data-testid={`auto-approve-${key}`}>
-												<span className={`codicon codicon-${icon} text-sm flex-shrink-0`} />
-												<span className="flex-1 truncate">{t(labelKey)}</span>
-												{isEnabled && (
-													<span className="codicon codicon-check text-xs flex-shrink-0" />
-												)}
-											</button>
-										</StandardTooltip>
-									)
-								})}
-							</div>
-						</div>
+					<div className="grid grid-cols-2 gap-x-2 gap-y-2 p-3">
+						{settingsArray.map(({ key, labelKey, descriptionKey, icon }) => {
+							const isEnabled = toggles[key]
+							return (
+								<StandardTooltip key={key} content={t(descriptionKey)}>
+									<button
+										onClick={() => onAutoApproveToggle(key, !isEnabled)}
+										className={cn(
+											"flex items-center gap-2 px-2 py-2 rounded text-sm text-left",
+											"transition-all duration-150",
+											"opacity-100 hover:opacity-70",
+											"cursor-pointer",
+											!effectiveAutoApprovalEnabled &&
+												"opacity-50 cursor-not-allowed hover:opacity-50",
+											isEnabled
+												? "bg-vscode-button-background text-vscode-button-foreground"
+												: "bg-vscode-button-background/15 text-vscode-foreground hover:bg-vscode-list-hoverBackground",
+										)}
+										disabled={!effectiveAutoApprovalEnabled}
+										data-testid={`auto-approve-${key}`}>
+										<span className={`codicon codicon-${icon} text-sm flex-shrink-0`} />
+										<span className="flex-1 truncate">{t(labelKey)}</span>
+									</button>
+								</StandardTooltip>
+							)
+						})}
 					</div>
 
 					{/* Bottom bar with Select All/None buttons */}
@@ -265,6 +239,7 @@ export const AutoApproveDropdown = ({ disabled = false, triggerClassName = "" }:
 							<button
 								aria-label={t("chat:autoApprove.selectAll")}
 								onClick={handleSelectAll}
+								disabled={!effectiveAutoApprovalEnabled}
 								className={cn(
 									"relative inline-flex items-center justify-center gap-1",
 									"bg-transparent border-none px-2 py-1",
@@ -275,6 +250,7 @@ export const AutoApproveDropdown = ({ disabled = false, triggerClassName = "" }:
 									"focus:outline-none focus-visible:ring-1 focus-visible:ring-vscode-focusBorder",
 									"active:bg-[rgba(255,255,255,0.1)]",
 									"cursor-pointer",
+									!effectiveAutoApprovalEnabled && "opacity-50 hover:opacity-50 cursor-not-allowed",
 								)}>
 								<ListChecks className="w-3.5 h-3.5" />
 								<span>{t("chat:autoApprove.all")}</span>
@@ -282,6 +258,7 @@ export const AutoApproveDropdown = ({ disabled = false, triggerClassName = "" }:
 							<button
 								aria-label={t("chat:autoApprove.selectNone")}
 								onClick={handleSelectNone}
+								disabled={!effectiveAutoApprovalEnabled}
 								className={cn(
 									"relative inline-flex items-center justify-center gap-1",
 									"bg-transparent border-none px-2 py-1",
@@ -292,11 +269,30 @@ export const AutoApproveDropdown = ({ disabled = false, triggerClassName = "" }:
 									"focus:outline-none focus-visible:ring-1 focus-visible:ring-vscode-focusBorder",
 									"active:bg-[rgba(255,255,255,0.1)]",
 									"cursor-pointer",
+									!effectiveAutoApprovalEnabled && "opacity-50 hover:opacity-50 cursor-not-allowed",
 								)}>
 								<LayoutList className="w-3.5 h-3.5" />
 								<span>{t("chat:autoApprove.none")}</span>
 							</button>
 						</div>
+
+						<label
+							className="flex items-center gap-2 pr-2 cursor-pointer"
+							onClick={(e) => {
+								// Prevent label click when clicking on the toggle switch itself
+								if ((e.target as HTMLElement).closest('[role="switch"]')) {
+									e.preventDefault()
+									return
+								}
+								handleAutoApprovalToggle()
+							}}>
+							<ToggleSwitch
+								checked={effectiveAutoApprovalEnabled}
+								aria-label="Toggle auto-approval"
+								onChange={handleAutoApprovalToggle}
+							/>
+							<span className={cn("text-sm font-bold select-none")}>Enabled</span>
+						</label>
 					</div>
 				</div>
 			</PopoverContent>

+ 12 - 28
webview-ui/src/components/settings/AutoApproveSettings.tsx

@@ -4,7 +4,7 @@ import { X, CheckCheck } from "lucide-react"
 import { useAppTranslation } from "@/i18n/TranslationContext"
 import { VSCodeCheckbox } from "@vscode/webview-ui-toolkit/react"
 import { vscode } from "@/utils/vscode"
-import { Button, Input, Slider, StandardTooltip } from "@/components/ui"
+import { Button, Input, Slider } from "@/components/ui"
 
 import { SetCachedStateField } from "./types"
 import { SectionHeader } from "./SectionHeader"
@@ -88,7 +88,7 @@ export const AutoApproveSettings = ({
 
 	const toggles = useAutoApprovalToggles()
 
-	const { hasEnabledOptions, effectiveAutoApprovalEnabled } = useAutoApprovalState(toggles, autoApprovalEnabled)
+	const { effectiveAutoApprovalEnabled } = useAutoApprovalState(toggles, autoApprovalEnabled)
 
 	const handleAddCommand = () => {
 		const currentCommands = allowedCommands ?? []
@@ -124,32 +124,16 @@ export const AutoApproveSettings = ({
 			<Section>
 				<div className="space-y-4">
 					<div>
-						{!hasEnabledOptions ? (
-							<StandardTooltip content={t("settings:autoApprove.selectOptionsFirst")}>
-								<VSCodeCheckbox
-									checked={effectiveAutoApprovalEnabled}
-									disabled={!hasEnabledOptions}
-									aria-label={t("settings:autoApprove.disabledAriaLabel")}
-									onChange={() => {
-										// Do nothing when no options are enabled
-										return
-									}}>
-									<span className="font-medium">{t("settings:autoApprove.enabled")}</span>
-								</VSCodeCheckbox>
-							</StandardTooltip>
-						) : (
-							<VSCodeCheckbox
-								checked={effectiveAutoApprovalEnabled}
-								disabled={!hasEnabledOptions}
-								aria-label={t("settings:autoApprove.toggleAriaLabel")}
-								onChange={() => {
-									const newValue = !(autoApprovalEnabled ?? false)
-									setAutoApprovalEnabled(newValue)
-									vscode.postMessage({ type: "autoApprovalEnabled", bool: newValue })
-								}}>
-								<span className="font-medium">{t("settings:autoApprove.enabled")}</span>
-							</VSCodeCheckbox>
-						)}
+						<VSCodeCheckbox
+							checked={effectiveAutoApprovalEnabled}
+							aria-label={t("settings:autoApprove.toggleAriaLabel")}
+							onChange={() => {
+								const newValue = !(autoApprovalEnabled ?? false)
+								setAutoApprovalEnabled(newValue)
+								vscode.postMessage({ type: "autoApprovalEnabled", bool: newValue })
+							}}>
+							<span className="font-medium">{t("settings:autoApprove.enabled")}</span>
+						</VSCodeCheckbox>
 						<div className="text-vscode-descriptionForeground text-sm mt-1">
 							{t("settings:autoApprove.description")}
 						</div>

+ 4 - 4
webview-ui/src/hooks/__tests__/useAutoApprovalState.spec.ts

@@ -124,7 +124,7 @@ describe("useAutoApprovalState", () => {
 			expect(result.current.effectiveAutoApprovalEnabled).toBe(false)
 		})
 
-		it("should return false when autoApprovalEnabled is true but no toggles are enabled", () => {
+		it("should return true when autoApprovalEnabled is true but no toggles are enabled", () => {
 			const toggles = {
 				alwaysAllowReadOnly: false,
 				alwaysAllowWrite: false,
@@ -140,7 +140,7 @@ describe("useAutoApprovalState", () => {
 
 			const { result } = renderHook(() => useAutoApprovalState(toggles, true))
 
-			expect(result.current.effectiveAutoApprovalEnabled).toBe(false)
+			expect(result.current.effectiveAutoApprovalEnabled).toBe(true)
 		})
 
 		it("should return true when autoApprovalEnabled is true and at least one toggle is enabled", () => {
@@ -217,7 +217,7 @@ describe("useAutoApprovalState", () => {
 			rerender({ toggles: newToggles, autoApprovalEnabled: true })
 
 			expect(result.current.hasEnabledOptions).toBe(false)
-			expect(result.current.effectiveAutoApprovalEnabled).toBe(false)
+			expect(result.current.effectiveAutoApprovalEnabled).toBe(true)
 		})
 
 		it("should recompute effectiveAutoApprovalEnabled when autoApprovalEnabled changes", () => {
@@ -263,7 +263,7 @@ describe("useAutoApprovalState", () => {
 			const { result } = renderHook(() => useAutoApprovalState(toggles, true))
 
 			expect(result.current.hasEnabledOptions).toBe(false)
-			expect(result.current.effectiveAutoApprovalEnabled).toBe(false)
+			expect(result.current.effectiveAutoApprovalEnabled).toBe(true)
 		})
 
 		it("should handle mixed truthy/falsy values correctly", () => {

+ 2 - 2
webview-ui/src/hooks/useAutoApprovalState.ts

@@ -19,8 +19,8 @@ export function useAutoApprovalState(toggles: AutoApprovalToggles, autoApprovalE
 	}, [toggles])
 
 	const effectiveAutoApprovalEnabled = useMemo(() => {
-		return hasEnabledOptions && (autoApprovalEnabled ?? false)
-	}, [hasEnabledOptions, autoApprovalEnabled])
+		return autoApprovalEnabled ?? false
+	}, [autoApprovalEnabled])
 
 	return {
 		hasEnabledOptions,

+ 2 - 1
webview-ui/src/i18n/locales/ca/chat.json

@@ -258,7 +258,8 @@
 		"triggerLabel_zero": "Sense aprovació automàtica",
 		"triggerLabel_one": "1 aprovació automàtica",
 		"triggerLabel_other": "{{count}} aprovacions automàtiques",
-		"triggerLabelAll": "YOLO"
+		"triggerLabelAll": "YOLO",
+		"triggerLabelOff": "Auto-approve desactivat"
 	},
 	"reasoning": {
 		"thinking": "Pensant",

+ 2 - 1
webview-ui/src/i18n/locales/de/chat.json

@@ -258,7 +258,8 @@
 		"triggerLabel_zero": "Keine automatische Genehmigung",
 		"triggerLabel_one": "1 automatisch genehmigt",
 		"triggerLabel_other": "{{count}} automatisch genehmigt",
-		"triggerLabelAll": "YOLO"
+		"triggerLabelAll": "YOLO",
+		"triggerLabelOff": "Automatische Genehmigung aus"
 	},
 	"reasoning": {
 		"thinking": "Denke nach",

+ 2 - 1
webview-ui/src/i18n/locales/en/chat.json

@@ -279,7 +279,8 @@
 		"selectOptionsFirst": "Select at least one option below to enable auto-approval",
 		"toggleAriaLabel": "Toggle auto-approval",
 		"disabledAriaLabel": "Auto-approval disabled - select options first",
-		"triggerLabel_zero": "No auto-approve",
+		"triggerLabelOff": "Auto-approve off",
+		"triggerLabel_zero": "0 auto-approve",
 		"triggerLabel_one": "1 auto-approved",
 		"triggerLabel_other": "{{count}} auto-approved",
 		"triggerLabelAll": "YOLO"

+ 2 - 1
webview-ui/src/i18n/locales/es/chat.json

@@ -258,7 +258,8 @@
 		"triggerLabel_zero": "Sin aprobación automática",
 		"triggerLabel_one": "1 aprobado automáticamente",
 		"triggerLabel_other": "{{count}} aprobados automáticamente",
-		"triggerLabelAll": "YOLO"
+		"triggerLabelAll": "YOLO",
+		"triggerLabelOff": "Auto-aprobar desactivado"
 	},
 	"reasoning": {
 		"thinking": "Pensando",

+ 2 - 1
webview-ui/src/i18n/locales/fr/chat.json

@@ -258,7 +258,8 @@
 		"triggerLabel_zero": "Pas d'approbation automatique",
 		"triggerLabel_one": "1 approuvé automatiquement",
 		"triggerLabel_other": "{{count}} approuvés automatiquement",
-		"triggerLabelAll": "YOLO"
+		"triggerLabelAll": "YOLO",
+		"triggerLabelOff": "Approbation automatique désactivée"
 	},
 	"reasoning": {
 		"thinking": "Réflexion",

+ 2 - 1
webview-ui/src/i18n/locales/hi/chat.json

@@ -258,7 +258,8 @@
 		"triggerLabel_zero": "कोई स्वतः-अनुमोदन नहीं",
 		"triggerLabel_one": "1 स्वतः-अनुमोदित",
 		"triggerLabel_other": "{{count}} स्वतः-अनुमोदित",
-		"triggerLabelAll": "योलो"
+		"triggerLabelAll": "योलो",
+		"triggerLabelOff": "स्वतः-अनुमोदन बंद"
 	},
 	"reasoning": {
 		"thinking": "विचार कर रहा है",

+ 2 - 1
webview-ui/src/i18n/locales/id/chat.json

@@ -285,7 +285,8 @@
 		"triggerLabel_zero": "Tidak ada persetujuan otomatis",
 		"triggerLabel_one": "1 disetujui otomatis",
 		"triggerLabel_other": "{{count}} disetujui otomatis",
-		"triggerLabelAll": "YOLO"
+		"triggerLabelAll": "YOLO",
+		"triggerLabelOff": "Persetujuan otomatis nonaktif"
 	},
 	"announcement": {
 		"title": "🎉 Roo Code {{version}} Dirilis",

+ 2 - 1
webview-ui/src/i18n/locales/it/chat.json

@@ -258,7 +258,8 @@
 		"triggerLabel_zero": "Nessuna approvazione automatica",
 		"triggerLabel_one": "1 approvato automaticamente",
 		"triggerLabel_other": "{{count}} approvati automaticamente",
-		"triggerLabelAll": "YOLO"
+		"triggerLabelAll": "YOLO",
+		"triggerLabelOff": "Approvazione automatica disattivata"
 	},
 	"reasoning": {
 		"thinking": "Sto pensando",

+ 2 - 1
webview-ui/src/i18n/locales/ja/chat.json

@@ -258,7 +258,8 @@
 		"triggerLabel_zero": "自動承認なし",
 		"triggerLabel_one": "1件自動承認済み",
 		"triggerLabel_other": "{{count}}件自動承認済み",
-		"triggerLabelAll": "YOLO"
+		"triggerLabelAll": "YOLO",
+		"triggerLabelOff": "自動承認オフ"
 	},
 	"reasoning": {
 		"thinking": "考え中",

+ 2 - 1
webview-ui/src/i18n/locales/ko/chat.json

@@ -258,7 +258,8 @@
 		"triggerLabel_zero": "자동 승인 없음",
 		"triggerLabel_one": "1개 자동 승인됨",
 		"triggerLabel_other": "{{count}}개 자동 승인됨",
-		"triggerLabelAll": "욜로"
+		"triggerLabelAll": "욜로",
+		"triggerLabelOff": "자동 승인 꺼짐"
 	},
 	"reasoning": {
 		"thinking": "생각 중",

+ 2 - 1
webview-ui/src/i18n/locales/nl/chat.json

@@ -258,7 +258,8 @@
 		"triggerLabel_zero": "Geen automatische goedkeuring",
 		"triggerLabel_one": "1 automatisch goedgekeurd",
 		"triggerLabel_other": "{{count}} automatisch goedgekeurd",
-		"triggerLabelAll": "YOLO"
+		"triggerLabelAll": "YOLO",
+		"triggerLabelOff": "Automatisch goedkeuren uit"
 	},
 	"announcement": {
 		"title": "🎉 Roo Code {{version}} uitgebracht",

+ 2 - 1
webview-ui/src/i18n/locales/pl/chat.json

@@ -260,7 +260,8 @@
 		"triggerLabel_few": "{{count}} automatycznie zaakceptowane",
 		"triggerLabel_many": "{{count}} automatycznie zaakceptowanych",
 		"triggerLabel_other": "{{count}} automatycznie zaakceptowanych",
-		"triggerLabelAll": "YOLO"
+		"triggerLabelAll": "YOLO",
+		"triggerLabelOff": "Automatyczne zatwierdzanie wyłączone"
 	},
 	"reasoning": {
 		"thinking": "Myślenie",

+ 2 - 1
webview-ui/src/i18n/locales/pt-BR/chat.json

@@ -258,7 +258,8 @@
 		"triggerLabel_zero": "Nenhuma aprovação automática",
 		"triggerLabel_one": "1 aprovado automaticamente",
 		"triggerLabel_other": "{{count}} aprovados automaticamente",
-		"triggerLabelAll": "YOLO"
+		"triggerLabelAll": "YOLO",
+		"triggerLabelOff": "Aprovação automática desativada"
 	},
 	"reasoning": {
 		"thinking": "Pensando",

+ 2 - 1
webview-ui/src/i18n/locales/ru/chat.json

@@ -260,7 +260,8 @@
 		"triggerLabel_few": "{{count}} авто-утверждено",
 		"triggerLabel_many": "{{count}} авто-утверждено",
 		"triggerLabel_other": "{{count}} авто-утверждено",
-		"triggerLabelAll": "YOLO"
+		"triggerLabelAll": "YOLO",
+		"triggerLabelOff": "Авто-утверждение выкл"
 	},
 	"announcement": {
 		"title": "🎉 Выпущен Roo Code {{version}}",

+ 2 - 1
webview-ui/src/i18n/locales/tr/chat.json

@@ -258,7 +258,8 @@
 		"triggerLabel_zero": "Otomatik onay yok",
 		"triggerLabel_one": "1 otomatik onaylandı",
 		"triggerLabel_other": "{{count}} otomatik onaylandı",
-		"triggerLabelAll": "YOLO"
+		"triggerLabelAll": "YOLO",
+		"triggerLabelOff": "Otomatik onay kapalı"
 	},
 	"reasoning": {
 		"thinking": "Düşünüyor",

+ 2 - 1
webview-ui/src/i18n/locales/vi/chat.json

@@ -258,7 +258,8 @@
 		"triggerLabel_zero": "Không có tự động phê duyệt",
 		"triggerLabel_one": "1 được tự động phê duyệt",
 		"triggerLabel_other": "{{count}} được tự động phê duyệt",
-		"triggerLabelAll": "YOLO"
+		"triggerLabelAll": "YOLO",
+		"triggerLabelOff": "Tự động phê duyệt tắt"
 	},
 	"reasoning": {
 		"thinking": "Đang suy nghĩ",

+ 2 - 1
webview-ui/src/i18n/locales/zh-CN/chat.json

@@ -258,7 +258,8 @@
 		"triggerLabel_zero": "无自动批准",
 		"triggerLabel_one": "1 个自动批准",
 		"triggerLabel_other": "{{count}} 个自动批准",
-		"triggerLabelAll": "人生只有一次"
+		"triggerLabelAll": "人生只有一次",
+		"triggerLabelOff": "自动批准已关闭"
 	},
 	"reasoning": {
 		"thinking": "思考中",

+ 2 - 1
webview-ui/src/i18n/locales/zh-TW/chat.json

@@ -282,7 +282,8 @@
 		"triggerLabel_zero": "無自動核准",
 		"triggerLabel_one": "1 個自動核准",
 		"triggerLabel_other": "{{count}} 個自動核准",
-		"triggerLabelAll": "人生只有一次"
+		"triggerLabelAll": "人生只有一次",
+		"triggerLabelOff": "自動批准已關閉"
 	},
 	"announcement": {
 		"title": "🎉 Roo Code {{version}} 已發布",