diff --git a/prisma/seed.ts b/prisma/seed.ts
index 840d94c..744d717 100644
--- a/prisma/seed.ts
+++ b/prisma/seed.ts
@@ -181,7 +181,7 @@ async function main() {
await prisma.expense.create({
data: {
title: "Muster: Kabelbinder",
- description: "Beispiel fuer einen automatisch freigegebenen Infrastrukturposten.",
+ description: "Beispiel für einen automatisch freigegebenen Infrastrukturposten.",
amount: 24.5,
creatorId: technikUser.id,
agId: technik.id,
@@ -206,7 +206,7 @@ async function main() {
await prisma.expense.create({
data: {
title: "Muster: Vereinssoftware Abo",
- description: "Monatlich wiederkehrendes Beispielabo fuer die Uebersicht.",
+ description: "Monatlich wiederkehrendes Beispielabo für die Übersicht.",
amount: 19,
creatorId: financeUser.id,
agId: technik.id,
diff --git a/src/app/api/budgets/[id]/route.ts b/src/app/api/budgets/[id]/route.ts
index a61ff53..9bfe55d 100644
--- a/src/app/api/budgets/[id]/route.ts
+++ b/src/app/api/budgets/[id]/route.ts
@@ -99,7 +99,7 @@ export async function DELETE(_: Request, { params }: Context) {
}
if (!canManageBudgets(viewer.role)) {
- return NextResponse.json({ error: "Nur Vorstand oder Finanz-AG duerfen Budgets loeschen." }, { status: 403 });
+ return NextResponse.json({ error: "Nur Vorstand oder Finanz-AG dürfen Budgets löschen." }, { status: 403 });
}
const budget = await prisma.budget.findUnique({
diff --git a/src/app/api/expenses/[id]/approve/route.ts b/src/app/api/expenses/[id]/approve/route.ts
index 64cb66a..30ee78f 100644
--- a/src/app/api/expenses/[id]/approve/route.ts
+++ b/src/app/api/expenses/[id]/approve/route.ts
@@ -120,7 +120,7 @@ export async function POST(request: Request, { params }: Context) {
entityType: "expense",
entityId: expense.id,
entityLabel: expense.title,
- summary: `${parsed.data.approvalType} fuer ${expense.title} wurde gesetzt.`,
+ summary: `${parsed.data.approvalType} für ${expense.title} wurde gesetzt.`,
metadata: {
approvalType: parsed.data.approvalType,
approvalThreshold,
diff --git a/src/app/api/expenses/[id]/route.ts b/src/app/api/expenses/[id]/route.ts
index 7de6a5b..17c0240 100644
--- a/src/app/api/expenses/[id]/route.ts
+++ b/src/app/api/expenses/[id]/route.ts
@@ -35,7 +35,7 @@ export async function DELETE(_: Request, { params }: Context) {
if (!isAdminDelete && !isOwnPendingExpense) {
return NextResponse.json(
- { error: "Du darfst nur eigene ungepruefte Ausgaben loeschen." },
+ { error: "Du darfst nur eigene ungeprüfte Ausgaben löschen." },
{ status: 403 }
);
}
diff --git a/src/app/api/expenses/route.ts b/src/app/api/expenses/route.ts
index 039858b..3321307 100644
--- a/src/app/api/expenses/route.ts
+++ b/src/app/api/expenses/route.ts
@@ -33,7 +33,7 @@ export async function POST(request: Request) {
const parsed = expenseSchema.safeParse(body);
if (!parsed.success) {
- return NextResponse.json({ error: "Bitte Titel, Betrag und AG korrekt ausfuellen." }, { status: 400 });
+ return NextResponse.json({ error: "Bitte Titel, Betrag und AG korrekt ausfüllen." }, { status: 400 });
}
if (!canCreateExpenseForGroup(viewer.role, viewer.workingGroupId, parsed.data.agId)) {
diff --git a/src/app/api/import/csv/route.ts b/src/app/api/import/csv/route.ts
index 209a60d..b63e791 100644
--- a/src/app/api/import/csv/route.ts
+++ b/src/app/api/import/csv/route.ts
@@ -58,14 +58,14 @@ export async function POST(request: Request) {
const uploadedFile = formData?.get("file");
if (!(uploadedFile instanceof File)) {
- return NextResponse.json({ error: "Bitte eine CSV-Datei auswaehlen." }, { status: 400 });
+ return NextResponse.json({ error: "Bitte eine CSV-Datei auswählen." }, { status: 400 });
}
const content = await uploadedFile.text();
const rows = parseCsv(content);
if (rows.length < 2) {
- return NextResponse.json({ error: "Die CSV-Datei enthaelt keine Daten." }, { status: 400 });
+ return NextResponse.json({ error: "Die CSV-Datei enthält keine Daten." }, { status: 400 });
}
const headers = rows[0];
@@ -81,7 +81,7 @@ export async function POST(request: Request) {
if (userRows.some((entry) => !entry.passwordHash)) {
return NextResponse.json(
- { error: "Dieses Backup stammt aus einem alten Format ohne Passwort-Hashes und kann nicht vollstaendig eingespielt werden." },
+ { error: "Dieses Backup stammt aus einem alten Format ohne Passwort-Hashes und kann nicht vollständig eingespielt werden." },
{ status: 400 }
);
}
@@ -119,7 +119,7 @@ export async function POST(request: Request) {
const endsAt = toDate(row.periodEndsAt);
if (!startsAt || !endsAt) {
- throw new Error(`Zeitraum ${row.periodName || row.id} enthaelt kein gueltiges Datum.`);
+ throw new Error(`Zeitraum ${row.periodName || row.id} enthält kein gültiges Datum.`);
}
await tx.accountingPeriod.create({
@@ -169,7 +169,7 @@ export async function POST(request: Request) {
const totalBudget = toNumber(row.totalBudget);
if (totalBudget === null) {
- throw new Error(`Budget ${row.budgetName || row.id} enthaelt keinen gueltigen Betrag.`);
+ throw new Error(`Budget ${row.budgetName || row.id} enthält keinen gültigen Betrag.`);
}
await tx.budget.create({
@@ -189,7 +189,7 @@ export async function POST(request: Request) {
const amount = toNumber(row.amount);
if (amount === null) {
- throw new Error(`Ausgabe ${row.title || row.id} enthaelt keinen gueltigen Betrag.`);
+ throw new Error(`Ausgabe ${row.title || row.id} enthält keinen gültigen Betrag.`);
}
await tx.expense.create({
@@ -216,7 +216,7 @@ export async function POST(request: Request) {
const timestamp = toDate(row.createdAt);
if (!timestamp) {
- throw new Error(`Freigabe ${row.id} enthaelt keinen gueltigen Zeitstempel.`);
+ throw new Error(`Freigabe ${row.id} enthält keinen gültigen Zeitstempel.`);
}
await tx.approval.create({
diff --git a/src/app/api/periods/[id]/route.ts b/src/app/api/periods/[id]/route.ts
index 00e5eab..4b53232 100644
--- a/src/app/api/periods/[id]/route.ts
+++ b/src/app/api/periods/[id]/route.ts
@@ -20,7 +20,7 @@ export async function DELETE(_: Request, { params }: Context) {
}
if (!canManageBudgets(viewer.role)) {
- return NextResponse.json({ error: "Nur Vorstand oder Finanz-AG duerfen Zeitraeume loeschen." }, { status: 403 });
+ return NextResponse.json({ error: "Nur Vorstand oder Finanz-AG dürfen Zeiträume löschen." }, { status: 403 });
}
const period = await prisma.accountingPeriod.findUnique({
@@ -40,12 +40,12 @@ export async function DELETE(_: Request, { params }: Context) {
}
if (period.isCurrent) {
- return NextResponse.json({ error: "Der aktuell aktive Zeitraum kann nicht geloescht werden." }, { status: 400 });
+ return NextResponse.json({ error: "Der aktuell aktive Zeitraum kann nicht gelöscht werden." }, { status: 400 });
}
if (period._count.budgets > 0 || period._count.expenses > 0) {
return NextResponse.json(
- { error: "Dieser Zeitraum enthaelt noch Budgets oder Ausgaben und kann deshalb nicht geloescht werden." },
+ { error: "Dieser Zeitraum enthält noch Budgets oder Ausgaben und kann deshalb nicht gelöscht werden." },
{ status: 400 }
);
}
@@ -60,7 +60,7 @@ export async function DELETE(_: Request, { params }: Context) {
entityType: "period",
entityId: period.id,
entityLabel: period.name,
- summary: `Zeitraum ${period.name} wurde geloescht.`,
+ summary: `Zeitraum ${period.name} wurde gelöscht.`,
metadata: {
rollback: {
kind: "period.delete",
diff --git a/src/app/api/periods/current/route.ts b/src/app/api/periods/current/route.ts
index 6a45248..13e3577 100644
--- a/src/app/api/periods/current/route.ts
+++ b/src/app/api/periods/current/route.ts
@@ -18,14 +18,14 @@ export async function PATCH(request: Request) {
}
if (!canManageBudgets(viewer.role)) {
- return NextResponse.json({ error: "Nur Vorstand oder Finanz-AG duerfen den aktuellen Zeitraum wechseln." }, { status: 403 });
+ return NextResponse.json({ error: "Nur Vorstand oder Finanz-AG dürfen den aktuellen Zeitraum wechseln." }, { status: 403 });
}
const body = await request.json().catch(() => null);
const parsed = currentPeriodSchema.safeParse(body);
if (!parsed.success) {
- return NextResponse.json({ error: "Bitte einen gueltigen Zeitraum auswaehlen." }, { status: 400 });
+ return NextResponse.json({ error: "Bitte einen gültigen Zeitraum auswählen." }, { status: 400 });
}
const period = await prisma.accountingPeriod.findUnique({
diff --git a/src/app/api/periods/route.ts b/src/app/api/periods/route.ts
index d26daa1..a4d0425 100644
--- a/src/app/api/periods/route.ts
+++ b/src/app/api/periods/route.ts
@@ -22,7 +22,7 @@ export async function POST(request: Request) {
}
if (!canManageBudgets(viewer.role)) {
- return NextResponse.json({ error: "Nur Vorstand oder Finanz-AG duerfen Zeitraeume verwalten." }, { status: 403 });
+ return NextResponse.json({ error: "Nur Vorstand oder Finanz-AG dürfen Zeiträume verwalten." }, { status: 403 });
}
const body = await request.json().catch(() => null);
diff --git a/src/app/api/users/[id]/password/route.ts b/src/app/api/users/[id]/password/route.ts
index fad5beb..4b0cdec 100644
--- a/src/app/api/users/[id]/password/route.ts
+++ b/src/app/api/users/[id]/password/route.ts
@@ -25,7 +25,7 @@ export async function POST(request: Request, { params }: Context) {
}
if (!canManageUsers(viewer.role)) {
- return NextResponse.json({ error: "Nur Vorstand oder Finanz-AG duerfen Passwoerter neu setzen." }, { status: 403 });
+ return NextResponse.json({ error: "Nur Vorstand oder Finanz-AG dürfen Passwörter neu setzen." }, { status: 403 });
}
const body = await request.json().catch(() => null);
diff --git a/src/app/api/users/[id]/route.ts b/src/app/api/users/[id]/route.ts
index aa1c86b..3d6471c 100644
--- a/src/app/api/users/[id]/route.ts
+++ b/src/app/api/users/[id]/route.ts
@@ -124,11 +124,11 @@ export async function DELETE(_: Request, { params }: Context) {
}
if (!canManageUsers(viewer.role)) {
- return NextResponse.json({ error: "Nur Vorstand oder Finanz-AG duerfen Nutzer loeschen." }, { status: 403 });
+ return NextResponse.json({ error: "Nur Vorstand oder Finanz-AG dürfen Nutzer löschen." }, { status: 403 });
}
if (viewer.id === params.id) {
- return NextResponse.json({ error: "Du kannst dein eigenes Konto hier nicht loeschen." }, { status: 400 });
+ return NextResponse.json({ error: "Du kannst dein eigenes Konto hier nicht löschen." }, { status: 400 });
}
const user = await prisma.user.findUnique({
@@ -149,7 +149,7 @@ export async function DELETE(_: Request, { params }: Context) {
if (user._count.approvals > 0 || user._count.createdExpenses > 0) {
return NextResponse.json(
- { error: "Nutzer mit Freigaben oder Ausgaben koennen nicht geloescht werden." },
+ { error: "Nutzer mit Freigaben oder Ausgaben können nicht gelöscht werden." },
{ status: 400 }
);
}
diff --git a/src/app/api/working-groups/[id]/route.ts b/src/app/api/working-groups/[id]/route.ts
index 84d2ad9..d7f6638 100644
--- a/src/app/api/working-groups/[id]/route.ts
+++ b/src/app/api/working-groups/[id]/route.ts
@@ -25,7 +25,7 @@ export async function PATCH(request: Request, { params }: Context) {
}
if (!canManageBudgets(viewer.role)) {
- return NextResponse.json({ error: "Nur Vorstand oder Finanz-AG duerfen AGs bearbeiten." }, { status: 403 });
+ return NextResponse.json({ error: "Nur Vorstand oder Finanz-AG dürfen AGs bearbeiten." }, { status: 403 });
}
const body = await request.json().catch(() => null);
@@ -95,7 +95,7 @@ export async function DELETE(_: Request, { params }: Context) {
}
if (!canManageBudgets(viewer.role)) {
- return NextResponse.json({ error: "Nur Vorstand oder Finanz-AG duerfen AGs loeschen." }, { status: 403 });
+ return NextResponse.json({ error: "Nur Vorstand oder Finanz-AG dürfen AGs löschen." }, { status: 403 });
}
const workingGroup = await prisma.workingGroup.findUnique({
diff --git a/src/app/api/working-groups/route.ts b/src/app/api/working-groups/route.ts
index 4242837..7300ffd 100644
--- a/src/app/api/working-groups/route.ts
+++ b/src/app/api/working-groups/route.ts
@@ -19,7 +19,7 @@ export async function POST(request: Request) {
}
if (!canManageBudgets(viewer.role)) {
- return NextResponse.json({ error: "Nur Vorstand oder Finanz-AG duerfen AGs verwalten." }, { status: 403 });
+ return NextResponse.json({ error: "Nur Vorstand oder Finanz-AG dürfen AGs verwalten." }, { status: 403 });
}
const body = await request.json().catch(() => null);
diff --git a/src/components/dashboard/budget-column.tsx b/src/components/dashboard/budget-column.tsx
index 56f9163..38c3571 100644
--- a/src/components/dashboard/budget-column.tsx
+++ b/src/components/dashboard/budget-column.tsx
@@ -275,7 +275,7 @@ export function BudgetColumn({
fullWidth
/>
- AGs lassen sich nur loeschen, wenn keine Mitglieder, Budgets oder Ausgaben mehr daran haengen.
+ AGs lassen sich nur löschen, wenn keine Mitglieder, Budgets oder Ausgaben mehr daran hängen.
@@ -472,7 +472,7 @@ export function BudgetColumn({
sx={{ ...wrappingChipSx, width: "fit-content" }}
/>
- {`Unter ${formatCurrency(approvalThreshold)} werden sofort freigegeben. Groessere Ausgaben bleiben blass, bis alle drei Signaturen vorliegen.`}
+ {`Unter ${formatCurrency(approvalThreshold)} werden sofort freigegeben. Größere Ausgaben bleiben blass, bis alle drei Signaturen vorliegen.`}
diff --git a/src/components/dashboard/dashboard-shell.tsx b/src/components/dashboard/dashboard-shell.tsx
index 884ca5d..de81702 100644
--- a/src/components/dashboard/dashboard-shell.tsx
+++ b/src/components/dashboard/dashboard-shell.tsx
@@ -529,7 +529,7 @@ export function DashboardShell({
if (!budgetForm.workingGroupId) {
setMessage({
type: "error",
- text: "Bitte zuerst eine AG auswaehlen oder neu anlegen."
+ text: "Bitte zuerst eine AG auswählen oder neu anlegen."
});
return;
}
@@ -679,7 +679,7 @@ export function DashboardShell({
method: "DELETE"
})
);
- }, `Zeitraum ${periodName} wurde geloescht.`);
+ }, `Zeitraum ${periodName} wurde gelöscht.`);
}
async function handleSetCurrentPeriod() {
@@ -732,7 +732,7 @@ export function DashboardShell({
agId: current.agId === groupId ? nextGroup?.id ?? "" : current.agId,
budgetId: current.agId === groupId ? nextGroup?.budgets[0]?.id ?? "" : current.budgetId
}));
- }, `AG ${groupName} wurde geloescht.`);
+ }, `AG ${groupName} wurde gelöscht.`);
}
async function handleCreateUser(event: FormEvent) {
@@ -773,7 +773,7 @@ export function DashboardShell({
};
},
({ createdUsername, createdPassword }) =>
- `Nutzer wurde angelegt. Startpasswort fuer ${createdUsername}: ${createdPassword}`
+ `Nutzer wurde angelegt. Startpasswort für ${createdUsername}: ${createdPassword}`
);
}
@@ -983,7 +983,7 @@ export function DashboardShell({
Zeitraum wechseln
- {"Nur Vorstand und Finanz-AG koennen die aktuelle Uebersicht global umstellen."}
+ {"Nur Vorstand und Finanz-AG können die aktuelle Übersicht global umstellen."}
setSelectedCurrentPeriodId(event.target.value)}
fullWidth
@@ -1018,7 +1018,7 @@ export function DashboardShell({
onClick={handleSetCurrentPeriod}
sx={{ minWidth: 0, minHeight: 56, px: 2 }}
>
- {"Uebersicht setzen"}
+ {"Übersicht setzen"}
{selectedPeriodForManagement?.isCurrent
- ? "Der aktuell aktive Zeitraum kann nicht geloescht werden."
- : "Leere, nicht aktive Zeitraeume lassen sich hier wieder entfernen."}
+ ? "Der aktuell aktive Zeitraum kann nicht gelöscht werden."
+ : "Leere, nicht aktive Zeiträume lassen sich hier wieder entfernen."}
@@ -1087,7 +1087,7 @@ export function DashboardShell({
setPeriodForm((current) => ({
@@ -1096,9 +1096,9 @@ export function DashboardShell({
}))
}
fullWidth
- helperText={"Optional kopiert die vorhandenen Budgettoepfe direkt in den neuen Zeitraum."}
+ helperText={"Optional kopiert die vorhandenen Budgettöpfe direkt in den neuen Zeitraum."}
>
-
+
{accountingPeriods.map((period) => (
@@ -1330,8 +1330,8 @@ export function DashboardShell({
{selectedBudgetWorkingGroup
- ? `Neue Budgettoepfe landen in ${selectedBudgetWorkingGroup.name}.`
- : "Waehle zuerst eine bestehende AG aus."}
+ ? `Neue Budgettöpfe landen in ${selectedBudgetWorkingGroup.name}.`
+ : "Wähle zuerst eine bestehende AG aus."}
setUserForm((current) => ({ ...current, username: event.target.value }))}
required
@@ -1452,7 +1452,7 @@ export function DashboardShell({
}
required
fullWidth
- helperText={"Dieses Passwort wird nach dem Anlegen oben als Bestaetigung angezeigt."}
+ helperText={"Dieses Passwort wird nach dem Anlegen oben als Bestätigung angezeigt."}
/>
@@ -1631,14 +1631,14 @@ export function DashboardShell({
startIcon={}
disabled={busy || !canDelete}
onClick={async () => {
- if (!window.confirm(`Nutzer "${user.username}" wirklich loeschen?`)) {
+ if (!window.confirm(`Nutzer "${user.username}" wirklich löschen?`)) {
return;
}
await handleDeleteUser(user.id);
}}
>
- {"Loeschen"}
+ {"Löschen"}
@@ -1695,7 +1695,7 @@ export function DashboardShell({
? "Lege zuerst eine AG an."
: draft.role === "MEMBER"
? "AG-Mitglieder brauchen eine feste AG-Zuordnung."
- : "Optional: Auch Vorstand und Finanz-AG koennen einer AG zugeordnet werden."
+ : "Optional: Auch Vorstand und Finanz-AG können einer AG zugeordnet werden."
}
>
{draft.role !== "MEMBER" ? : null}
@@ -1754,7 +1754,7 @@ export function DashboardShell({
}
fullWidth
helperText={
- "Nur neu gesetzte Passwoerter sind sichtbar. Das alte Passwort bleibt absichtlich verborgen."
+ "Nur neu gesetzte Passwörter sind sichtbar. Das alte Passwort bleibt absichtlich verborgen."
}
/>
@@ -1907,16 +1907,16 @@ export function DashboardShell({
const overviewContent = (
- {isCompactLayout && visibleGroups.length > 1 ? (
+ {visibleGroups.length > 1 ? (
- {"AG ausw\u00e4hlen"}
+ AG auswählen
- {"Mobil zeigen wir jeweils eine AG auf einmal, damit die Budgetkarten sauber lesbar bleiben."}
+ Wähle die AG, die gerade in der Übersicht angezeigt werden soll.
) : null}
-
- {(isCompactLayout ? (mobileSelectedGroup ? [mobileSelectedGroup] : []) : visibleGroups).map((group) => (
+
+ {(mobileSelectedGroup ? [mobileSelectedGroup] : []).map((group) => (
))}