mirror of
https://github.com/MBombeck/HealthLog.git
synced 2026-11-08 12:32:43 +00:00
* fix(measurements): close issue #109 + sync body composition across UI/PDF/thresholds User-visible: TOTAL_BODY_WATER, BONE_MASS, and BLOOD_GLUCOSE now appear in the measurements filter, badge, mobile icon, and edit dialog (issue #109). Server-rendered doctor report now includes body composition rows (audit C-9). Body water + bone mass have proper effective-range thresholds so severity logic doesn't silently return `nominal` (audit C-15). Structural: extracted the per-type display maps from measurement-list.tsx into measurement-list-meta.ts as a deliberate first step toward the single-source manifest planned for phase P5. Coverage tests now fail-fast if a future enum addition skips any of: list label/icon/color, doctor-PDF label/unit/vital-types, chart label, threshold metric order/label/bounds. Audit-2026-05-07 / phase P0: - closes #109 (filter UI gap, root cause for the German raw-enum display) - closes audit C-9 (server PDF used a stale type map) - closes audit C-15 (no warn/critical bands for body composition) Tests: 282 → 296 (14 new). Typecheck clean. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * docs: align OpenAPI spec + migration comment with body-composition reality - OpenAPI MeasurementType enum: add TOTAL_BODY_WATER + BONE_MASS (was at v1.3.0 baseline; spec drifted past the v1.3 server release) - Bump openapi version 1.3.0 → 1.3.2 to match package.json - Migration 0022 comment: TOTAL_BODY_WATER stores kg (water content), not percent of body weight. Validators (VALUE_RANGES) and the Withings client (type 77 → kg) treat it as kg already; the comment was the lone outlier and would mislead the next reviewer. Audit-2026-05-07 / phase P1a — closes audit M-B1 (partial; OpenAPI enum) and M-B2 (migration unit comment). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * fix(security): close 3 audit CRITICALs (Withings header / idempotency Bearer / GlitchTip URL strip) C-3 (Withings webhook secret in URL): Now reads X-Withings-Webhook-Secret header in preference; URL ?secret=… fallback retained for legacy Withings configurations and emits a Wide Event warning so operators can spot still-using-the-old-flow integrators. The query-string secret was leaking into Coolify access logs and any GlitchTip event whose request.url got captured. C-4 (idempotency dead for Bearer-token clients): The default userIdResolver only consulted getSession(). Bearer-authed clients (the iOS / n8n / headless-API fleet that PR #117 was built for) fell through, so every retry created duplicate measurements. The default now tries cookie session first, then Bearer token via hashToken+apiToken.findUnique with revoked/expiry checks. All three existing call sites (measurements, mood-entries, medications/intake) get the fix automatically. H-B7 (request.url with secrets shipped to GlitchTip): reportToGlitchtip now strips the query string before forwarding the URL, so Withings legacy ?secret=… and any OAuth ?code=… that errors during the callback don't end up in someone else's incident UI. Audit-2026-05-07 / phase P2. Tests: 296 → 301 (5 new in idempotency.test for the Bearer fallback + revoked/expired/null cases). Deferred to a follow-up (needs DB migration / lock primitive): C-2 moodLog webhook → AES-GCM at rest + HMAC-over-body C-5 idempotency TOCTOU advisory_lock or in-flight sentinel row Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * feat(measurements): add OXYGEN_SATURATION (SpO2) as first-class measurement type — v1.3.3 Closes the OxygenSaturation feature request from #109. - Migration 0024 extends MeasurementType enum (additive, IF NOT EXISTS) - Zod validators: plausibility 50–100% (below 50 is incompatible with sustained life; above 100 is physically impossible) - effective-range thresholds: green 95–100, orange 92–94, red <92. Sources: BTS Guideline 2017 (target 94–98%), ATS clinical practice (≥95% at rest is healthy), AHA/clinical literature (<92% = call provider, <88% = ER). Lower-only concern — upper orange wing collapses to greenMax since saturation cannot exceed 100%. - Personalisation: existing thresholds-override UI lets COPD / chronic-respiratory users with a doctor-set 88–92 baseline tune the bands. METRIC_ORDER + METRIC_LABEL_KEYS extended in thresholds-section.tsx; the exhaustive `Record<ThresholdMetric>` forces TS to catch any missed surface. - Withings ScanWatch type 54 mapping (best-effort — only fires for pulse-ox-capable devices). - Wired through measurement-form, measurement-list-meta (icon: Wind), health-chart, both doctor-report-pdf renderers (core + browser-side near-duplicate), OpenAPI spec (version 1.3.0 → 1.3.3), and i18n in 4 sections × 2 locales. - iOS DTO already declared `OXYGEN_SATURATION` — server enum addition closes the long-standing drift flagged in audit V2. - 4 new tests: numeric green band, upper-wing collapse, user-override (COPD baseline), METRIC_BOUNDS shape. Tests: 301 → 305. Typecheck: clean. Audit-2026-05-07 / v1.3.3 / closes #109 SpO2 feature request. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * fix(analytics): truthfulness pass on medical citations + clamp override orangeMax Doctor-agent + hallucination-hunter audit V3 found six medical citations in effective-range.ts that the code did not actually implement. Plus a latent bug in the user-override path that produced physically-impossible orangeMax values (>100% saturation, <0% body-fat). Citation rewrites (no numeric changes): - ACTIVITY_STEPS: "WHO ≥8000 steps/day" → Saint-Maurice JAMA 2020. WHO publishes activity in min/week, not steps. Step-count was a misattribution that also leaked into AI prompts. - TOTAL_BODY_WATER: "ESPEN Body Composition Guidance 2017" → Watson formula / ICRP Reference Man. ESPEN 2017 is BIA practice guidance, it does not publish kg cut-offs. - BONE_MASS: "DEXA-equivalent bone mineral content" → "Bioimpedance- estimated; not DEXA-comparable". Withings BIA values typically run 5–7% below DEXA — calling them DEXA-equivalent in a doctor-report PDF was a real legal-exposure misattribution. - OXYGEN_SATURATION: "BTS Guideline 2017 (target 94–98%) + ATS clinical practice (≥95% at rest is healthy)" → "consumer pulse- oximeter consensus (≥95% normal at rest); slightly tighter than BTS 2017 (94–98%); NICE NG115 ≤92% escalation, BMJ panel / FDA pulse-oximeter labelling ≤88% ER threshold". Code uses 95-100/92-100 band — that's an ATS/consumer-consensus number, not BTS's literal 94-98 target. Soften the citation to match the code, not vice versa. Bug fix (1 latent, 1 real-today): - effective-range override path now clamps orangeMin/orangeMax to METRIC_BOUNDS.{min,max}. Without the clamp, a COPD user setting SpO2 override to {95,100} emitted orangeMax = 100.75 (impossible saturation), and a BODY_FAT override of {2,80} emitted orangeMin = -9.7 (negative percent). Default-range case 210 already hard-coded orangeMax: 100 for the same reason — the override path was the only branch missing the invariant. Tests: 305 → 306 (1 new: clamps override orangeMax to physiological 100%). Typecheck: clean. Audit-2026-05-07-V3 / closes Doctor + Senior-Dev medical-citation findings. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * fix(security): Bearer-scope wildcard handling + GDPR Art.17 account-delete erasure Two CRITICAL fixes from audit V3. NEW-V3-1: Bearer-scope bypass. apiToken.permissions ["*"] is meant to be the wildcard "session-equivalent" scope (the iOS app receives this on login). The previous check permissions.includes(requiredPermission) treated "*" as a literal string — never matched. Today many sensitive routes call requireAuth() *without* a requiredPermission, so a leaked iOS token can act as a full-scope token (account delete, settings wipe). Once those routes adopt requireAuth("scope:name"), this wildcard handling keeps the iOS app working while narrower-scoped tokens (e.g. user-issued ["medication:ingest"]) get correctly 403'd. Same wildcard handling added to the standalone permission checks in src/app/api/ingest/medication/route.ts:65, 119. NEW-V3-2: GDPR Art. 17 account-delete erasure completeness. Feedback + AuditLog rows had `onDelete: SetNull` in the schema, which preserved PII (free-text symptom descriptions, IP addresses, login-city geolocation) after the user was deleted. We now explicitly prisma.feedback.deleteMany + prisma.auditLog.deleteMany before the cascade-delete, making account deletion genuinely complete erasure. Tests 306/306 still pass; typecheck clean. Audit V3. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * test(pdf): real text-content assertions for body composition + SpO2 rows Replaces bytes-only "renders body composition rows" theatre test with pdf-parse-driven text extraction that asserts the actual rendered labels + values for TOTAL_BODY_WATER, BONE_MASS, OXYGEN_SATURATION (DE + EN). Closes V3 audit finding STILL-V2-NEW-3: the previous test only verified "%PDF-" header + byte-count, so a regression that drops a row would still pass. Now a missing label fails the test. - adds dev dep: pdf-parse@^2.4.5 - 308/308 tests pass (was 306, +2 SpO2 + EN-locale coverage) Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * fix(measurements): close enum drift cousins — derive 5 type-arrays from canonical enum + extend 2 contract enums V3 audit finding "enum drift cousins": 7 hardcoded module-level type arrays silently dropped SpO2/TBW/BoneMass/BloodGlucose from their respective domains. Adding a new measurement type required hunting these down. Now all aggregation paths derive from `measurementTypeEnum.options`: - /api/insights/comprehensive (AI insights) - /api/dashboard/summary (iOS dashboard adapter) - /api/analytics (analytics aggregator) - /lib/insights/general-status (AI general-status fetch) - /api/import (Zod schema — round-trip now covers all 11 types) External-contract enums extended additively (no breakage for old clients): - /api/measurements/series kindEnum: + oxygen, totalBodyWater, boneMass - /api/dashboard/widgets widgetIdEnum: + oxygenSaturation - DashboardWidgetId + DEFAULT_DASHBOARD_LAYOUT: + oxygenSaturation row - formatMeasurementsForExport: glucoseContext now round-trips Coverage test (`measurement-type-enum-coverage.test.ts`) asserts the canonical enum stays the source of truth and documents PDF exclusions (BLOOD_GLUCOSE renders via context section, SLEEP/STEPS lifestyle-only). 313/313 tests pass (was 308, +5 new). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * fix(security): close 6 V3-audit HIGH findings (CSP, web-push SSRF, IP geo, AI provider leak, import rate-limit) - CSP: chatgpt.com + api.openai.com only on /settings/ai/** routes (was blanket connect-src on every page including /auth/login → DOM-XSS exfil channel) - web-push: webPushSubscriptionSchema.endpoint requires HTTPS + isPublicUrl refinement; was z.url() only → blind SSRF probe via Push subscription - isPublicUrl: also fixes a regression where DNS labels starting with "fc"/"fd" (fcm.googleapis.com etc.) were falsely classified as IPv6 unique-local. Check is now gated on a colon being present in the host. - /api/ai/test: stop returning provider err.message + bodyExcerpt to the client (leaked provider URLs / partial keys / internal headers). Now returns categorised generic message; full details land in the wide-event via annotate() for the operator. - /lib/geo (auditLog IP geo lookup): switch default provider to ipwho.is over HTTPS, accept ipwho.is + ip-api pro response shapes, add IP_GEO_LOOKUP_DISABLED env, refuse non-HTTPS configured URLs. Previously leaked IP+timestamp over plaintext HTTP every auth event (GDPR Art. 32 + Art. 44). - /api/import: add 5/hour rate-limit (was unlimited; bulk-injection vector) Tests: 325/325 pass (was 313, +12 new — webPushSubscriptionSchema SSRF guards, fc/fd-prefix domain regression, geo HTTPS-only, geo provider shapes, geo opt-out env). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * fix(security,gdpr): trusted-proxy IP, audit-log retention, idempotency cachable filter, Bearer mock tightening V3 audit follow-on bundle covering 4 HIGH findings. (I) getClientIp — TRUST_PROXY_HOPS env (default 1) replaces blind XFF trust. Reads chain right-to-left so client-supplied leftmost entries cannot rotate the per-IP rate-limit bucket. Default 1 matches typical single-proxy self-host (Coolify/Caddy/Cloudflare-Tunnel); 0 forces x-real-ip / null. New 7-test suite covers the rotation attack + malformed entries + zero-hop fallback. (F) Audit-log retention job — daily 03:15 cleanup of audit_logs older than AUDIT_LOG_RETENTION_DAYS (default 365). Closes GDPR Art. 5(1)(e) "storage limitation" gap; previously IPs + city + login events accumulated forever. 6-test suite covers default + override + misconfig guard (rejects <7 days). (G) isCachableStatus — extracted the inline 4xx/5xx filter into a named, exported, tested function. 7 cases cover the full do-not-cache contract (401 / 403 / 408 / 429 / any 5xx) and confirm 2xx + 4xx validation are still cached. (H) Bearer-mock tightening — apiToken.findUnique mocks in require-auth-bearer.test + idempotency.test now assert the where.tokenHash shape uses the hashed value (not the raw bearer). A regression that switched back to raw-token comparison would have been silent without this assertion. Tests: 345/345 pass (was 332, +13 new). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * fix(security): encrypt moodLog webhook secret at rest with AES-256-GCM (V3 audit STILL-V2-C-2) The mood_log_webhook_secret column previously stored a plaintext secret that the webhook handler compared timing-safe against every enabled user. A DB dump or backup snapshot leaked active webhook credentials. New contract — no schema migration required: - Writes go through encryptMoodLogSecret() (AES-256-GCM via existing crypto helper, ENCRYPTION_KEY). - Reads go through readMoodLogSecret() which transparently decrypts envelopes and tolerates legacy plaintext rows during the transition (graceful upgrade path — no breaking change for self-hosted users). - Webhook lookup decrypts each candidate before timing-safe compare. - Status endpoint decrypts for the user's settings page. One-shot startup migration in reminder-worker rotates any leftover plaintext rows on next worker boot. Idempotent; encrypted rows are skipped. Tests: 350/350 pass (was 345, +5 new — round-trip, legacy passthrough, isLegacyPlaintext semantics, rotateLegacy idempotence). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * docs: sync README + AGENTS + CLAUDE + CHANGELOG + OpenAPI for v1.3.3 (V3 audit doc-drift) V3 audit Doku Specialist findings — drift between code and meta-docs. - README §Key Features now mentions pulse oximetry (SpO₂) + Withings ScanWatch sync; Tech Stack model count corrected 23 → 25. - AGENTS.md status promoted v1.3.2 → v1.3.3; vitest config corrected `vitest.config.ts` → `vitest.config.mts`; migration range corrected `0001–0022` → `0001–0024`; model count + list updated to 25 (adds Device, IdempotencyKey). - CLAUDE.md model count updated (2 occurrences). - CHANGELOG.md v1.3.3 expanded with Security + Internal sections that were missing the audit-fix-marathon work (Bearer-scope, account-delete cascade, moodLog encryption, CSP tightening, Web-Push SSRF, IP-geo HTTPS, AI-test leak fix, import rate-limit, trusted-proxy XFF, audit-log retention, idempotency cachable filter, Bearer mock tightening, enum-drift cousins, PDF text-content tests). - OpenAPI Bearer description corrected `SHA-256 hashes` → `HMAC-SHA-256 hashes (keyed with API_TOKEN_HMAC_KEY)` so the docs match the actual server-side implementation. Wildcard scope contract documented. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * fix(audit-review): close 4 HIGH + 2 MEDIUM findings from multi-agent review pass Multi-agent review of the audit-fix branch surfaced four HIGH issues and a couple of MEDIUM hardenings. All addressed before merge. HIGH-1 — OpenAPI MetricKind enum drift (iOS strict-decode crash risk). The dashboard-summary route now emits totalBodyWater/boneMass/ oxygenSaturation MetricCards, but the spec still listed only the original 7 kinds. Generated iOS Codable would have crashed the dash the moment a user logged SpO2. MetricKind extended with the 3 new kinds + comment documenting unknown-value defensive decoding. HIGH-2 — kindEnum naming consistency on /api/measurements/series. The series adapter shipped "oxygen" while the dashboard summary used "oxygenSaturation"; both routes now use "oxygenSaturation" so iOS decoders can share a single MetricKind type across endpoints. HIGH-3 — /api/ai/test no-leak guard had no test. Added 4 tests that mock provider errors with sk-leaked-key + provider URLs in the err fields and assert the response body never echoes them, plus the 3-status-categorised generic messages (401/429/5xx/other). HIGH-4 — /api/import 5/hour rate-limit had no test. Added 2 tests that mock checkRateLimit allowed/disallowed and assert the 429 path uses the right key shape (`import:<userId>`, 5, 1h) and that the within- quota path proceeds. MEDIUM-3 — getClientIp under-length XFF chain regression. With TRUST_PROXY_HOPS=2 and a chain of length 1, the previous clamp returned the leftmost (attacker-controlled) entry, silently re-introducing the rotation attack the helper was meant to close. Now: when chain is shorter than configured hops, refuse XFF entirely (fall back to x-real-ip / null). Added regression test. LOW-1 — TRUST_PROXY_HOPS=garbage now throws at boot instead of silently degrading to hops=0. Added regression test. Tests: 358/358 pass (was 350, +8 new). Typecheck clean. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1634 lines
74 KiB
JSON
1634 lines
74 KiB
JSON
{
|
||
"common": {
|
||
"save": "Speichern",
|
||
"cancel": "Abbrechen",
|
||
"delete": "Löschen",
|
||
"edit": "Bearbeiten",
|
||
"moreOptions": "Weitere Optionen",
|
||
"create": "Erstellen",
|
||
"close": "Schließen",
|
||
"loading": "Laden...",
|
||
"error": "Fehler",
|
||
"success": "Erfolgreich",
|
||
"saved": "Gespeichert",
|
||
"confirm": "Bestätigen",
|
||
"back": "Zurück",
|
||
"next": "Weiter",
|
||
"yes": "Ja",
|
||
"no": "Nein",
|
||
"search": "Suchen",
|
||
"filter": "Filtern",
|
||
"noData": "Keine Daten vorhanden",
|
||
"optional": "Optional",
|
||
"required": "Erforderlich",
|
||
"all": "Alle",
|
||
"active": "Aktiv",
|
||
"inactive": "Inaktiv",
|
||
"enabled": "Aktiviert",
|
||
"disabled": "Deaktiviert",
|
||
"networkError": "Netzwerkfehler",
|
||
"unknownError": "Unbekannter Fehler",
|
||
"notLoggedIn": "Nicht angemeldet",
|
||
"noAccess": "Kein Zugriff",
|
||
"copied": "Kopiert!",
|
||
"or": "oder",
|
||
"unknown": "Unbekannt",
|
||
"replace": "Ersetzen",
|
||
"add": "Hinzufügen",
|
||
"import": "Importieren",
|
||
"test": "Test",
|
||
"reset": "Zurücksetzen",
|
||
"copy": "Kopieren",
|
||
"copyDetails": "Details kopieren",
|
||
"retry": "Erneut versuchen",
|
||
"reportIssue": "Fehler melden"
|
||
},
|
||
"doctorReport": {
|
||
"title": "Gesundheitsbericht",
|
||
"subtitle": "HealthLog — Persönlicher Gesundheitsbericht",
|
||
"patient": "Patient",
|
||
"dateOfBirth": "Geburtsdatum",
|
||
"gender": "Geschlecht",
|
||
"genderMale": "Männlich",
|
||
"genderFemale": "Weiblich",
|
||
"genderOther": "Divers",
|
||
"height": "Körpergröße",
|
||
"period": "Berichtszeitraum",
|
||
"createdOn": "Erstellt am",
|
||
"vitalsTitle": "Vitalparameter — Übersicht",
|
||
"colParameter": "Parameter",
|
||
"colCurrent": "Aktuell",
|
||
"colAvgPeriod": "Ø Zeitraum",
|
||
"colMin": "Min",
|
||
"colMax": "Max",
|
||
"colN": "n",
|
||
"bpClassificationTitle": "Blutdruck — ESC/ESH-Klassifikation (2018)",
|
||
"avgBp": "Durchschnittlicher Blutdruck",
|
||
"classification": "Klassifikation",
|
||
"bmiTitle": "Body-Mass-Index (BMI)",
|
||
"bmiRow": "BMI: {bmi} kg/m² — Klassifikation: {class} (WHO)",
|
||
"complianceTitle": "Medikamenten-Compliance",
|
||
"colMedication": "Medikament",
|
||
"colTaken": "Eingenommen",
|
||
"colSkipped": "Übersprungen",
|
||
"colMissed": "Verpasst",
|
||
"colTotal": "Gesamt",
|
||
"colComplianceRate": "Compliance-Rate",
|
||
"moodTitle": "Stimmungsverlauf",
|
||
"moodSummary": "Durchschnitt: {avg} / 5,0 · Einträge: {count} · Bereich: {min}–{max}",
|
||
"colMood": "Stimmung",
|
||
"colCount": "Anzahl",
|
||
"colShare": "Anteil",
|
||
"footerDisclaimer1": "Dieser Bericht wurde automatisch aus selbst erfassten Daten generiert und dient ausschließlich zur Unterstützung",
|
||
"footerDisclaimer2": "des Arzt-Patienten-Gesprächs. Er ersetzt keine ärztliche Diagnose. Korrelationen implizieren keine Kausalität.",
|
||
"footerSource": "Quelle: HealthLog | Zeitzone: Europe/Berlin | Erstellt: {timestamp}",
|
||
"typeWeight": "Körpergewicht",
|
||
"typeBpSys": "Systolischer Blutdruck",
|
||
"typeBpDia": "Diastolischer Blutdruck",
|
||
"typePulse": "Ruhepuls",
|
||
"typeBodyFat": "Körperfettanteil",
|
||
"typeSleep": "Schlafdauer",
|
||
"typeSteps": "Aktivität (Schritte)",
|
||
"typeTotalBodyWater": "Gesamtkörperwasser",
|
||
"typeBoneMass": "Knochenmasse",
|
||
"typeOxygenSaturation": "Sauerstoffsättigung",
|
||
"unitSteps": "Schritte",
|
||
"bmiUnderweight": "Untergewicht",
|
||
"bmiNormal": "Normalgewicht",
|
||
"bmiOverweight": "Übergewicht (Präadipositas)",
|
||
"bmiObeseGrade1": "Adipositas Grad I",
|
||
"bmiObeseGrade2": "Adipositas Grad II",
|
||
"bmiObeseGrade3": "Adipositas Grad III",
|
||
"bpOptimal": "Optimal",
|
||
"bpNormal": "Normal",
|
||
"bpHighNormal": "Hochnormal",
|
||
"bpHypertensionGrade1": "Hypertonie Grad 1",
|
||
"bpHypertensionGrade2": "Hypertonie Grad 2",
|
||
"bpHypertensionGrade3": "Hypertonie Grad 3",
|
||
"moodAwful": "Sehr schlecht",
|
||
"moodBad": "Schlecht",
|
||
"moodNeutral": "Neutral",
|
||
"moodGood": "Gut",
|
||
"moodGreat": "Sehr gut",
|
||
"typeGlucoseFasting": "Glukose (nüchtern)",
|
||
"typeGlucosePostprandial": "Glukose (postprandial)",
|
||
"typeGlucoseRandom": "Glukose (beliebig)",
|
||
"typeGlucoseBedtime": "Glukose (vor dem Schlafen)",
|
||
"glucoseClassificationTitle": "Blutzucker — Referenzbereiche (ADA 2024 / DDG)",
|
||
"glucoseRow": "{label}: Ø {avg} {unit} (Ziel {rangeMin}–{rangeMax}) — {class}",
|
||
"glucoseInTarget": "im Ziel",
|
||
"glucoseBelowTarget": "unter Ziel",
|
||
"glucoseAboveTarget": "über Ziel"
|
||
},
|
||
"errorBoundary": {
|
||
"title": "Da ist etwas schiefgelaufen",
|
||
"description": "Ein unerwarteter Fehler ist aufgetreten. Du kannst es erneut versuchen, die technischen Details kopieren oder einen Bug-Report öffnen."
|
||
},
|
||
"nav": {
|
||
"home": "Home",
|
||
"dashboard": "Dashboard",
|
||
"measurements": "Messungen",
|
||
"medications": "Medikamente",
|
||
"charts": "Verlauf",
|
||
"insights": "Insights",
|
||
"targets": "Zielwerte",
|
||
"achievements": "Erfolge",
|
||
"settings": "Einstellungen",
|
||
"bugreport": "Bugreport",
|
||
"admin": "Admin-Konsole",
|
||
"logout": "Abmelden",
|
||
"login": "Anmelden",
|
||
"notifications": "Benachrichtigungen",
|
||
"theme": "Darstellung",
|
||
"themeSystem": "System",
|
||
"themeDark": "Dunkel",
|
||
"themeLight": "Hell",
|
||
"collapseSidebar": "Einklappen",
|
||
"userMenu": "Benutzermenü",
|
||
"mood": "Stimmung",
|
||
"skipToContent": "Zum Inhalt springen",
|
||
"sidebar": "Sidebar",
|
||
"mainNavigation": "Hauptnavigation",
|
||
"mobileNavigation": "Mobile Navigation",
|
||
"loadingScreen": "Laden…"
|
||
},
|
||
"auth": {
|
||
"login": "Anmelden",
|
||
"register": "Registrieren",
|
||
"loginTitle": "Anmeldung",
|
||
"registerTitle": "Registrierung",
|
||
"username": "Benutzername",
|
||
"password": "Passwort",
|
||
"email": "E-Mail-Adresse",
|
||
"emailPlaceholder": "name@beispiel.de",
|
||
"emailOrUsername": "E-Mail-Adresse oder Benutzername",
|
||
"emailOrUsernamePlaceholder": "name@beispiel.de oder benutzername",
|
||
"loginWithPasskey": "Mit Passkey anmelden",
|
||
"loginWithPassword": "Mit Passwort anmelden",
|
||
"noAccount": "Noch kein Konto?",
|
||
"hasAccount": "Bereits ein Konto?",
|
||
"registerDisabled": "Registrierung ist deaktiviert.",
|
||
"loginFailed": "Anmeldung fehlgeschlagen",
|
||
"passkeyFailed": "Passkey-Anmeldung abgebrochen oder fehlgeschlagen",
|
||
"registerFailed": "Registrierung fehlgeschlagen",
|
||
"createAccount": "Konto erstellen",
|
||
"newAccount": "Neues Konto erstellen",
|
||
"backToPasskey": "Zurück zu Passkey",
|
||
"passkeySetupLater": "Passkeys kannst du jederzeit in den Einstellungen einrichten.",
|
||
"passwordMinLength": "Min. 12 Zeichen",
|
||
"passwordTooShort": "Passwort muss mindestens {minLength} Zeichen lang sein.",
|
||
"passwordStrength": "Passwortstärke",
|
||
"strengthWeak": "Sehr schwach",
|
||
"strengthFair": "Schwach",
|
||
"strengthGood": "Mittel",
|
||
"strengthStrong": "Stark",
|
||
"strengthVeryStrong": "Sehr stark"
|
||
},
|
||
"dashboard": {
|
||
"title": "Dashboard",
|
||
"subtitle": "Dein Gesundheitsüberblick",
|
||
"greeting": {
|
||
"morning": "Guten Morgen",
|
||
"day": "Hallo",
|
||
"evening": "Guten Abend"
|
||
},
|
||
"welcomeBack": "{greeting}, willkommen zurück.",
|
||
"welcomeBackWithName": "{greeting} {name}, willkommen zurück.",
|
||
"weight": "Gewicht",
|
||
"bloodPressure": "Blutdruck",
|
||
"bloodPressureSys": "Blutdruck (Sys)",
|
||
"bloodPressureDia": "Blutdruck (Dia)",
|
||
"pulse": "Puls",
|
||
"bodyFat": "Körperfett",
|
||
"sleep": "Schlaf",
|
||
"steps": "Schritte",
|
||
"bpInTarget": "BD im Zielbereich",
|
||
"days30Short": "30T",
|
||
"medications": "Medikamente",
|
||
"lastMeasurement": "Letzter Messwert",
|
||
"noMeasurements": "Noch keine Messwerte",
|
||
"trend": "Trend",
|
||
"trendUp": "steigend",
|
||
"trendDown": "fallend",
|
||
"trendStable": "stabil",
|
||
"quickEntry": "Schnelleingabe",
|
||
"addMeasurement": "Messwert hinzufügen",
|
||
"compliance7d": "Einnahmetreue (7 Tage)",
|
||
"complianceGood": "Gut",
|
||
"complianceLow": "Niedrig",
|
||
"mood": "Stimmung",
|
||
"customizeTitle": "Dashboard-Layout",
|
||
"customizeSubtitle": "Wähle, welche Karten auf dem Dashboard angezeigt werden und in welcher Reihenfolge. Defaults funktionieren sofort.",
|
||
"layoutReset": "Auf Defaults zurücksetzen",
|
||
"layoutSaveSuccess": "Dashboard-Layout gespeichert",
|
||
"layoutSaveError": "Layout konnte nicht gespeichert werden",
|
||
"layoutResetSuccess": "Auf Standard-Layout zurückgesetzt",
|
||
"layoutUsingDefaults": "Standard-Layout aktiv",
|
||
"layoutCustomized": "Eigenes Layout aktiv",
|
||
"moveUp": "Nach oben",
|
||
"moveDown": "Nach unten"
|
||
},
|
||
"measurements": {
|
||
"title": "Messungen",
|
||
"subtitle": "Gewicht, Blutdruck, Puls & mehr",
|
||
"addMeasurement": "Hinzufügen",
|
||
"editMeasurement": "Messwert bearbeiten",
|
||
"type": "Typ",
|
||
"value": "Wert",
|
||
"unit": "Einheit",
|
||
"date": "Datum",
|
||
"source": "Quelle",
|
||
"notes": "Notizen",
|
||
"typeWeight": "Gewicht",
|
||
"typeBloodPressure": "Blutdruck",
|
||
"typeBpSys": "Sys",
|
||
"typeBpDia": "Dia",
|
||
"typePulse": "Puls",
|
||
"typeBodyFat": "Körperfett",
|
||
"typeSleep": "Schlaf",
|
||
"typeSteps": "Schritte",
|
||
"typeBloodGlucose": "Blutzucker",
|
||
"typeTotalBodyWater": "Gesamtkörperwasser",
|
||
"typeBoneMass": "Knochenmasse",
|
||
"typeOxygenSaturation": "Sauerstoffsättigung",
|
||
"glucoseContext": "Kontext",
|
||
"glucoseContextFasting": "Nüchtern (≥8 h ohne Nahrung)",
|
||
"glucoseContextPostprandial": "Postprandial (2 h nach dem Essen)",
|
||
"glucoseContextRandom": "Beliebig / ohne Kontext",
|
||
"glucoseContextBedtime": "Vor dem Schlafen",
|
||
"glucoseUnit": "Blutzucker-Einheit",
|
||
"glucoseUnitHint": "Gespeichert in mg/dL; Anzeige-Einheit ist deine Präferenz.",
|
||
"unitHours": "Stunden",
|
||
"unitSteps": "Schritte",
|
||
"sourceManual": "Manuell",
|
||
"sourceWithings": "Withings",
|
||
"sourceImport": "Import",
|
||
"systolicLabel": "Systolisch (mmHg)",
|
||
"diastolicLabel": "Diastolisch (mmHg)",
|
||
"pulseLabel": "Puls (bpm)",
|
||
"valueWithUnit": "Wert ({unit})",
|
||
"timestamp": "Zeitpunkt",
|
||
"notesPlaceholder": "z.B. nach dem Essen",
|
||
"formReset": "Formular zurücksetzen",
|
||
"saveError": "Fehler beim Speichern",
|
||
"deleteError": "Fehler beim Löschen",
|
||
"invalidValue": "Bitte einen gültigen Wert eingeben.",
|
||
"invalidTimestamp": "Bitte einen gültigen Zeitpunkt wählen.",
|
||
"loginRequired": "Bitte anmelden, um Messwerte zu sehen.",
|
||
"allTypes": "Alle Typen",
|
||
"measurementCount": "{count} Messwerte",
|
||
"noMeasurements": "Keine Messwerte vorhanden",
|
||
"comment": "Kommentar",
|
||
"actions": "Aktionen",
|
||
"deleteConfirmTitle": "Messwert löschen?",
|
||
"deleteConfirmDescription": "Dieser Messwert wird unwiderruflich gelöscht.",
|
||
"pageInfo": "Seite {page} von {total}",
|
||
"showing": "Zeigt",
|
||
"of": "von",
|
||
"entries": "Einträgen"
|
||
},
|
||
"mood": {
|
||
"title": "Stimmung",
|
||
"subtitle": "Stimmungsverlauf & Einträge",
|
||
"addEntry": "Hinzufügen",
|
||
"editEntry": "Eintrag bearbeiten",
|
||
"moodLevel": "Stimmung",
|
||
"tags": "Tags",
|
||
"tagsPlaceholder": "z.B. Sport, Arbeit, Familie",
|
||
"tagsHelp": "Kommagetrennt eingeben",
|
||
"timestamp": "Zeitpunkt",
|
||
"date": "Datum",
|
||
"source": "Quelle",
|
||
"levelSuperGut": "Super gut",
|
||
"levelGut": "Gut",
|
||
"levelOkay": "Okay",
|
||
"levelSchlecht": "Schlecht",
|
||
"levelLausig": "Lausig",
|
||
"sourceManual": "Manuell",
|
||
"sourceMoodlog": "moodLog",
|
||
"sourceWeb": "Web",
|
||
"sourceTelegram": "Telegram",
|
||
"sourceDaylio": "Daylio",
|
||
"allMoods": "Alle Stimmungen",
|
||
"entryCount": "{count} Einträge",
|
||
"noEntries": "Keine Stimmungseinträge vorhanden",
|
||
"actions": "Aktionen",
|
||
"formReset": "Formular zurücksetzen",
|
||
"saveError": "Fehler beim Speichern",
|
||
"deleteError": "Fehler beim Löschen",
|
||
"invalidTimestamp": "Bitte einen gültigen Zeitpunkt wählen.",
|
||
"deleteConfirmTitle": "Eintrag löschen?",
|
||
"deleteConfirmDescription": "Dieser Stimmungseintrag wird unwiderruflich gelöscht.",
|
||
"pageInfo": "Seite {page} von {total}",
|
||
"loginRequired": "Bitte anmelden, um Stimmungseinträge zu sehen."
|
||
},
|
||
"medications": {
|
||
"title": "Medikamente",
|
||
"subtitle": "Medikation, Zeitpläne & Einnahmen",
|
||
"loginRequired": "Bitte anmelden, um Medikamente zu verwalten.",
|
||
"addMedication": "Hinzufügen",
|
||
"editMedication": "Medikament bearbeiten",
|
||
"newMedication": "Neues Medikament",
|
||
"firstMedication": "Erstes Medikament anlegen",
|
||
"noMedicationsYet": "Noch keine Medikamente angelegt",
|
||
"loadFailed": "Medikamente konnten nicht geladen werden",
|
||
"retryLoad": "Erneut laden",
|
||
"name": "Name",
|
||
"dose": "Dosis",
|
||
"doseAmount": "Menge",
|
||
"doseUnit": "Einheit",
|
||
"category": "Kategorie",
|
||
"schedule": "Zeitfenster",
|
||
"scheduleFrom": "Von",
|
||
"scheduleTo": "Bis",
|
||
"scheduleLabel": "Bezeichnung",
|
||
"scheduleDays": "Tage",
|
||
"scheduleDaily": "Täglich",
|
||
"active": "Aktiv",
|
||
"inactive": "Pausiert",
|
||
"intakeHistory": "Einnahme-Verlauf",
|
||
"showIntakeHistory": "Einnahme-Verlauf anzeigen",
|
||
"hideIntakeHistory": "Einnahme-Verlauf ausblenden",
|
||
"markTaken": "Eingenommen",
|
||
"markSkipped": "Übersprungen",
|
||
"deleteConfirm": "Medikament löschen?",
|
||
"deleteDescription": "Das Medikament und alle Einnahmen werden unwiderruflich gelöscht.",
|
||
"noMedications": "Keine Medikamente vorhanden.",
|
||
"compliance": "Einnahmetreue",
|
||
"import": "Import",
|
||
"importIntakes": "Einnahmen importieren",
|
||
"importDescription": "JSON-Array mit Einnahme-Daten einfügen. Erwartetes Format:",
|
||
"importUploadFile": "JSON-Datei hochladen",
|
||
"importPaste": "JSON hier einfügen...",
|
||
"importSelected": "Ausgewählt: {name}",
|
||
"importFileLoaded": "Datei \"{name}\" geladen",
|
||
"importInvalidJson": "Datei enthält kein gültiges JSON",
|
||
"importNoArray": "Kein Array gefunden",
|
||
"importResult": "{imported} Einnahmen importiert",
|
||
"importDuplicatesSkipped": "{count} Duplikate übersprungen",
|
||
"importInvalidSkipped": "{count} ungültige Einträge übersprungen",
|
||
"importFailed": "Import fehlgeschlagen",
|
||
"importInvalidFormat": "Ungültiges JSON-Format",
|
||
"apiAccess": "API-Zugang",
|
||
"apiEndpointTitle": "API-Endpoint: {name}",
|
||
"apiEndpointDescription": "Nutze diesen Endpoint, um Einnahmen per API zu erfassen (z.B. via iPhone-Kurzbefehl oder cron-Job).",
|
||
"apiEndpointActive": "API-Endpoint aktiv",
|
||
"apiEndpointActivated": "API-Endpoint aktiviert",
|
||
"apiEndpointDeactivated": "API-Endpoint deaktiviert",
|
||
"apiTokenCount": "Aktiv ({count} Token)",
|
||
"apiToken": "API-Token",
|
||
"apiTokenActiveHint": "Endpoint ist aktiv. Vorhandene Tokens bleiben gültig, können aber nicht erneut im Klartext angezeigt werden.",
|
||
"apiTokenActivateHint": "Aktiviere den Endpoint, um einen neuen Token zu erstellen.",
|
||
"apiTokenOnceHint": "Der Token wird nur bei der Erstellung einmal im Klartext angezeigt.",
|
||
"requestExample": "Request-Beispiel",
|
||
"statusLoadFailed": "Status konnte nicht geladen werden",
|
||
"changeFailed": "Ändern fehlgeschlagen",
|
||
"categoryBloodPressure": "Blutdrucksenker",
|
||
"categoryCholesterol": "Cholesterin",
|
||
"categoryDiabetes": "Diabetes",
|
||
"categoryVitamin": "Vitamine",
|
||
"categoryThyroid": "Schilddrüse",
|
||
"categoryHormone": "Hormone",
|
||
"categorySupplement": "Nahrungsergänzung",
|
||
"categoryPainRelief": "Schmerzmittel",
|
||
"categoryAllergy": "Allergie",
|
||
"categoryDigestive": "Magen/Darm",
|
||
"categorySkin": "Hautpflege",
|
||
"categorySleepAid": "Schlafmittel",
|
||
"categoryOther": "Sonstiges",
|
||
"daysSun": "So",
|
||
"daysMon": "Mo",
|
||
"daysTue": "Di",
|
||
"daysWed": "Mi",
|
||
"daysThu": "Do",
|
||
"daysFri": "Fr",
|
||
"daysSat": "Sa",
|
||
"intakeHistoryTitle": "Einnahme-Verlauf",
|
||
"newIntake": "Hinzufügen",
|
||
"editIntake": "Einnahme bearbeiten",
|
||
"intakeScheduledFor": "Geplant",
|
||
"intakeTakenAt": "Eingenommen um",
|
||
"intakeStatus": "Status",
|
||
"intakeSource": "Quelle",
|
||
"intakeStatusTaken": "Eingenommen",
|
||
"intakeStatusSkipped": "Übersprungen",
|
||
"intakeStatusMissed": "Verpasst",
|
||
"intakeDeleteConfirm": "Einnahme-Eintrag löschen?",
|
||
"intakeDeleteDescription": "Dieser Einnahme-Eintrag wird unwiderruflich gelöscht.",
|
||
"intakeCount": "{count} Einnahmen",
|
||
"viewHistory": "Verlauf",
|
||
"today": "Heute",
|
||
"yesterday": "Gestern",
|
||
"tomorrow": "Morgen",
|
||
"withoutNotification": "Ohne Benachrichtigung",
|
||
"pausedSince": "Pausiert seit",
|
||
"takeNow": "Jetzt einnehmen",
|
||
"overdue": "Überfällig",
|
||
"veryOverdue": "Stark überfällig",
|
||
"compliance7d": "7-Tage-Compliance",
|
||
"compliance30d": "30-Tage-Compliance",
|
||
"lastIntake": "Letzte Einnahme:",
|
||
"nextIntake": "Nächste Einnahme:",
|
||
"dayStreak": "Tage Serie",
|
||
"taken": "Genommen",
|
||
"skipped": "Übersprungen",
|
||
"weekdaySunday": "Sonntag",
|
||
"weekdayMonday": "Montag",
|
||
"weekdayTuesday": "Dienstag",
|
||
"weekdayWednesday": "Mittwoch",
|
||
"weekdayThursday": "Donnerstag",
|
||
"weekdayFriday": "Freitag",
|
||
"weekdaySaturday": "Samstag",
|
||
"weekdaySundayPlural": "Sonntags",
|
||
"weekdayMondayPlural": "Montags",
|
||
"weekdayTuesdayPlural": "Dienstags",
|
||
"weekdayWednesdayPlural": "Mittwochs",
|
||
"weekdayThursdayPlural": "Donnerstags",
|
||
"weekdayFridayPlural": "Freitags",
|
||
"weekdaySaturdayPlural": "Samstags",
|
||
"formType": "Typ",
|
||
"formDose": "Dosis",
|
||
"formUnit": "Einheit",
|
||
"formSchedule": "Zeitfenster",
|
||
"newSchedule": "Neues Zeitfenster",
|
||
"removeSchedule": "Zeitfenster entfernen",
|
||
"advancedEditing": "Erweiterte Bearbeitung",
|
||
"advancedEditingHide": "Erweiterte Bearbeitung ausblenden",
|
||
"scheduleInterval": "Intervall",
|
||
"scheduleEveryWeek": "jede Woche",
|
||
"scheduleEveryNWeeks": "alle {n} Wochen",
|
||
"scheduleIntervalPrefix": "Intervall:",
|
||
"nextSchedulePrefix": "Nächstes Zeitfenster:",
|
||
"nextScheduleDaily": "täglich",
|
||
"importIntakesAction": "Einnahmen importieren",
|
||
"apiEndpointAction": "API-Endpunkt",
|
||
"pause": "Pausieren",
|
||
"activate": "Aktivieren",
|
||
"disableNotifications": "Benachrichtigungen deaktivieren",
|
||
"enableNotifications": "Benachrichtigungen aktivieren",
|
||
"purgeRecords": "Alle Aufzeichnungen löschen",
|
||
"formReset": "Formular zurücksetzen",
|
||
"createMedication": "Medikament anlegen",
|
||
"deleteConfirmDescription": "Das Medikament und die gesamte Einnahme-Historie werden unwiderruflich gelöscht.",
|
||
"purgeConfirmTitle": "Alle Aufzeichnungen löschen?",
|
||
"purgeConfirmDescription": "Alle Einnahme-Aufzeichnungen für dieses Medikament werden unwiderruflich gelöscht. Das Medikament selbst bleibt bestehen und startet ohne Verlaufsdaten.",
|
||
"saveError": "Fehler beim Speichern",
|
||
"deleteError": "Fehler beim Löschen",
|
||
"purgeError": "Fehler beim Löschen der Aufzeichnungen",
|
||
"invalidTimestamp": "Bitte einen gültigen Zeitpunkt wählen.",
|
||
"noIntakesYet": "Noch keine Einnahmen vorhanden",
|
||
"noIntakesForMedication": "Noch keine Einnahmen für",
|
||
"deleteIntakeAriaLabel": "Einnahme löschen",
|
||
"actions": "Aktionen",
|
||
"pageInfo": "Seite {page} von {total}",
|
||
"loginRequiredIntakes": "Bitte anmelden, um Einnahmen zu sehen.",
|
||
"clear": "Löschen",
|
||
"phaseConfig": "Erinnerungsphasen",
|
||
"phaseConfigDescription": "Konfiguriere die Zeitpunkte für Erinnerungen.",
|
||
"phaseGreen": "Grün",
|
||
"phaseYellow": "Gelb",
|
||
"phaseOrange": "Orange",
|
||
"phaseRed": "Rot",
|
||
"phaseMinutes": "Min",
|
||
"phasePercent": "%",
|
||
"phaseBeforeEnd": "vor Ende",
|
||
"phaseAfterEnd": "nach Ende",
|
||
"phaseResetDefaults": "Auf Defaults zurücksetzen",
|
||
"phaseSaved": "Erinnerungsphasen gespeichert",
|
||
"phaseReset": "Auf Defaults zurückgesetzt",
|
||
"sourceWeb": "Webseite",
|
||
"sourceApi": "Externe API",
|
||
"sourceReminder": "Telegram / Erinnerung",
|
||
"sourceImport": "CSV-Import",
|
||
"unitDrops": "Tropfen",
|
||
"unitTablets": "Tablette(n)",
|
||
"unitCapsules": "Kapsel(n)",
|
||
"unitPieces": "Stück",
|
||
"namePlaceholder": "z.B. Ibuprofen",
|
||
"dosePlaceholder": "z.B. 400",
|
||
"labelPlaceholder": "z.B. Morgens",
|
||
"defaultDose": "Standard",
|
||
"dayDeactivate": "{day} deaktivieren",
|
||
"dayActivate": "{day} aktivieren"
|
||
},
|
||
"charts": {
|
||
"title": "Verlauf",
|
||
"subtitle": "Visualisierung deiner Gesundheitsdaten",
|
||
"timeRange": "Zeitraum",
|
||
"days7": "7 Tage",
|
||
"days30": "30 Tage",
|
||
"days90": "90 Tage",
|
||
"days365": "1 Jahr",
|
||
"daysAll": "Alle",
|
||
"weight": "Gewicht",
|
||
"bloodPressure": "Blutdruck",
|
||
"pulse": "Puls",
|
||
"bodyFat": "Körperfett",
|
||
"sleep": "Schlaf",
|
||
"steps": "Schritte",
|
||
"compliance": "Einnahmetreue",
|
||
"noData": "Keine Daten im gewählten Zeitraum",
|
||
"movingAverage": "Gleitender Durchschnitt",
|
||
"target": "Zielbereich",
|
||
"points7Label": "7 Pkt",
|
||
"points7Title": "Letzte 7 Messpunkte",
|
||
"points30Label": "30 Pkt",
|
||
"points30Title": "Letzte 30 Messpunkte",
|
||
"points90Label": "90 Pkt",
|
||
"points90Title": "Letzte 90 Messpunkte",
|
||
"pointsAllLabel": "Alle",
|
||
"pointsAllTitle": "Alle verfügbaren Messpunkte",
|
||
"systolic": "Systolisch",
|
||
"diastolic": "Diastolisch",
|
||
"bodyWater": "Körperwasser",
|
||
"boneMass": "Knochenmasse",
|
||
"spo2": "SpO₂",
|
||
"movingAverage7d": "7T-Schnitt",
|
||
"avg7dShort": "7T",
|
||
"avg30dShort": "30T",
|
||
"trend": "Trend",
|
||
"targetRanges": "Zielbereiche",
|
||
"perWeek": "/Woche",
|
||
"selectMedication": "Medikament wählen",
|
||
"noComplianceData": "Keine Compliance-Daten verfügbar",
|
||
"history": "Verlauf",
|
||
"complianceDays90": "Einnahmetreue (90 Tage)",
|
||
"colorGreen": "Grün:",
|
||
"colorOrange": "Orange:",
|
||
"colorRed": "Rot:",
|
||
"mood": "Stimmung",
|
||
"moodScore": "Stimmungswert",
|
||
"moodMA": "7-Tage-Schnitt",
|
||
"moodLabel1": "Lausig",
|
||
"moodLabel2": "Schlecht",
|
||
"moodLabel3": "Okay",
|
||
"moodLabel4": "Gut",
|
||
"moodLabel5": "Super",
|
||
"weekdays": {
|
||
"mon": "Mo",
|
||
"wed": "Mi",
|
||
"fri": "Fr",
|
||
"sun": "So"
|
||
},
|
||
"months": {
|
||
"jan": "Jan",
|
||
"feb": "Feb",
|
||
"mar": "Mär",
|
||
"apr": "Apr",
|
||
"may": "Mai",
|
||
"jun": "Jun",
|
||
"jul": "Jul",
|
||
"aug": "Aug",
|
||
"sep": "Sep",
|
||
"oct": "Okt",
|
||
"nov": "Nov",
|
||
"dec": "Dez"
|
||
},
|
||
"heatmapOnTime": "pünktlich",
|
||
"heatmapLate": "spät",
|
||
"heatmapVeryLate": "sehr spät",
|
||
"legendOnTime": "Pünktlich",
|
||
"legendLate": "Spät",
|
||
"legendVeryLate": "Sehr spät",
|
||
"legendMissed": "Verpasst"
|
||
},
|
||
"insights": {
|
||
"aiAnalysisTitle": "KI-Gesundheitsanalyse",
|
||
"noAnalysisYet": "Noch keine Analyse vorhanden.",
|
||
"noProviderConfigured": "KI-Provider nicht konfiguriert.",
|
||
"startAnalysis": "Analyse starten",
|
||
"refreshAnalysis": "Analyse aktualisieren",
|
||
"keyTakeaway": "Das Wichtigste",
|
||
"findingsTitle": "Befunde",
|
||
"correlationsTitle": "Zusammenhänge",
|
||
"recommendationsTitle": "Empfehlungen",
|
||
"dataFoundation": "Datengrundlage",
|
||
"dataGaps": "Datenlücken:",
|
||
"lastUpdated": "Zuletzt aktualisiert",
|
||
"confidenceHoch": "Hoch",
|
||
"confidenceMittel": "Mittel",
|
||
"confidenceGering": "Gering",
|
||
"loadError": "Auswertungen konnten nicht geladen werden",
|
||
"generationFailed": "Die Analyse konnte nicht erstellt werden. Bitte erneut versuchen.",
|
||
"title": "Insights",
|
||
"subtitle": "KI-basierte Analyse deiner Gesundheitsdaten",
|
||
"overviewSubtitle": "Trends, Risiken, Fortschritt auf einen Blick",
|
||
"navGeneral": "Allgemein",
|
||
"navBloodPressure": "Blutdruck",
|
||
"navWeight": "Gewicht",
|
||
"navPulse": "Puls",
|
||
"navMood": "Stimmung",
|
||
"navMedication": "Medikamente",
|
||
"navBmi": "BMI",
|
||
"measurementsOverDays": "{count} Messungen über {days} Tage",
|
||
"healthStatus": "Gesundheitsstatus",
|
||
"noWeightData": "Keine Gewichtsdaten oder Größe nicht hinterlegt.",
|
||
"notEnoughBpData": "Nicht genügend Blutdruckdaten.",
|
||
"bpTargetRange": "Zielbereich Blutdruck",
|
||
"inTargetRange": "im Zielbereich",
|
||
"bpTarget": "Ziel: {range}",
|
||
"noDobSet": "Geburtsdatum nicht hinterlegt.",
|
||
"avg30dEsc": "30T-Durchschnitt · ESC/ESH 2018",
|
||
"whoClassification": "WHO-Klassifikation",
|
||
"correlations": "Korrelationen",
|
||
"weightVsBp": "Gewicht vs. Blutdruck (Systolisch)",
|
||
"strengthStrong": "Starke Korrelation",
|
||
"strengthModerate": "Moderate Korrelation",
|
||
"strengthWeak": "Schwache Korrelation",
|
||
"strengthNone": "Keine Korrelation",
|
||
"weightBpStrong": "Es besteht ein starker Zusammenhang zwischen Gewicht und Blutdruck.",
|
||
"weightBpModerate": "Es besteht ein moderater Zusammenhang zwischen Gewicht und Blutdruck.",
|
||
"weightBpWeak": "Es besteht ein schwacher Zusammenhang zwischen Gewicht und Blutdruck.",
|
||
"weightBpNone": "Kein erkennbarer Zusammenhang zwischen Gewicht und Blutdruck.",
|
||
"notEnoughCorrelationData": "Zu wenig Daten für Korrelationsanalyse.",
|
||
"minCorrelationData": "Mindestens 5 zeitlich übereinstimmende Gewichts- und Blutdruckmessungen nötig.",
|
||
"bpMedContinuity": "Blutdrucksenker-Kontinuität vs. Blutdruck (Systolisch)",
|
||
"continuityLabel": "Kontinuität",
|
||
"continuityBpLabel": "Kontinuität Blutdrucksenker (%)",
|
||
"weightKgLabel": "Gewicht (kg)",
|
||
"bpMedNegative": "Negativer Zusammenhang: höhere Kontinuität geht eher mit niedrigerem systolischen Blutdruck einher.",
|
||
"bpMedPositive": "Positiver Zusammenhang: höhere Kontinuität geht in deinen Daten eher mit höherem systolischen Blutdruck einher.",
|
||
"bpMedNone": "Kein erkennbarer Zusammenhang in deinen Daten.",
|
||
"bpMedCount": "{count} Blutdrucksenker",
|
||
"notEnoughMedData": "Zu wenig Daten für diese Analyse.",
|
||
"notEnoughMedDataHint": "Markiere Medikamente als Blutdrucksenker und erfasse ausreichend Einnahmen + Blutdruckmessungen.",
|
||
"medicationCompliance": "Medikamenten-Compliance",
|
||
"dayStreak": "{count} Tage Serie",
|
||
"compliance7d": "7-Tage-Compliance",
|
||
"compliance30d": "30-Tage-Compliance",
|
||
"taken": "genommen",
|
||
"skipped": "übersprungen",
|
||
"missed": "verpasst",
|
||
"complianceTrend": "Compliance-Verlauf",
|
||
"generalStatusTitle": "Allgemeiner Gesundheitszustand",
|
||
"generalStatusLoading": "Allgemeiner Zustand wird erstellt...",
|
||
"generalStatusNoKey": "Der allgemeine Zustand kann nicht erstellt werden, da kein OpenAI-KI-Schlüssel hinterlegt ist.",
|
||
"generalStatusUnavailable": "Der allgemeine Zustand konnte aktuell nicht geladen werden.",
|
||
"generalStatusBadge": {
|
||
"good": "Gut",
|
||
"watch": "Beobachten",
|
||
"critical": "Kritisch"
|
||
},
|
||
"assessmentTitle": "Einschätzung",
|
||
"bloodPressureSectionTitle": "Blutdruck",
|
||
"bloodPressureMedicationListTitle": "Blutdrucksenker & Compliance",
|
||
"bloodPressureMedicationListEmpty": "Keine aktiven Blutdrucksenker hinterlegt.",
|
||
"bloodPressureStatusLoading": "Blutdruck-Zusammenfassung wird erstellt...",
|
||
"bloodPressureStatusNoKey": "Die Blutdruck-Zusammenfassung kann nicht erstellt werden, da kein OpenAI-KI-Schlüssel hinterlegt ist.",
|
||
"bloodPressureStatusUnavailable": "Die Blutdruck-Zusammenfassung konnte aktuell nicht geladen werden.",
|
||
"weightSectionTitle": "Gewicht",
|
||
"weightStatusLoading": "Gewichts-Zusammenfassung wird erstellt...",
|
||
"weightStatusNoKey": "Die Gewichts-Zusammenfassung kann nicht erstellt werden, da kein OpenAI-KI-Schlüssel hinterlegt ist.",
|
||
"weightStatusUnavailable": "Die Gewichts-Zusammenfassung konnte aktuell nicht geladen werden.",
|
||
"pulseSectionTitle": "Puls",
|
||
"pulseStatusLoading": "Puls-Zusammenfassung wird erstellt...",
|
||
"pulseStatusNoKey": "Die Puls-Zusammenfassung kann nicht erstellt werden, da kein OpenAI-KI-Schlüssel hinterlegt ist.",
|
||
"pulseStatusUnavailable": "Die Puls-Zusammenfassung konnte aktuell nicht geladen werden.",
|
||
"bmiSectionTitle": "BMI",
|
||
"bmiStatusLoading": "BMI-Zusammenfassung wird erstellt...",
|
||
"bmiStatusNoKey": "Die BMI-Zusammenfassung kann nicht erstellt werden, da kein OpenAI-KI-Schlüssel hinterlegt ist.",
|
||
"bmiStatusUnavailable": "Die BMI-Zusammenfassung konnte aktuell nicht geladen werden.",
|
||
"medicationComplianceStatusLoading": "Text zur Medikamentencompliance wird erstellt...",
|
||
"medicationComplianceStatusNoKey": "Der Text zur Medikamentencompliance kann nicht erstellt werden, da kein OpenAI-KI-Schlüssel hinterlegt ist.",
|
||
"medicationComplianceStatusUnavailable": "Der Text zur Medikamentencompliance konnte aktuell nicht geladen werden.",
|
||
"complianceNoData": "Keine Compliance-Daten verfügbar",
|
||
"aiInsights": "KI-Insights",
|
||
"configureApiKey": "Konfiguriere einen OpenAI API-Key in den Einstellungen, um KI-basierte Insights zu erhalten.",
|
||
"alertsTitle": "Hinweise & Empfehlungen",
|
||
"showLess": "Weniger anzeigen",
|
||
"showMore": "+{count} weitere",
|
||
"generate": "Neue Analyse erstellen",
|
||
"generating": "Analyse wird erstellt...",
|
||
"lastGenerated": "Letzte Analyse",
|
||
"noInsights": "Noch keine Analyse vorhanden.",
|
||
"rateLimit": "Bitte warte, bevor du eine neue Analyse erstellst.",
|
||
"noApiKey": "Bitte hinterlege zuerst einen OpenAI API-Key in den Einstellungen.",
|
||
"sendRawData": "Rohdaten mitsenden",
|
||
"minMoodCorrelationData": "Mindestens 5 zeitlich übereinstimmende Stimmungs- und Messdaten nötig.",
|
||
"moodBpModerate": "Es besteht ein moderater Zusammenhang zwischen Stimmung und Blutdruck.",
|
||
"moodBpNone": "Kein erkennbarer Zusammenhang zwischen Stimmung und Blutdruck.",
|
||
"moodBpStrong": "Es besteht ein starker Zusammenhang zwischen Stimmung und Blutdruck.",
|
||
"moodBpWeak": "Es besteht ein schwacher Zusammenhang zwischen Stimmung und Blutdruck.",
|
||
"moodScoreLabel": "Stimmung (Ø)",
|
||
"moodSectionTitle": "Stimmung",
|
||
"moodStatusLoading": "Stimmungsanalyse wird erstellt...",
|
||
"moodStatusNoKey": "Die Stimmungs-Zusammenfassung kann nicht erstellt werden, da kein OpenAI-KI-Schlüssel hinterlegt ist.",
|
||
"moodStatusUnavailable": "Stimmungsanalyse nicht verfügbar",
|
||
"moodVsBp": "Stimmung vs. Blutdruck (Systolisch)",
|
||
"moodVsPulse": "Stimmung vs. Puls",
|
||
"moodVsWeight": "Stimmung vs. Gewicht",
|
||
"moodWeightModerate": "Es besteht ein moderater Zusammenhang zwischen Stimmung und Gewicht.",
|
||
"moodWeightNone": "Kein erkennbarer Zusammenhang zwischen Stimmung und Gewicht.",
|
||
"moodWeightStrong": "Es besteht ein starker Zusammenhang zwischen Stimmung und Gewicht.",
|
||
"moodWeightWeak": "Es besteht ein schwacher Zusammenhang zwischen Stimmung und Gewicht.",
|
||
"notEnoughMoodCorrelationData": "Zu wenig Stimmungsdaten für Korrelationsanalyse.",
|
||
"refreshButton": "Aktualisieren",
|
||
"generateButton": "Generieren",
|
||
"analyzing": "Analysiere Gesundheitsdaten...",
|
||
"confidence": "Konfidenz",
|
||
"confidence_niedrig": "niedrig",
|
||
"confidence_mittel": "mittel",
|
||
"confidence_hoch": "hoch",
|
||
"cached": "Gecacht",
|
||
"sectionChanged": "Was hat sich verändert",
|
||
"sectionStable": "Was ist stabil",
|
||
"sectionDrivers": "Mögliche Zusammenhänge",
|
||
"sectionNextSteps": "Nächste Schritte",
|
||
"generatePrompt": "Klicke auf \"Generieren\" für KI-basierte Insights deiner Gesundheitsdaten."
|
||
},
|
||
"thresholds": {
|
||
"title": "Persönliche Zielwerte",
|
||
"subtitle": "Überschreibe den berechneten Zielbereich für jede Metrik. Ohne Eintrag gilt der Default.",
|
||
"defaultLabel": "Default",
|
||
"overrideLabel": "Dein Wert",
|
||
"autoModeLabel": "Auto",
|
||
"overrideModeLabel": "Überschrieben",
|
||
"resetAction": "Auf Default zurücksetzen",
|
||
"resetAllAction": "Alle auf Default zurücksetzen",
|
||
"minLabel": "Min",
|
||
"maxLabel": "Max",
|
||
"unitSuffix": "({unit})",
|
||
"outOfBoundsHint": "Erlaubter Bereich: {min}–{max} {unit}",
|
||
"overrideWarning": "Werte außerhalb der Leitlinien können zu ungesunden Zielen führen. Nur nach ärztlicher Rücksprache überschreiben.",
|
||
"saveSuccess": "Zielwerte aktualisiert",
|
||
"saveError": "Zielwerte konnten nicht gespeichert werden",
|
||
"resetSuccess": "Auf Default zurückgesetzt",
|
||
"sourceOverride": "Eigener Wert",
|
||
"metricWeight": "Gewicht",
|
||
"metricBpSys": "Blutdruck (systolisch)",
|
||
"metricBpDia": "Blutdruck (diastolisch)",
|
||
"metricPulse": "Ruhepuls",
|
||
"metricBodyFat": "Körperfett",
|
||
"metricSleep": "Schlafdauer",
|
||
"metricSteps": "Schritte/Tag",
|
||
"metricGlucoseFasting": "Glukose — nüchtern",
|
||
"metricGlucosePostprandial": "Glukose — postprandial",
|
||
"metricGlucoseRandom": "Glukose — beliebig",
|
||
"metricGlucoseBedtime": "Glukose — vor dem Schlafen",
|
||
"metricBodyWater": "Körperwasser",
|
||
"metricBoneMass": "Knochenmasse",
|
||
"metricOxygenSaturation": "Sauerstoffsättigung (SpO₂)",
|
||
"unsetExplanation": "Kein eigener Wert — berechneter Default aktiv.",
|
||
"loadError": "Zielwerte konnten nicht geladen werden"
|
||
},
|
||
"onboarding": {
|
||
"welcome": "Willkommen bei HealthLog!",
|
||
"setupDescription": "Richte dein Profil ein, um loszulegen. Du kannst das auch später in den Einstellungen ändern.",
|
||
"completeSetup": "Einrichtung abschließen",
|
||
"skip": "Überspringen",
|
||
"medicationsTitle": "Nimmst du Medikamente?",
|
||
"medicationsDescription": "Füge deine Medikamente hinzu, um Erinnerungen und Compliance-Tracking zu nutzen.",
|
||
"medNamePlaceholder": "Name",
|
||
"medDosePlaceholder": "Dosis",
|
||
"notificationsTitle": "Erinnerungen",
|
||
"notificationsDescription": "HealthLog kann dich an deine Medikamente erinnern. Konfiguriere dies später in den Einstellungen.",
|
||
"telegramHint": "Erinnerungen per Telegram-Bot mit Snooze-Buttons",
|
||
"webPushHint": "Browser-Benachrichtigungen direkt auf dein Gerät",
|
||
"notificationsLater": "Du kannst dies jederzeit in den Einstellungen einrichten.",
|
||
"targetsTitle": "Zielwerte",
|
||
"targetsDescription": "Setze optionale Zielwerte für Blutdruck und Gewicht.",
|
||
"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.",
|
||
"medScheduleHint": "Wir legen ein Standard-Erinnerungsfenster an (08:00–09:00 täglich). Du kannst es jederzeit unter „Medikamente\" anpassen."
|
||
},
|
||
"settings": {
|
||
"title": "Einstellungen",
|
||
"subtitle": "Profil, Sicherheit & Verbindungen",
|
||
"sectionsTitle": "Settings",
|
||
"categoryGeneral": "Allgemein",
|
||
"categoryNotifications": "Benachrichtigungen",
|
||
"categoryAi": "KI",
|
||
"categoryPersonalization": "Personalisierung",
|
||
"categoryIntegration": "Integration",
|
||
"categoryApi": "API",
|
||
"profile": "Profil",
|
||
"security": "Sicherheit",
|
||
"language": "Sprache",
|
||
"languageDescription": "Wähle die Anzeigesprache der Anwendung.",
|
||
"languageSystem": "System (automatisch)",
|
||
"username": "Benutzername",
|
||
"height": "Körpergröße (cm)",
|
||
"dateOfBirth": "Geburtsdatum",
|
||
"dateOfBirthHint": "Wird für die automatische Berechnung der Blutdruck-Zielwerte benötigt.",
|
||
"gender": "Geschlecht",
|
||
"genderNone": "Keine Angabe",
|
||
"genderMale": "Männlich",
|
||
"genderFemale": "Weiblich",
|
||
"genderHint": "Wird für geschlechtsspezifische Zielwerte verwendet.",
|
||
"profileSaved": "Profil gespeichert",
|
||
"changePassword": "Passwort ändern",
|
||
"changePasswordDescription": "Ersetze dein aktuelles Passwort durch ein neues.",
|
||
"passwordReset": "Passwort-Reset",
|
||
"currentPassword": "Aktuelles Passwort",
|
||
"newPassword": "Neues Passwort",
|
||
"confirmNewPassword": "Neues Passwort bestätigen",
|
||
"passwordMismatch": "Neue Passwörter stimmen nicht überein",
|
||
"passwordUpdated": "Passwort erfolgreich geändert",
|
||
"passkeys": "Passkeys",
|
||
"registeredPasskeys": "Registrierte Passkeys",
|
||
"passkeysDescription": "Passkeys ermöglichen sicheres Anmelden ohne Passwort.",
|
||
"passkeyName": "Name",
|
||
"passkeyDevice": "Gerät",
|
||
"passkeyBackup": "Backup",
|
||
"passkeyCreated": "Erstellt",
|
||
"passkeyActions": "Aktionen",
|
||
"noPasskeys": "Keine Passkeys registriert.",
|
||
"addPasskey": "Passkey hinzufügen",
|
||
"passkeyAdded": "Passkey erfolgreich hinzugefügt!",
|
||
"passkeyOptionsError": "Konnte Passkey-Optionen nicht laden",
|
||
"passkeyRegistrationFailed": "Fehler bei Passkey-Registrierung",
|
||
"passkeyRegistrationCancelled": "Passkey-Registrierung abgebrochen",
|
||
"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.",
|
||
"passkeyUnknownError": "Passkey-Registrierung fehlgeschlagen: {message}",
|
||
"deletePasskey": "Passkey löschen?",
|
||
"deletePasskeyDescription": "Der Passkey wird unwiderruflich gelöscht.",
|
||
"singleDevice": "Einzelgerät",
|
||
"multiDevice": "Multi-Gerät",
|
||
"backedUp": "gesichert",
|
||
"telegram": "Telegram-Benachrichtigungen",
|
||
"telegramDescription": "Erhalte Erinnerungen bei vergessenen Medikamenten-Einnahmen per Telegram.",
|
||
"telegramSaved": "Telegram-Einstellungen gespeichert",
|
||
"botToken": "Bot-Token",
|
||
"chatId": "Chat-ID",
|
||
"enableNotifications": "Benachrichtigungen aktivieren",
|
||
"testMessage": "Test-Nachricht",
|
||
"testSent": "Test-Nachricht gesendet!",
|
||
"telegramStep1": "1. Erstelle einen Bot über @BotFather in Telegram und kopiere den Token.",
|
||
"telegramStep2": "2. Sende /start an deinen Bot, um den Chat zu aktivieren.",
|
||
"telegramStep3": "3. Finde deine Chat-ID über @userinfobot oder die Bot-API.",
|
||
"ntfy": "ntfy",
|
||
"ntfyDescription": "Benachrichtigungen über ntfy (self-hosted oder ntfy.sh).",
|
||
"ntfyEnable": "ntfy aktivieren",
|
||
"ntfyServer": "Server-URL",
|
||
"ntfyTopic": "Topic",
|
||
"ntfyAuthToken": "Auth-Token (optional)",
|
||
"ntfyAuthTokenHint": "Nur nötig bei privaten Topics mit Zugangsschutz.",
|
||
"webPush": "Browser-Push",
|
||
"webPushDescription": "Erhalte Benachrichtigungen direkt im Browser, auch wenn HealthLog nicht geöffnet ist.",
|
||
"webPushNotSupported": "Dein Browser unterstützt keine Push-Benachrichtigungen.",
|
||
"webPushDenied": "Push-Benachrichtigungen wurden blockiert. Erlaube sie in den Browser-Einstellungen.",
|
||
"webPushNotConfigured": "Web Push ist serverseitig nicht konfiguriert.",
|
||
"webPushSubscribe": "Push aktivieren",
|
||
"webPushUnsubscribe": "Push deaktivieren",
|
||
"webPushSubscribed": "Push-Benachrichtigungen aktiviert!",
|
||
"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.",
|
||
"kiInsightsBenefitsTitle": "Vorteile mit OpenAI-Key",
|
||
"kiInsightsBenefit1": "Tägliche Zusammenfassungen für allgemeinen Zustand, Blutdruck, Gewicht, Puls, BMI und Medikamenten-Compliance.",
|
||
"kiInsightsBenefit2": "Bessere Einordnung von Trends und Korrelationen auf Basis deiner letzten 30 Tagesmesspunkte pro Bereich.",
|
||
"kiInsightsBenefit3": "Automatische Aktualisierung im Hintergrund, damit die Insights-Seite immer aktuelle Bewertungen zeigt.",
|
||
"createApiKeyHint": "API-Key erstellen unter:",
|
||
"createApiKeyLinkLabel": "platform.openai.com/api-keys",
|
||
"apiKey": "API-Key",
|
||
"apiKeyStored": "Key hinterlegt — neuen eingeben zum Ersetzen",
|
||
"apiKeySaved": "API-Key gespeichert",
|
||
"apiKeyRemoved": "API-Key entfernt",
|
||
"codexConnected": "ChatGPT erfolgreich verbunden! KI-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.",
|
||
"regenerateInsights": "Reports neu generieren",
|
||
"regenerateSuccess": "Reports wurden neu generiert",
|
||
"regenerateRateLimit": "Bitte warte — maximal 2 Analysen pro Stunde.",
|
||
"lastGeneratedAt": "Zuletzt generiert",
|
||
"withings": "Withings",
|
||
"withingsDescription": "Verbinde deine Withings-Waage und Blutdruckmessgeräte.",
|
||
"withingsCredentials": "API-Zugangsdaten",
|
||
"withingsClientId": "Client-ID",
|
||
"withingsClientSecret": "Client-Secret",
|
||
"withingsCredentialsSaved": "Zugangsdaten gespeichert",
|
||
"withingsCredentialsSavedPlaceholder": "Gespeichert — neue eingeben zum Ersetzen",
|
||
"withingsCredentialsSavedPlaceholderSecret": "Gespeichert — neues eingeben zum Ersetzen",
|
||
"withingsSaveCredentials": "Zugangsdaten speichern",
|
||
"withingsConnected": "Verbunden",
|
||
"configured": "Konfiguriert",
|
||
"withingsTokenExpired": "Token abgelaufen",
|
||
"withingsLastSync": "Letzte Sync",
|
||
"withingsSync": "Jetzt synchronisieren",
|
||
"withingsFullSync": "Alle Daten synchronisieren",
|
||
"withingsFullSyncTitle": "Vollsynchronisierung?",
|
||
"withingsFullSyncDescription": "Alle verfügbaren Withings-Daten werden vollständig synchronisiert. Das kann je nach Historie etwas dauern.",
|
||
"withingsSyncResult": "{count} Messwerte synchronisiert",
|
||
"withingsFullSyncResult": "{count} Messwerte vollständig synchronisiert",
|
||
"withingsSyncFailed": "Sync fehlgeschlagen",
|
||
"withingsSynchronize": "Synchronisieren",
|
||
"withingsDisconnect": "Trennen",
|
||
"withingsDisconnectTitle": "Withings-Verbindung trennen?",
|
||
"withingsDisconnectDescription": "Die Verbindung zu Withings wird getrennt. Bereits synchronisierte Daten bleiben erhalten.",
|
||
"withingsConnect": "Mit Withings verbinden",
|
||
"withingsNoCredentials": "Bitte zuerst die API-Zugangsdaten oben eingeben, um Withings zu verbinden.",
|
||
"apiTokens": "API-Tokens",
|
||
"apiTokensDescription": "Erstelle API-Tokens für die externe Medikamenten-Einnahme (z.B. Shortcuts, Automationen).",
|
||
"tokenName": "Token-Name",
|
||
"tokenNamePlaceholder": "Token-Name (z.B. iPhone Shortcut)",
|
||
"tokenCreated": "Token erstellt — kopiere ihn jetzt! Er wird nicht erneut angezeigt.",
|
||
"tokenRevoke": "Token widerrufen?",
|
||
"tokenRevokeDescription": "Der Token wird unwiderruflich deaktiviert. Anwendungen, die ihn nutzen, verlieren den Zugriff.",
|
||
"tokenRevoked": "Widerrufen",
|
||
"tokenExpired": "Abgelaufen",
|
||
"tokenActive": "Aktiv",
|
||
"activeTokensTitle": "Aktive Tokens",
|
||
"revokedTokensTitle": "Widerrufene Tokens ({count})",
|
||
"tokenTableName": "Name",
|
||
"tokenTablePermissions": "Berechtigungen",
|
||
"tokenTableStatus": "Status",
|
||
"tokenTableCreated": "Erstellt",
|
||
"tokenTableLastUsed": "Zuletzt genutzt",
|
||
"tokenTableActions": "Aktionen",
|
||
"noActiveTokens": "Keine aktiven Tokens vorhanden.",
|
||
"tokenNeverUsed": "Nie",
|
||
"tokenLastUsed": "Zuletzt:",
|
||
"tokenCreatedAt": "Erstellt:",
|
||
"apiEndpoint": "API-Endpoint für Medikamenten-Einnahme:",
|
||
"apiEndpointsTitle": "API-Endpoints",
|
||
"apiEndpointsDescription": "Übersicht der derzeit verfügbaren externen Endpoint(s) für Token-basierte Eingaben.",
|
||
"apiEndpointMethod": "Methode",
|
||
"apiEndpointPath": "Pfad",
|
||
"apiEndpointAuth": "Authentifizierung",
|
||
"apiEndpointExample": "Body-Beispiel",
|
||
"export": "Daten-Export",
|
||
"exportDescription": "Exportiere alle deine Gesundheitsdaten.",
|
||
"exportJson": "JSON-Export",
|
||
"exportCsv": "CSV-Export",
|
||
"doctorReport": "Arztreport (PDF)",
|
||
"auditLog": "Aktivitätsprotokoll",
|
||
"auditLogHidden": "Protokoll ausgeblendet.",
|
||
"auditLogShowing": "Zeigt die letzten {count} von {total} Einträgen",
|
||
"auditNoActivities": "Keine Aktivitäten vorhanden.",
|
||
"auditAction": "Aktion",
|
||
"auditCategory": "Kategorie",
|
||
"auditIp": "IP",
|
||
"auditLocation": "Standort",
|
||
"auditTimestamp": "Zeitpunkt",
|
||
"auditOther": "Sonstig",
|
||
"auditCategoryAuth": "Auth",
|
||
"auditCategoryData": "Daten",
|
||
"auditCategoryIntegration": "Integration",
|
||
"auditCategoryAI": "KI",
|
||
"auditCategoryAdmin": "Admin",
|
||
"auditActionAuthRegister": "Registrierung",
|
||
"auditActionAuthLogin": "Anmeldung",
|
||
"auditActionAuthLoginPasskey": "Passkey-Anmeldung",
|
||
"auditActionAuthLoginPassword": "Passwort-Anmeldung",
|
||
"auditActionAuthLoginFailed": "Fehlgeschlagene Anmeldung",
|
||
"auditActionAuthLogout": "Abmeldung",
|
||
"auditActionAuthPasskeyRegister": "Passkey hinzugefügt",
|
||
"auditActionAuthPasskeyDelete": "Passkey gelöscht",
|
||
"auditActionAuthPasswordChange": "Passwort geändert",
|
||
"auditActionMeasurementCreate": "Messwert erstellt",
|
||
"auditActionMeasurementUpdate": "Messwert aktualisiert",
|
||
"auditActionMeasurementDelete": "Messwert gelöscht",
|
||
"auditActionMedicationCreate": "Medikament erstellt",
|
||
"auditActionMedicationUpdate": "Medikament aktualisiert",
|
||
"auditActionMedicationDelete": "Medikament gelöscht",
|
||
"auditActionMedicationIntake": "Einnahme erfasst",
|
||
"auditActionMedicationIngestExternal": "Externe Einnahme",
|
||
"auditActionWithingsConnect": "Withings verbunden",
|
||
"auditActionWithingsDisconnect": "Withings getrennt",
|
||
"auditActionExportDownload": "Export heruntergeladen",
|
||
"auditActionInsightsGenerate": "KI-Insight generiert",
|
||
"auditActionAdminUserUpdate": "Admin: Benutzer aktualisiert",
|
||
"auditActionAdminUserResetPassword": "Admin: Passwort zurückgesetzt",
|
||
"auditActionAdminSettingsUpdate": "Admin: Einstellungen geändert",
|
||
"collapse": "Einklappen",
|
||
"expand": "Ausklappen",
|
||
"dangerZoneTitle": "Danger Zone",
|
||
"dangerZone": "Alle Daten löschen",
|
||
"dangerZoneDescription": "Löscht alle deine Gesundheitsdaten und Integrationen. Dein Benutzerkonto bleibt erhalten.",
|
||
"dangerZoneConfirm": "Alle Daten löschen?",
|
||
"dangerZoneConfirmDescription": "Dieser Vorgang löscht alle deine Gesundheitsdaten und Integrationen unwiderruflich. Dein Benutzerkonto bleibt erhalten.",
|
||
"dangerZoneSuccess": "Alle persönlichen Daten wurden gelöscht",
|
||
"dangerZoneDeleteFailed": "Löschen fehlgeschlagen",
|
||
"finalDelete": "Endgültig löschen",
|
||
"saved": "Gespeichert",
|
||
"savingError": "Fehler beim Speichern",
|
||
"adminAreaTitle": "Admin-Bereich",
|
||
"adminAreaDescription": "Systemweite Einstellungen und Benutzerverwaltung findest du in der Admin-Konsole.",
|
||
"openAdminConsole": "Admin-Konsole öffnen",
|
||
"moodLogTitle": "moodLog",
|
||
"moodLogDescription": "Stimmungsdaten aus moodLog importieren",
|
||
"moodLogUrl": "moodLog URL",
|
||
"moodLogUrlPlaceholder": "https://mood.example.com",
|
||
"moodLogApiKey": "API-Key",
|
||
"moodLogApiKeyPlaceholder": "ml_...",
|
||
"moodLogWebhookSecret": "Webhook-Secret",
|
||
"moodLogWebhookSecretHelp": "Dieses Secret in moodLog als Webhook-Secret eintragen",
|
||
"moodLogSync": "Sync starten",
|
||
"moodLogFullSync": "Voll-Sync",
|
||
"moodLogFullSyncTitle": "Vollsynchronisierung?",
|
||
"moodLogFullSyncDescription": "Alle verfügbaren Stimmungsdaten werden vollständig synchronisiert.",
|
||
"moodLogDisconnect": "Trennen",
|
||
"moodLogDisconnectTitle": "moodLog trennen?",
|
||
"moodLogDisconnectDescription": "Die Verbindung wird getrennt und alle importierten Stimmungsdaten werden gelöscht.",
|
||
"moodLogLastSync": "Letzter Sync",
|
||
"moodLogEntries": "Einträge",
|
||
"moodLogSyncResult": "{count} Einträge synchronisiert",
|
||
"moodLogSyncFailed": "Sync fehlgeschlagen",
|
||
"moodLogSaved": "moodLog-Verbindung gespeichert",
|
||
"moodLogDisconnected": "moodLog getrennt"
|
||
},
|
||
"admin": {
|
||
"title": "Administration",
|
||
"subtitle": "Systemstatus, Benutzer und Einstellungen",
|
||
"settingsSaveError": "Einstellungen konnten nicht gespeichert werden",
|
||
"settingsSaveValidationError": "Bitte markierte Felder prüfen",
|
||
"sectionsTitle": "Admin",
|
||
"systemStatus": "Systemstatus",
|
||
"version": "Version",
|
||
"database": "Datenbank",
|
||
"databaseConnected": "Verbunden",
|
||
"databaseError": "Fehler",
|
||
"gitCommit": "Git Commit",
|
||
"startedAt": "Gestartet",
|
||
"users": "Benutzer",
|
||
"measurementsCount": "Messwerte",
|
||
"activeTokens": "Aktive API-Tokens",
|
||
"activeSessions": "Aktive Sessions",
|
||
"loadingStatus": "Lade Status...",
|
||
"workerStatus": "Job-Worker",
|
||
"workerRunning": "Aktiv",
|
||
"workerStopped": "Gestoppt",
|
||
"lastReminderCheck": "Letzter Reminder-Check",
|
||
"appSettings": "Anwendungseinstellungen",
|
||
"registrationEnabled": "Registrierung erlauben",
|
||
"registrationEnabledDescription": "Wenn deaktiviert, können sich keine neuen Benutzer registrieren.",
|
||
"defaultLanguage": "Standard-Sprache",
|
||
"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.",
|
||
"integrationWebPush": "Web Push",
|
||
"integrationBugReport": "Bug-Reports",
|
||
"apiGlobal": "API-Endpunkte und API-Tokens systemweit erlauben.",
|
||
"moodLogGlobal": "moodLog-Integration systemweit erlauben.",
|
||
"sectionGeneral": "Allgemein",
|
||
"sectionIntegrations": "Integrationen",
|
||
"sectionMedication": "Medikamente",
|
||
"sectionManagement": "Verwaltung",
|
||
"umamiTitle": "Umami",
|
||
"umamiDescription": "Web-Analyse mit Umami",
|
||
"glitchtipTitle": "GlitchTip",
|
||
"glitchtipDescription": "Fehler-Tracking mit GlitchTip",
|
||
"webPushVapidTitle": "Web Push VAPID",
|
||
"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",
|
||
"glitchtipDsnPlaceholder": "https://<public-key>@glitchtip.example.com/<project-id>",
|
||
"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.",
|
||
"webPushVapidPublicKey": "VAPID Public Key",
|
||
"webPushVapidPublicKeyPlaceholder": "BElx... (Base64URL)",
|
||
"webPushVapidPrivateKey": "VAPID Private Key",
|
||
"webPushVapidPrivateKeyPlaceholder": "Optional: neuen Private Key eintragen",
|
||
"webPushVapidSubject": "VAPID Subject",
|
||
"webPushVapidSubjectPlaceholder": "mailto:deine-adresse@example.com",
|
||
"configured": "Konfiguriert",
|
||
"notConfigured": "Nicht konfiguriert",
|
||
"monitoringTestUmami": "Umami-Test senden",
|
||
"monitoringTestGlitchtip": "Glitchtip-Test senden",
|
||
"monitoringTestSuccess": "Testevent wurde gesendet",
|
||
"monitoringTestFailed": "Monitoring-Test fehlgeschlagen",
|
||
"monitoringSave": "Monitoring speichern",
|
||
"bugReportGithub": "Bugreport (GitHub Issues)",
|
||
"bugReportGithubDescription": "Hinterlege GitHub-Issue-Token und Repository für eingehende Bugreports.",
|
||
"bugReportRepo": "Repository",
|
||
"bugReportRepoPlaceholder": "owner/repo",
|
||
"bugReportToken": "Issue-Token",
|
||
"bugReportTokenPlaceholder": "ghp_...",
|
||
"bugReportConfigured": "Bugreport ist konfiguriert.",
|
||
"bugReportNotConfigured": "Bugreport ist noch nicht vollständig konfiguriert.",
|
||
"bugReportSave": "Bugreport speichern",
|
||
"userManagement": "Benutzerverwaltung",
|
||
"userEmail": "E-Mail",
|
||
"userRole": "Rolle",
|
||
"userPasskeys": "Passkeys",
|
||
"userCreated": "Erstellt",
|
||
"userActions": "Aktionen",
|
||
"editUser": "Benutzer bearbeiten",
|
||
"editUserTitle": "Benutzer bearbeiten: {name}",
|
||
"demoteToUser": "Zu User degradieren",
|
||
"promoteToAdmin": "Zum Admin befördern",
|
||
"toUser": "→ User",
|
||
"toAdmin": "→ Admin",
|
||
"ownRoleUnchangeable": "Eigene Rolle nicht änderbar",
|
||
"lastAdminError": "Der letzte Admin kann nicht degradiert werden",
|
||
"resetPassword": "Passwort zurücksetzen",
|
||
"resetPasswordTitle": "Passwort zurücksetzen: {name}",
|
||
"newPassword": "Neues Passwort",
|
||
"newPasswordPlaceholder": "Mindestens 12 Zeichen",
|
||
"passwordReset": "Passwort wurde zurückgesetzt",
|
||
"reset": "Zurücksetzen",
|
||
"loadingUsers": "Lade Benutzer...",
|
||
"apiTokens": "API-Tokens",
|
||
"tokenUser": "Benutzer",
|
||
"tokenName": "Name",
|
||
"tokenPermissions": "Berechtigungen",
|
||
"tokenStatus": "Status",
|
||
"tokenLastUsed": "Zuletzt benutzt",
|
||
"tokenCreated": "Erstellt",
|
||
"tokenNeverUsed": "Nie",
|
||
"noTokens": "Keine API-Tokens vorhanden.",
|
||
"loginOverview": "Anmeldeübersicht",
|
||
"allAuthEvents": "Alle Auth-Ereignisse",
|
||
"failedOnly": "Nur fehlgeschlagene",
|
||
"noEntries": "Keine Einträge vorhanden.",
|
||
"showingEntries": "Zeigt {count} von {total} Auth-Einträgen",
|
||
"status": "Status",
|
||
"action": "Aktion",
|
||
"ip": "IP",
|
||
"location": "Standort",
|
||
"timestamp": "Zeitpunkt",
|
||
"dangerZone": "Gefahrenzone",
|
||
"deleteAllData": "Alle Daten global löschen",
|
||
"deleteAllDescription": "Löscht alle Mess-, Medikamenten-, Integrations- und Protokoll-Daten aller Benutzer. Benutzerkonten bleiben bestehen.",
|
||
"deleteAllConfirm": "Alle Daten wirklich löschen?",
|
||
"deleteAllConfirmDescription": "Dieser Vorgang löscht alle Messwerte, Medikamente, Einnahmen und Integrationsdaten aller Benutzer unwiderruflich. Benutzerkonten bleiben erhalten.",
|
||
"deleteButton": "Alle Daten löschen",
|
||
"finalDelete": "Endgültig löschen",
|
||
"deletedResult": "Gelöscht: {measurements} Messwerte, {medications} Medikamente, {intakeEvents} Einnahmen",
|
||
"authRegister": "Registrierung",
|
||
"authLogin": "Anmeldung",
|
||
"authLoginPasskey": "Passkey-Anmeldung",
|
||
"authLoginPassword": "Passwort-Anmeldung",
|
||
"authLoginFailed": "Fehlgeschlagen",
|
||
"authLogout": "Abmeldung",
|
||
"authPasskeyRegister": "Passkey hinzugefügt",
|
||
"authPasskeyDelete": "Passkey gelöscht",
|
||
"medicationReminders": "Medikamentenerinnerungen",
|
||
"medicationRemindersDescription": "Schwellenwerte für die Farbübergänge der Erinnerungs-Badges auf den Medikamentenkarten.",
|
||
"reminderLateMinutes": "Spät-Schwellenwert (Minuten)",
|
||
"reminderLateMinutesDescription": "Minuten nach Fenster-Ende bis der Badge von Gelb auf Orange wechselt.",
|
||
"reminderMissedMinutes": "Verpasst-Schwellenwert (Minuten)",
|
||
"reminderMissedMinutesDescription": "Minuten nach Fenster-Ende bis die Einnahme als verpasst gilt.",
|
||
"reminderThresholdsSave": "Schwellenwerte speichern",
|
||
"notificationTest": "Benachrichtigungen testen",
|
||
"notificationTestSend": "Test-Notification senden",
|
||
"notificationTestSuccess": "Test-Notification wurde gesendet",
|
||
"notificationTestFailed": "Test-Notification konnte nicht gesendet werden",
|
||
"reminderCheckRun": "Reminder-Check ausführen",
|
||
"reminderCheckSuccess": "Reminder-Check abgeschlossen",
|
||
"reminderCheckFailed": "Reminder-Check konnte nicht ausgeführt werden",
|
||
"reminderCheckResults": "Ergebnisse",
|
||
"reminderCheckNotifOn": "Benachrichtigungen an",
|
||
"reminderCheckNotifOff": "Benachrichtigungen aus",
|
||
"reminderCheckEventsToday": "Heutige Events",
|
||
"reminderCheckNotifSent": "Gesendet",
|
||
"feedback": {
|
||
"title": "Feedback-Postfach",
|
||
"description": "Eingegangene Rückmeldungen, Fehlerberichte und Feature-Wünsche.",
|
||
"tabOpen": "Offen",
|
||
"tabAcknowledged": "Bestätigt",
|
||
"tabResolved": "Erledigt",
|
||
"tabArchived": "Archiviert",
|
||
"subject": "Betreff",
|
||
"category": "Kategorie",
|
||
"user": "Benutzer",
|
||
"createdAt": "Eingegangen",
|
||
"actions": "Aktionen",
|
||
"details": "Details",
|
||
"noEntries": "Keine Feedback-Einträge in dieser Kategorie.",
|
||
"loading": "Lade Feedback...",
|
||
"anonymous": "anonym",
|
||
"categoryBug": "Bug",
|
||
"categoryFeature": "Feature",
|
||
"categoryQuestion": "Frage",
|
||
"categoryOther": "Sonstiges",
|
||
"statusOpen": "Offen",
|
||
"statusAcknowledged": "Bestätigt",
|
||
"statusResolved": "Erledigt",
|
||
"statusArchived": "Archiviert",
|
||
"dialogTitle": "Feedback-Details",
|
||
"metadataHeading": "Metadaten",
|
||
"metaUrl": "URL",
|
||
"metaLocale": "Sprache",
|
||
"metaUserAgent": "User-Agent",
|
||
"metaAppVersion": "App-Version",
|
||
"screenshotHeading": "Screenshot",
|
||
"adminNote": "Admin-Notiz",
|
||
"adminNotePlaceholder": "Interne Notiz (nicht für Benutzer sichtbar)",
|
||
"saveNote": "Notiz speichern",
|
||
"noteSaved": "Notiz gespeichert",
|
||
"actionAcknowledge": "Bestätigen",
|
||
"actionResolve": "Erledigen",
|
||
"actionArchive": "Archivieren",
|
||
"actionPublishGithub": "Auf GitHub veröffentlichen",
|
||
"publishedToGithub": "Auf GitHub veröffentlicht",
|
||
"viewIssue": "Issue ansehen",
|
||
"publishSuccess": "Issue erstellt",
|
||
"publishFailed": "GitHub-Veröffentlichung fehlgeschlagen",
|
||
"updateFailed": "Aktualisierung fehlgeschlagen",
|
||
"archiveConfirm": "Diesen Feedback-Eintrag archivieren?",
|
||
"submittedBy": "Eingereicht von",
|
||
"sectionTitle": "Feedback"
|
||
}
|
||
},
|
||
"achievements": {
|
||
"title": "Erfolge",
|
||
"subtitle": "Sammle Erfolge ab Feature-Start durch konsequente Gesundheitstrends und Medikamentenroutinen.",
|
||
"loginRequired": "Bitte anmelden, um Erfolge zu sehen.",
|
||
"points": "Punkte",
|
||
"unlocked": "Freigeschaltet",
|
||
"nextGoal": "Nächstes Ziel",
|
||
"allCompleted": "Alle Erfolge freigeschaltet!",
|
||
"completed": "Abgeschlossen",
|
||
"inProgress": "In Arbeit",
|
||
"progress": "Fortschritt",
|
||
"goalReached": "Ziel erreicht",
|
||
"remaining": "Noch {count} bis zum Ziel",
|
||
"remainingUnlocks": "Noch {count} freischaltbar",
|
||
"noneUnlockedYet": "Noch keine Erfolge freigeschaltet.",
|
||
"pointsValue": "{points} Punkte",
|
||
"metricCount": "{count}",
|
||
"metricDays": "{count} Tage",
|
||
"metricPercent": "{count}%",
|
||
"badges": {
|
||
"intakeTotal1": {
|
||
"title": "Erste Einnahme",
|
||
"description": "Dokumentiere dein erstes eingenommenes Medikament."
|
||
},
|
||
"intakeTotal10": {
|
||
"title": "Einnahme-Starter",
|
||
"description": "Dokumentiere 10 eingenommene Medikamente."
|
||
},
|
||
"intakeTotal50": {
|
||
"title": "Einnahme-Routine",
|
||
"description": "Dokumentiere 50 eingenommene Medikamente."
|
||
},
|
||
"intakeTotal150": {
|
||
"title": "Einnahme-Profi",
|
||
"description": "Dokumentiere 150 eingenommene Medikamente."
|
||
},
|
||
"intakeTotal300": {
|
||
"title": "Einnahme-Legende",
|
||
"description": "Dokumentiere 300 eingenommene Medikamente."
|
||
},
|
||
"overIntake1": {
|
||
"title": "Idiot",
|
||
"description": "Nimm mindestens einmal mehr ein als vorgesehen."
|
||
},
|
||
"skippedIntake1": {
|
||
"title": "Lazy Boy",
|
||
"description": "Überspringe mindestens eine geplante Einnahme."
|
||
},
|
||
"passkeyCreated1": {
|
||
"title": "Passkey gesetzt",
|
||
"description": "Erstelle deinen ersten Passkey."
|
||
},
|
||
"passkeyLogin1": {
|
||
"title": "Passkey genutzt",
|
||
"description": "Melde dich mindestens einmal per Passkey an."
|
||
},
|
||
"passwordLogin1": {
|
||
"title": "Oldschool",
|
||
"description": "Melde dich mindestens einmal mit Username und Passwort an."
|
||
},
|
||
"bugReport1": {
|
||
"title": "Fehlerjäger",
|
||
"description": "Reiche einen Bugreport ein."
|
||
},
|
||
"loginStreak7": {
|
||
"title": "Login-Serie 7T",
|
||
"description": "Logge dich an 7 Tagen in Folge ein."
|
||
},
|
||
"loginStreak30": {
|
||
"title": "Login-Serie 30T",
|
||
"description": "Logge dich an 30 Tagen in Folge ein."
|
||
},
|
||
"onTimePerfect1": {
|
||
"title": "Zeitfenster 1T",
|
||
"description": "Nimm 1 Tage in Folge alle Medikamente im Zeitfenster ein."
|
||
},
|
||
"compliance801": {
|
||
"title": "Treue 80% · 1T",
|
||
"description": "Erreiche 1 Tage in Folge eine 30-Tage-Einnahmetreue von mindestens 80%."
|
||
},
|
||
"bmiGreen1": {
|
||
"title": "BMI im Grün · 1T",
|
||
"description": "Halte deinen BMI 1 Tage in Folge im Normalbereich."
|
||
},
|
||
"bpGreen1": {
|
||
"title": "Blutdruck im Grün · 1T",
|
||
"description": "Halte deinen Blutdruck 1 Tage in Folge im Normalbereich."
|
||
},
|
||
"pulseGreen1": {
|
||
"title": "Puls im Grün · 1T",
|
||
"description": "Halte deinen Ruhepuls 1 Tage in Folge im Normalbereich."
|
||
},
|
||
"onTimePerfect7": {
|
||
"title": "Zeitfenster 7T",
|
||
"description": "Nimm 7 Tage in Folge alle Medikamente im Zeitfenster ein."
|
||
},
|
||
"compliance807": {
|
||
"title": "Treue 80% · 7T",
|
||
"description": "Erreiche 7 Tage in Folge eine 30-Tage-Einnahmetreue von mindestens 80%."
|
||
},
|
||
"bmiGreen7": {
|
||
"title": "BMI im Grün · 7T",
|
||
"description": "Halte deinen BMI 7 Tage in Folge im Normalbereich."
|
||
},
|
||
"bpGreen7": {
|
||
"title": "Blutdruck im Grün · 7T",
|
||
"description": "Halte deinen Blutdruck 7 Tage in Folge im Normalbereich."
|
||
},
|
||
"pulseGreen7": {
|
||
"title": "Puls im Grün · 7T",
|
||
"description": "Halte deinen Ruhepuls 7 Tage in Folge im Normalbereich."
|
||
},
|
||
"onTimePerfect30": {
|
||
"title": "Zeitfenster 30T",
|
||
"description": "Nimm 30 Tage in Folge alle Medikamente im Zeitfenster ein."
|
||
},
|
||
"compliance8030": {
|
||
"title": "Treue 80% · 30T",
|
||
"description": "Erreiche 30 Tage in Folge eine 30-Tage-Einnahmetreue von mindestens 80%."
|
||
},
|
||
"bmiGreen30": {
|
||
"title": "BMI im Grün · 30T",
|
||
"description": "Halte deinen BMI 30 Tage in Folge im Normalbereich."
|
||
},
|
||
"bpGreen30": {
|
||
"title": "Blutdruck im Grün · 30T",
|
||
"description": "Halte deinen Blutdruck 30 Tage in Folge im Normalbereich."
|
||
},
|
||
"pulseGreen30": {
|
||
"title": "Puls im Grün · 30T",
|
||
"description": "Halte deinen Ruhepuls 30 Tage in Folge im Normalbereich."
|
||
},
|
||
"onTimePerfect180": {
|
||
"title": "Zeitfenster 180T",
|
||
"description": "Nimm 180 Tage in Folge alle Medikamente im Zeitfenster ein."
|
||
},
|
||
"compliance80180": {
|
||
"title": "Treue 80% · 180T",
|
||
"description": "Erreiche 180 Tage in Folge eine 30-Tage-Einnahmetreue von mindestens 80%."
|
||
},
|
||
"bmiGreen180": {
|
||
"title": "BMI im Grün · 180T",
|
||
"description": "Halte deinen BMI 180 Tage in Folge im Normalbereich."
|
||
},
|
||
"bpGreen180": {
|
||
"title": "Blutdruck im Grün · 180T",
|
||
"description": "Halte deinen Blutdruck 180 Tage in Folge im Normalbereich."
|
||
},
|
||
"pulseGreen180": {
|
||
"title": "Puls im Grün · 180T",
|
||
"description": "Halte deinen Ruhepuls 180 Tage in Folge im Normalbereich."
|
||
},
|
||
"onTimePerfect360": {
|
||
"title": "Zeitfenster 360T",
|
||
"description": "Nimm 360 Tage in Folge alle Medikamente im Zeitfenster ein."
|
||
},
|
||
"compliance80360": {
|
||
"title": "Treue 80% · 360T",
|
||
"description": "Erreiche 360 Tage in Folge eine 30-Tage-Einnahmetreue von mindestens 80%."
|
||
},
|
||
"bmiGreen360": {
|
||
"title": "BMI im Grün · 360T",
|
||
"description": "Halte deinen BMI 360 Tage in Folge im Normalbereich."
|
||
},
|
||
"bpGreen360": {
|
||
"title": "Blutdruck im Grün · 360T",
|
||
"description": "Halte deinen Blutdruck 360 Tage in Folge im Normalbereich."
|
||
},
|
||
"pulseGreen360": {
|
||
"title": "Puls im Grün · 360T",
|
||
"description": "Halte deinen Ruhepuls 360 Tage in Folge im Normalbereich."
|
||
}
|
||
},
|
||
"nextProgressLabel": "Fortschritt bis Freischaltung",
|
||
"completedOn": "Abgeschlossen am {date}"
|
||
},
|
||
"bugreport": {
|
||
"title": "Bugreport",
|
||
"subtitle": "Sende eine Fehlermeldung, einen Feature-Wunsch oder eine Frage. Der Server-Administrator sieht deine Einreichung.",
|
||
"loginRequired": "Bitte anmelden, um einen Bug zu melden.",
|
||
"bugTitle": "Titel",
|
||
"description": "Beschreibung",
|
||
"descriptionPlaceholder": "Beschreibe den Fehler möglichst genau. Was hast du getan? Was ist passiert? Was hättest du erwartet?",
|
||
"screenshot": "Screenshot (optional)",
|
||
"screenshotPreview": "Screenshot-Vorschau",
|
||
"attachScreenshot": "Screenshot anhängen",
|
||
"imageOnly": "Nur Bilddateien erlaubt",
|
||
"tooLarge": "Screenshot ist zu groß (max. 5 MB)",
|
||
"submit": "Senden",
|
||
"success": "Vielen Dank! Dein Bug Report wurde erfolgreich übermittelt.",
|
||
"viewOnGithub": "Auf GitHub ansehen",
|
||
"errorCreating": "Fehler beim Erstellen",
|
||
"notConfiguredTitle": "Bug-Reports noch nicht aktiviert",
|
||
"notConfiguredUser": "Bug-Reports sind auf diesem Server nicht aktiv. Bitte wende dich an den Administrator.",
|
||
"notConfiguredAdmin": "Für Bug-Reports wird eine GitHub-Integration benötigt (Issue-Token + Repository). Im Admin-Panel unter Einstellungen → Bug-Reports einrichten.",
|
||
"openAdminSettings": "Admin-Einstellungen öffnen",
|
||
"category": "Art",
|
||
"categoryBug": "Fehlermeldung",
|
||
"categoryFeature": "Feature-Wunsch",
|
||
"categoryQuestion": "Frage",
|
||
"categoryOther": "Sonstiges Feedback",
|
||
"bugTitlePlaceholder": "Kurze Zusammenfassung (optional)",
|
||
"githubEscalationNote": "Dein Feedback wird lokal gespeichert. Wenn der Administrator die GitHub-Integration aktiviert, kann es auf Wunsch als öffentliches Issue veröffentlicht werden.",
|
||
"internalOnlyNote": "Dein Feedback wird lokal gespeichert und ist nur für den Administrator dieses Servers sichtbar."
|
||
},
|
||
"notifications": {
|
||
"title": "Benachrichtigungen",
|
||
"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",
|
||
"channelDisabled": "Deaktiviert",
|
||
"eventMedicationReminder": "Medikamenten-Erinnerung",
|
||
"eventMedicationReminderDesc": "Erinnerung, wenn eine Einnahme aussteht.",
|
||
"eventMeasurementAnomaly": "Anomale Messwerte",
|
||
"eventMeasurementAnomalyDesc": "Warnung bei ungewöhnlichen Messungen (z.B. hoher Blutdruck).",
|
||
"eventComplianceLow": "Niedrige Einnahmetreue",
|
||
"eventComplianceLowDesc": "Benachrichtigung, wenn die Einnahmetreue unter einen Schwellwert fällt.",
|
||
"eventWithingsSyncFailed": "Withings-Sync-Fehler",
|
||
"eventWithingsSyncFailedDesc": "Meldung bei Fehlern beim automatischen Withings-Datenabgleich.",
|
||
"eventSystemAlert": "System-Hinweise",
|
||
"eventSystemAlertDesc": "Wichtige Systemnachrichten und administrative Hinweise."
|
||
},
|
||
"format": {
|
||
"dateShort": "{day}.{month}.{year}",
|
||
"timeShort": "{hours}:{minutes}",
|
||
"dateTime": "{day}.{month}.{year}, {hours}:{minutes}"
|
||
},
|
||
"classifications": {
|
||
"bmi": {
|
||
"Underweight": "Untergewicht",
|
||
"Normal": "Normalgewicht",
|
||
"Overweight": "Übergewicht",
|
||
"ObesityGradeI": "Adipositas Grad I",
|
||
"ObesityGradeII": "Adipositas Grad II",
|
||
"ObesityGradeIII": "Adipositas Grad III"
|
||
},
|
||
"bp": {
|
||
"Optimal": "Optimal",
|
||
"Normal": "Normal",
|
||
"HighNormal": "Hoch-normal",
|
||
"HypertensionGrade1": "Hypertonie Grad 1",
|
||
"HypertensionGrade2": "Hypertonie Grad 2",
|
||
"HypertensionGrade3": "Hypertonie Grad 3"
|
||
},
|
||
"pulse": {
|
||
"Bradycardia": "Bradykardie",
|
||
"Normal": "Normal",
|
||
"Elevated": "Erhöht",
|
||
"Tachycardia": "Tachykardie"
|
||
},
|
||
"pulseTarget": {
|
||
"SignificantlyLow": "Deutlich niedrig",
|
||
"SlightlyLow": "Leicht niedrig",
|
||
"OnTarget": "Zielbereich",
|
||
"SlightlyElevated": "Leicht erhöht",
|
||
"SignificantlyElevated": "Deutlich erhöht"
|
||
},
|
||
"sleep": {
|
||
"FarTooShort": "Deutlich zu kurz",
|
||
"TooShort": "Zu kurz",
|
||
"OnTarget": "Zielbereich",
|
||
"SlightlyLong": "Etwas lang",
|
||
"FarTooLong": "Deutlich zu lang"
|
||
},
|
||
"bodyFat": {
|
||
"Essential": "Essenziell",
|
||
"Athletic": "Athletisch",
|
||
"Fitness": "Fitness",
|
||
"Average": "Durchschnitt",
|
||
"Obese": "Adipös"
|
||
},
|
||
"steps": {
|
||
"VeryLow": "Sehr wenig",
|
||
"LowActive": "Wenig aktiv",
|
||
"ModeratelyActive": "Moderat aktiv",
|
||
"Active": "Aktiv",
|
||
"VeryActive": "Sehr aktiv"
|
||
},
|
||
"general": {
|
||
"Good": "Gut",
|
||
"Moderate": "Moderat",
|
||
"Low": "Niedrig",
|
||
"VeryGood": "Sehr gut",
|
||
"VeryStable": "Sehr stabil",
|
||
"Stable": "Stabil",
|
||
"Fluctuating": "Schwankend"
|
||
},
|
||
"alerts": {
|
||
"bmiBelowNormalTitle": "BMI unter Normalbereich",
|
||
"bmiBelowNormalMessage": "Ihr BMI von {bmi} liegt unter dem Normalbereich (18,5–24,9).",
|
||
"bmiOverweightTitle": "BMI im Bereich Übergewicht",
|
||
"bmiOverweightMessage": "Ihr BMI von {bmi} liegt im Bereich Übergewicht. Regelmäßige Bewegung und ausgewogene Ernährung können helfen.",
|
||
"bmiObesityTitle": "BMI im Bereich Adipositas",
|
||
"bmiObesityMessage": "Ihr BMI von {bmi} liegt im Bereich Adipositas.",
|
||
"bmiNormalTitle": "BMI im Normalbereich",
|
||
"bmiNormalMessage": "Ihr BMI von {bmi} liegt im gesunden Bereich.",
|
||
"bpDangerTitle": "Blutdruck deutlich erhöht",
|
||
"bpDangerMessage": "Ihr durchschnittlicher Blutdruck ({sys}/{dia}) wird als \"{category}\" eingestuft.",
|
||
"bpWarningTitle": "Blutdruck leicht erhöht",
|
||
"bpWarningMessage": "Ihr durchschnittlicher Blutdruck ({sys}/{dia}) liegt im Bereich \"{category}\".",
|
||
"bpTargetGoodTitle": "Gute Blutdruck-Zielbereichstreue",
|
||
"bpTargetGoodMessage": "{pct}% Ihrer Messungen liegen im Zielbereich.",
|
||
"bpTargetBadTitle": "Blutdruck oft außerhalb des Zielbereichs",
|
||
"bpTargetBadMessage": "Nur {pct}% Ihrer Messungen liegen im Zielbereich.",
|
||
"weightIncreasingTitle": "Gewicht steigend",
|
||
"weightIncreasingMessage": "Ihr Gewicht steigt um ca. {change} kg pro Woche in den letzten 30 Tagen.",
|
||
"weightDecreasingTitle": "Gewicht fallend",
|
||
"weightDecreasingMessage": "Ihr Gewicht sinkt um ca. {change} kg pro Woche in den letzten 30 Tagen.",
|
||
"pulseOutliersTitle": "Puls-Ausreißer erkannt",
|
||
"pulseOutliersMessage": "{count} ungewöhnliche Pulsmessungen in den letzten 30 Tagen.",
|
||
"complianceLowTitle": "Niedrige Einnahmetreue: {name}",
|
||
"complianceLowMessage": "Ihre 7-Tage-Compliance für {name} liegt bei nur {pct}%. Regelmäßige Einnahme ist wichtig.",
|
||
"complianceGoodTitle": "Sehr gute Einnahmetreue: {name}",
|
||
"complianceGoodMessage": "{pct}% Compliance in den letzten 7 Tagen. Weiter so!"
|
||
}
|
||
},
|
||
"targets": {
|
||
"title": "Zielwerte",
|
||
"introText": "Deine aktuellen Werte im Vergleich zu empfohlenen Zielbereichen. Quellen der Leitlinien sind auf jeder Karte verlinkt.",
|
||
"weight": "Gewicht",
|
||
"bloodPressure": "Blutdruck",
|
||
"bloodPressureOnTarget": "Blutdruck im Zielbereich",
|
||
"restingPulse": "Ruhepuls",
|
||
"sleepDuration": "Schlafdauer",
|
||
"bmi": "BMI",
|
||
"bodyFat": "Körperfett",
|
||
"stepsPerDay": "Schritte/Tag",
|
||
"medicationCompliance": "Einnahmetreue",
|
||
"mood": "Stimmung",
|
||
"moodStability": "Stimmungsstabilität",
|
||
"steps": "Schritte",
|
||
"average30d": "30-Tage-Schnitt:",
|
||
"currentValue": "Aktuell: {value} {unit}",
|
||
"targetRangeValue": "Zielbereich: {min}–{max} {unit}",
|
||
"sourceLabel": "Quelle: {source}",
|
||
"inTarget": "Im Zielbereich",
|
||
"aboveTarget": "{delta} {unit} über Zielbereich",
|
||
"belowTarget": "{delta} {unit} unter Zielbereich",
|
||
"diastolic": "Diastolisch",
|
||
"noMeasurementYet": "Noch keine Messungen",
|
||
"noMeasurementData": "Keine Messdaten verfügbar. Füge Messwerte hinzu, um deine Ziele zu sehen.",
|
||
"profileIncomplete": "Profil unvollständig",
|
||
"profileIncompleteHeight": "Trage deine Körpergröße im Profil ein, um BMI-Ziele zu aktivieren.",
|
||
"profileIncompleteAge": "Trage dein Geburtsdatum im Profil ein, um altersspezifische Ziele zu aktivieren.",
|
||
"profileIncompleteHeightAge": "Trage Körpergröße und Geburtsdatum im Profil ein, um personalisierte Ziele zu sehen.",
|
||
"compliancePerMedication": "Einnahmetreue pro Medikament",
|
||
"glucoseFasting": "Glukose — nüchtern",
|
||
"glucosePostprandial": "Glukose — postprandial",
|
||
"glucoseRandom": "Glukose — beliebig",
|
||
"glucoseBedtime": "Glukose — vor dem Schlafen",
|
||
"loadError": "Zielwerte konnten nicht geladen werden"
|
||
},
|
||
"passwordStrength": {
|
||
"veryWeak": "Sehr schwach",
|
||
"weak": "Schwach",
|
||
"acceptable": "Akzeptabel",
|
||
"strong": "Stark",
|
||
"veryStrong": "Sehr stark",
|
||
"tooShort": "Zu kurz",
|
||
"characters": "Zeichen",
|
||
"minLength": "Mindestens {count} Zeichen erforderlich."
|
||
},
|
||
"telegram": {
|
||
"errorInvalidAction": "Ungültige Aktion.",
|
||
"errorMedicationNotFound": "Medikament nicht gefunden.",
|
||
"errorMedicationInactive": "Medikament nicht gefunden oder inaktiv.",
|
||
"errorUnknownAction": "Unbekannte Aktion.",
|
||
"snoozeOneHour": "1 Stunde",
|
||
"snoozeThreeHours": "3 Stunden",
|
||
"snoozedFor": "{name} für {duration} zurückgestellt.",
|
||
"skipped": "{name} übersprungen.",
|
||
"alreadyRecorded": "{name} war bereits erfasst.",
|
||
"recordedAsTaken": "{name} als eingenommen erfasst.",
|
||
"confirmed": "{name} bestätigt.",
|
||
"genericConfirmed": "Bestätigt.",
|
||
"cancelled": "Abgebrochen.",
|
||
"noActiveMedications": "Keine aktiven Medikamente gefunden.",
|
||
"whichMedication": "<b>Welches Medikament eingenommen?</b>",
|
||
"cancelButton": "Abbrechen",
|
||
"askMedicationName": "Bitte Medikament angeben, z.B. <b>genommen Ramipril</b>.",
|
||
"medicationNotFoundExact": "Medikament nicht gefunden. Bitte Namen exakt wie in HealthLog senden.",
|
||
"helpHeader": "<b>Verfügbare Befehle:</b>",
|
||
"helpBody": "/help — Diese Hilfe anzeigen\n/add — Einnahme erfassen\n/start — Bot starten\n\n<b>Textbefehle:</b>\ngenommen <Name> — Einnahme bestätigen\n\n<b>Über die Buttons in Erinnerungen:</b>\n• Genommen — Einnahme bestätigen\n• 🕐 1h / 🕐 3h — Erinnerung verschieben\n• ⏭ Überspringen — Einnahme überspringen\n• ✓ Bestätigen — Verpasste Einnahme bestätigen"
|
||
}
|
||
}
|