mirror of
https://github.com/MBombeck/HealthLog.git
synced 2026-11-07 12:22:03 +00:00
i18n+ui: backlog quick-wins sweep (F-32/33/34/35/44/45/47/50/58/62 + 2 mediums)
Cluster of the v1.4.21 carry-over items that each landed in ≤5 LOC.
- F-32 — drop the duplicate help paragraph beneath the dashboard
settings header; the page-level description already covers it
- F-33 / F-34 — replace `&` with "and"/"und" in the measurements and
mood subtitles
- F-35 — unify the test-notification button label
(notificationTestSend) with the user-facing notificationStatus.sendTest
- F-44 — drop the `LOKI_ENDPOINT` env-var name from the user-facing
monitoring help text; reads as "Loki integration" instead
- F-45 — admin/users table column reads "Name" instead of repeating
the page title "Users"
- F-47 — /notifications event-matrix first column reads "Event" instead
of repeating the page title "Notifications" — new notifications.eventColumn key
- F-50 — soften every DE error-toast "Bitte erneut versuchen" to
"Bitte versuche es erneut", matching the friendlier tone we already
use in the Coach error path
- F-58 — admin/reminders section header swaps Clock for Bell so the
card icon matches the admin-shell nav tile
- F-62 — DE dashboard `greetingSalutation` reads "Hallo, {name}"
instead of the English "Hi, {name}"
- D-CR-M-03 — formatTokenName regex broadens to non-Z ISO offsets so a
`+02:00` timestamp suffix renders as the locale-aware chunk like a
`Z` suffix already does
- D-DSGN-M-04 — moodLog "Copy" button uses common.copy instead of
stripping the `!` off common.copied
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
1 parent
15796c148b
commit
1499e6f83c
8 files changed
+46
-23
No files matched your search
+13
-11
@@ -216,7 +216,7 @@
|
||||
},
|
||||
"welcomeBack": "{greeting}, willkommen zurück.",
|
||||
"welcomeBackWithName": "{greeting} {name}, willkommen zurück.",
|
||||
"greetingSalutation": "Hi, {name}",
|
||||
"greetingSalutation": "Hallo, {name}",
|
||||
"streakLabel": "Tage in Folge",
|
||||
"weight": "Gewicht",
|
||||
"bloodPressure": "Blutdruck",
|
||||
@@ -262,7 +262,7 @@
|
||||
},
|
||||
"measurements": {
|
||||
"title": "Messungen",
|
||||
"subtitle": "Gewicht, Blutdruck, Puls & mehr",
|
||||
"subtitle": "Gewicht, Blutdruck, Puls und mehr",
|
||||
"addMeasurement": "Hinzufügen",
|
||||
"editMeasurement": "Messwert bearbeiten",
|
||||
"type": "Typ",
|
||||
@@ -327,7 +327,7 @@
|
||||
},
|
||||
"mood": {
|
||||
"title": "Stimmung",
|
||||
"subtitle": "Stimmungsverlauf & Einträge",
|
||||
"subtitle": "Stimmungsverlauf und Einträge",
|
||||
"addEntry": "Hinzufügen",
|
||||
"editEntry": "Eintrag bearbeiten",
|
||||
"moodLevel": "Stimmung",
|
||||
@@ -744,7 +744,7 @@
|
||||
"confidenceMittel": "Mittel",
|
||||
"confidenceGering": "Gering",
|
||||
"loadError": "Auswertungen konnten nicht geladen werden",
|
||||
"generationFailed": "Die Analyse konnte nicht erstellt werden. Bitte erneut versuchen.",
|
||||
"generationFailed": "Die Analyse konnte nicht erstellt werden. Bitte versuche es erneut.",
|
||||
"title": "Insights",
|
||||
"subtitle": "KI-basierte Analyse deiner Gesundheitsdaten",
|
||||
"overviewSubtitle": "Trends, Risiken, Fortschritt auf einen Blick",
|
||||
@@ -1071,10 +1071,10 @@
|
||||
"targetSys": "Systolisch (mmHg)",
|
||||
"targetDia": "Diastolisch (mmHg)",
|
||||
"targetWeight": "Zielgewicht (kg)",
|
||||
"errorProfile": "Dein Profil konnte nicht gespeichert werden. Bitte erneut versuchen.",
|
||||
"errorMedication": "Das Medikament „{name}\" konnte nicht angelegt werden. Bitte erneut versuchen oder später unter „Medikamente\" hinzufügen.",
|
||||
"errorTargets": "Deine Zielwerte konnten nicht gespeichert werden. Bitte erneut versuchen.",
|
||||
"errorGeneric": "Beim Abschluss des Setups ist etwas schiefgelaufen. Bitte erneut versuchen.",
|
||||
"errorProfile": "Dein Profil konnte nicht gespeichert werden. Bitte versuche es erneut.",
|
||||
"errorMedication": "Das Medikament „{name}\" konnte nicht angelegt werden. Bitte versuche es erneut oder lege es später unter „Medikamente\" an.",
|
||||
"errorTargets": "Deine Zielwerte konnten nicht gespeichert werden. Bitte versuche es erneut.",
|
||||
"errorGeneric": "Beim Abschluss des Setups ist etwas schiefgelaufen. Bitte versuche es erneut.",
|
||||
"medScheduleHint": "Wir legen ein Standard-Erinnerungsfenster an (08:00–09:00 täglich). Du kannst es jederzeit unter „Medikamente\" anpassen.",
|
||||
"v2": {
|
||||
"title": "Willkommen bei HealthLog",
|
||||
@@ -1306,7 +1306,7 @@
|
||||
"passkeyNotSupported": "Dein Browser oder Gerät unterstützt Passkeys noch nicht. Bitte einen anderen Browser oder ein anderes Gerät verwenden.",
|
||||
"passkeyAlreadyRegistered": "Dieses Gerät ist bereits als Passkey für dein Konto registriert.",
|
||||
"passkeySecurityBlocked": "Dein Browser hat die Passkey-Anfrage aus Sicherheitsgründen blockiert. Bitte auf einer vertrauenswürdigen HTTPS-URL erneut versuchen.",
|
||||
"passkeyTimeout": "Die Passkey-Aufforderung ist abgelaufen. Bitte erneut versuchen.",
|
||||
"passkeyTimeout": "Die Passkey-Aufforderung ist abgelaufen. Bitte versuche es erneut.",
|
||||
"passkeyUnknownError": "Passkey-Registrierung fehlgeschlagen: {message}",
|
||||
"deletePasskey": "Passkey löschen?",
|
||||
"deletePasskeyDescription": "Der Passkey wird unwiderruflich gelöscht.",
|
||||
@@ -1810,6 +1810,7 @@
|
||||
"bugReportNotConfigured": "Bugreport ist noch nicht vollständig konfiguriert.",
|
||||
"bugReportSave": "Bugreport speichern",
|
||||
"userManagement": "Benutzerverwaltung",
|
||||
"userName": "Name",
|
||||
"userEmail": "E-Mail",
|
||||
"userRole": "Rolle",
|
||||
"userPasskeys": "Passkeys",
|
||||
@@ -1885,7 +1886,7 @@
|
||||
"reminderMissedMinutesDescription": "Minuten nach Fenster-Ende bis die Einnahme als verpasst gilt.",
|
||||
"reminderThresholdsSave": "Schwellenwerte speichern",
|
||||
"notificationTest": "Benachrichtigungen testen",
|
||||
"notificationTestSend": "Test-Notification senden",
|
||||
"notificationTestSend": "Test senden",
|
||||
"notificationTestSuccess": "Test-Notification wurde gesendet",
|
||||
"notificationTestFailed": "Test-Notification konnte nicht gesendet werden",
|
||||
"reminderCheckRun": "Reminder-Check ausführen",
|
||||
@@ -2045,7 +2046,7 @@
|
||||
"app-logs": {
|
||||
"title": "App-Logs",
|
||||
"subtitle": "Letzte strukturierte Wide-Events dieses Prozesses anzeigen.",
|
||||
"processNote": "Es werden nur App-Prozess-Logs angezeigt — Worker-Logs landen in Loki, sofern LOKI_ENDPOINT konfiguriert ist. Der Puffer ist flüchtig und auf 500 Einträge begrenzt.",
|
||||
"processNote": "Es werden nur App-Prozess-Logs angezeigt — Worker-Logs landen in Loki, sofern die Integration konfiguriert ist. Der Puffer ist flüchtig und auf 500 Einträge begrenzt.",
|
||||
"filterTraceId": "Trace-ID",
|
||||
"filterAction": "Aktion enthält…",
|
||||
"filterLevel": "Level",
|
||||
@@ -2433,6 +2434,7 @@
|
||||
},
|
||||
"notifications": {
|
||||
"title": "Benachrichtigungen",
|
||||
"eventColumn": "Ereignis",
|
||||
"subtitle": "Wähle aus, welche Benachrichtigungen du über welchen Kanal erhalten möchtest.",
|
||||
"noChannels": "Konfiguriere zuerst einen Benachrichtigungskanal in den Einstellungen.",
|
||||
"goToSettings": "Zu den Einstellungen",
|
||||
|
||||
+6
-4
@@ -262,7 +262,7 @@
|
||||
},
|
||||
"measurements": {
|
||||
"title": "Measurements",
|
||||
"subtitle": "Weight, blood pressure, pulse & more",
|
||||
"subtitle": "Weight, blood pressure, pulse and more",
|
||||
"addMeasurement": "Add",
|
||||
"editMeasurement": "Edit measurement",
|
||||
"type": "Type",
|
||||
@@ -327,7 +327,7 @@
|
||||
},
|
||||
"mood": {
|
||||
"title": "Mood",
|
||||
"subtitle": "Mood tracker & entries",
|
||||
"subtitle": "Mood tracker and entries",
|
||||
"addEntry": "Add",
|
||||
"editEntry": "Edit entry",
|
||||
"moodLevel": "Mood",
|
||||
@@ -1810,6 +1810,7 @@
|
||||
"bugReportNotConfigured": "Bug report is not fully configured yet.",
|
||||
"bugReportSave": "Save bug report settings",
|
||||
"userManagement": "User Management",
|
||||
"userName": "Name",
|
||||
"userEmail": "Email",
|
||||
"userRole": "Role",
|
||||
"userPasskeys": "Passkeys",
|
||||
@@ -1885,7 +1886,7 @@
|
||||
"reminderMissedMinutesDescription": "Minutes after window end until the intake is considered missed.",
|
||||
"reminderThresholdsSave": "Save thresholds",
|
||||
"notificationTest": "Test Notifications",
|
||||
"notificationTestSend": "Send test notification",
|
||||
"notificationTestSend": "Send test",
|
||||
"notificationTestSuccess": "Test notification sent",
|
||||
"notificationTestFailed": "Failed to send test notification",
|
||||
"reminderCheckRun": "Run reminder check",
|
||||
@@ -2045,7 +2046,7 @@
|
||||
"app-logs": {
|
||||
"title": "App Logs",
|
||||
"subtitle": "Tail the most recent structured wide-events emitted by this process.",
|
||||
"processNote": "Showing app-process logs only — worker-process logs go to Loki when LOKI_ENDPOINT is configured. Buffer is volatile and capped at 500 entries.",
|
||||
"processNote": "Showing app-process logs only — worker-process logs go to Loki when that integration is configured. Buffer is volatile and capped at 500 entries.",
|
||||
"filterTraceId": "Trace ID",
|
||||
"filterAction": "Action contains…",
|
||||
"filterLevel": "Level",
|
||||
@@ -2433,6 +2434,7 @@
|
||||
},
|
||||
"notifications": {
|
||||
"title": "Notifications",
|
||||
"eventColumn": "Event",
|
||||
"subtitle": "Choose which notifications you want to receive through which channel.",
|
||||
"noChannels": "Configure a notification channel in Settings first.",
|
||||
"goToSettings": "Go to Settings",
|
||||
|
||||
@@ -191,7 +191,7 @@ export default function NotificationsPage() {
|
||||
<thead>
|
||||
<tr className="border-border border-b">
|
||||
<th className="text-muted-foreground px-4 py-3 text-left text-xs font-medium tracking-wider uppercase">
|
||||
{t("notifications.title")}
|
||||
{t("notifications.eventColumn")}
|
||||
</th>
|
||||
{activeChannels.map((ch) => (
|
||||
<th
|
||||
|
||||
@@ -63,8 +63,13 @@ function TruncatedCell({
|
||||
* "iOS auto-login · 05.05.2026 19:46" while leaving any non-ISO suffix
|
||||
* (manual names, device fingerprints, etc.) untouched.
|
||||
*/
|
||||
// v1.4.22 D / D-CR-M-03 — broaden the ISO match to include non-Z
|
||||
// offsets (e.g. `+02:00`, `-05:30`). The previous regex only matched
|
||||
// UTC (`Z`), so a token name carrying a local-tz timestamp slipped
|
||||
// through unformatted and rendered the raw `2026-05-05T19:46:20.603+02:00`
|
||||
// suffix instead of the locale-aware `05.05.2026 21:46` chunk.
|
||||
const TOKEN_NAME_ISO_RE =
|
||||
/^(.+?)\s+(\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(?:\.\d+)?Z)(.*)$/;
|
||||
/^(.+?)\s+(\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(?:\.\d+)?(?:Z|[+-]\d{2}:?\d{2}))(.*)$/;
|
||||
|
||||
// Locale-fixed dd.MM.yyyy HH:mm in the Europe/Berlin display zone — the
|
||||
// rest of the app shows timestamps in Berlin time (`format-locale.ts`),
|
||||
|
||||
@@ -115,7 +115,10 @@ export function RemindersSection() {
|
||||
return (
|
||||
<div className="bg-card border-border rounded-xl border p-6">
|
||||
<div className="flex items-center gap-2">
|
||||
<Clock className="text-primary h-5 w-5" />
|
||||
{/* v1.4.22 D / F-58 — icon swap so the section header matches
|
||||
the admin-shell nav tile (Bell). Clock now lives on the
|
||||
timing chips inline instead of competing as the page icon. */}
|
||||
<Bell className="text-primary h-5 w-5" />
|
||||
<div className="text-lg font-semibold">
|
||||
{t("admin.medicationReminders")}
|
||||
</div>
|
||||
|
||||
@@ -311,7 +311,7 @@ export function UserManagementSection() {
|
||||
<thead>
|
||||
<tr className="text-muted-foreground border-b text-xs">
|
||||
<th className="px-3 py-2 text-left font-medium">
|
||||
{t("admin.users")}
|
||||
{t("admin.userName")}
|
||||
</th>
|
||||
<th className="px-3 py-2 text-left font-medium">
|
||||
{t("admin.userEmail")}
|
||||
|
||||
@@ -181,9 +181,17 @@ export function DashboardLayoutSection({ id }: { id: string }) {
|
||||
{t("dashboard.layoutReset")}
|
||||
</Button>
|
||||
</div>
|
||||
<p className="text-muted-foreground text-sm">
|
||||
{t("dashboard.customizeSubtitle")}
|
||||
</p>
|
||||
{/*
|
||||
v1.4.22 D / F-32 — the surrounding `<DashboardSection>` page
|
||||
already renders a `settings.sections.dashboard.description`
|
||||
paragraph beneath the H1. The previous in-card help line
|
||||
repeated the same idea ("Choose which cards appear …
|
||||
Defaults work out of the box.") right next to the comparison
|
||||
picker, giving the page three muted-foreground help blocks
|
||||
stacked on top of each other. Removing this duplicate keeps
|
||||
the comparison picker as the only thing between the header
|
||||
and the widget table.
|
||||
*/}
|
||||
|
||||
{/* v1.4.16 phase B8 — comparison baseline picker. Lives at the top
|
||||
of the section because it changes how every chart + tile below
|
||||
|
||||
@@ -721,7 +721,10 @@ function MoodLogCard({
|
||||
setMsgType("success");
|
||||
}}
|
||||
>
|
||||
{t("common.copied").replace("!", "")}
|
||||
{/* v1.4.22 D / D-DSGN-M-04 — use the proper
|
||||
common.copy key instead of stripping the
|
||||
exclamation off common.copied. */}
|
||||
{t("common.copy")}
|
||||
</Button>
|
||||
</div>
|
||||
<p className="text-muted-foreground mt-1 text-xs">
|
||||
|
||||
Reference in new issue
Block a user