i18n(admin,settings): copy consistency sweep

Several smaller A8 copy nits in one pass:

- Notifications settings subtitle no longer hard-codes "Telegram,
  ntfy, Web Push" — the channel-reliability board only shows
  configured channels, so naming all three made one of them look
  missing.
- Admin /feedback page subtitle widened to "feedback, bug reports,
  and feature requests" so it matches what the inbox actually
  contains; the duplicate card-level title + description on
  /admin/feedback is gone (page header already provides them).
- /admin/services subtitle now mentions integrations alongside
  notification channels (the API and moodLog toggles live there
  too); per-row "system-wide" suffixes dropped — the section
  subtitle already establishes the scope.
- /admin/ai-quality subtitle reads as a sentence instead of the
  jargon "(severity x provider)" expression.
- /admin/feedback empty state is "All caught up" / "Alles erledigt"
  instead of the English-idiom "Inbox zero".
- /achievements subtitle rewritten in both EN + DE to drop the
  dev-speak "from feature rollout onward".
- /admin/api-tokens permission badges show "All" (with a tooltip)
  instead of the bare regex glob `*`.
- Brand spelling normalized: every Glitchtip → GlitchTip.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Marc-André BombeckandClaude Opus 4.7 committed 2026-05-10 13:47:51 +02:00
1 parent 1f4d6a28a5
commit 3f6e670894
5 files changed
+57 -42

No files matched your search

+18 -16
View File
@@ -1057,7 +1057,7 @@
},
"notifications": {
"title": "Benachrichtigungen",
"description": "Zustellung pro Kanal — Telegram, ntfy, Web Push — und die Live-Übersicht der Kanalzuverlässigkeit."
"description": "Zustellung pro Kanal und die Live-Übersicht der Kanalzuverlässigkeit für jeden konfigurierten Kanal."
},
"dashboard": {
"title": "Dashboard",
@@ -1618,13 +1618,13 @@
"defaultLanguageDescription": "Wird für neue Benutzer und als Fallback verwendet.",
"servicesGlobal": "Dienste (global)",
"servicesGlobalDescription": "Deaktivierte Dienste stehen keinem Benutzer zur Verfügung.",
"telegramGlobal": "Telegram-Benachrichtigungen systemweit erlauben.",
"ntfyGlobal": "ntfy-Benachrichtigungen systemweit erlauben.",
"webPushGlobal": "Browser-Push-Benachrichtigungen systemweit erlauben.",
"telegramGlobal": "Telegram-Benachrichtigungen erlauben.",
"ntfyGlobal": "ntfy-Benachrichtigungen erlauben.",
"webPushGlobal": "Browser-Push-Benachrichtigungen erlauben.",
"integrationWebPush": "Web Push",
"integrationBugReport": "Bug-Reports",
"apiGlobal": "API-Endpunkte und API-Tokens systemweit erlauben.",
"moodLogGlobal": "moodLog-Integration systemweit erlauben.",
"apiGlobal": "API-Endpunkte und API-Tokens erlauben.",
"moodLogGlobal": "moodLog-Integration erlauben.",
"sectionGeneral": "Allgemein",
"sectionIntegrations": "Integrationen",
"sectionMedication": "Medikamente",
@@ -1634,17 +1634,17 @@
"glitchtipTitle": "GlitchTip",
"glitchtipDescription": "Fehler-Tracking mit GlitchTip",
"webPushVapidTitle": "Web Push VAPID",
"monitoring": "Monitoring (Umami/Glitchtip)",
"monitoring": "Monitoring (Umami/GlitchTip)",
"monitoringDescription": "Konfiguration für Website-Analytics und Fehler-Tracking.",
"umamiEnabled": "Umami-Tracking aktivieren.",
"umamiScriptUrl": "Umami Script-URL",
"umamiScriptUrlPlaceholder": "https://analytics.example.com/script.js",
"umamiWebsiteId": "Umami Website-ID",
"umamiWebsiteIdPlaceholder": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
"glitchtipEnabled": "Glitchtip Fehler-Tracking aktivieren.",
"glitchtipDsn": "Glitchtip DSN",
"glitchtipEnabled": "GlitchTip Fehler-Tracking aktivieren.",
"glitchtipDsn": "GlitchTip DSN",
"glitchtipDsnPlaceholder": "https://<public-key>@glitchtip.example.com/<project-id>",
"glitchtipEnvironment": "Glitchtip Environment",
"glitchtipEnvironment": "GlitchTip Environment",
"glitchtipEnvironmentPlaceholder": "production",
"webPushVapid": "Web Push (VAPID)",
"webPushVapidDescription": "Konfiguriere VAPID-Schlüssel und Subject direkt hier, damit Browser-Push ohne ENV-Variablen funktioniert.",
@@ -1657,7 +1657,7 @@
"configured": "Konfiguriert",
"notConfigured": "Nicht konfiguriert",
"monitoringTestUmami": "Umami-Test senden",
"monitoringTestGlitchtip": "Glitchtip-Test senden",
"monitoringTestGlitchTip": "GlitchTip-Test senden",
"monitoringTestSuccess": "Testevent wurde gesendet",
"monitoringTestFailed": "Monitoring-Test fehlgeschlagen",
"monitoringSave": "Monitoring speichern",
@@ -1697,6 +1697,8 @@
"tokenUser": "Benutzer",
"tokenName": "Name",
"tokenPermissions": "Berechtigungen",
"tokenPermissionAll": "Alle",
"tokenPermissionAllTooltip": "Wildcard-Berechtigung — dieses Token kann jede API-Route ansprechen.",
"tokenStatus": "Status",
"tokenLastUsed": "Zuletzt benutzt",
"tokenCreated": "Erstellt",
@@ -1768,7 +1770,7 @@
"actions": "Aktionen",
"details": "Details",
"noEntries": "Keine Feedback-Einträge in dieser Kategorie.",
"emptyTitle": "Inbox leer",
"emptyTitle": "Alles erledigt",
"emptyDescription": "Kein Nutzer-Feedback in diesem Status. Bug-Reports, Fragen und Feature-Wünsche erscheinen hier.",
"loading": "Lade Feedback...",
"anonymous": "anonym",
@@ -1837,7 +1839,7 @@
},
"services": {
"title": "Dienste",
"subtitle": "Benachrichtigungskanäle systemweit aktivieren oder deaktivieren."
"subtitle": "Benachrichtigungskanäle und Integrationen systemweit aktivieren oder deaktivieren."
},
"integrations": {
"title": "Integrationen",
@@ -1845,11 +1847,11 @@
},
"ai-quality": {
"title": "KI-Qualität",
"subtitle": "Hilfreich-Quote pro (Schweregrad x Provider) aus Nutzer-Feedback der letzten 30 Tage."
"subtitle": "Hilfreichkeit nach Schweregrad und Provider — Nutzer-Feedback der letzten 30 Tage."
},
"feedback": {
"title": "Feedback",
"subtitle": "Feedback und Bug-Reports der Nutzer sichten."
"subtitle": "Feedback, Bug-Reports und Feature-Wünsche der Nutzer sichten."
},
"reminders": {
"title": "Erinnerungen",
@@ -1974,7 +1976,7 @@
},
"achievements": {
"title": "Erfolge",
"subtitle": "Sammle Erfolge ab Feature-Start durch konsequente Gesundheitstrends und Medikamentenroutinen.",
"subtitle": "Sammle Erfolge, indem du regelmäßig misst und deine Medikamente nimmst.",
"loginRequired": "Bitte anmelden, um Erfolge zu sehen.",
"points": "Punkte",
"unlocked": "Freigeschaltet",
+18 -16
View File
@@ -1057,7 +1057,7 @@
},
"notifications": {
"title": "Notifications",
"description": "Per-channel delivery — Telegram, ntfy, Web Push — plus the live channel-reliability board."
"description": "Per-channel delivery and the live reliability board for every configured channel."
},
"dashboard": {
"title": "Dashboard",
@@ -1618,13 +1618,13 @@
"defaultLanguageDescription": "Used for new users and as fallback.",
"servicesGlobal": "Services (global)",
"servicesGlobalDescription": "Disabled services are not available to any user.",
"telegramGlobal": "Allow Telegram notifications system-wide.",
"ntfyGlobal": "Allow ntfy notifications system-wide.",
"webPushGlobal": "Allow browser push notifications system-wide.",
"telegramGlobal": "Allow Telegram notifications.",
"ntfyGlobal": "Allow ntfy notifications.",
"webPushGlobal": "Allow browser push notifications.",
"integrationWebPush": "Web Push",
"integrationBugReport": "Bug Report",
"apiGlobal": "Allow API endpoints and API tokens system-wide.",
"moodLogGlobal": "Allow moodLog integration system-wide.",
"apiGlobal": "Allow API endpoints and API tokens.",
"moodLogGlobal": "Allow the moodLog integration.",
"sectionGeneral": "General",
"sectionIntegrations": "Integrations",
"sectionMedication": "Medications",
@@ -1634,17 +1634,17 @@
"glitchtipTitle": "GlitchTip",
"glitchtipDescription": "Error tracking with GlitchTip",
"webPushVapidTitle": "Web Push VAPID",
"monitoring": "Monitoring (Umami/Glitchtip)",
"monitoring": "Monitoring (Umami/GlitchTip)",
"monitoringDescription": "Configuration for website analytics and error tracking.",
"umamiEnabled": "Enable Umami tracking.",
"umamiScriptUrl": "Umami script URL",
"umamiScriptUrlPlaceholder": "https://analytics.example.com/script.js",
"umamiWebsiteId": "Umami website ID",
"umamiWebsiteIdPlaceholder": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
"glitchtipEnabled": "Enable Glitchtip error tracking.",
"glitchtipDsn": "Glitchtip DSN",
"glitchtipEnabled": "Enable GlitchTip error tracking.",
"glitchtipDsn": "GlitchTip DSN",
"glitchtipDsnPlaceholder": "https://<public-key>@glitchtip.example.com/<project-id>",
"glitchtipEnvironment": "Glitchtip environment",
"glitchtipEnvironment": "GlitchTip environment",
"glitchtipEnvironmentPlaceholder": "production",
"webPushVapid": "Web Push (VAPID)",
"webPushVapidDescription": "Configure VAPID keys and subject here so browser push works without environment variables.",
@@ -1657,7 +1657,7 @@
"configured": "Configured",
"notConfigured": "Not configured",
"monitoringTestUmami": "Send Umami test",
"monitoringTestGlitchtip": "Send Glitchtip test",
"monitoringTestGlitchTip": "Send GlitchTip test",
"monitoringTestSuccess": "Test event sent",
"monitoringTestFailed": "Monitoring test failed",
"monitoringSave": "Save monitoring",
@@ -1697,6 +1697,8 @@
"tokenUser": "User",
"tokenName": "Name",
"tokenPermissions": "Permissions",
"tokenPermissionAll": "All",
"tokenPermissionAllTooltip": "Wildcard permission — this token can call every API route.",
"tokenStatus": "Status",
"tokenLastUsed": "Last used",
"tokenCreated": "Created",
@@ -1768,7 +1770,7 @@
"actions": "Actions",
"details": "Details",
"noEntries": "No feedback in this category.",
"emptyTitle": "Inbox zero",
"emptyTitle": "All caught up",
"emptyDescription": "No user feedback in this status. Submitted bugs, questions, and feature requests will appear here.",
"loading": "Loading feedback...",
"anonymous": "anonymous",
@@ -1837,7 +1839,7 @@
},
"services": {
"title": "Services",
"subtitle": "Enable or disable notification channels system-wide."
"subtitle": "Enable or disable notification channels and integrations system-wide."
},
"integrations": {
"title": "Integrations",
@@ -1845,11 +1847,11 @@
},
"ai-quality": {
"title": "AI Quality",
"subtitle": "Helpful-rate per (severity x provider) from user feedback over the last 30 days."
"subtitle": "Helpfulness scores grouped by severity and provider, from the last 30 days of user feedback."
},
"feedback": {
"title": "Feedback",
"subtitle": "Triage user-submitted feedback and bug reports."
"subtitle": "Triage user feedback, bug reports, and feature requests."
},
"reminders": {
"title": "Reminders",
@@ -1974,7 +1976,7 @@
},
"achievements": {
"title": "Achievements",
"subtitle": "Unlock achievements from feature rollout onward through consistent health trends and medication habits.",
"subtitle": "Earn achievements by tracking your health and taking your meds on time.",
"loginRequired": "Please sign in to view achievements.",
"points": "Points",
"unlocked": "Unlocked",
@@ -109,7 +109,10 @@ describe("ApiTokenOverviewSection — responsive", () => {
// last-used/created labels are all present.
expect(html).toContain("marc"); // username
expect(html).toContain("iOS app"); // token name
expect(html).toMatch(/\*/); // permission badge content
// F-19 (v1.4.19): the wildcard `*` permission renders as the
// human-readable "All" with a tooltip explaining the semantics,
// not the literal asterisk.
expect(html).toContain("All");
});
it("uses a smaller card padding on mobile (p-4 sm:p-6)", () => {
@@ -162,9 +162,13 @@ export function ApiTokenOverviewSection() {
key={p}
variant="secondary"
className="max-w-full truncate text-xs"
title={p}
title={
p === "*"
? t("admin.tokenPermissionAllTooltip")
: p
}
>
{p}
{p === "*" ? t("admin.tokenPermissionAll") : p}
</Badge>
))}
</div>
@@ -254,9 +258,13 @@ export function ApiTokenOverviewSection() {
key={p}
variant="secondary"
className="max-w-full truncate text-[10px]"
title={p}
title={
p === "*"
? t("admin.tokenPermissionAllTooltip")
: p
}
>
{p}
{p === "*" ? t("admin.tokenPermissionAll") : p}
</Badge>
))}
</div>
@@ -74,13 +74,13 @@ export function FeedbackInboxSection() {
return (
<div className="bg-card border-border rounded-xl border p-6">
{/* v1.4.19 A8 / F-08 + F-20: this is the only card on
`/admin/feedback`, so the page header already provides the
title + description — the card-level repetition was just
visual noise. The icon stays as a low-key card affordance. */}
<div className="flex items-center gap-2">
<Inbox className="text-primary h-5 w-5" />
<div className="text-lg font-semibold">{t("admin.feedback.title")}</div>
<Inbox className="text-primary h-5 w-5" aria-hidden="true" />
</div>
<p className="text-muted-foreground mt-1 text-xs">
{t("admin.feedback.description")}
</p>
<Tabs
value={activeStatus}