fix(i18n): drop the "KI"/"AI" prefix from user-facing copy

Marc-Voice rule — the product never names itself "KI" or "AI" in
copy. Settings -> "KI-Auswertungen" becomes "Auswertungen" / "Insights",
the inner "KI-Insights" card heading collapses into the parent section
heading, "Aktiver KI-Provider" becomes "Aktiver Provider", and the
admin "AI Quality" view becomes "Insights Quality".

Sweep across de / en / es / fr / it / pl. Provider product names
(Anthropic, Claude, ChatGPT, OpenAI) are unchanged — those are
proper nouns, not the "AI" label.
This commit is contained in:
Marc-André Bombeck committed 2026-05-16 17:56:34 +02:00
1 parent 0cac3d3545
commit 432ebccdae
11 files changed
+173 -151

No files matched your search

+22 -22
View File
@@ -1024,7 +1024,7 @@
"refusalOutOfScope": "Ich kann nur bei den Gesundheitsdaten in deinem Log helfen — Messwerte, Medikamente, Stimmung, Trends. Fragen außerhalb dieses Themas beantworte ich nicht.",
"refusalInjection": "In deiner Nachricht stehen Anweisungen, die meine Vorgaben überschreiben sollen. Ich bin der HealthLog-Coach und fasse ausschließlich deine eigenen Gesundheitsdaten zusammen — formuliere deine Frage bitte in diesem Rahmen neu.",
"errorBudget": "Du hast das heutige Coach-Limit erreicht. Das Budget setzt sich um Mitternacht (UTC) zurück.",
"errorProvider": "Der Coach konnte gerade keinen KI-Anbieter erreichen. Bitte versuche es in einem Moment erneut.",
"errorProvider": "Der Coach konnte gerade keinen Auswertungs-Anbieter erreichen. Bitte versuche es in einem Moment erneut.",
"tagline": "Persönlicher Gesundheitscoach, auf deine Daten gestützt.",
"newChat": "Neuer Chat",
"send": "Senden",
@@ -1162,19 +1162,19 @@
}
},
"subPage": {
"blutdruckDescription": "Dein systolisch-/diastolisch-Verlauf mit altersangepassten Zielbereichen und einer textbasierten KI-Einschätzung.",
"gewichtDescription": "Gewichtsverlauf gegen das aus deiner Größe abgeleitete gesunde Band, mit KI-Einschätzung.",
"pulsDescription": "Pulsverlauf gegenüber dem persönlichen Karvonen-Zielband, mit KI-Einschätzung.",
"stimmungDescription": "Tägliche Stimmungswerte im Zeitverlauf mit einer textbasierten KI-Einschätzung.",
"blutdruckDescription": "Dein systolisch-/diastolisch-Verlauf mit altersangepassten Zielbereichen und einer textbasierten Einschätzung.",
"gewichtDescription": "Gewichtsverlauf gegen das aus deiner Größe abgeleitete gesunde Band, mit Einschätzung.",
"pulsDescription": "Pulsverlauf gegenüber dem persönlichen Karvonen-Zielband, mit Einschätzung.",
"stimmungDescription": "Tägliche Stimmungswerte im Zeitverlauf mit einer textbasierten Einschätzung.",
"stimmungEmptyTitle": "Erste Stimmung erfassen",
"stimmungEmptyDescription": "Stimmungs-Insights erscheinen, sobald du einige Einträge protokolliert hast. Tippe unten, um zu beginnen.",
"stimmungEmptyAction": "Stimmungs-Tagebuch öffnen",
"medikamenteDescription": "Einnahme-Kalender pro Medikament plus eine textbasierte KI-Einschätzung.",
"medikamenteDescription": "Einnahme-Kalender pro Medikament plus eine textbasierte Einschätzung.",
"medikamenteEmptyTitle": "Erstes Medikament hinzufügen",
"medikamenteEmptyDescription": "Adhärenz-Insights brauchen mindestens ein erfasstes Medikament.",
"medikamenteEmptyAction": "Medikamente öffnen",
"therapyTimelineDescription": "Chronologisches GLP-1-Therapieprotokoll — Dosis-Änderungen, Injektionen, Bestand, Nebenwirkungen.",
"bmiDescription": "BMI aus deinem Gewicht und deiner Größe abgeleitet, mit KI-Einschätzung."
"bmiDescription": "BMI aus deinem Gewicht und deiner Größe abgeleitet, mit Einschätzung."
},
"sleep": {
"title": "Schlaf",
@@ -1370,12 +1370,12 @@
"body": "Über den Hinzufügen-Button kannst du Messungen oder Stimmungseinträge anlegen, ohne das Dashboard zu verlassen. Das Formular merkt sich deinen letzten Kontext und Tags."
},
"insights": {
"title": "KI-gestützte Einblicke",
"body": "Insights verwandelt deine Werte in eine klare Gesundheits-Zusammenfassung, mit Einordnung von Blutdruck, Gewicht und Stimmung. Eigener KI-Key oder Standard — du entscheidest."
"title": "Automatische Einblicke",
"body": "Insights verwandelt deine Werte in eine klare Gesundheits-Zusammenfassung, mit Einordnung von Blutdruck, Gewicht und Stimmung. Eigener Provider-Key oder Standard — du entscheidest."
},
"integrations": {
"title": "Geräte verbinden",
"body": "In den Einstellungen verbindest du Withings (Auto-Sync für Gewicht, Blutdruck, Puls), moodLog oder deinen KI-Provider. Alles bleibt optional und verschlüsselt."
"body": "In den Einstellungen verbindest du Withings (Auto-Sync für Gewicht, Blutdruck, Puls), moodLog oder deinen Auswertungs-Provider. Alles bleibt optional und verschlüsselt."
},
"achievements": {
"title": "Streaks und Badges sammeln",
@@ -1569,7 +1569,7 @@
}
},
"ai": {
"title": "KI-Auswertungen",
"title": "Auswertungen",
"description": "Provider, Modell, API-Key."
},
"api": {
@@ -1699,22 +1699,22 @@
"webPushUnsubscribed": "Push-Benachrichtigungen deaktiviert.",
"webPushSubscribeFailed": "Aktivierung fehlgeschlagen",
"webPushActive": "Aktiv",
"kiInsights": "KI-Insights (OpenAI)",
"kiInsightsDescription": "Optional: Hinterlege deinen OpenAI-Key für tägliche, automatische KI-Auswertungen in den Insights.",
"codexConnected": "ChatGPT erfolgreich verbunden! KI-Insights sind jetzt aktiv.",
"kiInsights": "Insights (OpenAI)",
"kiInsightsDescription": "Optional: Hinterlege deinen OpenAI-Key für tägliche, automatische Auswertungen in den Insights.",
"codexConnected": "ChatGPT erfolgreich verbunden! Insights sind jetzt aktiv.",
"codexDisconnected": "ChatGPT-Verbindung getrennt.",
"codexConnectionFailed": "ChatGPT-Verbindung fehlgeschlagen. Bitte versuche es erneut.",
"rawData": "Rohdaten mitsenden",
"rawDataOnDescription": "Es werden aggregierte Kennzahlen plus anonymisierte Rohdaten der letzten 30 Tage gesendet. Dazu zählen einzelne Messpunkte je Bereich (z. B. Gewicht, Blutdruck, Puls) mit Zeitbezug, damit die KI zeitliche Muster, Ausreißer und Zusammenhänge zuverlässiger erkennen kann. Nicht übertragen werden Name, E-Mail oder direkte Kontodaten.",
"rawDataOffDescription": "Es werden nur zusammengefasste Werte gesendet (z. B. Durchschnitt, Trend, Minimum/Maximum). Keine einzelnen Messpunkte und keine exakten Zeitbezüge. Das ist datensparsamer, die KI kann dafür aber weniger fein auf Muster und kurzfristige Schwankungen eingehen.",
"rawDataWarning": "Rohdaten aktiv: Die KI erhält zusätzlich anonymisierte Messpunkte der letzten 30 Tage für eine präzisere Auswertung.",
"rawDataOnDescription": "Es werden aggregierte Kennzahlen plus anonymisierte Rohdaten der letzten 30 Tage gesendet. Dazu zählen einzelne Messpunkte je Bereich (z. B. Gewicht, Blutdruck, Puls) mit Zeitbezug, damit der Provider zeitliche Muster, Ausreißer und Zusammenhänge zuverlässiger erkennen kann. Nicht übertragen werden Name, E-Mail oder direkte Kontodaten.",
"rawDataOffDescription": "Es werden nur zusammengefasste Werte gesendet (z. B. Durchschnitt, Trend, Minimum/Maximum). Keine einzelnen Messpunkte und keine exakten Zeitbezüge. Das ist datensparsamer, der Provider kann dafür aber weniger fein auf Muster und kurzfristige Schwankungen eingehen.",
"rawDataWarning": "Rohdaten aktiv: Der Provider erhält zusätzlich anonymisierte Messpunkte der letzten 30 Tage für eine präzisere Auswertung.",
"regenerateInsights": "Reports neu generieren",
"regenerateSuccess": "Reports wurden neu generiert",
"regenerateRateLimit": "Bitte warte — du hast das stündliche Limit für Analysen erreicht.",
"lastGeneratedAt": "Zuletzt generiert",
"ai": {
"chatgptConnectedBadge": "ChatGPT verbunden",
"adminAiActiveBadge": "Admin-KI aktiv",
"adminAiActiveBadge": "Admin-Provider aktiv",
"connectionExpiredBadge": "Verbindung abgelaufen",
"connectedSince": "Verbunden seit {when}.",
"deviceCodeHeading": "Verbindung auf chatgpt.com abschließen",
@@ -1760,7 +1760,7 @@
"resetConfirmTitle": "Kette auf Standard zurücksetzen?",
"resetConfirmBody": "Die Kette wird auf Codex → OpenAI → Anthropic → Lokal → Admin-OpenAI zurückgesetzt. Gespeicherte Zugangsdaten bleiben erhalten."
},
"activeProviderHeading": "Aktiver KI-Provider",
"activeProviderHeading": "Aktiver Provider",
"activeProviderBody": "Wähle den Provider, der zuerst genutzt wird. Das Formular darunter konfiguriert ausschließlich den ausgewählten Provider; die Fallback-Kette unten regelt, was passiert, wenn er ausfällt.",
"activeProviderLabel": "Primärer Provider",
"providerConfigTitle": "Provider-Konfiguration",
@@ -1988,9 +1988,9 @@
"loadError": "Host-Metriken konnten nicht geladen werden. Bitte die Seite neu laden."
},
"aiQuality": {
"title": "KI-Qualität",
"title": "Auswertungs-Qualität",
"loading": "Feedback-Zusammenfassung wird geladen...",
"loadError": "KI-Qualitätszusammenfassung konnte nicht geladen werden. Bitte die Seite neu laden.",
"loadError": "Qualitätszusammenfassung konnte nicht geladen werden. Bitte die Seite neu laden.",
"empty": "Noch kein Feedback. Der Aggregator läuft täglich um 04:00 — sobald Nutzer Empfehlungen bewerten, erscheinen hier die Hilfreich-Quoten.",
"windowLabel": "Letzte {days} Tage",
"generatedAtLabel": "Erstellt",
@@ -2276,7 +2276,7 @@
"subtitle": "Umami, GlitchTip, Web Push und Bug-Reports konfigurieren."
},
"ai-quality": {
"title": "KI-Qualität",
"title": "Auswertungs-Qualität",
"subtitle": "Hilfreichkeit nach Schweregrad und Provider — Nutzer-Feedback der letzten 30 Tage."
},
"assistant": {
+22 -22
View File
@@ -1024,7 +1024,7 @@
"refusalOutOfScope": "I can only help with the health metrics in your log — measurements, medications, mood, trends. I cannot answer questions outside that scope.",
"refusalInjection": "I noticed wording that tries to override my instructions. I am the HealthLog Coach and only summarise your own health data — please rephrase your question in those terms.",
"errorBudget": "You've reached today's Coach usage limit. The budget refreshes at midnight UTC.",
"errorProvider": "The Coach could not reach an AI provider just now. Please try again in a moment.",
"errorProvider": "The Coach could not reach an Insights provider just now. Please try again in a moment.",
"tagline": "Personal health coach, grounded in your data.",
"newChat": "New chat",
"send": "Send",
@@ -1162,19 +1162,19 @@
}
},
"subPage": {
"blutdruckDescription": "Your systolic / diastolic trend with age-personalised target zones and a written AI assessment.",
"gewichtDescription": "Weight trend mapped against your height-derived healthy band, plus an AI assessment.",
"pulsDescription": "Pulse trend against the personalised Karvonen target band, plus an AI assessment.",
"stimmungDescription": "Daily mood scores over time with a written AI assessment.",
"blutdruckDescription": "Your systolic / diastolic trend with age-personalised target zones and a written assessment.",
"gewichtDescription": "Weight trend mapped against your height-derived healthy band, plus a written assessment.",
"pulsDescription": "Pulse trend against the personalised Karvonen target band, plus a written assessment.",
"stimmungDescription": "Daily mood scores over time with a written assessment.",
"stimmungEmptyTitle": "Log your first mood",
"stimmungEmptyDescription": "Mood insights light up once you've logged a few entries. Tap below to get started.",
"stimmungEmptyAction": "Open mood journal",
"medikamenteDescription": "Per-medication adherence calendars and a written AI assessment.",
"medikamenteDescription": "Per-medication adherence calendars and a written assessment.",
"medikamenteEmptyTitle": "Add your first medication",
"medikamenteEmptyDescription": "Compliance insights need at least one tracked medication.",
"medikamenteEmptyAction": "Open medications",
"therapyTimelineDescription": "Chronological GLP-1 therapy log — dose changes, injections, inventory, side effects.",
"bmiDescription": "BMI derived from your weight and height, with a written AI assessment."
"bmiDescription": "BMI derived from your weight and height, with a written assessment."
},
"sleep": {
"title": "Sleep",
@@ -1370,12 +1370,12 @@
"body": "Use the Add button to drop a measurement or mood entry without leaving the dashboard. The form remembers your last context and tags."
},
"insights": {
"title": "AI-assisted insights",
"body": "Insights turns your readings into a plain-English health summary, with classifications for blood pressure, weight trend and mood. Bring your own AI key or use the built-in default."
"title": "Automatic insights",
"body": "Insights turns your readings into a plain-English health summary, with classifications for blood pressure, weight trend and mood. Bring your own provider key or use the built-in default."
},
"integrations": {
"title": "Connect your devices",
"body": "Open Settings to link Withings (auto-sync weight, BP and pulse), moodLog, or your AI provider. Everything stays optional and encrypted."
"body": "Open Settings to link Withings (auto-sync weight, BP and pulse), moodLog, or your Insights provider. Everything stays optional and encrypted."
},
"achievements": {
"title": "Earn streaks and badges",
@@ -1569,7 +1569,7 @@
}
},
"ai": {
"title": "AI Insights",
"title": "Insights",
"description": "Provider, model, key."
},
"api": {
@@ -1699,22 +1699,22 @@
"webPushUnsubscribed": "Push notifications disabled.",
"webPushSubscribeFailed": "Activation failed",
"webPushActive": "Active",
"kiInsights": "AI Insights (OpenAI)",
"kiInsightsDescription": "Optional: Save your OpenAI key for daily, automatic AI evaluations in Insights.",
"codexConnected": "ChatGPT connected successfully! AI insights are now active.",
"kiInsights": "Insights (OpenAI)",
"kiInsightsDescription": "Optional: Save your OpenAI key for daily, automatic evaluations in Insights.",
"codexConnected": "ChatGPT connected successfully! Insights are now active.",
"codexDisconnected": "ChatGPT connection removed.",
"codexConnectionFailed": "ChatGPT connection failed. Please try again.",
"rawData": "Send raw data",
"rawDataOnDescription": "Aggregated metrics plus anonymized raw points from the last 30 days are sent. This includes per-metric measurements (for example weight, blood pressure, pulse) with time context so AI can detect patterns, outliers, and correlations more reliably. Name, email, and direct account identifiers are not transmitted.",
"rawDataOffDescription": "Only summarized metrics are sent (for example averages, trends, minimum/maximum). No individual points and no exact time context. This is more privacy-preserving, but AI can be less precise for short-term patterns and fluctuations.",
"rawDataWarning": "Raw mode enabled: AI receives additional anonymized points from the last 30 days for higher analysis accuracy.",
"rawDataOnDescription": "Aggregated metrics plus anonymized raw points from the last 30 days are sent. This includes per-metric measurements (for example weight, blood pressure, pulse) with time context so the provider can detect patterns, outliers, and correlations more reliably. Name, email, and direct account identifiers are not transmitted.",
"rawDataOffDescription": "Only summarized metrics are sent (for example averages, trends, minimum/maximum). No individual points and no exact time context. This is more privacy-preserving, but the provider can be less precise for short-term patterns and fluctuations.",
"rawDataWarning": "Raw mode enabled: the provider receives additional anonymized points from the last 30 days for higher analysis accuracy.",
"regenerateInsights": "Regenerate reports",
"regenerateSuccess": "Reports regenerated successfully",
"regenerateRateLimit": "Please wait — you've hit the hourly limit for analyses.",
"lastGeneratedAt": "Last generated",
"ai": {
"chatgptConnectedBadge": "ChatGPT connected",
"adminAiActiveBadge": "Admin AI active",
"adminAiActiveBadge": "Admin provider active",
"connectionExpiredBadge": "Connection expired",
"connectedSince": "Connected since {when}.",
"deviceCodeHeading": "Finish connecting on chatgpt.com",
@@ -1760,7 +1760,7 @@
"resetConfirmTitle": "Reset chain to defaults?",
"resetConfirmBody": "The chain reverts to Codex → OpenAI → Anthropic → Local → Admin OpenAI. Your saved credentials are not touched."
},
"activeProviderHeading": "Active AI provider",
"activeProviderHeading": "Active provider",
"activeProviderBody": "Pick the provider you want to use first. The form below configures only the selected provider; the fallback chain at the bottom decides what happens if it fails.",
"activeProviderLabel": "Primary provider",
"providerConfigTitle": "Provider configuration",
@@ -1988,9 +1988,9 @@
"loadError": "Failed to load host metrics. Try refreshing the page."
},
"aiQuality": {
"title": "AI Quality",
"title": "Insights Quality",
"loading": "Loading feedback summary...",
"loadError": "Failed to load AI quality summary. Try refreshing the page.",
"loadError": "Failed to load Insights quality summary. Try refreshing the page.",
"empty": "No feedback yet. The aggregator runs daily at 04:00 — once users start rating recommendations, helpful-rate bands appear here.",
"windowLabel": "Last {days} days",
"generatedAtLabel": "Generated",
@@ -2276,7 +2276,7 @@
"subtitle": "Configure Umami, GlitchTip, Web Push, and bug reports."
},
"ai-quality": {
"title": "AI Quality",
"title": "Insights Quality",
"subtitle": "Helpfulness scores grouped by severity and provider, from the last 30 days of user feedback."
},
"assistant": {
+23 -23
View File
@@ -867,7 +867,7 @@
"bmiEmptyTitle": "Set your height to see BMI",
"bmiEmptyDescription": "BMI needs your height. Add it under Settings → Account.",
"bmiEmptyAction": "Open account settings",
"noProviderConfigured": "AI provider not configured.",
"noProviderConfigured": "Assessment unavailable.",
"startAnalysis": "Start analysis",
"refreshAnalysis": "Refresh analysis",
"keyTakeaway": "Key Takeaway",
@@ -1024,7 +1024,7 @@
"refusalOutOfScope": "I can only help with the health metrics in your log — measurements, medications, mood, trends. I cannot answer questions outside that scope.",
"refusalInjection": "I noticed wording that tries to override my instructions. I am the HealthLog Coach and only summarise your own health data — please rephrase your question in those terms.",
"errorBudget": "You've reached today's Coach usage limit. The budget refreshes at midnight UTC.",
"errorProvider": "The Coach could not reach an AI provider just now. Please try again in a moment.",
"errorProvider": "The Coach could not reach an Insights provider just now. Please try again in a moment.",
"tagline": "Personal health coach, grounded in your data.",
"newChat": "New chat",
"send": "Send",
@@ -1162,19 +1162,19 @@
}
},
"subPage": {
"blutdruckDescription": "Your systolic / diastolic trend with age-personalised target zones and a written AI assessment.",
"gewichtDescription": "Weight trend mapped against your height-derived healthy band, plus an AI assessment.",
"pulsDescription": "Resting pulse vs. the personalised Karvonen target band, plus an AI assessment.",
"stimmungDescription": "Daily mood scores over time with a written AI assessment.",
"blutdruckDescription": "Your systolic / diastolic trend with age-personalised target zones and a written assessment.",
"gewichtDescription": "Weight trend mapped against your height-derived healthy band, plus a written assessment.",
"pulsDescription": "Resting pulse vs. the personalised Karvonen target band, plus a written assessment.",
"stimmungDescription": "Daily mood scores over time with a written assessment.",
"stimmungEmptyTitle": "Log your first mood",
"stimmungEmptyDescription": "Mood insights light up once you've logged a few entries. Tap below to get started.",
"stimmungEmptyAction": "Open mood journal",
"medikamenteDescription": "Per-medication adherence calendars and a written AI assessment.",
"medikamenteDescription": "Per-medication adherence calendars and a written assessment.",
"medikamenteEmptyTitle": "Add your first medication",
"medikamenteEmptyDescription": "Compliance insights need at least one tracked medication.",
"medikamenteEmptyAction": "Open medications",
"therapyTimelineDescription": "Chronological GLP-1 therapy log — dose changes, injections, inventory, side effects.",
"bmiDescription": "BMI derived from your weight and height, with a written AI assessment."
"bmiDescription": "BMI derived from your weight and height, with a written assessment."
},
"sleep": {
"title": "Sueño",
@@ -1370,12 +1370,12 @@
"body": "Use the Add button to drop a measurement or mood entry without leaving the dashboard. The form remembers your last context and tags."
},
"insights": {
"title": "AI-assisted insights",
"body": "Insights turns your readings into a plain-English health summary, with classifications for blood pressure, weight trend and mood. Bring your own AI key or use the built-in default."
"title": "Automatic insights",
"body": "Insights turns your readings into a plain-English health summary, with classifications for blood pressure, weight trend and mood. Bring your own provider key or use the built-in default."
},
"integrations": {
"title": "Connect your devices",
"body": "Open Settings to link Withings (auto-sync weight, BP and pulse), moodLog, or your AI provider. Everything stays optional and encrypted."
"body": "Open Settings to link Withings (auto-sync weight, BP and pulse), moodLog, or your Insights provider. Everything stays optional and encrypted."
},
"achievements": {
"title": "Earn streaks and badges",
@@ -1569,7 +1569,7 @@
}
},
"ai": {
"title": "AI Insights",
"title": "Insights",
"description": "Provider, model, key."
},
"api": {
@@ -1699,22 +1699,22 @@
"webPushUnsubscribed": "Push notifications disabled.",
"webPushSubscribeFailed": "Activation failed",
"webPushActive": "Activo",
"kiInsights": "AI Insights (OpenAI)",
"kiInsightsDescription": "Optional: Save your OpenAI key for daily, automatic AI evaluations in Insights.",
"codexConnected": "ChatGPT connected successfully! AI insights are now active.",
"kiInsights": "Insights (OpenAI)",
"kiInsightsDescription": "Optional: Save your OpenAI key for daily, automatic evaluations in Insights.",
"codexConnected": "ChatGPT connected successfully! Insights are now active.",
"codexDisconnected": "ChatGPT connection removed.",
"codexConnectionFailed": "ChatGPT connection failed. Please try again.",
"rawData": "Send raw data",
"rawDataOnDescription": "Aggregated metrics plus anonymized raw points from the last 30 days are sent. This includes per-metric measurements (for example weight, blood pressure, pulse) with time context so AI can detect patterns, outliers, and correlations more reliably. Name, email, and direct account identifiers are not transmitted.",
"rawDataOffDescription": "Only summarized metrics are sent (for example averages, trends, minimum/maximum). No individual points and no exact time context. This is more privacy-preserving, but AI can be less precise for short-term patterns and fluctuations.",
"rawDataWarning": "Raw mode enabled: AI receives additional anonymized points from the last 30 days for higher analysis accuracy.",
"rawDataOnDescription": "Aggregated metrics plus anonymized raw points from the last 30 days are sent. This includes per-metric measurements (for example weight, blood pressure, pulse) with time context so the provider can detect patterns, outliers, and correlations more reliably. Name, email, and direct account identifiers are not transmitted.",
"rawDataOffDescription": "Only summarized metrics are sent (for example averages, trends, minimum/maximum). No individual points and no exact time context. This is more privacy-preserving, but the provider can be less precise for short-term patterns and fluctuations.",
"rawDataWarning": "Raw mode enabled: the provider receives additional anonymized points from the last 30 days for higher analysis accuracy.",
"regenerateInsights": "Regenerate reports",
"regenerateSuccess": "Reports regenerated successfully",
"regenerateRateLimit": "Please wait — you've hit the hourly limit for analyses.",
"lastGeneratedAt": "Last generated",
"ai": {
"chatgptConnectedBadge": "ChatGPT connected",
"adminAiActiveBadge": "Admin AI active",
"adminAiActiveBadge": "Admin provider active",
"connectionExpiredBadge": "Connection expired",
"connectedSince": "Connected since {when}.",
"deviceCodeHeading": "Finish connecting on chatgpt.com",
@@ -1760,7 +1760,7 @@
"resetConfirmTitle": "Reset chain to defaults?",
"resetConfirmBody": "The chain reverts to Codex → OpenAI → Anthropic → Local → Admin OpenAI. Your saved credentials are not touched."
},
"activeProviderHeading": "Active AI provider",
"activeProviderHeading": "Active provider",
"activeProviderBody": "Pick the provider you want to use first. The form below configures only the selected provider; the fallback chain at the bottom decides what happens if it fails.",
"activeProviderLabel": "Primary provider",
"providerConfigTitle": "Provider configuration",
@@ -1988,9 +1988,9 @@
"loadError": "Failed to load host metrics. Try refreshing the page."
},
"aiQuality": {
"title": "AI Quality",
"title": "Insights Quality",
"loading": "Loading feedback summary...",
"loadError": "Failed to load AI quality summary. Try refreshing the page.",
"loadError": "Failed to load Insights quality summary. Try refreshing the page.",
"empty": "No feedback yet. The aggregator runs daily at 04:00 — once users start rating recommendations, helpful-rate bands appear here.",
"windowLabel": "Last {days} days",
"generatedAtLabel": "Generated",
@@ -2276,7 +2276,7 @@
"subtitle": "Configure Umami, GlitchTip, Web Push, and bug reports."
},
"ai-quality": {
"title": "AI Quality",
"title": "Insights Quality",
"subtitle": "Helpfulness scores grouped by severity and provider, from the last 30 days of user feedback."
},
"assistant": {
+23 -23
View File
@@ -867,7 +867,7 @@
"bmiEmptyTitle": "Set your height to see BMI",
"bmiEmptyDescription": "BMI needs your height. Add it under Settings → Account.",
"bmiEmptyAction": "Open account settings",
"noProviderConfigured": "AI provider not configured.",
"noProviderConfigured": "Assessment unavailable.",
"startAnalysis": "Start analysis",
"refreshAnalysis": "Refresh analysis",
"keyTakeaway": "Key Takeaway",
@@ -1024,7 +1024,7 @@
"refusalOutOfScope": "I can only help with the health metrics in your log — measurements, medications, mood, trends. I cannot answer questions outside that scope.",
"refusalInjection": "I noticed wording that tries to override my instructions. I am the HealthLog Coach and only summarise your own health data — please rephrase your question in those terms.",
"errorBudget": "You've reached today's Coach usage limit. The budget refreshes at midnight UTC.",
"errorProvider": "The Coach could not reach an AI provider just now. Please try again in a moment.",
"errorProvider": "The Coach could not reach an Insights provider just now. Please try again in a moment.",
"tagline": "Personal health coach, grounded in your data.",
"newChat": "New chat",
"send": "Send",
@@ -1162,19 +1162,19 @@
}
},
"subPage": {
"blutdruckDescription": "Your systolic / diastolic trend with age-personalised target zones and a written AI assessment.",
"gewichtDescription": "Weight trend mapped against your height-derived healthy band, plus an AI assessment.",
"pulsDescription": "Resting pulse vs. the personalised Karvonen target band, plus an AI assessment.",
"stimmungDescription": "Daily mood scores over time with a written AI assessment.",
"blutdruckDescription": "Your systolic / diastolic trend with age-personalised target zones and a written assessment.",
"gewichtDescription": "Weight trend mapped against your height-derived healthy band, plus a written assessment.",
"pulsDescription": "Resting pulse vs. the personalised Karvonen target band, plus a written assessment.",
"stimmungDescription": "Daily mood scores over time with a written assessment.",
"stimmungEmptyTitle": "Log your first mood",
"stimmungEmptyDescription": "Mood insights light up once you've logged a few entries. Tap below to get started.",
"stimmungEmptyAction": "Open mood journal",
"medikamenteDescription": "Per-medication adherence calendars and a written AI assessment.",
"medikamenteDescription": "Per-medication adherence calendars and a written assessment.",
"medikamenteEmptyTitle": "Add your first medication",
"medikamenteEmptyDescription": "Compliance insights need at least one tracked medication.",
"medikamenteEmptyAction": "Open medications",
"therapyTimelineDescription": "Chronological GLP-1 therapy log — dose changes, injections, inventory, side effects.",
"bmiDescription": "BMI derived from your weight and height, with a written AI assessment."
"bmiDescription": "BMI derived from your weight and height, with a written assessment."
},
"sleep": {
"title": "Sommeil",
@@ -1370,12 +1370,12 @@
"body": "Use the Add button to drop a measurement or mood entry without leaving the dashboard. The form remembers your last context and tags."
},
"insights": {
"title": "AI-assisted insights",
"body": "Insights turns your readings into a plain-English health summary, with classifications for blood pressure, weight trend and mood. Bring your own AI key or use the built-in default."
"title": "Automatic insights",
"body": "Insights turns your readings into a plain-English health summary, with classifications for blood pressure, weight trend and mood. Bring your own provider key or use the built-in default."
},
"integrations": {
"title": "Connect your devices",
"body": "Open Settings to link Withings (auto-sync weight, BP and pulse), moodLog, or your AI provider. Everything stays optional and encrypted."
"body": "Open Settings to link Withings (auto-sync weight, BP and pulse), moodLog, or your Insights provider. Everything stays optional and encrypted."
},
"achievements": {
"title": "Earn streaks and badges",
@@ -1569,7 +1569,7 @@
}
},
"ai": {
"title": "AI Insights",
"title": "Insights",
"description": "Provider, model, key."
},
"api": {
@@ -1699,22 +1699,22 @@
"webPushUnsubscribed": "Push notifications disabled.",
"webPushSubscribeFailed": "Activation failed",
"webPushActive": "Actif",
"kiInsights": "AI Insights (OpenAI)",
"kiInsightsDescription": "Optional: Save your OpenAI key for daily, automatic AI evaluations in Insights.",
"codexConnected": "ChatGPT connected successfully! AI insights are now active.",
"kiInsights": "Insights (OpenAI)",
"kiInsightsDescription": "Optional: Save your OpenAI key for daily, automatic evaluations in Insights.",
"codexConnected": "ChatGPT connected successfully! Insights are now active.",
"codexDisconnected": "ChatGPT connection removed.",
"codexConnectionFailed": "ChatGPT connection failed. Please try again.",
"rawData": "Send raw data",
"rawDataOnDescription": "Aggregated metrics plus anonymized raw points from the last 30 days are sent. This includes per-metric measurements (for example weight, blood pressure, pulse) with time context so AI can detect patterns, outliers, and correlations more reliably. Name, email, and direct account identifiers are not transmitted.",
"rawDataOffDescription": "Only summarized metrics are sent (for example averages, trends, minimum/maximum). No individual points and no exact time context. This is more privacy-preserving, but AI can be less precise for short-term patterns and fluctuations.",
"rawDataWarning": "Raw mode enabled: AI receives additional anonymized points from the last 30 days for higher analysis accuracy.",
"rawDataOnDescription": "Aggregated metrics plus anonymized raw points from the last 30 days are sent. This includes per-metric measurements (for example weight, blood pressure, pulse) with time context so the provider can detect patterns, outliers, and correlations more reliably. Name, email, and direct account identifiers are not transmitted.",
"rawDataOffDescription": "Only summarized metrics are sent (for example averages, trends, minimum/maximum). No individual points and no exact time context. This is more privacy-preserving, but the provider can be less precise for short-term patterns and fluctuations.",
"rawDataWarning": "Raw mode enabled: the provider receives additional anonymized points from the last 30 days for higher analysis accuracy.",
"regenerateInsights": "Regenerate reports",
"regenerateSuccess": "Reports regenerated successfully",
"regenerateRateLimit": "Please wait — you've hit the hourly limit for analyses.",
"lastGeneratedAt": "Last generated",
"ai": {
"chatgptConnectedBadge": "ChatGPT connected",
"adminAiActiveBadge": "Admin AI active",
"adminAiActiveBadge": "Admin provider active",
"connectionExpiredBadge": "Connection expired",
"connectedSince": "Connected since {when}.",
"deviceCodeHeading": "Finish connecting on chatgpt.com",
@@ -1760,7 +1760,7 @@
"resetConfirmTitle": "Reset chain to defaults?",
"resetConfirmBody": "The chain reverts to Codex → OpenAI → Anthropic → Local → Admin OpenAI. Your saved credentials are not touched."
},
"activeProviderHeading": "Active AI provider",
"activeProviderHeading": "Active provider",
"activeProviderBody": "Pick the provider you want to use first. The form below configures only the selected provider; the fallback chain at the bottom decides what happens if it fails.",
"activeProviderLabel": "Primary provider",
"providerConfigTitle": "Provider configuration",
@@ -1988,9 +1988,9 @@
"loadError": "Failed to load host metrics. Try refreshing the page."
},
"aiQuality": {
"title": "AI Quality",
"title": "Insights Quality",
"loading": "Loading feedback summary...",
"loadError": "Failed to load AI quality summary. Try refreshing the page.",
"loadError": "Failed to load Insights quality summary. Try refreshing the page.",
"empty": "No feedback yet. The aggregator runs daily at 04:00 — once users start rating recommendations, helpful-rate bands appear here.",
"windowLabel": "Last {days} days",
"generatedAtLabel": "Generated",
@@ -2276,7 +2276,7 @@
"subtitle": "Configure Umami, GlitchTip, Web Push, and bug reports."
},
"ai-quality": {
"title": "AI Quality",
"title": "Insights Quality",
"subtitle": "Helpfulness scores grouped by severity and provider, from the last 30 days of user feedback."
},
"assistant": {
+23 -23
View File
@@ -867,7 +867,7 @@
"bmiEmptyTitle": "Set your height to see BMI",
"bmiEmptyDescription": "BMI needs your height. Add it under Settings → Account.",
"bmiEmptyAction": "Open account settings",
"noProviderConfigured": "AI provider not configured.",
"noProviderConfigured": "Assessment unavailable.",
"startAnalysis": "Start analysis",
"refreshAnalysis": "Refresh analysis",
"keyTakeaway": "Key Takeaway",
@@ -1024,7 +1024,7 @@
"refusalOutOfScope": "I can only help with the health metrics in your log — measurements, medications, mood, trends. I cannot answer questions outside that scope.",
"refusalInjection": "I noticed wording that tries to override my instructions. I am the HealthLog Coach and only summarise your own health data — please rephrase your question in those terms.",
"errorBudget": "You've reached today's Coach usage limit. The budget refreshes at midnight UTC.",
"errorProvider": "The Coach could not reach an AI provider just now. Please try again in a moment.",
"errorProvider": "The Coach could not reach an Insights provider just now. Please try again in a moment.",
"tagline": "Personal health coach, grounded in your data.",
"newChat": "New chat",
"send": "Send",
@@ -1162,19 +1162,19 @@
}
},
"subPage": {
"blutdruckDescription": "Your systolic / diastolic trend with age-personalised target zones and a written AI assessment.",
"gewichtDescription": "Weight trend mapped against your height-derived healthy band, plus an AI assessment.",
"pulsDescription": "Resting pulse vs. the personalised Karvonen target band, plus an AI assessment.",
"stimmungDescription": "Daily mood scores over time with a written AI assessment.",
"blutdruckDescription": "Your systolic / diastolic trend with age-personalised target zones and a written assessment.",
"gewichtDescription": "Weight trend mapped against your height-derived healthy band, plus a written assessment.",
"pulsDescription": "Resting pulse vs. the personalised Karvonen target band, plus a written assessment.",
"stimmungDescription": "Daily mood scores over time with a written assessment.",
"stimmungEmptyTitle": "Log your first mood",
"stimmungEmptyDescription": "Mood insights light up once you've logged a few entries. Tap below to get started.",
"stimmungEmptyAction": "Open mood journal",
"medikamenteDescription": "Per-medication adherence calendars and a written AI assessment.",
"medikamenteDescription": "Per-medication adherence calendars and a written assessment.",
"medikamenteEmptyTitle": "Add your first medication",
"medikamenteEmptyDescription": "Compliance insights need at least one tracked medication.",
"medikamenteEmptyAction": "Open medications",
"therapyTimelineDescription": "Chronological GLP-1 therapy log — dose changes, injections, inventory, side effects.",
"bmiDescription": "BMI derived from your weight and height, with a written AI assessment."
"bmiDescription": "BMI derived from your weight and height, with a written assessment."
},
"sleep": {
"title": "Sonno",
@@ -1370,12 +1370,12 @@
"body": "Use the Add button to drop a measurement or mood entry without leaving the dashboard. The form remembers your last context and tags."
},
"insights": {
"title": "AI-assisted insights",
"body": "Insights turns your readings into a plain-English health summary, with classifications for blood pressure, weight trend and mood. Bring your own AI key or use the built-in default."
"title": "Automatic insights",
"body": "Insights turns your readings into a plain-English health summary, with classifications for blood pressure, weight trend and mood. Bring your own provider key or use the built-in default."
},
"integrations": {
"title": "Connect your devices",
"body": "Open Settings to link Withings (auto-sync weight, BP and pulse), moodLog, or your AI provider. Everything stays optional and encrypted."
"body": "Open Settings to link Withings (auto-sync weight, BP and pulse), moodLog, or your Insights provider. Everything stays optional and encrypted."
},
"achievements": {
"title": "Earn streaks and badges",
@@ -1569,7 +1569,7 @@
}
},
"ai": {
"title": "AI Insights",
"title": "Insights",
"description": "Provider, model, key."
},
"api": {
@@ -1699,22 +1699,22 @@
"webPushUnsubscribed": "Push notifications disabled.",
"webPushSubscribeFailed": "Activation failed",
"webPushActive": "Attivo",
"kiInsights": "AI Insights (OpenAI)",
"kiInsightsDescription": "Optional: Save your OpenAI key for daily, automatic AI evaluations in Insights.",
"codexConnected": "ChatGPT connected successfully! AI insights are now active.",
"kiInsights": "Insights (OpenAI)",
"kiInsightsDescription": "Optional: Save your OpenAI key for daily, automatic evaluations in Insights.",
"codexConnected": "ChatGPT connected successfully! Insights are now active.",
"codexDisconnected": "ChatGPT connection removed.",
"codexConnectionFailed": "ChatGPT connection failed. Please try again.",
"rawData": "Send raw data",
"rawDataOnDescription": "Aggregated metrics plus anonymized raw points from the last 30 days are sent. This includes per-metric measurements (for example weight, blood pressure, pulse) with time context so AI can detect patterns, outliers, and correlations more reliably. Name, email, and direct account identifiers are not transmitted.",
"rawDataOffDescription": "Only summarized metrics are sent (for example averages, trends, minimum/maximum). No individual points and no exact time context. This is more privacy-preserving, but AI can be less precise for short-term patterns and fluctuations.",
"rawDataWarning": "Raw mode enabled: AI receives additional anonymized points from the last 30 days for higher analysis accuracy.",
"rawDataOnDescription": "Aggregated metrics plus anonymized raw points from the last 30 days are sent. This includes per-metric measurements (for example weight, blood pressure, pulse) with time context so the provider can detect patterns, outliers, and correlations more reliably. Name, email, and direct account identifiers are not transmitted.",
"rawDataOffDescription": "Only summarized metrics are sent (for example averages, trends, minimum/maximum). No individual points and no exact time context. This is more privacy-preserving, but the provider can be less precise for short-term patterns and fluctuations.",
"rawDataWarning": "Raw mode enabled: the provider receives additional anonymized points from the last 30 days for higher analysis accuracy.",
"regenerateInsights": "Regenerate reports",
"regenerateSuccess": "Reports regenerated successfully",
"regenerateRateLimit": "Please wait — you've hit the hourly limit for analyses.",
"lastGeneratedAt": "Last generated",
"ai": {
"chatgptConnectedBadge": "ChatGPT connected",
"adminAiActiveBadge": "Admin AI active",
"adminAiActiveBadge": "Admin provider active",
"connectionExpiredBadge": "Connection expired",
"connectedSince": "Connected since {when}.",
"deviceCodeHeading": "Finish connecting on chatgpt.com",
@@ -1760,7 +1760,7 @@
"resetConfirmTitle": "Reset chain to defaults?",
"resetConfirmBody": "The chain reverts to Codex → OpenAI → Anthropic → Local → Admin OpenAI. Your saved credentials are not touched."
},
"activeProviderHeading": "Active AI provider",
"activeProviderHeading": "Active provider",
"activeProviderBody": "Pick the provider you want to use first. The form below configures only the selected provider; the fallback chain at the bottom decides what happens if it fails.",
"activeProviderLabel": "Primary provider",
"providerConfigTitle": "Provider configuration",
@@ -1988,9 +1988,9 @@
"loadError": "Failed to load host metrics. Try refreshing the page."
},
"aiQuality": {
"title": "AI Quality",
"title": "Insights Quality",
"loading": "Loading feedback summary...",
"loadError": "Failed to load AI quality summary. Try refreshing the page.",
"loadError": "Failed to load Insights quality summary. Try refreshing the page.",
"empty": "No feedback yet. The aggregator runs daily at 04:00 — once users start rating recommendations, helpful-rate bands appear here.",
"windowLabel": "Last {days} days",
"generatedAtLabel": "Generated",
@@ -2276,7 +2276,7 @@
"subtitle": "Configure Umami, GlitchTip, Web Push, and bug reports."
},
"ai-quality": {
"title": "AI Quality",
"title": "Insights Quality",
"subtitle": "Helpfulness scores grouped by severity and provider, from the last 30 days of user feedback."
},
"assistant": {
+23 -23
View File
@@ -867,7 +867,7 @@
"bmiEmptyTitle": "Set your height to see BMI",
"bmiEmptyDescription": "BMI needs your height. Add it under Settings → Account.",
"bmiEmptyAction": "Open account settings",
"noProviderConfigured": "AI provider not configured.",
"noProviderConfigured": "Assessment unavailable.",
"startAnalysis": "Start analysis",
"refreshAnalysis": "Refresh analysis",
"keyTakeaway": "Key Takeaway",
@@ -1024,7 +1024,7 @@
"refusalOutOfScope": "I can only help with the health metrics in your log — measurements, medications, mood, trends. I cannot answer questions outside that scope.",
"refusalInjection": "I noticed wording that tries to override my instructions. I am the HealthLog Coach and only summarise your own health data — please rephrase your question in those terms.",
"errorBudget": "You've reached today's Coach usage limit. The budget refreshes at midnight UTC.",
"errorProvider": "The Coach could not reach an AI provider just now. Please try again in a moment.",
"errorProvider": "The Coach could not reach an Insights provider just now. Please try again in a moment.",
"tagline": "Personal health coach, grounded in your data.",
"newChat": "New chat",
"send": "Send",
@@ -1162,19 +1162,19 @@
}
},
"subPage": {
"blutdruckDescription": "Your systolic / diastolic trend with age-personalised target zones and a written AI assessment.",
"gewichtDescription": "Weight trend mapped against your height-derived healthy band, plus an AI assessment.",
"pulsDescription": "Resting pulse vs. the personalised Karvonen target band, plus an AI assessment.",
"stimmungDescription": "Daily mood scores over time with a written AI assessment.",
"blutdruckDescription": "Your systolic / diastolic trend with age-personalised target zones and a written assessment.",
"gewichtDescription": "Weight trend mapped against your height-derived healthy band, plus a written assessment.",
"pulsDescription": "Resting pulse vs. the personalised Karvonen target band, plus a written assessment.",
"stimmungDescription": "Daily mood scores over time with a written assessment.",
"stimmungEmptyTitle": "Log your first mood",
"stimmungEmptyDescription": "Mood insights light up once you've logged a few entries. Tap below to get started.",
"stimmungEmptyAction": "Open mood journal",
"medikamenteDescription": "Per-medication adherence calendars and a written AI assessment.",
"medikamenteDescription": "Per-medication adherence calendars and a written assessment.",
"medikamenteEmptyTitle": "Add your first medication",
"medikamenteEmptyDescription": "Compliance insights need at least one tracked medication.",
"medikamenteEmptyAction": "Open medications",
"therapyTimelineDescription": "Chronological GLP-1 therapy log — dose changes, injections, inventory, side effects.",
"bmiDescription": "BMI derived from your weight and height, with a written AI assessment."
"bmiDescription": "BMI derived from your weight and height, with a written assessment."
},
"sleep": {
"title": "Sen",
@@ -1370,12 +1370,12 @@
"body": "Use the Add button to drop a measurement or mood entry without leaving the dashboard. The form remembers your last context and tags."
},
"insights": {
"title": "AI-assisted insights",
"body": "Insights turns your readings into a plain-English health summary, with classifications for blood pressure, weight trend and mood. Bring your own AI key or use the built-in default."
"title": "Automatic insights",
"body": "Insights turns your readings into a plain-English health summary, with classifications for blood pressure, weight trend and mood. Bring your own provider key or use the built-in default."
},
"integrations": {
"title": "Connect your devices",
"body": "Open Settings to link Withings (auto-sync weight, BP and pulse), moodLog, or your AI provider. Everything stays optional and encrypted."
"body": "Open Settings to link Withings (auto-sync weight, BP and pulse), moodLog, or your Insights provider. Everything stays optional and encrypted."
},
"achievements": {
"title": "Earn streaks and badges",
@@ -1569,7 +1569,7 @@
}
},
"ai": {
"title": "AI Insights",
"title": "Insights",
"description": "Provider, model, key."
},
"api": {
@@ -1699,22 +1699,22 @@
"webPushUnsubscribed": "Push notifications disabled.",
"webPushSubscribeFailed": "Activation failed",
"webPushActive": "Aktywne",
"kiInsights": "AI Insights (OpenAI)",
"kiInsightsDescription": "Optional: Save your OpenAI key for daily, automatic AI evaluations in Insights.",
"codexConnected": "ChatGPT connected successfully! AI insights are now active.",
"kiInsights": "Insights (OpenAI)",
"kiInsightsDescription": "Optional: Save your OpenAI key for daily, automatic evaluations in Insights.",
"codexConnected": "ChatGPT connected successfully! Insights are now active.",
"codexDisconnected": "ChatGPT connection removed.",
"codexConnectionFailed": "ChatGPT connection failed. Please try again.",
"rawData": "Send raw data",
"rawDataOnDescription": "Aggregated metrics plus anonymized raw points from the last 30 days are sent. This includes per-metric measurements (for example weight, blood pressure, pulse) with time context so AI can detect patterns, outliers, and correlations more reliably. Name, email, and direct account identifiers are not transmitted.",
"rawDataOffDescription": "Only summarized metrics are sent (for example averages, trends, minimum/maximum). No individual points and no exact time context. This is more privacy-preserving, but AI can be less precise for short-term patterns and fluctuations.",
"rawDataWarning": "Raw mode enabled: AI receives additional anonymized points from the last 30 days for higher analysis accuracy.",
"rawDataOnDescription": "Aggregated metrics plus anonymized raw points from the last 30 days are sent. This includes per-metric measurements (for example weight, blood pressure, pulse) with time context so the provider can detect patterns, outliers, and correlations more reliably. Name, email, and direct account identifiers are not transmitted.",
"rawDataOffDescription": "Only summarized metrics are sent (for example averages, trends, minimum/maximum). No individual points and no exact time context. This is more privacy-preserving, but the provider can be less precise for short-term patterns and fluctuations.",
"rawDataWarning": "Raw mode enabled: the provider receives additional anonymized points from the last 30 days for higher analysis accuracy.",
"regenerateInsights": "Regenerate reports",
"regenerateSuccess": "Reports regenerated successfully",
"regenerateRateLimit": "Please wait — you've hit the hourly limit for analyses.",
"lastGeneratedAt": "Last generated",
"ai": {
"chatgptConnectedBadge": "ChatGPT connected",
"adminAiActiveBadge": "Admin AI active",
"adminAiActiveBadge": "Admin provider active",
"connectionExpiredBadge": "Connection expired",
"connectedSince": "Connected since {when}.",
"deviceCodeHeading": "Finish connecting on chatgpt.com",
@@ -1760,7 +1760,7 @@
"resetConfirmTitle": "Reset chain to defaults?",
"resetConfirmBody": "The chain reverts to Codex → OpenAI → Anthropic → Local → Admin OpenAI. Your saved credentials are not touched."
},
"activeProviderHeading": "Active AI provider",
"activeProviderHeading": "Active provider",
"activeProviderBody": "Pick the provider you want to use first. The form below configures only the selected provider; the fallback chain at the bottom decides what happens if it fails.",
"activeProviderLabel": "Primary provider",
"providerConfigTitle": "Provider configuration",
@@ -1988,9 +1988,9 @@
"loadError": "Failed to load host metrics. Try refreshing the page."
},
"aiQuality": {
"title": "AI Quality",
"title": "Insights Quality",
"loading": "Loading feedback summary...",
"loadError": "Failed to load AI quality summary. Try refreshing the page.",
"loadError": "Failed to load Insights quality summary. Try refreshing the page.",
"empty": "No feedback yet. The aggregator runs daily at 04:00 — once users start rating recommendations, helpful-rate bands appear here.",
"windowLabel": "Last {days} days",
"generatedAtLabel": "Generated",
@@ -2276,7 +2276,7 @@
"subtitle": "Configure Umami, GlitchTip, Web Push, and bug reports."
},
"ai-quality": {
"title": "AI Quality",
"title": "Insights Quality",
"subtitle": "Helpfulness scores grouped by severity and provider, from the last 30 days of user feedback."
},
"assistant": {
@@ -57,7 +57,9 @@ describe("<AiQualitySection>", () => {
mockQueryState.isLoading = false;
mockQueryState.isError = false;
const html = render(<AiQualitySection />);
expect(html).toContain("AI Quality");
// v1.4.33 IW7 — admin section renamed from "AI Quality" to
// "Insights Quality" per the Marc-Voice rule.
expect(html).toContain("Insights Quality");
expect(html).toContain("No feedback yet");
});
@@ -118,6 +120,6 @@ describe("<AiQualitySection>", () => {
mockQueryState.isLoading = false;
mockQueryState.isError = true;
const html = render(<AiQualitySection />);
expect(html).toContain("Failed to load AI quality summary");
expect(html).toContain("Failed to load Insights quality summary");
});
});
@@ -148,7 +148,10 @@ describe("admin sections — SSR smoke", () => {
// ai-quality-section test.
it("<AiQualitySection> renders the empty-state when no summary exists", () => {
const html = render(<AiQualitySection />);
expect(html).toContain("AI Quality");
// v1.4.33 IW7 — section renamed from "AI Quality" to
// "Insights Quality" per the Marc-Voice rule (no "KI"/"AI" prefix
// in user-facing copy).
expect(html).toContain("Insights Quality");
expect(html).toContain("No feedback yet");
});
@@ -186,9 +186,13 @@ describe("<AiSection> — dropdown-driven UX (B2)", () => {
const html = render("de");
expect(html).toContain("Mit ChatGPT verbinden");
expect(html).toContain("ChatGPT-Account (Codex)");
// Heading uses the locale's full string ("Aktiver KI-Provider"); a
// shorter substring would also match the "Aktiver Provider" line
// in the chain summary.
expect(html).toContain("Aktiver KI-Provider");
// v1.4.33 IW7 — the active-provider heading and the parent section
// both ship without the "KI"/"AI" prefix per the Marc-Voice rule
// ("Aktiver KI-Provider" → "Aktiver Provider"). The heading and the
// chain summary now share the same phrase, so we assert against the
// explicit `activeProviderLabel` slot below it ("Primärer Provider")
// to keep the test pinned to the right surface.
expect(html).toContain("Aktiver Provider");
expect(html).toContain("Primärer Provider");
});
});
@@ -137,9 +137,13 @@ describe("settings sections — SSR smoke", () => {
expect(html).not.toContain("settings.about.");
});
it("<AiSection> renders the AI Insights card", () => {
it("<AiSection> renders the Insights card", () => {
const html = render(<AiSection />);
expect(html).toContain("AI Insights");
// v1.4.33 IW7 — section renamed from "AI Insights" to "Insights"
// per the Marc-Voice rule. The card title is replaced with a sparkles
// icon + status badges, and the section H1 carries the only heading.
expect(html).toContain("Insights");
expect(html).toContain("settings-section-ai-title");
});
it("<IntegrationsSection> renders Withings card title", () => {
@@ -150,7 +154,10 @@ describe("settings sections — SSR smoke", () => {
it("<NotificationsSection> renders heading", () => {
const html = render(<NotificationsSection />);
expect(html).toContain("Notifications");
// v1.4.33 IW7 — section renamed from "Notifications" to
// "Notification channels" so it doesn't collide with the inbox at
// `/notifications` ("Notification Center").
expect(html).toContain("Notification channels");
});
it("<DashboardSection> renders heading and embeds the layout customizer", () => {
+11 -5
View File
@@ -251,11 +251,17 @@ function AiInsightsCard({ isAuthenticated }: { isAuthenticated: boolean }) {
return (
<div className="bg-card border-border space-y-4 rounded-xl border p-6">
<div className="flex flex-wrap items-start justify-between gap-2">
<div className="flex items-center gap-2">
<Sparkles className="text-primary h-5 w-5" />
<h2 className="text-lg font-semibold">{t("settings.kiInsights")}</h2>
</div>
{/* v1.4.33 IW7 — the dedicated H2 ("KI-Insights") used to repeat
the parent section title ("KI-Auswertungen"). Both are gone now:
the section renders "Auswertungen" once at the top, and this
card carries only the Sparkles icon + the live provider-status
badges, mirroring the description that lives on the section
header. The configuration description is moved one level up
into the section subtitle so the visual hierarchy stays
two-level (section -> form) instead of three-level
(section -> card title -> form). */}
<div className="flex flex-wrap items-center justify-between gap-2">
<Sparkles className="text-primary h-5 w-5" aria-hidden="true" />
<ProviderStatusBadges
settings={insightsSettings}
activeProvider={chainData?.activeProvider ?? null}