feat(confirm): centralize confirmation dialogs and add i18n

Introduce a generic ConfirmDialog and a promise-based requestConfirmation API in
App.svelte so callers can await user responses instead of using window.confirm.
Provide helper builders (branchDeleteConfirmRequest, discardConfirmRequest) to
create dialog content for common cases. Many call sites were switched to use
requestConfirmation and now render the in-app ConfirmDialog; the previous
specialized confirm components (BranchDeleteConfirmDialog, DiscardConfirmDialog)
were removed.

Add lightweight i18n support (setLanguage, t()) and new messages/i18n modules,
and replace hardcoded English strings in several components (e.g. AiSettingsPage,
BlameDialog and many confirmation prompts) with translated keys.

Summary of effects:
- Replaces native window.confirm with awaitable in-app ConfirmDialog dialogs.
- Centralizes confirmation UI and content construction in App.svelte.
- Adds i18n plumbing and updates UI text to use t().
- Removes two specialized confirm dialog components and adds src/lib/components/ConfirmDialog.svelte.
This commit is contained in:
2026-09-17 21:41:35 +02:00
parent b00e3e5c18
commit 3e87c8f6a9
19 changed files with 1373 additions and 589 deletions
+21 -6
View File
@@ -17,6 +17,8 @@
X,
} from "@lucide/svelte";
import type { AppLanguage, GitLfsPattern, GitLfsStatus } from "../types";
import ConfirmDialog from "./ConfirmDialog.svelte";
import { t } from "../i18n.svelte";
interface Props {
status: GitLfsStatus | null;
@@ -81,11 +83,11 @@
}
}
async function confirmPrune() {
const confirmed = window.confirm(isGerman
? "Nicht mehr benötigte lokale LFS-Objekte sicher bereinigen? Nicht gepushte und aktuell verwendete Objekte bleiben erhalten."
: "Safely prune unused local LFS objects? Unpushed and currently used objects are retained.");
if (confirmed) await onPrune();
let pruneConfirmOpen = $state(false);
async function runPrune() {
pruneConfirmOpen = false;
await onPrune();
}
</script>
@@ -199,7 +201,7 @@
<footer class="lfs-footer">
<div><ShieldCheck size={14} aria-hidden="true" /><span>{isGerman ? ".gitattributes bleibt als normale Änderung sichtbar und muss committed werden." : ".gitattributes remains a normal change and must be committed."}</span></div>
<div>
<button class="btn-secondary" type="button" onclick={confirmPrune} disabled={isBusy || !status?.available}><Trash2 size={14} aria-hidden="true" />{isGerman ? "Cache bereinigen" : "Prune cache"}</button>
<button class="btn-secondary" type="button" onclick={() => { pruneConfirmOpen = true; }} disabled={isBusy || !status?.available}><Trash2 size={14} aria-hidden="true" />{isGerman ? "Cache bereinigen" : "Prune cache"}</button>
<button class="btn-primary" type="button" onclick={onPull} disabled={isBusy || !setupReady}><HardDriveDownload size={15} aria-hidden="true" />{isGerman ? "Objekte laden" : "Pull objects"}</button>
</div>
</footer>
@@ -293,3 +295,16 @@
.lfs-footer button { flex: 1; }
}
</style>
{#if pruneConfirmOpen}
<ConfirmDialog
request={{
title: t("confirm.lfsPrune.title"),
message: t("confirm.lfsPrune.message"),
note: t("confirm.lfsPrune.note"),
confirmLabel: t("confirm.lfsPrune.action"),
}}
onConfirm={runPrune}
onCancel={() => { pruneConfirmOpen = false; }}
/>
{/if}