mirror of
https://github.com/MBombeck/HealthLog.git
synced 2026-11-14 22:50:51 +00:00
i18n: migrate from German-first to English-first default locale
Switch defaultLocale from "de" to "en" and make English the code-level language throughout. All ~145 hardcoded German strings translated: - API error messages (52 routes) now return English - Zod validation messages in English - Classification/analytics functions return English categories - Notification type labels in English - Component strings use i18n t() calls (heatmap, mood chart, medication form, intake history, password strength, insights card) - ~50 new i18n keys in both de.json and en.json Route migration: - /stimmung → /mood, /zielwerte → /targets (new pages) - 301 redirects in proxy.ts for legacy URLs - Sidebar + bottom nav updated Bump version to 1.0.1.
This commit is contained in:
1 parent
38309932f3
commit
0c0c345e82
74 files changed
+871
-402
No files matched your search
@@ -30,11 +30,11 @@ export const DELETE = apiHandler(async (request: NextRequest) => {
|
||||
const body = await request.json();
|
||||
confirm = typeof body?.confirm === "string" ? body.confirm : "";
|
||||
} catch {
|
||||
return apiError("Ungültige Anfrage", 422);
|
||||
return apiError("Invalid request", 422);
|
||||
}
|
||||
|
||||
if (confirm !== "DELETE ALL") {
|
||||
return apiError("Bestätigung fehlt", 422);
|
||||
return apiError("Confirmation missing", 422);
|
||||
}
|
||||
|
||||
const result = await prisma.$transaction(async (tx) => {
|
||||
|
||||
@@ -12,10 +12,10 @@ export const POST = apiHandler(async () => {
|
||||
|
||||
const settings = await getGlitchtipSettings();
|
||||
if (!settings.glitchtipEnabled) {
|
||||
return apiError("Glitchtip ist deaktiviert", 422);
|
||||
return apiError("Glitchtip is disabled", 422);
|
||||
}
|
||||
if (!settings.glitchtipDsn) {
|
||||
return apiError("Glitchtip DSN fehlt", 422);
|
||||
return apiError("Glitchtip DSN is missing", 422);
|
||||
}
|
||||
|
||||
const delivery = await sendGlitchtipEvent({
|
||||
@@ -32,13 +32,13 @@ export const POST = apiHandler(async () => {
|
||||
if (!delivery.ok) {
|
||||
getEvent()?.addWarning("Glitchtip test event rejected: " + delivery.method + " " + delivery.status + " " + delivery.details);
|
||||
return apiError(
|
||||
`Glitchtip-Testevent wurde abgelehnt (HTTP ${delivery.status ?? 502})`,
|
||||
`Glitchtip test event rejected (HTTP ${delivery.status ?? 502})`,
|
||||
502,
|
||||
);
|
||||
}
|
||||
|
||||
return apiSuccess({
|
||||
sent: true,
|
||||
message: "Glitchtip-Testevent wurde gesendet",
|
||||
message: "Glitchtip test event sent",
|
||||
});
|
||||
});
|
||||
@@ -51,18 +51,18 @@ export const POST = apiHandler(async (request: NextRequest) => {
|
||||
|
||||
const settings = await getPublicMonitoringSettings();
|
||||
if (!settings.umamiEnabled) {
|
||||
return apiError("Umami ist deaktiviert", 422);
|
||||
return apiError("Umami is disabled", 422);
|
||||
}
|
||||
if (!settings.umamiScriptUrl || !settings.umamiWebsiteId) {
|
||||
return apiError(
|
||||
"Umami Script-URL und Website-ID müssen konfiguriert sein",
|
||||
"Umami script URL and website ID must be configured",
|
||||
422,
|
||||
);
|
||||
}
|
||||
|
||||
const targetUrls = resolveUmamiSendUrls(settings.umamiScriptUrl);
|
||||
if (targetUrls.length === 0) {
|
||||
return apiError("Umami Script-URL ist ungültig", 422);
|
||||
return apiError("Umami script URL is invalid", 422);
|
||||
}
|
||||
|
||||
const appUrl = resolveAppUrl(request);
|
||||
@@ -100,7 +100,7 @@ export const POST = apiHandler(async (request: NextRequest) => {
|
||||
if (upstream.ok) {
|
||||
return apiSuccess({
|
||||
sent: true,
|
||||
message: "Umami-Testevent wurde gesendet",
|
||||
message: "Umami test event sent",
|
||||
});
|
||||
}
|
||||
|
||||
@@ -117,7 +117,7 @@ export const POST = apiHandler(async (request: NextRequest) => {
|
||||
|
||||
getEvent()?.addWarning("Umami test event rejected: " + lastStatus);
|
||||
return apiError(
|
||||
`Umami-Testevent wurde abgelehnt (HTTP ${lastStatus})`,
|
||||
`Umami test event rejected (HTTP ${lastStatus})`,
|
||||
502,
|
||||
);
|
||||
});
|
||||
@@ -79,7 +79,7 @@ export const POST = apiHandler(async () => {
|
||||
if (channels.length === 0) {
|
||||
return apiSuccess({
|
||||
sent: false,
|
||||
message: "Keine aktivierten Benachrichtigungskanäle gefunden",
|
||||
message: "No enabled notification channels found",
|
||||
results: [],
|
||||
});
|
||||
}
|
||||
@@ -89,7 +89,7 @@ export const POST = apiHandler(async () => {
|
||||
userId: user.id,
|
||||
title: "Test-Notification",
|
||||
message:
|
||||
"<b>HealthLog Test:</b> Wenn du diese Nachricht siehst, funktionieren deine Benachrichtigungen!",
|
||||
"<b>HealthLog Test:</b> If you see this message, your notifications are working!",
|
||||
};
|
||||
|
||||
const results: Array<{
|
||||
@@ -104,7 +104,7 @@ export const POST = apiHandler(async () => {
|
||||
results.push({
|
||||
channel: channel.type,
|
||||
success: false,
|
||||
error: "SYSTEM_ALERT deaktiviert in Einstellungen",
|
||||
error: "SYSTEM_ALERT disabled in settings",
|
||||
});
|
||||
continue;
|
||||
}
|
||||
@@ -124,7 +124,7 @@ export const POST = apiHandler(async () => {
|
||||
results.push({
|
||||
channel: "TELEGRAM",
|
||||
success: false,
|
||||
error: `Telegram API hat Fehler gemeldet (chatId: ${config.chatId})`,
|
||||
error: `Telegram API reported error (chatId: ${config.chatId})`,
|
||||
});
|
||||
continue;
|
||||
}
|
||||
@@ -139,7 +139,7 @@ export const POST = apiHandler(async () => {
|
||||
results.push({
|
||||
channel: "NTFY",
|
||||
success: false,
|
||||
error: `Senden fehlgeschlagen (topic: ${config.topic})`,
|
||||
error: `Send failed (topic: ${config.topic})`,
|
||||
});
|
||||
continue;
|
||||
}
|
||||
@@ -153,7 +153,7 @@ export const POST = apiHandler(async () => {
|
||||
results.push({
|
||||
channel: type,
|
||||
success: false,
|
||||
error: "Unbekannter Kanaltyp",
|
||||
error: "Unknown channel type",
|
||||
});
|
||||
continue;
|
||||
}
|
||||
@@ -163,7 +163,7 @@ export const POST = apiHandler(async () => {
|
||||
results.push({
|
||||
channel: channel.type,
|
||||
success: false,
|
||||
error: err instanceof Error ? err.message : "Unbekannter Fehler",
|
||||
error: err instanceof Error ? err.message : "Unknown error",
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -173,11 +173,11 @@ export const POST = apiHandler(async () => {
|
||||
|
||||
let message: string;
|
||||
if (failCount === 0) {
|
||||
message = `Alle ${successCount} Kanäle erfolgreich`;
|
||||
message = `All ${successCount} channels successful`;
|
||||
} else if (successCount === 0) {
|
||||
message = `Alle ${failCount} Kanäle fehlgeschlagen`;
|
||||
message = `All ${failCount} channels failed`;
|
||||
} else {
|
||||
message = `${successCount} erfolgreich, ${failCount} fehlgeschlagen`;
|
||||
message = `${successCount} successful, ${failCount} failed`;
|
||||
}
|
||||
|
||||
return apiSuccess({ sent: successCount > 0, message, results });
|
||||
|
||||
@@ -180,7 +180,7 @@ export const PUT = apiHandler(async (request: NextRequest) => {
|
||||
}
|
||||
|
||||
if (Object.keys(updates).length === 0) {
|
||||
return apiError("Keine gültigen Felder", 422);
|
||||
return apiError("No valid fields", 422);
|
||||
}
|
||||
|
||||
const settings = await prisma.appSettings.upsert({
|
||||
|
||||
@@ -32,16 +32,16 @@ export const POST = apiHandler(async (
|
||||
const { password } = body as { password?: string };
|
||||
|
||||
if (!password || typeof password !== "string") {
|
||||
return apiError("Passwort erforderlich", 422);
|
||||
return apiError("Password required", 422);
|
||||
}
|
||||
|
||||
const target = await prisma.user.findUnique({ where: { id } });
|
||||
if (!target) return apiError("Benutzer nicht gefunden", 404);
|
||||
if (!target) return apiError("User not found", 404);
|
||||
|
||||
const strength = checkPasswordStrength(password, [target.username]);
|
||||
if (!strength.isAcceptable) {
|
||||
return apiError(
|
||||
strength.feedback[0] || "Passwort zu schwach (Score < 3)",
|
||||
strength.feedback[0] || "Password too weak (score < 3)",
|
||||
422,
|
||||
);
|
||||
}
|
||||
|
||||
@@ -30,13 +30,13 @@ export const PUT = apiHandler(async (
|
||||
}
|
||||
|
||||
const target = await prisma.user.findUnique({ where: { id } });
|
||||
if (!target) return apiError("Benutzer nicht gefunden", 404);
|
||||
if (!target) return apiError("User not found", 404);
|
||||
|
||||
// Prevent removing the last admin
|
||||
if (parsed.data.role === "USER" && target.role === "ADMIN") {
|
||||
const adminCount = await prisma.user.count({ where: { role: "ADMIN" } });
|
||||
if (adminCount <= 1) {
|
||||
return apiError("Der letzte Admin kann nicht degradiert werden", 400);
|
||||
return apiError("The last admin cannot be demoted", 400);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in new issue
Block a user