diff --git a/e2e/timeline.spec.ts b/e2e/timeline.spec.ts index ed0f4e542..0a5280be6 100644 --- a/e2e/timeline.spec.ts +++ b/e2e/timeline.spec.ts @@ -173,22 +173,21 @@ test("the timeline hands the selected day to the day view through ?day=", async await page.keyboard.press("Enter"); await expect(page).toHaveURL(new RegExp(`[?&]day=${after}`)); - // "Open " in the selection bar does the same for the selected day. + // An incoming ?day= selects that day; the selection bar has no separate + // "Open " link, a chip opens the day it touches. await page.goto("/timeline?day=2026-01-03"); - const open = page.locator('[data-slot="timeline-open-day"]'); - await expect(open).toHaveAttribute("data-date", "2026-01-03", { - timeout: 20_000, - }); + await expect( + page.locator('[data-slot="timeline-selection"]'), + ).toHaveAttribute("data-date", "2026-01-03", { timeout: 20_000 }); await expect( page.locator('[data-slot="timeline-zoom"] [data-value="quarter"]'), ).toHaveAttribute("aria-checked", "true"); - await expect( - page.locator('[data-slot="timeline-selection-chip"][data-item="ill-5"]'), - ).toBeVisible(); - await page.goto("/timeline"); - await expect(chart).toBeVisible({ timeout: 20_000 }); - await page.locator('[data-slot="timeline-zoom"] [data-value="year"]').click(); - await open.click(); + await expect(page.locator('[data-slot="timeline-open-day"]')).toHaveCount(0); + const chip = page.locator( + '[data-slot="timeline-selection-chip"][data-item="ill-5"]', + ); + await expect(chip).toBeVisible(); + await chip.click(); await expect(page).toHaveURL(/[?&]day=\d{4}-\d{2}-\d{2}/); }); @@ -546,3 +545,233 @@ test("on a phone the chronicle replaces the chart and opens a day per row", asyn .click(); await expect(page).toHaveURL(/[?&]day=2026-01-03/); }); + +/** A calendar date `days` before today, in the account's zone. */ +function daysAgo(days: number): string { + const at = new Date(`${TODAY}T12:00:00Z`); + at.setUTCDate(at.getUTCDate() - days); + return at.toISOString().slice(0, 10); +} + +test("every medication still taken is drawn, from the account's real record", async ({ + page, +}) => { + await setTimelineModuleOn(page); + // Written through the app's own routes, once: a medication with a start + // date (it opens a course), one without (its first intake is its start). + const list = await page.request.get("/api/medications"); + const held = JSON.stringify(await list.json()); + const create = async (body: Record) => { + const res = await page.request.post("/api/medications", { data: body }); + expect(res.status()).toBeLessThan(300); + return ((await res.json()) as { data: { id: string } }).data.id; + }; + if (!held.includes("E2E Ramipril")) { + await create({ + name: "E2E Ramipril", + dose: "5 mg", + startsOn: daysAgo(40), + schedules: [{ windowStart: "08:00", windowEnd: "09:00" }], + }); + } + if (!held.includes("E2E Vitamin D3")) { + const id = await create({ + name: "E2E Vitamin D3", + dose: "2000 IU", + schedules: [{ windowStart: "08:00", windowEnd: "09:00" }], + }); + const intake = await page.request.post(`/api/medications/${id}/intake`, { + data: { takenAt: new Date(Date.now() - 20 * 86_400_000).toISOString() }, + }); + expect(intake.status()).toBeLessThan(300); + } + + await page.goto("/timeline?zoom=quarter"); + const lane = page.locator('svg [data-lane="medications"]'); + await expect(lane).toHaveCount(1, { timeout: 20_000 }); + // One row each, and every one of them reaches today. + for (const name of ["E2E Ramipril", "E2E Vitamin D3"]) { + const bars = lane.locator("g[data-row]", { + has: page.locator(`title:text-matches("^${name}")`), + }); + await expect(bars.first()).toBeAttached(); + const rows = await bars.evaluateAll((els) => + els.map((el) => el.getAttribute("data-row")), + ); + expect(new Set(rows).size).toBe(1); + } +}); + +test("an open day stays open from the timeline to another page", async ({ + page, +}) => { + await setTimelineModuleOn(page); + await mockTimeline(page, "full", TODAY); + await page.setViewportSize({ width: 1440, height: 900 }); + const day = daysAgo(3); + await page.goto(`/timeline?day=${day}`); + const panel = page.locator('[data-slot="day-panel"]'); + await expect(panel).toBeVisible({ timeout: 20_000 }); + + await page.locator('a[href="/labs"]').first().click(); + await expect(page).toHaveURL(new RegExp(`/labs\\?(.*&)?day=${day}`)); + await expect(panel).toBeVisible(); + await expect(page.locator('[data-slot="day-view"]')).toHaveAttribute( + "data-day", + day, + ); + + // Folded by the person, it stays folded on the next page. + await page.locator('[data-slot="day-close"]').click(); + await expect(panel).toHaveCount(0); + await page.locator('a[href="/timeline"]').first().click(); + await expect(page).toHaveURL(/\/timeline$/); + await expect(page.locator('[data-slot="day-rail"]')).toBeVisible(); + await expect(panel).toHaveCount(0); +}); + +test("a value point reads on its own, by pointer and by keyboard", async ({ + page, +}) => { + await setTimelineModuleOn(page); + await mockTimeline(page, "full", TODAY); + await page.setViewportSize({ width: 1440, height: 900 }); + await page.goto("/timeline"); + const targets = page.locator('[data-slot="timeline-point-target"]'); + await expect(targets.first()).toBeAttached({ timeout: 20_000 }); + + const target = targets.last(); + const series = await target.getAttribute("data-series"); + const t = await target.getAttribute("data-t"); + await target.hover(); + const tip = page.locator('[data-slot="timeline-point-tip"]'); + await expect(tip).toBeVisible(); + await expect(tip).toHaveAttribute("data-series", series!); + await expect(tip).toHaveAttribute("data-t", t!); + // One line only, never the whole bucket. + await expect(tip.locator('[data-slot="rich-chart-tooltip-row"]')).toHaveCount( + 1, + ); + // Inside the chart, and the page does not scroll sideways for it. + const chart = (await page + .locator('[data-slot="timeline-chart"]') + .boundingBox())!; + const box = (await tip.boundingBox())!; + expect(box.x).toBeGreaterThanOrEqual(chart.x - 1); + expect(box.x + box.width).toBeLessThanOrEqual(chart.x + chart.width + 1); + + // The keyboard: focus shows the card, the arrows walk the line. + await page.mouse.move(0, 0); + await target.focus(); + await expect(tip).toHaveAttribute("data-t", t!); + await page.keyboard.press("ArrowLeft"); + await expect(tip).not.toHaveAttribute("data-t", t!); + await expect(tip).toHaveAttribute("data-series", series!); +}); + +test("the timeline page ends where its content does, at every desktop width", async ({ + page, +}) => { + await setTimelineModuleOn(page); + await mockTimeline(page, "full", TODAY); + for (const width of [1280, 1440, 1920]) { + for (const day of [null, daysAgo(3)]) { + await page.setViewportSize({ width, height: 900 }); + await page.goto(day ? `/timeline?day=${day}` : "/timeline"); + await expect( + page.locator('[data-slot="timeline-chart"] > svg'), + ).toBeVisible({ timeout: 20_000 }); + const m = await page.evaluate(() => { + const main = document.getElementById("main-content")!; + const page = document.querySelector('[data-slot="timeline-page"]')!; + const doc = document.scrollingElement!; + return { + mainSw: main.scrollWidth, + mainCw: main.clientWidth, + docSw: doc.scrollWidth, + docCw: doc.clientWidth, + docSh: doc.scrollHeight, + docCh: doc.clientHeight, + mainSh: main.scrollHeight, + contentBottom: + page.getBoundingClientRect().bottom - + main.getBoundingClientRect().top + + main.scrollTop, + }; + }); + const where = `${width}px ${day ? "with" : "without"} the day`; + expect(m.mainSw, where).toBeLessThanOrEqual(m.mainCw + 1); + expect(m.docSw, where).toBeLessThanOrEqual(m.docCw + 1); + expect(m.docSh, where).toBeLessThanOrEqual(m.docCh + 1); + // The shell's own buffer below the last card (pb-20 and the top + // padding), nothing more. + expect(m.mainSh, where).toBeLessThanOrEqual(m.contentBottom + 104 + 2); + } + } +}); + +test("listing all of a day's values scrolls the panel, never the page", async ({ + page, +}) => { + await setTimelineModuleOn(page); + await mockTimeline(page, "full", TODAY); + const day = daysAgo(3); + const types = [ + "WEIGHT", + "BODY_FAT", + "PULSE", + "RESTING_HEART_RATE", + "HEART_RATE_VARIABILITY", + "RESPIRATORY_RATE", + "OXYGEN_SATURATION", + "BODY_TEMPERATURE", + "MUSCLE_MASS", + "BONE_MASS", + "FAT_MASS", + "VISCERAL_FAT", + "BLOOD_GLUCOSE", + "ACTIVITY_STEPS", + ]; + await page.route(`**/api/day/${day}`, (route) => + route.fulfill({ + status: 200, + contentType: "application/json", + body: JSON.stringify({ + data: { + date: day, + tz: "Europe/Berlin", + counts: { values: types.length, entries: 0 }, + running: [], + values: types.map((type, i) => ({ + type, + value: 10 + i, + unit: "u", + at: `${day}T0${i % 10}:00:00.000Z`, + source: "MANUAL", + band: null, + })), + events: [], + notable: [], + scores: [], + sections: {}, + }, + error: null, + }), + }), + ); + await page.setViewportSize({ width: 1440, height: 800 }); + await page.goto(`/timeline?day=${day}`); + const all = page.locator('[data-slot="day-values-all"]'); + await expect(all).toBeVisible({ timeout: 20_000 }); + const heights = () => + page.evaluate(() => ({ + doc: document.scrollingElement!.scrollHeight, + main: document.getElementById("main-content")!.scrollHeight, + })); + const before = await heights(); + await all.click(); + await expect(all).toHaveAttribute("aria-expanded", "true"); + const after = await heights(); + expect(Math.abs(after.doc - before.doc)).toBeLessThanOrEqual(2); + expect(Math.abs(after.main - before.main)).toBeLessThanOrEqual(2); +}); diff --git a/messages/de.json b/messages/de.json index f5084079e..7e8193c6c 100644 --- a/messages/de.json +++ b/messages/de.json @@ -167,7 +167,7 @@ "anamnesisShiftSchedule": "Arbeitszeitmodell", "anamnesisColFact": "Profilangabe", "anamnesisColValue": "Erfasster Wert", - "subtitle": "HealthLog — Persönlicher Gesundheitsbericht", + "subtitle": "HealthLog: Persönlicher Gesundheitsbericht", "patient": "Patient", "dateOfBirth": "Geburtsdatum", "gender": "Geschlecht", @@ -177,18 +177,18 @@ "height": "Körpergröße", "period": "Berichtszeitraum", "createdOn": "Erstellt am", - "vitalsTitle": "Vitalparameter — Übersicht", + "vitalsTitle": "Vitalparameter: Übersicht", "colParameter": "Parameter", "colCurrent": "Aktuell", "colAvgPeriod": "Ø Zeitraum", "colMin": "Min", "colMax": "Max", "colN": "n", - "bpClassificationTitle": "Blutdruck — ESH-Klassifikation (2023)", + "bpClassificationTitle": "Blutdruck: ESH-Klassifikation (2023)", "avgBp": "Durchschnittlicher Blutdruck", "classification": "Klassifikation", "bmiTitle": "Body-Mass-Index (BMI)", - "bmiRow": "BMI: {bmi} kg/m² — Klassifikation: {class} (WHO)", + "bmiRow": "BMI: {bmi} kg/m², Klassifikation: {class} (WHO)", "complianceTitle": "Therapietreue", "glp1Title": "GLP-1-Therapie", "glp1WeightSummary": "Gewicht im Berichtszeitraum: {start} kg → {end} kg ({delta} kg)", @@ -236,8 +236,8 @@ "typeGlucoseRandom": "Glukose (beliebig)", "typeGlucoseBedtime": "Glukose (vor dem Schlafen)", "typeGlucoseUnspecified": "Glukose (ohne Angabe)", - "glucoseClassificationTitle": "Blutzucker — Referenzbereiche (ADA 2024 / DDG)", - "glucoseRow": "{label}: Ø {avg} {unit} (Ziel {rangeMin}–{rangeMax}) — {class}", + "glucoseClassificationTitle": "Blutzucker: Referenzbereiche (ADA 2024 / DDG)", + "glucoseRow": "{label}: Ø {avg} {unit} (Ziel {rangeMin}–{rangeMax}): {class}", "glucoseInTarget": "im Ziel", "glucoseBelowTarget": "unter Ziel", "glucoseAboveTarget": "über Ziel", @@ -289,7 +289,7 @@ "gmi": "Glukose-Management-Indikator (GMI)", "eA1c": "Geschätzter HbA1c", "cv": "Variabilität (VK%)", - "spotCaveat": "Dies sind Schätzwerte aus Einzelmessungen, kein Profil eines kontinuierlichen Messgeräts — als Tendenz und nicht als klinisches Urteil zu lesen." + "spotCaveat": "Dies sind Schätzwerte aus Einzelmessungen, kein Profil eines kontinuierlichen Messgeräts. Sie sind als Tendenz und nicht als klinisches Urteil zu lesen." }, "illnessTitle": "Erkrankungen", "illnessOngoing": "Andauernd", @@ -378,12 +378,12 @@ "backToDashboard": "Zurück zum Dashboard" }, "offlineBanner": { - "message": "Keine Verbindung — Änderungen können erst gespeichert werden, wenn du wieder online bist.", - "saveFailed": "Speichern fehlgeschlagen — du bist offline. Bitte versuche es erneut, sobald du wieder online bist.", + "message": "Keine Verbindung: Änderungen können erst gespeichert werden, wenn du wieder online bist.", + "saveFailed": "Speichern fehlgeschlagen, du bist offline. Bitte versuche es erneut, sobald du wieder online bist.", "showingCached": "Zeigt deine zuletzt synchronisierten Daten." }, "demoBanner": { - "message": "Demo-Modus — Änderungen werden nicht gespeichert." + "message": "Demo-Modus: Änderungen werden nicht gespeichert." }, "nav": { "dashboard": "Dashboard", @@ -458,7 +458,7 @@ "hasAccount": "Bereits ein Konto?", "loginFailed": "Anmeldung fehlgeschlagen", "registerFailed": "Registrierung fehlgeschlagen", - "invitedBanner": "Du wurdest eingeladen — erstelle dein Konto, auch wenn die Registrierung sonst geschlossen ist.", + "invitedBanner": "Du wurdest eingeladen. Erstelle dein Konto, auch wenn die Registrierung sonst geschlossen ist.", "alreadySignedIn": { "title": "Du bist bereits angemeldet", "body": "Du bist als {username} angemeldet. Eine Einladung legt ein neues Konto an. Melde dich ab, um sie anzunehmen.", @@ -646,7 +646,7 @@ "layoutTileColumn": "Kachel", "layoutChartColumn": "Chart", "layoutNativeOnlyTitle": "In der mobilen App sichtbar", - "layoutNativeOnlyHint": "Diese Widgets zeichnet die mobile App, nicht diese Seite. Sie liegen im selben gespeicherten Layout — hier wird ihre Sichtbarkeit gesetzt.", + "layoutNativeOnlyHint": "Diese Widgets zeichnet die mobile App, nicht diese Seite. Sie liegen im selben gespeicherten Layout, hier wird ihre Sichtbarkeit gesetzt.", "dragHandle": "Zum Verschieben ziehen", "dragHandleHint": "Pfeiltasten Hoch/Runter, oder Leertaste plus Pfeiltasten am fokussierten Griff.", "emptyTitle": "Dein Dashboard ist leer", @@ -775,7 +775,7 @@ "formReset": "Formular zurücksetzen", "saveError": "Fehler beim Speichern", "duplicateTimestamp": "Zum gewählten Zeitpunkt existiert bereits ein Messwert dieses Typs.", - "serverOwnedSource": "Werte aus einer verbundenen Quelle lassen sich nicht bearbeiten — Zeitpunkt und Notiz bleiben änderbar.", + "serverOwnedSource": "Werte aus einer verbundenen Quelle lassen sich nicht bearbeiten. Zeitpunkt und Notiz bleiben änderbar.", "deleteError": "Fehler beim Löschen", "deletedToast": "Messwert gelöscht", "restoredToast": "Messwert wiederhergestellt", @@ -875,7 +875,7 @@ }, "metricCatalog": { "title": "Was HealthLog erfassen kann", - "description": "Alle Messwert-Bereiche, die HealthLog unterstützt — auch die, für die noch keine Daten vorliegen — und was sie liefert.", + "description": "Alle Messwert-Bereiche, die HealthLog unterstützt (auch die, für die noch keine Daten vorliegen), und was sie liefert.", "statusPresent": "Erfasst", "statusAbsent": "Noch nicht erfasst", "statusModuleOff": "Aus", @@ -883,11 +883,11 @@ "connectCta": "Quelle verbinden", "viewCta": "Ansehen", "ecg": { - "source": "Einkanal-EKG-Streifen von einer kompatiblen Uhr — aktuell Withings ScanWatch — werden automatisch synchronisiert." + "source": "Einkanal-EKG-Streifen von einer kompatiblen Uhr (aktuell Withings ScanWatch) werden automatisch synchronisiert." }, "watchdog": { "title": "Automatische Überwachung", - "description": "HealthLog beobachtet außerdem still im Hintergrund — Benachrichtigungen zu unregelmäßigem Rhythmus und Atemstörungen von einer verbundenen Uhr, Warnungen bei Abweichungen von deiner Baseline sowie auffällige Veränderungen zwischen deinen letzten beiden Laborwerten — und zeigt eine Karte nur, wenn etwas auffällt. Ist mindestens eine dieser Quellen verbunden, ist keine Karte ein gutes Zeichen, kein fehlendes Feature; ist noch keine verbunden, wird schlicht noch nichts überwacht." + "description": "HealthLog beobachtet außerdem still im Hintergrund: Benachrichtigungen zu unregelmäßigem Rhythmus und Atemstörungen von einer verbundenen Uhr, Warnungen bei Abweichungen von deiner Baseline sowie auffällige Veränderungen zwischen deinen letzten beiden Laborwerten. Eine Karte erscheint nur, wenn etwas auffällt. Ist mindestens eine dieser Quellen verbunden, ist keine Karte ein gutes Zeichen, kein fehlendes Feature; ist noch keine verbunden, wird schlicht noch nichts überwacht." } }, "mood": { @@ -1044,7 +1044,7 @@ "archive": "Archivieren", "restore": "Wiederherstellen", "archivedTitle": "Archivierte Tags", - "archivedDescription": "Archivierte Tags bleiben in deinen bisherigen Einträgen erhalten — sie verschwinden nur aus der Auswahl.", + "archivedDescription": "Archivierte Tags bleiben in deinen bisherigen Einträgen erhalten. Sie verschwinden nur aus der Auswahl.", "archivedEmpty": "Nichts archiviert.", "purgeTitle": "Tag endgültig löschen?", "purgeBody": "Der Tag wird aus {count} bisherigen Einträgen entfernt. Das lässt sich nicht rückgängig machen.", @@ -1069,7 +1069,7 @@ }, "sectionMoreTags": "Weitere Tags", "sectionNoteDetails": "Notiz & Details", - "quickTagsHelp": "Häufig genutzte Tags — ein Tipp genügt", + "quickTagsHelp": "Häufig genutzte Tags: ein Tipp genügt", "quickTagsExpand": "Weitere", "loadError": "Stimmungseinträge konnten nicht geladen werden.", "sectionLevelA": "Gefühlslage", @@ -1247,8 +1247,8 @@ "dialogDescription": "Diese Medikamente sind jetzt fällig. Bestätige, um sie alle als genommen zu erfassen.", "confirm": "Alle einnehmen ({count})", "successToast": "{count} Einnahmen erfasst", - "partialToast": "{taken} erfasst, {failed} fehlgeschlagen — bitte erneut versuchen", - "failedToast": "Keine Einnahme erfasst — bitte erneut versuchen" + "partialToast": "{taken} erfasst, {failed} fehlgeschlagen. Bitte erneut versuchen", + "failedToast": "Keine Einnahme erfasst. Bitte erneut versuchen" }, "logIntake": { "dialogTitle": "Einnahme erfassen", @@ -1346,10 +1346,10 @@ "skipped": "Übersprungen", "intakeToastTaken": "{name} als genommen erfasst", "intakeToastSkipped": "{name} übersprungen", - "intakeToastFailed": "{name} konnte nicht erfasst werden — bitte erneut versuchen", + "intakeToastFailed": "{name} konnte nicht erfasst werden. Bitte erneut versuchen", "intakeUndo": "Rückgängig", "intakeUndone": "Eintrag zurückgenommen", - "intakeUndoFailed": "Rückgängig fehlgeschlagen — im Verlauf korrigieren", + "intakeUndoFailed": "Rückgängig fehlgeschlagen. Im Verlauf korrigieren", "glp1LastInjection": "{label}", "glp1NextInjectionDays": "{label} (in {days} Tagen)", "glp1NextInjectionToday": "heute", @@ -1417,7 +1417,7 @@ "scheduling": { "naturalLanguage": { "title": "Medikament beschreiben", - "description": "Beschreibe das Medikament in eigenen Worten — das Formular wird automatisch vorausgefüllt.", + "description": "Beschreibe das Medikament in eigenen Worten, das Formular wird automatisch vorausgefüllt.", "placeholder": "z. B. Mounjaro 5 mg wöchentlich am Mittwochmorgen ab nächstem Montag", "submit": "Extrahieren", "submitBusy": "Wird verarbeitet…", @@ -1431,10 +1431,10 @@ "error": { "empty": "Gib zuerst eine Beschreibung ein.", "tooLong": "Beschreibung muss unter 2000 Zeichen bleiben.", - "rateLimit": "Zu viele Anfragen — bitte kurz warten und erneut versuchen.", - "noProvider": "Kein KI-Anbieter konfiguriert — bitte in den Einstellungen einrichten.", - "budget": "Tägliches KI-Budget erreicht — bitte morgen erneut versuchen.", - "network": "KI-Anbieter nicht erreichbar — bitte erneut versuchen.", + "rateLimit": "Zu viele Anfragen. Bitte kurz warten und erneut versuchen.", + "noProvider": "Kein KI-Anbieter konfiguriert. Bitte in den Einstellungen einrichten.", + "budget": "Tägliches KI-Budget erreicht. Bitte morgen erneut versuchen.", + "network": "KI-Anbieter nicht erreichbar. Bitte erneut versuchen.", "consent": "Für das Lesen deiner Beschreibung mit KI brauchst du zuerst deine Einwilligung.", "unavailable": "Das Lesen von Beschreibungen mit KI ist hier gerade nicht verfügbar." } @@ -1450,7 +1450,7 @@ "everyNMonths": "Alle N Monate an einem bestimmten Tag", "yearly": "Einmal im Jahr", "rolling": "Alle N Tage seit der letzten Einnahme (flexibel)", - "rollingExplainer": "Zählt ab der letzten erfassten Einnahme — pausiert, wenn du eine Dosis auslässt.", + "rollingExplainer": "Zählt ab der letzten erfassten Einnahme und pausiert, wenn du eine Dosis auslässt.", "oneShot": "Einmaldosis" }, "weekdays": { @@ -1508,7 +1508,7 @@ "night": "Nachts" }, "max": { - "reached": "Maximum erreicht — bitte zuerst eine Uhrzeit entfernen." + "reached": "Maximum erreicht. Bitte zuerst eine Uhrzeit entfernen." } }, "courseWindow": { @@ -1558,7 +1558,7 @@ }, "step3": { "title": "Wie hoch ist die Dosis?", - "subline": "Eine Tablette, ein Hub, ein Tropfen — je nach Form.", + "subline": "Eine Tablette, ein Hub, ein Tropfen, je nach Form.", "amountLabel": "Menge", "amountPlaceholder": "z. B. 5", "unitLabel": "Einheit", @@ -1584,10 +1584,10 @@ }, "dosesPerUnitLabel": "Dosen pro Einheit", "dosesPerUnitPlaceholder": "z. B. 4", - "dosesPerUnitHint": "Dosen pro Pen / Ampulle — leer lassen, wenn kein Bestand getrackt wird.", + "dosesPerUnitHint": "Dosen pro Pen / Ampulle. Leer lassen, wenn kein Bestand getrackt wird.", "short": "Dosis", "unitsPerDoseLabel": "Einheiten pro Dosis", - "unitsPerDoseHint": "z. B. 2 Tabletten à 2 mg für eine 4-mg-Dosis — oder ½ Tablette bei geteilter Dosis" + "unitsPerDoseHint": "z. B. 2 Tabletten à 2 mg für eine 4-mg-Dosis oder ½ Tablette bei geteilter Dosis" }, "step4": { "title": "Über welchen Zeitraum nimmst du es?", @@ -1596,7 +1596,7 @@ }, "step5": { "title": "Wie oft nimmst du es?", - "subline": "Wähle die Regelmäßigkeit — die Details kommen im nächsten Schritt.", + "subline": "Wähle die Regelmäßigkeit, die Details kommen im nächsten Schritt.", "short": "Takt" }, "step6": { @@ -1618,7 +1618,7 @@ }, "step7": { "title": "Wann nimmst du es?", - "subline": "Eine oder mehrere Uhrzeiten — die Erinnerungen richten sich danach.", + "subline": "Eine oder mehrere Uhrzeiten. Die Erinnerungen richten sich danach.", "presetsLabel": "Tagespresets", "presets": { "morning": "Morgens", @@ -1626,7 +1626,7 @@ "evening": "Abends", "night": "Nachts" }, - "overrideHint": "Optional — für diese Uhrzeit eine abweichende Dosis oder Stückzahl festlegen. Leer lassen, um den Standard des Medikaments zu verwenden.", + "overrideHint": "Optional: für diese Uhrzeit eine abweichende Dosis oder Stückzahl festlegen. Leer lassen, um den Standard des Medikaments zu verwenden.", "doseOverrideLabel": "Dosis für diese Uhrzeit (optional)", "doseOverridePlaceholder": "z. B. eine halbe Tablette", "unitsOverrideLabel": "Verbrauchte Einheiten zu dieser Uhrzeit", @@ -1634,11 +1634,11 @@ "short": "Zeiten" }, "step8": { - "title": "Fertig — soll HealthLog dich erinnern?", + "title": "Fertig! Soll HealthLog dich erinnern?", "subline": "Du kannst alles unten nochmal prüfen, bevor du speicherst.", "remindersLabel": "Erinnerungen aktiv", - "remindersDescription": "Push, Telegram oder ntfy — je nach deinen Einstellungen.", - "noChannelHint": "Erinnerungen brauchen einen Benachrichtigungskanal — aktuell ist keiner aktiv.", + "remindersDescription": "Push, Telegram oder ntfy, je nach deinen Einstellungen.", + "noChannelHint": "Erinnerungen brauchen einen Benachrichtigungskanal, aktuell ist keiner aktiv.", "noChannelHintLink": "Benachrichtigungen einrichten", "short": "Fertig" } @@ -1679,7 +1679,7 @@ }, "rolling": { "label": "Flexibel ab letzter Einnahme", - "description": "Du lässt den nächsten Termin offen, drückst 'genommen' wenn du sie genommen hast — ab dem Zeitpunkt zählt der Counter wieder." + "description": "Du lässt den nächsten Termin offen, drückst 'genommen', wenn du sie genommen hast. Ab dem Zeitpunkt zählt der Counter wieder." }, "oneShot": { "label": "Einmalig", @@ -1687,7 +1687,7 @@ }, "asNeeded": { "label": "Bei Bedarf", - "description": "Kein fester Plan — du erfasst eine Einnahme, wenn du sie brauchst (z. B. Schmerzmittel)." + "description": "Kein fester Plan: Du erfasst eine Einnahme, wenn du sie brauchst (z. B. Schmerzmittel)." } }, "summary": { @@ -1722,7 +1722,7 @@ } }, "errors": { - "submitFailed": "Medikament konnte nicht gespeichert werden — bitte erneut versuchen." + "submitFailed": "Medikament konnte nicht gespeichert werden. Bitte erneut versuchen." } }, "doseStrength": { @@ -1742,7 +1742,7 @@ }, "injectionSiteBodyOutlineAriaLabel": "Körperumriss", "injectionSitePickerAriaLabel": "Injektionsstelle auswählen", - "injectionSiteRecommendedAriaLabel": "{site} — empfohlene nächste Stelle", + "injectionSiteRecommendedAriaLabel": "{site}: empfohlene nächste Stelle", "injectionSiteLegendAriaLabel": "Legende der Markierungen", "injectionSiteLegendRecommended": "Empfohlene nächste Stelle", "injectionSiteLegendLastUsed": "Zuletzt verwendete Stelle", @@ -1830,7 +1830,7 @@ "cadence": { "oneShotOn": "Einmalige Dosis am {date}.", "oneShotPending": "Einmalige Dosis ausstehend.", - "asNeeded": "Bei Bedarf — kein fester Plan." + "asNeeded": "Bei Bedarf, kein fester Plan." }, "intake": { "title": "Einnahmeverlauf", @@ -1857,7 +1857,7 @@ "dialogTitle": "Einnahme bearbeiten", "takenAtLabel": "Eingenommen um", "scheduledForHint": "Geplant: {dateTime}", - "farFromScheduledWarning": "Liegt weit vom geplanten Zeitpunkt entfernt — Datum prüfen.", + "farFromScheduledWarning": "Liegt weit vom geplanten Zeitpunkt entfernt. Datum prüfen.", "skippedLabel": "Übersprungen", "save": "Speichern", "cancel": "Abbrechen", @@ -1901,10 +1901,10 @@ }, "addDialog": { "title": "Einnahme hinzufügen", - "description": "Dosis nachtragen — auch rückwirkend oder außerplanmäßig.", + "description": "Dosis nachtragen, auch rückwirkend oder außerplanmäßig.", "takenAtLabel": "Genommen um", "skippedLabel": "Übersprungen", - "nudgeHint": "Liegt nah am Slot {slot} — beim Speichern fragen wir, ob zugeordnet werden soll.", + "nudgeHint": "Liegt nah am Slot {slot}. Beim Speichern fragen wir, ob zugeordnet werden soll.", "cancel": "Abbrechen", "submit": "Speichern" }, @@ -1953,7 +1953,7 @@ }, "codes": { "label": "Klinische Codes (ATC / RxNorm)", - "note": "Optional. Werden beim FHIR-Export der Gesundheitsakte verwendet. Codes werden genau wie eingegeben übernommen — nie geraten.", + "note": "Optional. Werden beim FHIR-Export der Gesundheitsakte verwendet. Codes werden genau wie eingegeben übernommen, nie geraten.", "atcLabel": "ATC", "rxNormLabel": "RxNorm", "saved": "Klinische Codes gespeichert", @@ -1973,7 +1973,7 @@ "title": "Medikament beenden", "helper": "Erinnerungen stoppen und das Medikament als beendet markieren. Verlauf bleibt sichtbar.", "button": "Beenden", - "dialogTitle": "{name} beenden — Erinnerungen stoppen, Verlauf bleibt sichtbar", + "dialogTitle": "{name} beenden: Erinnerungen stoppen, Verlauf bleibt sichtbar", "dialogBody": "Keine weiteren Erinnerungen. Alte Einträge bleiben in der Übersicht.", "toast": "Medikament beendet", "failed": "Medikament konnte nicht beendet werden." @@ -2011,7 +2011,7 @@ "copyFailed": "Kopieren fehlgeschlagen.", "tokenCopied": "Token kopiert", "copyToken": "Token kopieren", - "mintedHint": "Token jetzt kopieren — es wird nur einmal angezeigt." + "mintedHint": "Token jetzt kopieren, es wird nur einmal angezeigt." }, "advanced": { "dataPortability": { @@ -2051,9 +2051,9 @@ "statusTitle": "Status", "nextDoseLabel": "Nächste Dosis", "nextDoseNone": "Keine anstehende Dosis.", - "nextDoseAsNeeded": "Bei Bedarf — keine geplante Dosis.", + "nextDoseAsNeeded": "Bei Bedarf, keine geplante Dosis.", "nextDoseNotTracked": "Nicht erfasst, nur dokumentiert.", - "pausedHint": "Pausiert — keine Erinnerungen.", + "pausedHint": "Pausiert, keine Erinnerungen.", "reminderLabel": "Erinnerung", "reminderOn": "Aktiv", "reminderOff": "Aus", @@ -2124,7 +2124,7 @@ "packagingDefaultPack": "Standard-Packungsgröße: {units} Einheiten", "packagingNoDefaultPack": "Keine Standard-Packungsgröße hinterlegt", "packagingEdit": "Bearbeiten", - "packagingDescription": "Lege fest, wie viele Einheiten eine Dosis verbraucht und wie groß eine neue Packung üblicherweise ist — z. B. nach einem Herstellerwechsel mit anderer Blistergröße.", + "packagingDescription": "Lege fest, wie viele Einheiten eine Dosis verbraucht und wie groß eine neue Packung üblicherweise ist, z. B. nach einem Herstellerwechsel mit anderer Blistergröße.", "packagingUnitsPerDoseLabel": "Einheiten pro Dosis", "packagingUnitsPerDoseHelper": "Z. B. 2 Tabletten à 2 mg für eine 4-mg-Dosis oder 1,5 für anderthalb (über 0, bis 100). Bereits erfasste Einnahmen bleiben unverändert.", "packagingDefaultPackLabel": "Standard-Packungsgröße (Einheiten)", @@ -2175,11 +2175,11 @@ "hideEras": "Frühere Ären ausblenden", "addEra": "Frühere Ära ergänzen", "addEraTitle": "Frühere Ära ergänzen", - "addEraDescription": "Halte fest, zu welchen Uhrzeiten dieses Medikament früher eingenommen wurde — etwa bevor du es hier angepasst hast.", + "addEraDescription": "Halte fest, zu welchen Uhrzeiten dieses Medikament früher eingenommen wurde, etwa bevor du es hier angepasst hast.", "editAria": "Ära bearbeiten", "editEraTitle": "Ära bearbeiten", "editEraDescription": "Passe die Einnahmezeiten und den Zeitraum dieser Ära an.", - "archivedEditHint": "Diese Ära wurde automatisch aufgezeichnet — deine Änderung korrigiert die aufgezeichnete Historie; das Original bleibt intern als Beleg erhalten.", + "archivedEditHint": "Diese Ära wurde automatisch aufgezeichnet. Deine Änderung korrigiert die aufgezeichnete Historie; das Original bleibt intern als Beleg erhalten.", "updatedToast": "Ära aktualisiert", "updateError": "Die Ära konnte nicht aktualisiert werden. Sie darf sich nicht mit anderen Ären überschneiden und muss vor dem aktuellen Plan enden.", "timesLabel": "Einnahmezeiten", @@ -2205,7 +2205,7 @@ "saved": "Zeitplan gespeichert", "failed": "Zeitplan konnte nicht gespeichert werden", "window": { - "intro": "Lege je Dosis fest, wann eine Einnahme als pünktlich gilt — ein genauer Zeitpunkt (±1 Std.) oder ein eigenes Fenster wie 07:00–09:00.", + "intro": "Lege je Dosis fest, wann eine Einnahme als pünktlich gilt: ein genauer Zeitpunkt (±1 Std.) oder ein eigenes Fenster wie 07:00–09:00.", "explicitToggle": "Eigenes Fenster", "startLabel": "Fensterbeginn", "endLabel": "Fensterende", @@ -2218,10 +2218,10 @@ } }, "logInjectionSiteTitle": "Injektionsstelle erfassen", - "logInjectionSiteDescription": "Wo hast du {name} gespritzt? Optional — du kannst dies überspringen.", + "logInjectionSiteDescription": "Wo hast du {name} gespritzt? Optional, du kannst dies überspringen.", "logInjectionSiteSkip": "Überspringen", "logInjectionSiteConfirm": "Stelle speichern", - "logInjectionSiteNoneAvailable": "Keine Injektionsstelle verfügbar — alle Stellen sind in deinen Einstellungen ausgeschlossen.", + "logInjectionSiteNoneAvailable": "Keine Injektionsstelle verfügbar. Alle Stellen sind in deinen Einstellungen ausgeschlossen.", "logInjectionSiteSaveFailed": "Injektionsstelle konnte nicht gespeichert werden. Bitte versuche es erneut.", "perSlotUnits": "{units} pro Dosis", "trackInjectionSitesToggle": "Injektionsstellen erfassen", @@ -2246,15 +2246,15 @@ "tableStockDoses": "{count} Dosen", "tableStockRunway": "≈ {days} Tage übrig", "cardLowStockRunway": "Vorrat: ≈ {days} Tage", - "takeActionFor": "Einnehmen — {name}", - "skipActionFor": "Überspringen — {name}", - "reorderDescription": "Bestimme die Reihenfolge deiner Medikamente — sie gilt für die Karten- und die Tabellenansicht.", + "takeActionFor": "Einnehmen: {name}", + "skipActionFor": "Überspringen: {name}", + "reorderDescription": "Bestimme die Reihenfolge deiner Medikamente für die Karten- und die Tabellenansicht.", "reorderSaved": "Reihenfolge gespeichert", "reorderSaveFailed": "Reihenfolge konnte nicht gespeichert werden", "customize": "Medikamente anpassen", "efficacy": { "title": "Wirkung", - "intro": "Wie sich die Messwerte, die dieses Medikament beeinflussen soll, rund um den Beginn der Einnahme entwickelt haben. Es zeigt den zeitlichen Zusammenhang — eine Assoziation, keine Ursache — und keine Empfehlung zu Behandlung oder Dosis.", + "intro": "Wie sich die Messwerte, die dieses Medikament beeinflussen soll, rund um den Beginn der Einnahme entwickelt haben. Es zeigt den zeitlichen Zusammenhang (eine Assoziation, keine Ursache) und keine Empfehlung zu Behandlung oder Dosis.", "notEligible": "Für dieses Medikament gibt es keinen zugehörigen Messwert.", "startFallback": "Es ist kein Startdatum hinterlegt, daher dient der erste erfasste Wert als Bezugspunkt.", "noStart": "Hinterlege ein Startdatum, um die Werte vor und nach Beginn zu vergleichen.", @@ -2267,7 +2267,7 @@ "levelShift": "Um {date} wurde eine Verschiebung des Niveaus erkannt.", "plateau": { "title": "Gewichts-Plateau auf aktueller Dosis", - "evidence": "Gewichtsveränderung von {delta} {unit} in den letzten {window} Tagen ({readings} Messungen) — seit {days} Tagen auf {dose}." + "evidence": "Gewichtsveränderung von {delta} {unit} in den letzten {window} Tagen ({readings} Messungen), seit {days} Tagen auf {dose}." }, "retarget": { "label": "Nicht der richtige Messwert?", @@ -2277,16 +2277,16 @@ "error": "Diese Änderung konnte nicht gespeichert werden. Bitte erneut versuchen." }, "beforeAfter": { - "summary": "Ø {before} davor → Ø {after} seitdem — eine Veränderung von {delta}.", + "summary": "Ø {before} davor → Ø {after} seitdem, eine Veränderung von {delta}.", "counts": "Basierend auf {beforeCount} Werten davor und {afterCount} seitdem.", - "needBefore": "Noch zu wenige Werte vor dem Beginn — für einen Vergleich werden etwa {weeks} Wochen davor und danach benötigt.", - "needAfter": "Noch zu wenige Werte seit dem Beginn — für einen Vergleich werden etwa {weeks} Wochen davor und danach benötigt.", + "needBefore": "Noch zu wenige Werte vor dem Beginn. Für einen Vergleich werden etwa {weeks} Wochen davor und danach benötigt.", + "needAfter": "Noch zu wenige Werte seit dem Beginn. Für einen Vergleich werden etwa {weeks} Wochen davor und danach benötigt.", "needStart": "Hinterlege ein Startdatum, um die Werte vor und nach Beginn zu vergleichen.", - "needData": "Noch zu wenige Werte — für einen Vergleich werden etwa {weeks} Wochen vor und nach dem Beginn benötigt." + "needData": "Noch zu wenige Werte. Für einen Vergleich werden etwa {weeks} Wochen vor und nach dem Beginn benötigt." }, "insights": { "title": "Medikamenten-Wirkung", - "subtitle": "Was mit den Zielwerten deiner Medikamente zeitlich zusammenfällt — nur ein Zusammenhang, kein Urteil.", + "subtitle": "Was mit den Zielwerten deiner Medikamente zeitlich zusammenfällt: nur ein Zusammenhang, kein Urteil.", "link": "Wirkung öffnen", "empty": "Noch nicht genug Daten, um deine Medikamente mit ihren Zielwerten in Beziehung zu setzen." }, @@ -2320,9 +2320,9 @@ "reasonMissingMedication": "die Zeile nennt kein Medikament", "reasonUnreadableDosage": "die Dosis ist keine Zahl", "reasonUnreadableRow": "die Zeile hat weniger Spalten als die Kopfzeile", - "reasonStatusNoDoseInformation": "die Datei hält zu dieser Dosis nichts fest — niemand hat reagiert und nichts wurde eingetragen", + "reasonStatusNoDoseInformation": "die Datei hält zu dieser Dosis nichts fest; niemand hat reagiert und nichts wurde eingetragen", "reasonStatusReminderEvent": "die Zeile betrifft eine verschobene Erinnerung und sagt nichts über die Dosis", - "reasonStatusNotificationNotSent": "die Zeile hält fest, dass keine Benachrichtigung gesendet wurde — das betrifft die App, nicht die Dosis" + "reasonStatusNotificationNotSent": "die Zeile hält fest, dass keine Benachrichtigung gesendet wurde; das betrifft die App, nicht die Dosis" }, "unitsPerDoseField": { "other": "Andere…", @@ -2392,7 +2392,7 @@ }, "charts": { "loadingLabel": "Diagramm wird geladen…", - "loadingSlowHint": "Auswertungen werden berechnet — das kann einen Moment dauern.", + "loadingSlowHint": "Auswertungen werden berechnet. Das kann einen Moment dauern.", "weight": "Gewicht", "bloodPressure": "Blutdruck", "pulse": "Puls", @@ -2479,9 +2479,9 @@ "toggle": "Datenpunkte ({count})", "columnDate": "Datum", "noValue": "Kein Wert", - "captionDay": "Eine Zeile pro Tag für {metric} — genau die Punkte, die das Diagramm zeichnet.", - "captionWeek": "Eine Zeile pro Woche für {metric}, der Mittelwert der Tage dieser Woche — genau die Punkte, die das Diagramm zeichnet.", - "captionMonth": "Eine Zeile pro Monat für {metric}, der Mittelwert der Tage dieses Monats — genau die Punkte, die das Diagramm zeichnet.", + "captionDay": "Eine Zeile pro Tag für {metric}, genau die Punkte, die das Diagramm zeichnet.", + "captionWeek": "Eine Zeile pro Woche für {metric}, der Mittelwert der Tage dieser Woche, genau die Punkte, die das Diagramm zeichnet.", + "captionMonth": "Eine Zeile pro Monat für {metric}, der Mittelwert der Tage dieses Monats, genau die Punkte, die das Diagramm zeichnet.", "hourlyMeanNote": "{metric} ist der Tagesdurchschnitt, bei dem jede Stunde einmal zählt, damit ein Training nicht den Rest des Tages überwiegt." }, "personalBaseline": "Dein Mittel", @@ -2542,8 +2542,8 @@ }, "tooltipPrior": "Vorperiode", "unavailable": { - "lastMonth": "Vergleich nicht verfügbar — noch keine Daten aus dem Vormonat", - "lastYear": "Vergleich nicht verfügbar — noch keine Daten aus dem Vorjahr" + "lastMonth": "Vergleich nicht verfügbar: noch keine Daten aus dem Vormonat", + "lastYear": "Vergleich nicht verfügbar: noch keine Daten aus dem Vorjahr" }, "notAvailableForCompliance": "Vergleich für Therapietreue nicht verfügbar" }, @@ -2666,7 +2666,7 @@ "narrativeWeek": "Diese Woche", "narrativeMonth": "Dieser Monat", "narrativeUpdating": "Wird aktualisiert…", - "heroFallbackSubtitle": "Täglicher Blick auf deine Trends — direkt aus den Zahlen, die du protokollierst.", + "heroFallbackSubtitle": "Täglicher Blick auf deine Trends, direkt aus den Zahlen, die du protokollierst.", "heroGreetingMorning": "Guten Morgen", "heroGreetingAfternoon": "Guten Tag", "heroGreetingEvening": "Guten Abend", @@ -2777,7 +2777,7 @@ "emptyDescription": "Erstelle das heutige Briefing, um eine Zusammenfassung deiner Trends zu bekommen.", "emptyAction": "Briefing erstellen", "loadingLabel": "Briefing wird zusammengestellt", - "refreshFailedHint": "Briefing konnte nicht aktualisiert werden — es wird das letzte angezeigt.", + "refreshFailedHint": "Briefing konnte nicht aktualisiert werden. Es wird das letzte angezeigt.", "retryAction": "Erneut versuchen", "failedTitle": "Briefing konnte nicht erstellt werden", "failedDescription": "Der KI-Anbieter hat das Zeitlimit überschritten oder einen Fehler zurückgegeben. Versuche es erneut oder erhöhe in den KI-Einstellungen das Antwort-Zeitlimit für ein langsames lokales Modell.", @@ -2841,14 +2841,14 @@ } }, "coach": { - "refusalOutOfScope": "Ich kann nur bei den Gesundheitsdaten in deinem Log helfen — Messwerte, Medikamente, Stimmung, Trends. Fragen außerhalb dieses Themas beantworte ich nicht.", - "refusalInjection": "In deiner Nachricht stehen Anweisungen, die meine Vorgaben überschreiben sollen. Ich bin der HealthLog-Coach und fasse ausschließlich deine eigenen Gesundheitsdaten zusammen — formuliere deine Frage bitte in diesem Rahmen neu.", + "refusalOutOfScope": "Ich kann nur bei den Gesundheitsdaten in deinem Log helfen: Messwerte, Medikamente, Stimmung, Trends. Fragen außerhalb dieses Themas beantworte ich nicht.", + "refusalInjection": "In deiner Nachricht stehen Anweisungen, die meine Vorgaben überschreiben sollen. Ich bin der HealthLog-Coach und fasse ausschließlich deine eigenen Gesundheitsdaten zusammen. Formuliere deine Frage bitte in diesem Rahmen neu.", "errorBudget": "Du hast das heutige Coach-Limit erreicht. Das Budget setzt sich um Mitternacht (UTC) zurück.", "errorProvider": "Der Coach konnte gerade keinen Auswertungs-Anbieter erreichen. Bitte versuche es in einem Moment erneut.", "errorDemo": "In der Demo antwortet der Coach nicht.", - "errorNoProvider": "Der Coach liest deine erfassten Gesundheitsdaten und beantwortet Fragen dazu (keine medizinische Beratung). Dafür braucht HealthLog einen KI-Anbieter — verbinde deinen eigenen Schlüssel oder ein lokales Modell.", + "errorNoProvider": "Der Coach liest deine erfassten Gesundheitsdaten und beantwortet Fragen dazu (keine medizinische Beratung). Dafür braucht HealthLog einen KI-Anbieter. Verbinde deinen eigenen Schlüssel oder ein lokales Modell.", "errorNoProviderAction": "KI-Anbieter verbinden", - "errorNetwork": "Keine Internetverbindung — versuche es erneut, sobald du online bist.", + "errorNetwork": "Keine Internetverbindung. Versuche es erneut, sobald du online bist.", "prefsSaveError": "Coach-Einstellungen konnten nicht gespeichert werden. Bitte versuche es erneut.", "errorCredentialExpired": "Deine Verbindung zum KI-Anbieter ist abgelaufen. Stelle sie in den Einstellungen wieder her, damit der Coach weiterläuft.", "tagline": "Persönlicher Gesundheitscoach, auf deine Daten gestützt.", @@ -2867,7 +2867,7 @@ "thinking": "Denke nach…", "unverifiedFiguresNotice": "Einige Zahlen ließen sich nicht mit deinen Daten abgleichen und wurden weggelassen.", "composerPlaceholder": "Frag mich etwas…", - "nudgeBubbleLabel": "Neue Nachricht vom Coach — Chat öffnen", + "nudgeBubbleLabel": "Neue Nachricht vom Coach: Chat öffnen", "fabLabel": "Coach öffnen", "readAloud": "Vorlesen", "readAloudStop": "Vorlesen beenden", @@ -2891,7 +2891,7 @@ "guided": { "offerTitle": "Der Coach hat {count} Rückfragen an dich", "offerTitleOne": "Der Coach hat eine Rückfrage an dich", - "offerBody": "Kurze Antworten schärfen deine Selbstauskunft — eine Frage nach der anderen, direkt hier im Chat.", + "offerBody": "Kurze Antworten schärfen deine Selbstauskunft: eine Frage nach der anderen, direkt hier im Chat.", "offerStart": "Jetzt beantworten", "offerLater": "Später", "offerDismiss": "Nicht mehr fragen", @@ -2901,7 +2901,7 @@ "later": "Später", "dismissRemaining": "Nicht mehr fragen", "answerPlaceholder": "Deine Antwort…", - "summaryTitle": "Geschafft — danke für deine Antworten!", + "summaryTitle": "Geschafft, danke für deine Antworten!", "summaryAnswered": "{answered} von {total} beantwortet", "summaryAdopted": "{adopted} in die Selbstauskunft übernommen", "summaryAdoptedNone": "nichts Neues in die Selbstauskunft übernommen", @@ -2983,7 +2983,7 @@ "settingsVerbosityBrief": "Kurz", "settingsVerbosityDefault": "Standard", "settingsVerbosityDetailed": "Ausführlich", - "settingsVerbosityConciseHint": "Der knappe Tonfall hält Antworten ohnehin kurz — die Ausführlichkeit ist dabei fest auf „Kurz“ gesetzt.", + "settingsVerbosityConciseHint": "Der knappe Tonfall hält Antworten ohnehin kurz, die Ausführlichkeit ist dabei fest auf „Kurz“ gesetzt.", "settingsSourcesSummary": "Der Coach sieht {count} von {total} Datenbereichen und blickt {window} zurück.", "settingsSourcesSummaryAll": "Der Coach sieht {count} von {total} Datenbereichen und deinen ganzen Verlauf.", "settingsSourcesPointerLink": "Coach-Einstellungen öffnen", @@ -3090,7 +3090,7 @@ "steadyLatestWithin": "Deine Werte liegen meist bei {low} {unit}; dein letzter Wert vom {date} lag mit {value} genau dort.", "steadyLatestAbove": "Deine Werte liegen meist bei {low} {unit}; dein letzter Wert vom {date} lag mit {value} darüber.", "steadyLatestBelow": "Deine Werte liegen meist bei {low} {unit}; dein letzter Wert vom {date} lag mit {value} darunter.", - "insufficient": "Lerne noch deinen üblichen Bereich — protokolliere noch ein paar Tage weiter.", + "insufficient": "Lerne noch deinen üblichen Bereich. Protokolliere noch ein paar Tage weiter.", "driver": "{note}" }, "scope": { @@ -3104,39 +3104,39 @@ "groupEarlier": "Früher" }, "seed": { - "bloodPressure": "Geh mit mir meinen Blutdruckverlauf der letzten 30 Tage durch — gibt es etwas, das ich im Auge behalten sollte?", + "bloodPressure": "Geh mit mir meinen Blutdruckverlauf der letzten 30 Tage durch. Gibt es etwas, das ich im Auge behalten sollte?", "weight": "Wie hat sich mein Gewicht zuletzt entwickelt, und ist die Richtung etwas, worauf ich reagieren sollte?", "bmi": "Was sagt mir mein BMI-Verlauf, und wie sollte ich ihn lesen?", - "pulse": "Geh mit mir meine Pulswerte durch — ist irgendetwas ungewöhnlich?", + "pulse": "Geh mit mir meine Pulswerte durch. Ist irgendetwas ungewöhnlich?", "restingHr": "Wie hat sich mein Ruhepuls entwickelt, und was sagt er über meine Fitness?", "hrv": "Was sagt mir meine Herzfrequenzvariabilität zuletzt über Erholung und Stress?", - "sleep": "Geh mit mir meinen letzten Schlaf durch — Dauer, Regelmäßigkeit und was sich zu ändern lohnt.", + "sleep": "Geh mit mir meinen letzten Schlaf durch: Dauer, Regelmäßigkeit und was sich zu ändern lohnt.", "mood": "Welche Muster siehst du in meiner Stimmung über die letzten Wochen?", "medications": "Wie sieht meine Therapietreue aus, und passt sie dazu, wie ich mich gefühlt habe?", "steps": "Wie aktiv war ich zuletzt gemessen an meinen Schritten, und wie ist das im Vergleich zu einem gesunden Richtwert?", "activeEnergy": "Was sagt mein Aktivenergie-Verlauf über mein Aktivitätsniveau zuletzt?", "cardioFitness": "Was bedeutet mein Cardio-Fitness-Verlauf (VO₂max), und wie bewege ich ihn in die richtige Richtung?", - "bloodGlucose": "Geh mit mir meine letzten Glukosewerte durch — liegen sie in einem gesunden Bereich?", + "bloodGlucose": "Geh mit mir meine letzten Glukosewerte durch. Liegen sie in einem gesunden Bereich?", "oxygenSaturation": "Was sagt mir mein Sauerstoffsättigungs-Verlauf (SpO₂)?", "respiratoryRate": "Was sagt mein Atemfrequenz-Verlauf über meine Gesundheit?", - "workouts": "Geh mit mir meine letzten Workouts durch — Belastung, Häufigkeit und wie ich mich dazwischen erhole.", + "workouts": "Geh mit mir meine letzten Workouts durch: Belastung, Häufigkeit und wie ich mich dazwischen erhole.", "recoveryPage": "Warum steht meine Erholung gerade dort, wo sie steht, und was treibt das?", - "briefing": "Geh mit mir das heutige Briefing durch — worauf sollte ich mich konzentrieren, und gibt es etwas, das einen Schritt wert ist?", + "briefing": "Geh mit mir das heutige Briefing durch. Worauf sollte ich mich konzentrieren, und gibt es etwas, das einen Schritt wert ist?", "healthScore": "Warum liegt mein Gesundheits-Score bei {score} von 100, und was würde ihn am stärksten bewegen?", - "periodWeek": "Geh mit mir durch, wie meine letzte Woche über meine Gesundheitswerte hinweg lief — was sticht heraus?", - "periodMonth": "Geh mit mir durch, wie mein letzter Monat über meine Gesundheitswerte hinweg lief — was sticht heraus?", + "periodWeek": "Geh mit mir durch, wie meine letzte Woche über meine Gesundheitswerte hinweg lief. Was sticht heraus?", + "periodMonth": "Geh mit mir durch, wie mein letzter Monat über meine Gesundheitswerte hinweg lief. Was sticht heraus?", "correlationBpCompliance": "Wie hängt meine Therapietreue mit meinem Blutdruck zusammen? Geh mit mir durch, was dieser Zusammenhang für mich bedeutet.", "correlationMoodPulse": "Gibt es einen echten Zusammenhang zwischen meiner Stimmung und meinem Puls? Hilf mir, diesen Zusammenhang zu lesen.", "correlationWeightWeekday": "Folgt mein Gewicht einem Wochenmuster? Was sagt mir dieser Wochentags-Zusammenhang?", - "recommendation": "Erzähl mir mehr zu dieser Empfehlung: „{text}“ — warum trifft sie auf mich zu, und was sollte ich tun?" + "recommendation": "Erzähl mir mehr zu dieser Empfehlung: „{text}“ Warum trifft sie auf mich zu, und was sollte ich tun?" }, - "assessmentPrompt": "Erkläre mir meine {metric}-Einschätzung — was bedeutet sie und was sollte ich tun?", + "assessmentPrompt": "Erkläre mir meine {metric}-Einschätzung. Was bedeutet sie und was sollte ich tun?", "attach": { "menuChooseFromDocuments": "Aus Dokumenten wählen", "menuUploadNew": "Neues Dokument hochladen", "trigger": "Dokumente anhängen", "pickerTitle": "Dokumente anhängen", - "pickerDescription": "Der Coach liest nur die angehängten Dokumente — nicht deine Gesundheitsdaten.", + "pickerDescription": "Der Coach liest nur die angehängten Dokumente, nicht deine Gesundheitsdaten.", "pickerSearchPlaceholder": "Dokumente durchsuchen…", "pickerEmpty": "Noch keine Dokumente in deinem Tresor.", "pickerNotIndexed": "Noch nicht indexiert", @@ -3144,13 +3144,13 @@ "pickerConfirm": "Anhängen ({count})", "pillRemove": "{title} entfernen", "indexing": "Wird indexiert…", - "indexingHint": "Ein Dokument wird noch indexiert — du kannst senden, sobald es bereit ist.", - "fencedHint": "Diese Unterhaltung läuft ohne Zugriff auf deine Gesundheitsdaten — der Coach liest nur die angehängten Dokumente.", + "indexingHint": "Ein Dokument wird noch indexiert. Du kannst senden, sobald es bereit ist.", + "fencedHint": "Diese Unterhaltung läuft ohne Zugriff auf deine Gesundheitsdaten. Der Coach liest nur die angehängten Dokumente.", "documentsAttachedOne": "1 Dokument angehängt", "documentsAttachedOther": "{count} Dokumente angehängt", "railBadge": "Dokument-Chat (abgeschottet)", "uploadError": "Upload fehlgeschlagen. Bitte versuche es erneut.", - "notFoundError": "Dieser Dokumentlink ist nicht mehr gültig — es wird ein normaler Chat gestartet." + "notFoundError": "Dieser Dokumentlink ist nicht mehr gültig. Es wird ein normaler Chat gestartet." }, "interrupted": { "note": "Diese Antwort wurde unterbrochen, bevor sie fertig war.", @@ -3321,7 +3321,7 @@ }, "hrv": { "title": "HRV", - "description": "Herzratenvariabilität im Verlauf — dein Erholungssignal des autonomen Nervensystems, nächtlich von Apple Watch und kompatiblen Wearables erfasst.", + "description": "Herzratenvariabilität im Verlauf: dein Erholungssignal des autonomen Nervensystems, nächtlich von Apple Watch und kompatiblen Wearables erfasst.", "chartTitle": "Herzratenvariabilität", "emptyState": { "title": "Noch keine HRV-Werte", @@ -3330,17 +3330,17 @@ }, "restingHr": { "title": "Ruhepuls", - "description": "Die tägliche Grundlinie deines Herzschlags — unterschieden vom Spot-Puls. Apple Health liefert einen Wert pro Tag.", + "description": "Die tägliche Grundlinie deines Herzschlags, unterschieden vom Spot-Puls. Apple Health liefert einen Wert pro Tag.", "chartTitle": "Ruhepuls", "emptyState": { "title": "Noch kein Ruhepuls", "description": "Der Ruhepuls erscheint, sobald die Apple Watch oder ein kompatibles Withings-Gerät einen ruhigen Tag durchgetragen hat." }, - "coachPrefill": "Ich habe noch keinen Ruhepuls erfasst — warum unterscheidet sich der tägliche Ruhewert von einem punktuellen Puls, und wie verbessere ich ihn?" + "coachPrefill": "Ich habe noch keinen Ruhepuls erfasst. Warum unterscheidet sich der tägliche Ruhewert von einem punktuellen Puls, und wie verbessere ich ihn?" }, "oxygenSaturation": { "title": "Sauerstoffsättigung", - "description": "Blutsauerstoff (SpO₂) — klinischer Normalbereich 95–100 %; Zielzonen sind am Chart hinterlegt.", + "description": "Blutsauerstoff (SpO₂), klinischer Normalbereich 95–100 %; Zielzonen sind am Chart hinterlegt.", "chartTitle": "Sauerstoffsättigung", "emptyState": { "title": "Noch keine SpO₂-Werte", @@ -3353,13 +3353,13 @@ "chartTitle": "Körpertemperatur", "emptyState": { "title": "Noch keine Körpertemperatur", - "description": "Erfasse eine Körpertemperatur oder lass dein Wearable einen Wert synchronisieren — der Verlauf erscheint dann hier.", + "description": "Erfasse eine Körpertemperatur oder lass dein Wearable einen Wert synchronisieren. Der Verlauf erscheint dann hier.", "cta": "Körpertemperatur erfassen" } }, "steps": { "title": "Schritte", - "description": "Tägliche Schrittzahl — eine Zeile pro Tag, aus Apple Health oder einem verbundenen Aktivitätsgerät.", + "description": "Tägliche Schrittzahl, eine Zeile pro Tag, aus Apple Health oder einem verbundenen Aktivitätsgerät.", "chartTitle": "Schritte pro Tag", "emptyState": { "title": "Noch keine Schrittdaten", @@ -3368,7 +3368,7 @@ }, "activeEnergy": { "title": "Aktive Energie", - "description": "Tägliche aktive-Energie-Summe in Kilokalorien — eine Zeile pro Tag, aus Apple Health oder Withings-Aktivität.", + "description": "Tägliche aktive-Energie-Summe in Kilokalorien, eine Zeile pro Tag, aus Apple Health oder Withings-Aktivität.", "chartTitle": "Aktive Energie", "emptyState": { "title": "Noch keine Aktive-Energie-Werte", @@ -3388,11 +3388,11 @@ }, "explainer": { "bloodPressureBody": "Der Blutdruck ist die Kraft, die das Blut auf die Gefäßwände ausübt, angegeben als systolisch zu diastolisch (Spitzenwert beim Herzschlag über dem Ruhewert dazwischen). Dauerhaft hohe Werte belasten Herz und Gefäße auf Dauer.", - "pulseBody": "Der Puls gibt an, wie oft das Herz pro Minute schlägt. Eine Einzelmessung spiegelt den Moment wider — in Ruhe liegt er meist bei 60–100 Schlägen pro Minute und steigt natürlicherweise bei Bewegung, Stress oder Koffein.", + "pulseBody": "Der Puls gibt an, wie oft das Herz pro Minute schlägt. Eine Einzelmessung spiegelt den Moment wider. In Ruhe liegt er meist bei 60–100 Schlägen pro Minute und steigt natürlicherweise bei Bewegung, Stress oder Koffein.", "weightBody": "Das Körpergewicht ist eines der einfachsten Signale für die langfristige Energiebilanz und die allgemeine Gesundheit. Der Trend über Wochen zählt weit mehr als ein einzelner Wert, der mit Flüssigkeit, Ernährung und Tageszeit schwankt.", "bmiBody": "Der BMI ist dein Gewicht geteilt durch deine Körpergröße zum Quadrat und ordnet dich einer groben Gewichtskategorie zu. Er ist ein Orientierungswert, keine Diagnose, und unterscheidet nicht zwischen Muskeln und Fett.", "sleepBody": "Die Schlafdauer ist die tatsächlich geschlafene Zeit pro Nacht, aufgeteilt in Leicht-, Tief- und REM-Schlaf. Die meisten Erwachsenen brauchen etwa sieben bis neun Stunden; gleichmäßige Menge und Qualität unterstützen Erholung, Stimmung und Stoffwechsel.", - "moodBody": "Die Stimmungserfassung hält auf einer einfachen Skala fest, wie du dich fühlst. Regelmäßiges Protokollieren zeigt Muster — wie Schlaf, Aktivität oder Medikamente mit dem Befinden zusammenhängen –, die ein einzelner Tag nie offenbart.", + "moodBody": "Die Stimmungserfassung hält auf einer einfachen Skala fest, wie du dich fühlst. Regelmäßiges Protokollieren zeigt Muster (wie Schlaf, Aktivität oder Medikamente mit dem Befinden zusammenhängen), die ein einzelner Tag nie offenbart.", "medicationsBody": "Die Therapietreue zeigt, wie zuverlässig du deine Medikamente wie verordnet einnimmst, hier als Anteil der erwarteten Dosen, die du erfasst hast. Eine gleichmäßige Einnahme entscheidet oft darüber, ob eine Therapie wie beabsichtigt wirkt.", "restingHrBody": "Der Ruhepuls ist die Herzfrequenz in völliger Ruhe, meist über Nacht gemessen. Ein niedriger Ruhepuls deutet in der Regel auf eine bessere Herz-Kreislauf-Fitness hin, ein steigender Trend kann ein frühes Zeichen für Stress oder Krankheit sein.", "hrvBody": "Die HRV ist die kleine Schwankung der Zeit zwischen aufeinanderfolgenden Herzschlägen. Eine höhere Variabilität spiegelt meist ein gut erholtes, anpassungsfähiges Nervensystem wider, ein anhaltender Rückgang kann auf Erschöpfung, Stress oder mangelnde Erholung hinweisen.", @@ -3403,12 +3403,12 @@ "respiratoryRateBody": "Die Atemfrequenz ist die Anzahl der Atemzüge pro Minute. In Ruhe atmen die meisten Erwachsenen etwa zwölf- bis zwanzigmal pro Minute; ein anhaltender Anstieg kann mit Krankheit, Anstrengung oder Stress einhergehen.", "bodyWaterBody": "Das Gesamtkörperwasser ist der Anteil deines Körpergewichts, der aus Flüssigkeit in und um die Zellen besteht. Es schwankt mit Flüssigkeitshaushalt, Ernährung und Aktivität, daher sagt der Trend über Wochen mehr aus als ein einzelner Wert.", "boneMassBody": "Die Knochenmasse ist das geschätzte Gewicht der Mineralien in deinem Skelett. Waagengestützte Schätzungen sind ungefähr, doch ein gleichbleibender oder steigender Trend unterstützt die langfristige Knochenstärke.", - "fatFreeMassBody": "Die fettfreie Masse ist alles in deinem Körper, das kein Fett ist — Muskeln, Knochen, Organe und Wasser. Sie zu halten oder aufzubauen, während das Gewicht sinkt, deutet meist auf eine gesündere Körperzusammensetzung hin.", - "fatMassBody": "Die Fettmasse ist das Gesamtgewicht des Körperfetts. Etwas Fett ist für Hormone und Energiespeicher unverzichtbar, doch zu viel — besonders am Bauch — erhöht das langfristige Gesundheitsrisiko (WHO 2024).", + "fatFreeMassBody": "Die fettfreie Masse ist alles in deinem Körper, das kein Fett ist: Muskeln, Knochen, Organe und Wasser. Sie zu halten oder aufzubauen, während das Gewicht sinkt, deutet meist auf eine gesündere Körperzusammensetzung hin.", + "fatMassBody": "Die Fettmasse ist das Gesamtgewicht des Körperfetts. Etwas Fett ist für Hormone und Energiespeicher unverzichtbar, doch zu viel (besonders am Bauch) erhöht das langfristige Gesundheitsrisiko (WHO 2024).", "bodyFatBody": "Der Körperfettanteil ist der Teil deines Gewichts, der aus Fett besteht. Gesunde Bereiche hängen von Geschlecht und Alter ab, und Waagen schätzen den Wert per Bioimpedanz, deshalb sagt der Verlauf über mehrere Wochen mehr als eine einzelne Messung.", "muscleMassBody": "Die Muskelmasse ist das geschätzte Gewicht der Muskeln in deinem Körper. Mehr Muskeln unterstützen Kraft, Stoffwechsel und Beweglichkeit und müssen mit zunehmendem Alter aktiv erhalten werden.", "visceralFatBody": "Viszeralfett ist das Fett, das tief im Bauchraum um die Organe gespeichert wird. Anders als das Unterhautfett ist ein hoher Wert eng mit Herzkrankheiten und Typ-2-Diabetes verbunden, daher ist niedriger meist besser.", - "leanBodyMassBody": "Die Magermasse ist dein Gesamtgewicht abzüglich des Körperfetts — Muskeln, Knochen, Organe und Wasser zusammen. Sie neben dem Gewicht zu verfolgen zeigt, ob Veränderungen aus Muskeln oder aus Fett stammen.", + "leanBodyMassBody": "Die Magermasse ist dein Gesamtgewicht abzüglich des Körperfetts, also Muskeln, Knochen, Organe und Wasser zusammen. Sie neben dem Gewicht zu verfolgen zeigt, ob Veränderungen aus Muskeln oder aus Fett stammen.", "flightsClimbedBody": "Die gestiegenen Etagen zählen die Stockwerke, die du täglich nach oben gehst, wobei eine Etage etwa drei Metern Höhe entspricht. Es ist ein einfacher Marker für Alltagsaktivität und Beinarbeit.", "walkingDistanceBody": "Die Geh- und Laufstrecke ist die Strecke, die du täglich zu Fuß zurücklegst. Sie ergänzt die Schrittzahl, indem sie zeigt, wie weit du dich bewegt hast, nicht nur wie oft du getreten bist.", "walkingSteadinessBody": "Die Gehstabilität schätzt, wie stabil und ausgewogen dein Gangbild ist, eingeteilt von OK bis niedrig. Ein niedriger Wert deutet auf ein höheres Sturzrisiko hin und sollte ärztlich besprochen werden.", @@ -3425,28 +3425,28 @@ "daylightBody": "Die Zeit im Tageslicht ist, wie lange du dich täglich im Freien im Licht aufhältst. Regelmäßiges Tageslicht unterstützt einen gesunden Schlaf-Wach-Rhythmus und die Stimmung (CDC 2024), und Zeit im Freien ist mit der Augengesundheit verbunden.", "bloodGlucoseBody": "Der Blutzucker ist die Zuckermenge in deinem Blut, die wichtigste Energiequelle des Körpers. Er steigt nach dem Essen und pendelt sich zwischen den Mahlzeiten ein; dauerhaft hohe Werte können auf Diabetes oder Prädiabetes hinweisen.", "skinTemperatureBody": "Die Hauttemperatur ist hier die kleine nächtliche Abweichung deiner Handgelenkstemperatur von deinem eigenen Ausgangswert, keine absolute Fiebermessung. Veränderungen können Schlaf, Umgebung, Krankheit oder Zyklusphase widerspiegeln.", - "cardioFitnessBody": "VO₂max gibt an, wie viel Sauerstoff dein Körper bei maximaler Anstrengung verwerten kann — der beste Laborindex der Ausdauerfitness, den Wearables indirekt schätzen. Ein höherer oder steigender Trend ist ein starkes Zeichen für eine gute Herz-Kreislauf-Gesundheit.", - "cardioRecoveryBody": "Der Erholungspuls gibt an, um wie viele Schläge pro Minute dein Puls in der ersten Minute nach dem Ende einer anstrengenden Belastung fällt. Ein größerer Abfall bedeutet, dass sich dein Herz schneller beruhigt — ein Zeichen guter Fitness.", + "cardioFitnessBody": "VO₂max gibt an, wie viel Sauerstoff dein Körper bei maximaler Anstrengung verwerten kann. Es ist der beste Laborindex der Ausdauerfitness, den Wearables indirekt schätzen. Ein höherer oder steigender Trend ist ein starkes Zeichen für eine gute Herz-Kreislauf-Gesundheit.", + "cardioRecoveryBody": "Der Erholungspuls gibt an, um wie viele Schläge pro Minute dein Puls in der ersten Minute nach dem Ende einer anstrengenden Belastung fällt. Ein größerer Abfall bedeutet, dass sich dein Herz schneller beruhigt, ein Zeichen guter Fitness.", "wristTemperatureBody": "Die Handgelenktemperatur wird im Schlaf gemessen und als Abweichung von deinem persönlichen Ausgangswert angegeben, nicht als absoluter Wert. Ein gleichmäßiger Wert ist normal, ein anhaltender Anstieg kann auf Krankheit, intensives Training oder eine Zyklusveränderung hindeuten.", - "fallsBody": "Hier werden die von deinem Wearable erkannten schweren Stürze gezählt. Null ist das Ziel; eine steigende Zahl ist ein Hinweis auf ein erhöhtes Sturzrisiko, das du — besonders im höheren Alter — mit einer Ärztin oder einem Arzt besprechen solltest (CDC STEADI 2024).", - "sixMinuteWalkBody": "Dies ist eine Schätzung, wie weit du in sechs Minuten gehen könntest — ein etablierter klinischer Test für Mobilität und kardiopulmonale Ausdauer. Der Wearable-Wert ist ein Näherungswert, nicht der überwachte klinische Test; aussagekräftig ist der gleichbleibende oder steigende Trend.", - "stairAscentSpeedBody": "Dies gibt an, wie schnell du eine Treppe hinaufgehst. Es ist ein empfindlicher Marker für Beinkraft und Mobilität — ein gleichbleibendes oder steigendes Tempo ist gut, ein sinkendes solltest du im Blick behalten.", - "stairDescentSpeedBody": "Dies gibt an, wie schnell du eine Treppe hinabgehst. Zusammen mit dem Steig-Tempo zeigt es Beinkontrolle und Gleichgewicht — ein gleichmäßiges Tempo ist gut, ein sinkendes solltest du im Blick behalten.", - "breathingDisturbancesBody": "Ein Wearable kann schätzen, wie oft deine Atmung im Schlaf unterbrochen war. Ein niedriger Index ist besser; ein als erhöht eingestufter Wert — vor allem über viele Nächte — sollte mit einer Ärztin oder einem Arzt besprochen werden. Es ist ein Screening-Näherungswert, keine Schlafapnoe-Diagnose.", - "stepsBody": "Die Schrittzahl ist die Gesamtzahl der Schritte, die du täglich gehst — das einfachste Maß für Alltagsbewegung. Eine stetige Gewohnheit zählt mehr als ein einzelner großer Tag, und das runde Ziel von 10.000 Schritten ist ein Werbeslogan, keine Forschung.", - "readinessBody": "Die Bereitschaft ist ein einzelner Tageswert dafür, wie bereit dein Körper für den Tag ist — er verbindet Ruhepuls, Herzfrequenzvariabilität und Schlaf. Es ist ein Geräte-Näherungswert an deinem eigenen Ausgangswert, keine klinische Messung: ein höherer Wert heißt erholt, ein niedrigerer ist ein sanfter Hinweis, einen Gang zurückzuschalten.", - "sleepScoreBody": "Dein Schlafscore fasst eine ganze Nacht in einer Zahl zusammen — aus Dauer, Effizienz, Regelmäßigkeit und der Verteilung von Leicht-, Tief- und REM-Schlaf. Achte eher auf das Muster über Wochen als auf einen perfekten Wert in einer einzelnen Nacht.", - "recoveryBody": "Die Erholung zeigt, wie gut sich dein Körper regeneriert hat — gestützt auf nächtliche Signale wie Herzfrequenzvariabilität und Ruhepuls. Es ist ein geräteabgeleiteter Näherungswert an deinem eigenen Ausgangswert, keine klinische Messung, und zwischen Geräten nicht vergleichbar. Ein hoher Wert ist grünes Licht, mehr zu geben; ein niedrigerer deutet an, dass dein System noch aufbaut.", - "strainBody": "Die Belastung erfasst, wie viel kardiovaskuläre und körperliche Last du deinem Körper zugemutet hast — von Workouts bis zu einem aktiven Tag auf den Beinen. Es ist ein geräteabgeleiteter Index, gemessen an deinem eigenen üblichen Aufwand, keine klinische Messung, und der Kennwert ist zwischen Geräten nicht vergleichbar.", - "stressBody": "Stress ist hier eine Geräte-Heuristik aus Mustern der Herzfrequenzvariabilität — keine Cortisol-Messung und nicht, wie du dich bewusst fühlst, und auch kein klinischer Stress-Score. Lies ihn an deinem eigenen Ausgangswert; zwischen Geräten ist er nicht vergleichbar. Ein niedrigerer Wert deutet auf einen ruhigen, gut regulierten Zustand hin; ein höherer ist eine Einladung, Erholung einzuplanen.", - "recoveryPageBody": "Die Erholung fasst die nächtlichen Signale deines Wearables zusammen — Recharge, Belastung, Load sowie deine Herzfrequenz- und Energiewerte des Tages — und zeigt, wie gut sich dein Körper erholt hat. Achte eher auf das Muster über mehrere Tage als auf einen einzelnen Wert; ein schwächerer Wert ist eine Einladung, kürzerzutreten, kein Alarm.", + "fallsBody": "Hier werden die von deinem Wearable erkannten schweren Stürze gezählt. Null ist das Ziel; eine steigende Zahl ist ein Hinweis auf ein erhöhtes Sturzrisiko, das du (besonders im höheren Alter) mit einer Ärztin oder einem Arzt besprechen solltest (CDC STEADI 2024).", + "sixMinuteWalkBody": "Dies ist eine Schätzung, wie weit du in sechs Minuten gehen könntest, ein etablierter klinischer Test für Mobilität und kardiopulmonale Ausdauer. Der Wearable-Wert ist ein Näherungswert, nicht der überwachte klinische Test; aussagekräftig ist der gleichbleibende oder steigende Trend.", + "stairAscentSpeedBody": "Dies gibt an, wie schnell du eine Treppe hinaufgehst. Es ist ein empfindlicher Marker für Beinkraft und Mobilität. Ein gleichbleibendes oder steigendes Tempo ist gut, ein sinkendes solltest du im Blick behalten.", + "stairDescentSpeedBody": "Dies gibt an, wie schnell du eine Treppe hinabgehst. Zusammen mit dem Steig-Tempo zeigt es Beinkontrolle und Gleichgewicht. Ein gleichmäßiges Tempo ist gut, ein sinkendes solltest du im Blick behalten.", + "breathingDisturbancesBody": "Ein Wearable kann schätzen, wie oft deine Atmung im Schlaf unterbrochen war. Ein niedriger Index ist besser; ein als erhöht eingestufter Wert (vor allem über viele Nächte) sollte mit einer Ärztin oder einem Arzt besprochen werden. Es ist ein Screening-Näherungswert, keine Schlafapnoe-Diagnose.", + "stepsBody": "Die Schrittzahl ist die Gesamtzahl der Schritte, die du täglich gehst, das einfachste Maß für Alltagsbewegung. Eine stetige Gewohnheit zählt mehr als ein einzelner großer Tag, und das runde Ziel von 10.000 Schritten ist ein Werbeslogan, keine Forschung.", + "readinessBody": "Die Bereitschaft ist ein einzelner Tageswert dafür, wie bereit dein Körper für den Tag ist. Er verbindet Ruhepuls, Herzfrequenzvariabilität und Schlaf. Es ist ein Geräte-Näherungswert an deinem eigenen Ausgangswert, keine klinische Messung: ein höherer Wert heißt erholt, ein niedrigerer ist ein sanfter Hinweis, einen Gang zurückzuschalten.", + "sleepScoreBody": "Dein Schlafscore fasst eine ganze Nacht in einer Zahl zusammen, aus Dauer, Effizienz, Regelmäßigkeit und der Verteilung von Leicht-, Tief- und REM-Schlaf. Achte eher auf das Muster über Wochen als auf einen perfekten Wert in einer einzelnen Nacht.", + "recoveryBody": "Die Erholung zeigt, wie gut sich dein Körper regeneriert hat, gestützt auf nächtliche Signale wie Herzfrequenzvariabilität und Ruhepuls. Es ist ein geräteabgeleiteter Näherungswert an deinem eigenen Ausgangswert, keine klinische Messung, und zwischen Geräten nicht vergleichbar. Ein hoher Wert ist grünes Licht, mehr zu geben; ein niedrigerer deutet an, dass dein System noch aufbaut.", + "strainBody": "Die Belastung erfasst, wie viel kardiovaskuläre und körperliche Last du deinem Körper zugemutet hast, von Workouts bis zu einem aktiven Tag auf den Beinen. Es ist ein geräteabgeleiteter Index, gemessen an deinem eigenen üblichen Aufwand, keine klinische Messung, und der Kennwert ist zwischen Geräten nicht vergleichbar.", + "stressBody": "Stress ist hier eine Geräte-Heuristik aus Mustern der Herzfrequenzvariabilität. Sie ist keine Cortisol-Messung und nicht, wie du dich bewusst fühlst, und auch kein klinischer Stress-Score. Lies ihn an deinem eigenen Ausgangswert; zwischen Geräten ist er nicht vergleichbar. Ein niedrigerer Wert deutet auf einen ruhigen, gut regulierten Zustand hin; ein höherer ist eine Einladung, Erholung einzuplanen.", + "recoveryPageBody": "Die Erholung fasst die nächtlichen Signale deines Wearables zusammen (Recharge, Belastung, Load sowie deine Herzfrequenz- und Energiewerte des Tages) und zeigt, wie gut sich dein Körper erholt hat. Achte eher auf das Muster über mehrere Tage als auf einen einzelnen Wert; ein schwächerer Wert ist eine Einladung, kürzerzutreten, kein Alarm.", "pulsePressureBody": "Der Pulsdruck ist die Differenz zwischen deinem systolischen und diastolischen Wert (systolisch minus diastolisch). Als allgemeine Orientierung sind etwa 40 mmHg in Ruhe typisch; eine große Differenz über rund 60 mmHg im mittleren Alter kann auf versteifte Arterien hinweisen, eine kleine Differenz unter etwa 25 mmHg kann mit niedrigem Schlagvolumen einhergehen (StatPearls/NIH 2023). Ein Gesprächsanlass, keine Diagnose.", - "meanArterialPressureBody": "Der mittlere arterielle Druck ist der durchschnittliche Druck, den deine Organe über einen Herzschlag sehen — grob der diastolische Wert plus ein Drittel der Differenz zum systolischen. Als allgemeine Orientierung liegt ein Ruhewert bei etwa 70–100 mmHg (StatPearls/NIH 2023). Die oft genannte Grenze von ~60 mmHg ist ein Konzept der Akutmedizin, kein Alarm für die Selbstmessung.", - "cycleEducationBody": "Dein Zyklus durchläuft vier hormongesteuerte Phasen, und seine Länge und Regelmäßigkeit sind ein gut zugängliches Fenster auf die allgemeine Gesundheit. Als allgemeine Orientierung dauern Zyklen bei Erwachsenen typischerweise 21–35 Tage (klinische Referenzen nennen 24–38), mit einer Blutung von rund fünf Tagen (ACOG 2015). Die Lutealphase ist der stabile Anker, daher schätzt man den Eisprung am besten durch Rückrechnen von der nächsten erwarteten Periode — nie über einen festen „Tag 14“. Ein vorhergesagtes fruchtbares Fenster ist eine Schätzung, die mehrere erfasste Zyklen braucht und ungefähr bleibt, und die Basaltemperatur bestätigt den Eisprung im Nachhinein, statt ihn vorherzusagen. Dies ist keine Verhütungsmethode.", + "meanArterialPressureBody": "Der mittlere arterielle Druck ist der durchschnittliche Druck, den deine Organe über einen Herzschlag sehen, grob der diastolische Wert plus ein Drittel der Differenz zum systolischen. Als allgemeine Orientierung liegt ein Ruhewert bei etwa 70–100 mmHg (StatPearls/NIH 2023). Die oft genannte Grenze von ~60 mmHg ist ein Konzept der Akutmedizin, kein Alarm für die Selbstmessung.", + "cycleEducationBody": "Dein Zyklus durchläuft vier hormongesteuerte Phasen, und seine Länge und Regelmäßigkeit sind ein gut zugängliches Fenster auf die allgemeine Gesundheit. Als allgemeine Orientierung dauern Zyklen bei Erwachsenen typischerweise 21–35 Tage (klinische Referenzen nennen 24–38), mit einer Blutung von rund fünf Tagen (ACOG 2015). Die Lutealphase ist der stabile Anker, daher schätzt man den Eisprung am besten durch Rückrechnen von der nächsten erwarteten Periode, nie über einen festen „Tag 14“. Ein vorhergesagtes fruchtbares Fenster ist eine Schätzung, die mehrere erfasste Zyklen braucht und ungefähr bleibt, und die Basaltemperatur bestätigt den Eisprung im Nachhinein, statt ihn vorherzusagen. Dies ist keine Verhütungsmethode.", "sleepHygieneBody": "Einige evidenzbasierte Gewohnheiten unterstützen den Schlaf: gleichbleibende Zubett- und Aufstehzeiten auch am Wochenende, helles Morgenlicht und gedämpfte Abende, ein kühles, dunkles und ruhiges Zimmer sowie der Verzicht auf Koffein am Nachmittag, späten Alkohol und große späte Mahlzeiten (CDC 2024). Regelmäßigkeit sagt die Gesundheit mindestens so stark voraus wie die Dauer, und die Gesamtschlafzeit eines Wearables ist weit verlässlicher als seine Aufteilung in Tief-, Leicht- und REM-Schlaf." }, "bpDerived": { - "pulsePressure": "Der Pulsdruck (die Differenz zwischen deinen Werten) beträgt etwa {value} mmHg — rund 40 ist in Ruhe typisch.", + "pulsePressure": "Der Pulsdruck (die Differenz zwischen deinen Werten) beträgt etwa {value} mmHg; rund 40 ist in Ruhe typisch.", "meanArterialPressure": "Der mittlere arterielle Druck (der Durchschnitt, den deine Organe sehen) liegt bei etwa {value} mmHg, normalerweise um 70–100.", "caveat": "Diese Werte werden als allgemeine Orientierung aus deiner letzten Messung abgeleitet, nicht als Diagnose." }, @@ -3458,7 +3458,7 @@ "mean": "Mittelwert" }, "showAllValues": "Alle Werte anzeigen", - "valuesPageTitle": "{metric} — alle Werte", + "valuesPageTitle": "{metric}: alle Werte", "valuesPageDescription": "Jeder einzelne Wert hinter dieser Kennzahl. Einträge lassen sich direkt bearbeiten oder entfernen.", "diversity": { "trigger": "Messhinweis", @@ -3480,7 +3480,7 @@ }, "sleep": { "title": "Schlaf", - "description": "Phasen-Aufschlüsselung und nächtliche Dauer — gezogen aus Apple Health.", + "description": "Phasen-Aufschlüsselung und nächtliche Dauer, gezogen aus Apple Health.", "mainSleep": "Hauptschlaf", "totalSleep": "Schlaf gesamt", "compositionTitle": "Phasen-Verteilung", @@ -3498,11 +3498,11 @@ "inBed": "Im Bett", "nap": "Nickerchen", "napCount": "{count} Nickerchen", - "unavailable": "Noch keine Phasen-Daten — Schlafphasen erscheinen hier, sobald eine verbundene Quelle sie liefert." + "unavailable": "Noch keine Phasen-Daten. Schlafphasen erscheinen hier, sobald eine verbundene Quelle sie liefert." }, "empty": { "title": "Noch keine Schlafdaten", - "description": "Verbinde eine Quelle wie Apple Health oder ein Wearable — oder erfasse Schlaf manuell — und diese Ansicht füllt sich automatisch.", + "description": "Verbinde eine Quelle wie Apple Health oder ein Wearable (oder erfasse Schlaf manuell), und diese Ansicht füllt sich automatisch.", "action": "Geräte verwalten" }, "debt": { @@ -3511,21 +3511,21 @@ "caption": "Offene Bilanz der letzten {nights} Nächte", "clearValue": "Ausgeglichen", "clearCaption": "Nichts offen über die letzten {nights} Nächte", - "learning": "Dein Schlaf wird noch erfasst — {counted} Nächte bisher, noch {remaining} für eine verlässliche Bilanz.", + "learning": "Dein Schlaf wird noch erfasst: {counted} Nächte bisher, noch {remaining} für eine verlässliche Bilanz.", "computedInfo": "Das ist HealthLogs eigene Schätzung: eine gleitende Bilanz aus Bedarf minus Schlaf über die letzten Nächte, die Aufholschlaf wieder abbaut. Sie kann vom nativen Schlafdefizit eines Wearables abweichen, das ein eigenes Bedarfsmodell nutzt." }, "average": { "title": "Durchschnitt pro Nacht", "value": "{hours} Std. {minutes} Min.", "caption": "Mittlerer Schlaf über die letzten {nights} Nächte", - "learning": "Dein Schlaf wird noch erfasst — {counted} Nächte bisher, noch {remaining} für einen verlässlichen Durchschnitt." + "learning": "Dein Schlaf wird noch erfasst: {counted} Nächte bisher, noch {remaining} für einen verlässlichen Durchschnitt." }, "chronotype": { "title": "Chronotyp", - "learning": "Dein Rhythmus wird noch erfasst — {counted} von {total} freien Nächten. Ein Chronotyp braucht ein paar weckerfreie Morgen, um aussagekräftig zu sein.", + "learning": "Dein Rhythmus wird noch erfasst: {counted} von {total} freien Nächten. Ein Chronotyp braucht ein paar weckerfreie Morgen, um aussagekräftig zu sein.", "advancedToggle": "Mehr Details", "socialJetlagValue": "{hours} Std. {minutes} Min. sozialer Jetlag", - "socialJetlagCaption": "Der Unterschied zwischen deinem Schlaf an Arbeits- und freien Tagen — wie eine kleine wöchentliche Zeitzonenverschiebung.", + "socialJetlagCaption": "Der Unterschied zwischen deinem Schlaf an Arbeits- und freien Tagen, wie eine kleine wöchentliche Zeitzonenverschiebung.", "msfScValue": "Korrigierte Schlafmitte {clock}", "msfScCaption": "Bereinigt um den Schlaf, den du am Wochenende nachholst (MSFsc).", "dayTypeNote": "Freie Tage werden als Wochenenden angenommen, bis eine Tagestyp-Erfassung ergänzt wird.", @@ -3604,7 +3604,7 @@ "navRecovery": "Erholung", "workouts": { "title": "Workouts", - "description": "Letzte Läufe, Touren, Spaziergänge und Krafteinheiten — quellenübergreifend entdoppelt zwischen Apple Watch und Withings.", + "description": "Letzte Läufe, Touren, Spaziergänge und Krafteinheiten, quellenübergreifend entdoppelt zwischen Apple Watch und Withings.", "emptyState": { "title": "Noch keine Workouts", "description": "Workouts kommen per Apple Health vom iPhone und von Withings. Du kannst eins auch von Hand erfassen." @@ -3732,11 +3732,11 @@ "clinical": { "title": "Glukose-Überblick", "subtitle": "Ein Blick auf deine letzten {days} Tage, aus {count} Messungen.", - "spotCaveat": "Das sind Schätzungen aus einzelnen Stichproben-Messungen, kein Profil eines kontinuierlichen Sensors — lies sie als Richtung, nicht als klinisches Urteil.", + "spotCaveat": "Das sind Schätzungen aus einzelnen Stichproben-Messungen, kein Profil eines kontinuierlichen Sensors. Lies sie als Richtung, nicht als klinisches Urteil.", "labsLink": "Laborergebnisse? HbA1c und Nüchternglukose aus einer Blutabnahme trägst du unter Labor ein.", "learningTitle": "Lerne deine Glukose noch kennen", - "learningBody": "Bisher sind das {count} über {days}. Mit etwas mehr Verlauf wird das Bild klarer — mess weiter oder lass es ein verbundenes Gerät ergänzen.", - "learningBodyEmpty": "Sobald ein paar Messungen vorliegen — von dir erfasst oder von einem Gerät synchronisiert — nehmen Zeit-im-Zielbereich, Durchschnitt und Schwankung hier Gestalt an.", + "learningBody": "Bisher sind das {count} über {days}. Mit etwas mehr Verlauf wird das Bild klarer. Mess weiter oder lass es ein verbundenes Gerät ergänzen.", + "learningBodyEmpty": "Sobald ein paar Messungen vorliegen (von dir erfasst oder von einem Gerät synchronisiert), nehmen Zeit-im-Zielbereich, Durchschnitt und Schwankung hier Gestalt an.", "readingsCount": "{count} Messungen", "readingsCountOne": "1 Messung", "daysCount": "{days} Tage", @@ -3774,7 +3774,7 @@ "intro": "Forschungsnahe Kennzahlen für den genaueren Blick. Jede fasst deine Messungen zu einer risikogewichteten Zahl zusammen.", "jIndex": { "label": "J-Index", - "help": "Ein einzelner Wert aus Durchschnitt und Streuung — niedriger steht für engere Kontrolle." + "help": "Ein einzelner Wert aus Durchschnitt und Streuung; niedriger steht für engere Kontrolle." }, "lbgi": { "label": "Risiko für Tiefwerte (LBGI)", @@ -3891,7 +3891,7 @@ "navSkinTemperature": "Hauttemperatur", "pulseWaveVelocity": { "title": "Pulswellengeschwindigkeit", - "description": "Deine arterielle Pulswellengeschwindigkeit im Zeitverlauf, in m/s — höhere Werte deuten auf steifere Arterien hin.", + "description": "Deine arterielle Pulswellengeschwindigkeit im Zeitverlauf, in m/s. Höhere Werte deuten auf steifere Arterien hin.", "chartTitle": "Pulswellengeschwindigkeit", "emptyState": { "title": "Noch keine Daten", @@ -4084,7 +4084,7 @@ "inTargetCaption": "der letzten Tage im guten Stimmungsbereich", "narrative": { "title": "Das fällt auf", - "weekdayDip": "Deine Stimmung sinkt am stärksten am {weekday} — {delta} unter deinem Wochenschnitt.", + "weekdayDip": "Deine Stimmung sinkt am stärksten am {weekday}, {delta} unter deinem Wochenschnitt.", "weekdayPeak": "{weekday} ist durchgehend dein bester Tag mit einem Schnitt von {value}.", "trendUp": "Deine Stimmung steigt über die letzten {days} Tage (+{delta} gegenüber dem Vorzeitraum).", "trendDown": "Deine Stimmung sinkt über die letzten {days} Tage (-{delta} gegenüber dem Vorzeitraum).", @@ -4093,7 +4093,7 @@ "tagLift": "Tage mit „{tag}“ liegen im Schnitt {delta} über deiner allgemeinen Stimmung.", "tagDrop": "Tage mit „{tag}“ liegen {delta} unter deinem Durchschnitt.", "inTarget": "Du warst an {pct} % der letzten 30 Tage in deinem guten Stimmungsbereich.", - "streak": "Du hast deine Stimmung {days} Tage in Folge erfasst — weiter so.", + "streak": "Du hast deine Stimmung {days} Tage in Folge erfasst. Weiter so.", "timeOfDay": "Am {bucket} fühlst du dich am besten, im Schnitt {value}." }, "timeOfDay": { @@ -4164,7 +4164,7 @@ "title": "Was auffällt", "subheading": "Entdeckte Zusammenhänge", "footer": "Herausgefiltert aus {tested} Tag-zu-Tag-Paaren, die über all deine Werte getestet wurden, nach der Korrektur für Fehlentdeckungen.", - "disclaimer": "Statistisch gefiltert, aber weiterhin beobachtend — ein Muster, das einen Blick wert ist, keine Ursache.", + "disclaimer": "Statistisch gefiltert, aber weiterhin beobachtend: ein Muster, das einen Blick wert ist, keine Ursache.", "moodUp": "Höheres {factor} geht in deinen Daten tendenziell mit besserer Stimmung am Folgetag einher.", "moodDown": "Höheres {factor} geht in deinen Daten tendenziell mit schlechterer Stimmung am Folgetag einher.", "outcomeUp": "Bessere Stimmung geht in deinen Daten tendenziell mit höherem {factor} am Folgetag einher.", @@ -4203,8 +4203,8 @@ "deviationAbove": "Deine eigene Einschätzung liegt {amount} Punkte über diesem Bereich.", "deviationBelow": "Deine eigene Einschätzung liegt {amount} Punkte unter diesem Bereich.", "weightedTitle": "Was an diesem Tag am stärksten gewichtet wurde", - "weightedUp": "{label} — zählte in Richtung eines höheren erwarteten Werts", - "weightedDown": "{label} — zählte in Richtung eines niedrigeren erwarteten Werts", + "weightedUp": "{label}: zählte in Richtung eines höheren erwarteten Werts", + "weightedDown": "{label}: zählte in Richtung eines niedrigeren erwarteten Werts", "caveat": "Das ist ein Vergleich mit deinen eigenen bisherigen Tagen, keine Aussage darüber, wie ein Tag zustande gekommen ist.", "learning": "Lernphase: {entries} von {threshold} Tagen erfasst. Ein Vergleich erscheint, sobald genug davon zusammengekommen sind.", "noPattern": "In den bisher erfassten {entries} Tagen ist noch nichts gleichmäßig genug, um einen Tag damit zu vergleichen. Wenn du auch den Kontext eines Tages festhältst, wird mehr davon vergleichbar.", @@ -4221,7 +4221,7 @@ }, "scoreRing": { "aria": "Wert {score} von 100, {band}", - "ariaProvisional": "Wert noch nicht verfügbar — zu wenig Daten", + "ariaProvisional": "Wert noch nicht verfügbar, zu wenig Daten", "provisionalCaption": "Noch zu wenig Daten", "band": { "green": "gut", @@ -4245,7 +4245,7 @@ "loadingLabel": "Vitalwerte werden geladen", "loadError": "Deine Vitalwerte konnten gerade nicht geladen werden.", "infoLabel": "Wie wird das berechnet?", - "building": "Typischer Bereich entsteht — {count} von {target} Tagen", + "building": "Typischer Bereich entsteht: {count} von {target} Tagen", "typicalRange": "Typisch für dich: {low}–{high}", "fitnessYounger": "Ausdauer wie ~{years} J. jünger", "fitnessOlder": "Ausdauer ~{years} J. über deinem Alter", @@ -4297,7 +4297,7 @@ "READINESS": { "title": "Bereitschaft", "description": "Ein täglicher Wohlbefindens-Indikator daraus, wie deine Werte zu deiner eigenen Baseline stehen.", - "method": "Eine 0–100-Mischung aus Ruhepuls-Abweichung, HRV-(SDNN-)Abweichung, Schlaf, Atemfrequenz-Stabilität und Stimmungsstabilität — jeweils gegen deine persönliche Baseline gemessen. Gewichte werden über die von deinen Daten gestützten Komponenten neu verteilt. Ein Wohlbefindens-Indikator, kein Erholungs- oder klinischer Score.", + "method": "Eine 0–100-Mischung aus Ruhepuls-Abweichung, HRV-(SDNN-)Abweichung, Schlaf, Atemfrequenz-Stabilität und Stimmungsstabilität, jeweils gegen deine persönliche Baseline gemessen. Gewichte werden über die von deinen Daten gestützten Komponenten neu verteilt. Ein Wohlbefindens-Indikator, kein Erholungs- oder klinischer Score.", "component": { "rhr": "Ruhepuls", "hrv": "HRV (SDNN)", @@ -4307,28 +4307,28 @@ } }, "VITALS_BASELINE": { - "method": "Dein persönlicher Normalbereich ist der Median deiner Tageswerte über den Zeitraum, ± eine robuste Streuung (skalierte mittlere absolute Abweichung). Er folgt DEINEN Werten, keiner Bevölkerungsnorm — ein Wert im Band ist also typisch für dich." + "method": "Dein persönlicher Normalbereich ist der Median deiner Tageswerte über den Zeitraum, ± eine robuste Streuung (skalierte mittlere absolute Abweichung). Er folgt DEINEN Werten, keiner Bevölkerungsnorm. Ein Wert im Band ist also typisch für dich." }, "HRV_BALANCE": { "method": "Dein jüngster HRV-(SDNN-)Durchschnitt im Vergleich zu deiner eigenen gleitenden Baseline (Median ± robuste Streuung). Ausgeglichen heißt: er liegt in deinem persönlichen Bereich; das Band stammt aus deinen Daten, nie aus einem Bevölkerungswert." }, "BMI": { - "method": "Gewicht ÷ Größe², eingeordnet nach den WHO-Kategorien für Erwachsene (Untergewicht / Normal / Übergewicht / Adipositas). Nur ein Screening-Verhältnis — es unterscheidet nicht Muskel von Fett." + "method": "Gewicht ÷ Größe², eingeordnet nach den WHO-Kategorien für Erwachsene (Untergewicht / Normal / Übergewicht / Adipositas). Nur ein Screening-Verhältnis, es unterscheidet nicht Muskel von Fett." }, "FITNESS_AGE": { - "method": "Dein VO₂max im Vergleich zu alters- und geschlechtsbezogenen Perzentilen der kardiorespiratorischen Fitness, als Fitnessalter-Differenz. Das VO₂max ist die Schätzung deines Geräts — hier nie neu berechnet." + "method": "Dein VO₂max im Vergleich zu alters- und geschlechtsbezogenen Perzentilen der kardiorespiratorischen Fitness, als Fitnessalter-Differenz. Das VO₂max ist die Schätzung deines Geräts, hier nie neu berechnet." }, "VASCULAR_AGE_DELTA": { "method": "Die Gefäßalter- bzw. Pulswellengeschwindigkeits-Schätzung deines Geräts im Vergleich zu deinem chronologischen Alter, als Differenz in Jahren. Die Schätzung stammt vom Gerät; HealthLog ordnet sie nur ein.", - "caveat": "Die eigene Schätzung deines Geräts, nur eingeordnet — beschreibend, keine klinische Gefäßbewertung.", + "caveat": "Die eigene Schätzung deines Geräts, nur eingeordnet: beschreibend, keine klinische Gefäßbewertung.", "description": "Wie die Gefäßalter-Schätzung deines Geräts zu deinem chronologischen Alter steht." }, "COINCIDENT_DEVIATION": { "method": "Ein Hinweis, wenn zwei oder mehr deiner Vitalwerte am selben Tag außerhalb ihres persönlichen Normalbereichs liegen. Jedes Band ist der robuste Median ± k·MAD deiner eigenen Verlaufsdaten und passt sich an dich an, nicht an einen Bevölkerungswert.", - "caveat": "Ein Hinweis aus deinen eigenen Baselines — beschreibend, keine Diagnose und kein klinischer Alarm." + "caveat": "Ein Hinweis aus deinen eigenen Baselines: beschreibend, keine Diagnose und kein klinischer Alarm." }, "RECOVERY_SCORE": { - "method": "Ein nächtlicher 0–100-Erholungs-Proxy aus HRV, Ruhepuls und Schlaf gegenüber deiner Baseline. Höher heißt besser erholt. Einmal pro Nacht berechnet und hier nur ausgelesen — nie spontan neu berechnet.", + "method": "Ein nächtlicher 0–100-Erholungs-Proxy aus HRV, Ruhepuls und Schlaf gegenüber deiner Baseline. Höher heißt besser erholt. Einmal pro Nacht berechnet und hier nur ausgelesen, nie spontan neu berechnet.", "description": "Ein nächtlicher Erholungs-Proxy aus HRV, Ruhepuls und Schlaf." }, "STRESS_SCORE": { @@ -4337,35 +4337,35 @@ }, "STRAIN_SCORE": { "method": "Ein nächtlicher 0–100-Belastungs-Proxy aus deiner herzfrequenzgewichteten Aktivitätslast (ein TRIMP-ähnliches Trainingsimpuls-Modell). Höher heißt ein anstrengenderer Tag.", - "anchorPersonal": "An deine eigene jüngste Trainingstagslast angelehnt — bewertet relativ zu deiner typischen Anstrengung, sodass ein für dich wirklich harter Tag hoch ausfällt.", + "anchorPersonal": "An deine eigene jüngste Trainingstagslast angelehnt und bewertet relativ zu deiner typischen Anstrengung, sodass ein für dich wirklich harter Tag hoch ausfällt.", "anchorPopulation": "Gegen einen allgemeinen Referenzwert bewertet, während du noch Trainingsverlauf aufbaust; sobald genug vorhanden ist, wechselt die Bewertung auf deine eigene typische Anstrengung.", "description": "Ein nächtlicher Aktivitätslast-Proxy aus deiner herzfrequenzgewichteten Anstrengung, relativ zu deiner typischen Anstrengung.", "deviceCaption": "Tagesbelastung deines Geräts: {value} von {max}", "deviceSource": "Bis HealthLog nachts einen eigenen Wert berechnet hat, zeigt die Karte die Tagesbelastung deines Geräts, umgerechnet auf 0–100." }, "WRIST_TEMPERATURE_BASELINE": { - "method": "Deine typische nächtliche Handgelenkstemperatur ist der Median deiner nächtlichen Messwerte im Zeitraum, ± einer robusten Streuung (skalierte mittlere absolute Abweichung). Sie folgt DEINEN Werten — letzte Nacht wird als Abweichung von deiner eigenen Baseline gezeigt, nicht von einer Bevölkerungsnorm.", - "caveat": "Nur ein persönliches Abweichungsband — beschreibend, kein Anzeichen für Krankheit, Fieber oder Zyklusphase. Du interpretierst es selbst." + "method": "Deine typische nächtliche Handgelenkstemperatur ist der Median deiner nächtlichen Messwerte im Zeitraum, ± einer robusten Streuung (skalierte mittlere absolute Abweichung). Sie folgt DEINEN Werten: Letzte Nacht wird als Abweichung von deiner eigenen Baseline gezeigt, nicht von einer Bevölkerungsnorm.", + "caveat": "Nur ein persönliches Abweichungsband: beschreibend, kein Anzeichen für Krankheit, Fieber oder Zyklusphase. Du interpretierst es selbst." }, "STAIR_ASCENT_SPEED_BASELINE": { - "method": "Dein typisches Treppensteig-Tempo ist der Median deiner Tageswerte im Zeitraum, ± einer robusten Streuung (skalierte mittlere absolute Abweichung). Das Band wird aus deinen Daten gebildet — es gibt keinen Bevölkerungs-Grenzwert für Treppentempo, da es von Treppengeometrie und Beinlänge abhängt.", - "caveat": "Ein persönliches Mobilitäts-Trendband — beschreibend, keine Gebrechlichkeits- oder Sturzrisiko-Bewertung." + "method": "Dein typisches Treppensteig-Tempo ist der Median deiner Tageswerte im Zeitraum, ± einer robusten Streuung (skalierte mittlere absolute Abweichung). Das Band wird aus deinen Daten gebildet. Es gibt keinen Bevölkerungs-Grenzwert für Treppentempo, da es von Treppengeometrie und Beinlänge abhängt.", + "caveat": "Ein persönliches Mobilitäts-Trendband: beschreibend, keine Gebrechlichkeits- oder Sturzrisiko-Bewertung." }, "STAIR_DESCENT_SPEED_BASELINE": { - "method": "Dein typisches Treppen-Abstiegstempo ist der Median deiner Tageswerte im Zeitraum, ± einer robusten Streuung (skalierte mittlere absolute Abweichung). Das Band wird aus deinen Daten gebildet — es gibt keinen Bevölkerungs-Grenzwert für Treppentempo, da es von Treppengeometrie und Beinlänge abhängt.", - "caveat": "Ein persönliches Mobilitäts-Trendband — beschreibend, keine Gebrechlichkeits- oder Sturzrisiko-Bewertung." + "method": "Dein typisches Treppen-Abstiegstempo ist der Median deiner Tageswerte im Zeitraum, ± einer robusten Streuung (skalierte mittlere absolute Abweichung). Das Band wird aus deinen Daten gebildet. Es gibt keinen Bevölkerungs-Grenzwert für Treppentempo, da es von Treppengeometrie und Beinlänge abhängt.", + "caveat": "Ein persönliches Mobilitäts-Trendband: beschreibend, keine Gebrechlichkeits- oder Sturzrisiko-Bewertung." }, "SIX_MINUTE_WALK_BAND": { - "method": "Die von deinem Gerät GESCHÄTZTE 6-Minuten-Gehstrecke, eingeordnet gegen die Referenz von Enright & Sherrill für Alter, Größe, Gewicht und Geschlecht, als Prozent des Vorhersagewerts. Die Strecke ist die Schätzung des Geräts — hier nie neu berechnet. Ohne Alter, Größe, Gewicht und Geschlecht wird der Prozentwert ausgeblendet und nur Strecke und Trend gezeigt.", - "caveat": "Eine gegen eine veröffentlichte Referenz neu eingeordnete Schätzung — ein Hinweis zur funktionellen Kapazität, kein klinischer 6-Minuten-Gehtest und keine Diagnose. Die Referenz wurde für Alter 40–80 erstellt; außerhalb dieses Bereichs ist der Vorhersagewert eine Extrapolation." + "method": "Die von deinem Gerät GESCHÄTZTE 6-Minuten-Gehstrecke, eingeordnet gegen die Referenz von Enright & Sherrill für Alter, Größe, Gewicht und Geschlecht, als Prozent des Vorhersagewerts. Die Strecke ist die Schätzung des Geräts, hier nie neu berechnet. Ohne Alter, Größe, Gewicht und Geschlecht wird der Prozentwert ausgeblendet und nur Strecke und Trend gezeigt.", + "caveat": "Eine gegen eine veröffentlichte Referenz neu eingeordnete Schätzung: ein Hinweis zur funktionellen Kapazität, kein klinischer 6-Minuten-Gehtest und keine Diagnose. Die Referenz wurde für Alter 40–80 erstellt; außerhalb dieses Bereichs ist der Vorhersagewert eine Extrapolation." }, "TRAJECTORY": { - "method": "Eine Ausgleichsgerade (kleinste Quadrate), an deine jüngsten Tageswerte angepasst und über einen kurzen Zeitraum fortgeschrieben — mit dem klassischen Vorhersageintervall, das umso breiter wird, je weiter es reicht. Wird nur berechnet, wenn der jüngste Trend deutlich genug und deine Datenreihe lang und aktuell genug ist; sonst wird keine Linie gezeichnet.", - "caveat": "Eine Fortschreibung deines eigenen jüngsten Trends — keine Vorhersage, kein Ziel und keine klinische Prognose. Sie gilt nur, solange das jüngste Muster anhält; das schattierte Band zeigt, wie schnell diese Sicherheit nachlässt." + "method": "Eine Ausgleichsgerade (kleinste Quadrate), an deine jüngsten Tageswerte angepasst und über einen kurzen Zeitraum fortgeschrieben, mit dem klassischen Vorhersageintervall, das umso breiter wird, je weiter es reicht. Wird nur berechnet, wenn der jüngste Trend deutlich genug und deine Datenreihe lang und aktuell genug ist; sonst wird keine Linie gezeichnet.", + "caveat": "Eine Fortschreibung deines eigenen jüngsten Trends, keine Vorhersage, kein Ziel und keine klinische Prognose. Sie gilt nur, solange das jüngste Muster anhält; das schattierte Band zeigt, wie schnell diese Sicherheit nachlässt." }, "SAME_TIME_BASELINE": { "method": "Dein heutiger laufender Gesamtwert im Vergleich zum Median derselben Ortszeit-Stunde aus deinen letzten vier Wochen, mit einem robusten Median-±-MAD-Band darum. Nur Tage mit ausreichend aufgezeichneten Details zählen, und es wird kein Vergleich gezeigt, bevor mindestens vierzehn davon vorliegen.", - "caveat": "Ein Vergleich mit deiner eigenen jüngeren Vergangenheit, kein Ziel. Er sagt, wo der heutige Tag zu dieser Stunde gegenüber deinem üblichen Muster steht — und nichts darüber, ob dieses Muster für dich das richtige ist." + "caveat": "Ein Vergleich mit deiner eigenen jüngeren Vergangenheit, kein Ziel. Er sagt, wo der heutige Tag zu dieser Stunde gegenüber deinem üblichen Muster steht, und nichts darüber, ob dieses Muster für dich das richtige ist." } }, "scores": { @@ -4388,31 +4388,31 @@ "allClear": "Alle deine Vitalwerte liegen heute in ihrem persönlichen Bereich.", "allClearMeta": "{count} deiner Vitalwerte gegen deinen eigenen typischen Bereich geprüft.", "watch": "Ein Vitalwert liegt heute außerhalb seines üblichen Bereichs.", - "watchVital": "Außerhalb des Bereichs: {vital}. Oft nur einmalig — behalte es in den nächsten Tagen im Blick.", + "watchVital": "Außerhalb des Bereichs: {vital}. Oft nur einmalig. Behalte es in den nächsten Tagen im Blick.", "firedHeadline": "{count} deiner Vitalwerte liegen heute außerhalb ihres persönlichen Bereichs.", - "factors": "Mögliche Faktoren — nie eine Ursache: ein hartes Training, schlechter Schlaf, Alkohol, Höhe, Stress oder Krankheit. Das ist ein Hinweis aus deinen eigenen Baselines, keine Diagnose.", - "building": "Deine persönlichen Baselines entstehen — erfasse ein paar Tage mehr, dann erscheint dies.", + "factors": "Mögliche Faktoren (nie eine Ursache): ein hartes Training, schlechter Schlaf, Alkohol, Höhe, Stress oder Krankheit. Das ist ein Hinweis aus deinen eigenen Baselines, keine Diagnose.", + "building": "Deine persönlichen Baselines entstehen. Erfasse ein paar Tage mehr, dann erscheint dies.", "illnessExplained": "Diese Abweichungen hängen wahrscheinlich mit der erfassten Erkrankung zusammen." }, "trajectory": { "cardTitle": "Kurzfrist-Projektion", - "headline": "Wenn dieses Muster anhält — die nächsten {days} Tage", + "headline": "Wenn dieses Muster anhält: die nächsten {days} Tage", "range": "Projiziert auf rund {low}–{high} {unit} in {days} Tagen.", "caveat": "Eine Fortschreibung deines eigenen jüngsten Trends, keine Vorhersage. Das schattierte Band wird breiter und zeigt, wie schnell die Unsicherheit wächst.", - "insufficient": "Noch kein klar genuger Trend für eine Projektion — erfasse weiter, dann erscheint eine Projektion, sobald das jüngste Muster deutlich genug ist.", + "insufficient": "Noch kein klar genuger Trend für eine Projektion. Erfasse weiter, dann erscheint eine Projektion, sobald das jüngste Muster deutlich genug ist.", "daysNeeded": "Noch etwa {count} Tage Erfassung nötig, bis eine Projektion erscheinen kann." }, "sameTime": { "sectionTitle": "Heute bisher", "sectionSubtitle": "Deine laufenden Summen im Vergleich zu dem, was zu dieser Stunde für dich üblich ist", - "learning": "Lernt deinen üblichen Tag — {count} von {target} Tagen", + "learning": "Lernt deinen üblichen Tag: {count} von {target} Tagen", "framing": "Üblich bis {time}: {typical} {unit}", "comparisonLabel": "Dein üblicher Tag" } }, "cardioFitness": { "title": "Fitness", - "description": "Deine VO₂max im Zeitverlauf — das wichtigste Maß für die Ausdauerfitness.", + "description": "Deine VO₂max im Zeitverlauf, das wichtigste Maß für die Ausdauerfitness.", "chartTitle": "VO₂max (mL/(kg·min))", "emptyState": { "title": "Noch keine Fitnessdaten", @@ -4492,7 +4492,7 @@ "navBreathingDisturbances": "Atmung", "rhythmEvents": { "sectionTitle": "Gesundheitshinweise des Geräts", - "sectionIntro": "Hinweise, die deine Uhr eigenständig gesendet hat. HealthLog zeigt diese nur an — es erkennt, bestätigt oder interpretiert sie nicht.", + "sectionIntro": "Hinweise, die deine Uhr eigenständig gesendet hat. HealthLog zeigt diese nur an. Es erkennt, bestätigt oder interpretiert sie nicht.", "loadError": "Die Gerätehinweise konnten nicht geladen werden.", "disclaimer": "Dies sind Hinweise, die dein Gerät mit seiner eigenen integrierten Erkennung erzeugt hat. Sie werden hier nur zu deiner Information angezeigt. Dies ist keine medizinische Bewertung durch HealthLog, und HealthLog stellt keine Diagnose. Wenn dich ein Hinweis beunruhigt, sprich mit deiner Ärztin oder deinem Arzt.", "event": { @@ -4537,13 +4537,13 @@ "detail": "Ausgeblendete Detailseiten verschwinden auch aus der oberen Navigation." }, "customize": "Insights anpassen", - "regenerateRateLimited": "Aktualisierungslimit erreicht — bitte später erneut versuchen.", - "regenerateUnavailable": "Keine neue Analyse erhalten — bitte später erneut versuchen.", - "regenerateError": "Aktualisierung läuft noch — bitte gleich erneut versuchen.", + "regenerateRateLimited": "Aktualisierungslimit erreicht. Bitte später erneut versuchen.", + "regenerateUnavailable": "Keine neue Analyse erhalten. Bitte später erneut versuchen.", + "regenerateError": "Aktualisierung läuft noch. Bitte gleich erneut versuchen.", "regenerateSettling": "Die Einschätzung wird noch erstellt", "regenerateSettleFailed": "Die Aktualisierung konnte nicht abgeschlossen werden. Bitte später erneut versuchen.", "deviceScore": { - "learning": "Deine Basislinie wird noch gelernt — ein paar weitere Nächte vervollständigen den Verlauf.", + "learning": "Deine Basislinie wird noch gelernt. Ein paar weitere Nächte vervollständigen den Verlauf.", "average": "30-Tage-Durchschnitt {value}", "unitScore": "Punkte", "unitMinutes": "Min.", @@ -4556,14 +4556,14 @@ }, "recovery": { "title": "Erholung", - "description": "Wie gut sich dein Körper erholt hat — die Erholungs-, Belastungs- und Load-Signale, die dein Wearable über Nacht aufzeichnet.", + "description": "Wie gut sich dein Körper erholt hat: die Erholungs-, Belastungs- und Load-Signale, die dein Wearable über Nacht aufzeichnet.", "scoreCrossLink": "Den zusammengesetzten Erholungs-Score ansehen", "emptyTitle": "Noch keine Erholungsdaten", "empty": "Noch keine Erholungsdaten. Verbinde ein WHOOP-, Polar- oder Oura-Konto, dann füllen sich diese Werte, sobald dein Gerät synchronisiert.", "block": { - "ansChargeExplainer": "Wie aufgeladen dein autonomes Nervensystem in den Tag startet — ein Recharge-Wert aus deinen nächtlichen Herz- und Atemsignalen.", + "ansChargeExplainer": "Wie aufgeladen dein autonomes Nervensystem in den Tag startet, ein Recharge-Wert aus deinen nächtlichen Herz- und Atemsignalen.", "dayStrainExplainer": "Die kardiovaskuläre Tagesbelastung auf der Belastungsskala deines Geräts. Lies sie im Verhältnis zu deiner Erholung, nicht als Ziel für sich.", - "workoutStrainExplainer": "Wie fordernd ein einzelnes Training auf derselben Belastungsskala war — die kardiovaskuläre Last dieser Einheit.", + "workoutStrainExplainer": "Wie fordernd ein einzelnes Training auf derselben Belastungsskala war: die kardiovaskuläre Last dieser Einheit.", "cardioLoadExplainer": "Ein Trainingslast-Näherungswert, der die akut aufgebaute kardiovaskuläre Belastung abbildet. Vergleiche ihn mit deinen eigenen letzten Tagen.", "averageHeartRateExplainer": "Deine durchschnittliche Herzfrequenz über den ganzen Tag bzw. Zyklus, wie dein Wearable sie meldet.", "maxHeartRateExplainer": "Deine höchste Herzfrequenz über den ganzen Tag bzw. Zyklus, wie dein Wearable sie meldet.", @@ -4575,8 +4575,8 @@ "subtitle": "Nächtliche Abweichung von deiner Basislinie" }, "resilience": { - "explainer": "Wie gut dein Körper die tägliche Belastung mit der Erholung ausbalanciert — aus deinen nächtlichen Signalen der letzten Tage abgelesen.", - "learning": "Deine Resilienz wird noch erlernt — ein paar Tage mehr festigen das Niveau.", + "explainer": "Wie gut dein Körper die tägliche Belastung mit der Erholung ausbalanciert, aus deinen nächtlichen Signalen der letzten Tage abgelesen.", + "learning": "Deine Resilienz wird noch erlernt. Ein paar Tage mehr festigen das Niveau.", "band": { "limited": "Eingeschränkt", "adequate": "Ausreichend", @@ -4621,7 +4621,7 @@ "nights": "{count} Nächte erfasst", "indexLine": "jüngster Durchschnittsindex {value}", "eventsFlagged": "{count} vom Gerät gemeldete Ereignisse", - "disclaimer": "Dies ist ein Screening-Signal, keine Diagnose — bitte mit einer Ärztin oder einem Arzt besprechen." + "disclaimer": "Dies ist ein Screening-Signal, keine Diagnose. Bitte mit einer Ärztin oder einem Arzt besprechen." }, "labsChanges": { "sectionTitle": "Seit deinem letzten Laborbefund", @@ -4637,14 +4637,14 @@ "navWaistToHeight": "Taille/Größe", "gripStrength": { "title": "Griffkraft", - "description": "Maximale Handgriffkraft — ein robuster Stellvertreter für die Ganzkörperkraft. Unter dem geschlechtsspezifischen Grenzwert (Männer 27 kg, Frauen 16 kg) deutet sie auf eine mögliche Sarkopenie hin; dein eigener Verlauf führt die Einschätzung.", + "description": "Maximale Handgriffkraft, ein robuster Stellvertreter für die Ganzkörperkraft. Unter dem geschlechtsspezifischen Grenzwert (Männer 27 kg, Frauen 16 kg) deutet sie auf eine mögliche Sarkopenie hin; dein eigener Verlauf führt die Einschätzung.", "chartTitle": "Griffkraft", "emptyState": { "title": "Noch keine Griffkraft", - "description": "Erfasse einen Wert mit einem Handdynamometer — notiere den besten von mehreren Versuchen — und der Verlauf erscheint hier.", + "description": "Erfasse einen Wert mit einem Handdynamometer (notiere den besten von mehreren Versuchen), und der Verlauf erscheint hier.", "cta": "Griffkraft erfassen" }, - "coachPrefill": "Ich habe noch keine Griffkraft erfasst — was sagt sie über meine Muskelgesundheit aus, und wie messe und verbessere ich sie?" + "coachPrefill": "Ich habe noch keine Griffkraft erfasst. Was sagt sie über meine Muskelgesundheit aus, und wie messe und verbessere ich sie?" }, "pain": { "title": "Schmerz (0–10)", @@ -4655,29 +4655,29 @@ "description": "Erfasse auf der Skala 0–10, wie sich dein Schmerz gerade anfühlt, und der Verlauf erscheint hier.", "cta": "Schmerzwert erfassen" }, - "coachPrefill": "Ich habe noch keine Schmerzwerte erfasst — wie sollte ich Schmerz auf der Skala 0–10 verfolgen, und was gilt als bedeutsame Veränderung?" + "coachPrefill": "Ich habe noch keine Schmerzwerte erfasst. Wie sollte ich Schmerz auf der Skala 0–10 verfolgen, und was gilt als bedeutsame Veränderung?" }, "waist": { "title": "Taillenumfang", - "description": "Taillenumfang in Zentimetern — ein Marker für Bauchfett. Der WHO-Grenzwert für erhöhtes Risiko ist geschlechtsspezifisch (Männer 94 cm, Frauen 80 cm); dein eigener Verlauf führt die Einschätzung.", + "description": "Taillenumfang in Zentimetern, ein Marker für Bauchfett. Der WHO-Grenzwert für erhöhtes Risiko ist geschlechtsspezifisch (Männer 94 cm, Frauen 80 cm); dein eigener Verlauf führt die Einschätzung.", "chartTitle": "Taillenumfang", "emptyState": { "title": "Noch keine Taillenwerte", "description": "Miss deine Taille mittig zwischen der untersten Rippe und dem Hüftknochen am Ende einer normalen Ausatmung und erfasse den Wert hier.", "cta": "Taillenumfang erfassen" }, - "coachPrefill": "Ich habe noch keine Taillenwerte erfasst — wie messe ich meine Taille richtig, und was bedeutet der Wert für meine Gesundheit?" + "coachPrefill": "Ich habe noch keine Taillenwerte erfasst. Wie messe ich meine Taille richtig, und was bedeutet der Wert für meine Gesundheit?" }, "waistToHeight": { "title": "Taille-zu-Größe-Verhältnis", - "description": "Deine Taille geteilt durch deine Größe — die ethnienunabhängige Einzelzahl. Sie unter 0,5 zu halten (Taille unter der halben Körpergröße) ist das einfache Ziel.", + "description": "Deine Taille geteilt durch deine Größe, die ethnienunabhängige Einzelzahl. Sie unter 0,5 zu halten (Taille unter der halben Körpergröße) ist das einfache Ziel.", "chartTitle": "Taille-zu-Größe-Verhältnis", "emptyState": { "title": "Noch kein Taille-zu-Größe-Verhältnis", "description": "Erfasse ein Taille-zu-Größe-Verhältnis, und der Verlauf erscheint hier. Faustregel: Halte deine Taille unter der halben Körpergröße.", "cta": "Taille-zu-Größe-Verhältnis erfassen" }, - "coachPrefill": "Ich habe noch kein Taille-zu-Größe-Verhältnis erfasst — warum ist es eine nützliche Zahl, und wie halte ich es unter 0,5?" + "coachPrefill": "Ich habe noch kein Taille-zu-Größe-Verhältnis erfasst. Warum ist es eine nützliche Zahl, und wie halte ich es unter 0,5?" }, "ecg": { "sectionTitle": "EKG-Aufzeichnungen", @@ -4720,7 +4720,7 @@ "intradayPulse": { "title": "Puls über den Tag", "caption": "Gemittelt in 10-Minuten-Schritten.", - "hourlyNote": "Stündlicher Durchschnitt für diesen Tag — aktuelle Tage zeigen das volle 10-Minuten-Detail.", + "hourlyNote": "Stündlicher Durchschnitt für diesen Tag; aktuelle Tage zeigen das volle 10-Minuten-Detail.", "empty": "Für diesen Tag noch nicht genug Pulswerte, um den Tagesverlauf zu zeigen.", "coverageOne": "Basierend auf 1 Messung über {hours}h.", "coverageMany": "Basierend auf {count} Messungen über {hours}h.", @@ -4729,10 +4729,10 @@ "previousDay": "Vorheriger Tag", "nextDay": "Nächster Tag", "tension": { - "morning": "Eine anhaltend erhöhte Ruhephase heute Vormittag — möglicherweise etwas Anspannung.", - "afternoon": "Eine anhaltend erhöhte Ruhephase heute Nachmittag — möglicherweise etwas Anspannung.", - "evening": "Eine anhaltend erhöhte Ruhephase heute Abend — möglicherweise etwas Anspannung.", - "night": "Eine anhaltend erhöhte Ruhephase in der Nacht — möglicherweise etwas Anspannung." + "morning": "Eine anhaltend erhöhte Ruhephase heute Vormittag, möglicherweise etwas Anspannung.", + "afternoon": "Eine anhaltend erhöhte Ruhephase heute Nachmittag, möglicherweise etwas Anspannung.", + "evening": "Eine anhaltend erhöhte Ruhephase heute Abend, möglicherweise etwas Anspannung.", + "night": "Eine anhaltend erhöhte Ruhephase in der Nacht, möglicherweise etwas Anspannung." } }, "navEcg": "EKG", @@ -4785,14 +4785,14 @@ "metricBodyFat": "Körperfett", "metricSleep": "Schlafdauer", "metricSteps": "Schritte/Tag", - "metricGlucoseFasting": "Glukose — nüchtern", - "metricGlucosePostprandial": "Glukose — postprandial", - "metricGlucoseRandom": "Glukose — beliebig", - "metricGlucoseBedtime": "Glukose — vor dem Schlafen", + "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.", + "unsetExplanation": "Kein eigener Wert, berechneter Default aktiv.", "cardTitle": "Bereiche je Messgröße" }, "onboarding": { @@ -4806,11 +4806,11 @@ "steps": { "dashboardOverview": { "title": "Dein Dashboard", - "body": "Das Dashboard bündelt alle Module auf einen Blick. Halte eine Kachel lange gedrückt, um sie neu anzuordnen oder auszublenden (Einstellungen → Dashboard-Layout). Jede Kachel ist nur so aussagekräftig wie die Daten dahinter — die folgenden Module füllen sie." + "body": "Das Dashboard bündelt alle Module auf einen Blick. Halte eine Kachel lange gedrückt, um sie neu anzuordnen oder auszublenden (Einstellungen → Dashboard-Layout). Jede Kachel ist nur so aussagekräftig wie die Daten dahinter. Die folgenden Module füllen sie." }, "quickAdd": { "title": "In Sekunden erfasst", - "body": "Über „+ Hinzufügen“ trägst du jeden Messwert in Sekunden ein — Gewicht, Blutdruck, Puls, Glukose. Versteckte Stärke: Werte lassen sich nachträglich datieren. Alles, was du hier einträgst, fließt in Trends, Health-Score und die KI-Insights." + "body": "Über „+ Hinzufügen“ trägst du jeden Messwert in Sekunden ein: Gewicht, Blutdruck, Puls, Glukose. Versteckte Stärke: Werte lassen sich nachträglich datieren. Alles, was du hier einträgst, fließt in Trends, Health-Score und die KI-Insights." }, "measurements": { "title": "Messwerte & Zielbereiche", @@ -4822,7 +4822,7 @@ }, "labs": { "title": "Laborwerte", - "body": "Labore erfasst Biomarker mit Referenzbereichen — Blutbild, Cholesterin, HbA1c. Stärke: Import und FHIR-Export. Auffällige Laborwerte tauchen als Belege in den Insights und im Arztbericht wieder auf." + "body": "Labore erfasst Biomarker mit Referenzbereichen: Blutbild, Cholesterin, HbA1c. Stärke: Import und FHIR-Export. Auffällige Laborwerte tauchen als Belege in den Insights und im Arztbericht wieder auf." }, "illness": { "title": "Krankheits-Journal", @@ -4838,31 +4838,31 @@ }, "mood": { "title": "Stimmung", - "body": "Stimmung erfasst dein Befinden und Tags in zwei Sekunden. Stärke: eigene Tags. Stimmungsverläufe korrelieren mit Schlaf, Medikamenten und Zyklus — der Coach erkennt Muster." + "body": "Stimmung erfasst dein Befinden und Tags in zwei Sekunden. Stärke: eigene Tags. Stimmungsverläufe korrelieren mit Schlaf, Medikamenten und Zyklus, der Coach erkennt Muster." }, "insights": { "title": "Insights", - "body": "Insights ist das Herzstück: belegbasierte, dynamische Auswertungen statt generischer Tipps — jede Aussage verweist auf deine echten Daten. Versteckt: das Layout ist anpassbar. Insights zieht alles zusammen, was die Module oben liefern." + "body": "Insights ist das Herzstück: belegbasierte, dynamische Auswertungen statt generischer Tipps. Jede Aussage verweist auf deine echten Daten. Versteckt: das Layout ist anpassbar. Insights zieht alles zusammen, was die Module oben liefern." }, "coach": { "title": "Coach", - "body": "Der Coach beantwortet Fragen zu deinen Daten im Dialog und nutzt Anamnese, Medikamente und Laborwerte als Kontext. Den KI-Anbieter wählst du selbst (eigener Schlüssel oder lokal). Er rechnet nichts neu — er liest dieselben Zahlen wie das Dashboard." + "body": "Der Coach beantwortet Fragen zu deinen Daten im Dialog und nutzt Anamnese, Medikamente und Laborwerte als Kontext. Den KI-Anbieter wählst du selbst (eigener Schlüssel oder lokal). Er rechnet nichts neu, er liest dieselben Zahlen wie das Dashboard." }, "integrations": { "title": "Integrationen", - "body": "Integrationen synchronisieren Withings, WHOOP, Polar, Oura und Apple Health automatisch. So füllen sich Gewicht, Schlaf und Erholung ohne manuelles Tippen — und nähren wiederum Insights und Coach." + "body": "Integrationen synchronisieren Withings, WHOOP, Polar, Oura und Apple Health automatisch. So füllen sich Gewicht, Schlaf und Erholung ohne manuelles Tippen und nähren wiederum Insights und Coach." }, "export": { "title": "Arztbericht", - "body": "Der Arztbericht bündelt Messwerte, Medikamente, Laborwerte und Vorsorge als PDF oder FHIR für den Termin. Hier laufen alle Module zusammen — ein vollständiger Bericht entsteht nur bei gepflegten Daten." + "body": "Der Arztbericht bündelt Messwerte, Medikamente, Laborwerte und Vorsorge als PDF oder FHIR für den Termin. Hier laufen alle Module zusammen. Ein vollständiger Bericht entsteht nur bei gepflegten Daten." }, "achievements": { "title": "Erfolge", - "body": "Erfolge belohnen Konsistenz — Streaks und Meilensteine. Ein kleiner Motivations-Loop, der das Dranbleiben leichter macht." + "body": "Erfolge belohnen Konsistenz: Streaks und Meilensteine. Ein kleiner Motivations-Loop, der das Dranbleiben leichter macht." }, "wrapUp": { "title": "Das war die Tour", - "body": "Diese Führung läuft einmalig — sie öffnet sich nicht von selbst erneut. Alles Gezeigte bleibt erhalten, und du kannst Funktionen jederzeit unter Einstellungen → Module ein- oder ausschalten." + "body": "Diese Führung läuft einmalig und öffnet sich nicht von selbst erneut. Alles Gezeigte bleibt erhalten, und du kannst Funktionen jederzeit unter Einstellungen → Module ein- oder ausschalten." } } }, @@ -4893,7 +4893,7 @@ "title": "Alles bereit", "body": "Willkommen an Bord. Dein Dashboard wartet.", "returnCta": "Zum Dashboard", - "learning": "Manche Einblicke — Glukose, Schlafrhythmus, Blutdrucktrends, Zyklus — schärfen sich in den ersten ein bis zwei Wochen, sobald sich deine Daten ansammeln. Leere Kacheln heißen jetzt nur, dass wir deine Basislinie noch lernen.", + "learning": "Manche Einblicke (Glukose, Schlafrhythmus, Blutdrucktrends, Zyklus) schärfen sich in den ersten ein bis zwei Wochen, sobald sich deine Daten ansammeln. Leere Kacheln heißen jetzt nur, dass wir deine Basislinie noch lernen.", "connectCta": "Gerät verbinden", "logCta": "Ersten Wert eintragen", "importCta": "Bestehende Daten importieren", @@ -4910,33 +4910,33 @@ "anamnesis": { "title": "Zu deiner Gesundheit (optional)", "subtitle": "Etwas Kontext, damit HealthLog deine Werte fairer einordnet.", - "intro": "Teile so viel oder so wenig, wie du möchtest — jedes Feld ist optional und jederzeit in den Einstellungen änderbar.", + "intro": "Teile so viel oder so wenig, wie du möchtest. Jedes Feld ist optional und jederzeit in den Einstellungen änderbar.", "conditionsLabel": "Bestehende Erkrankungen", "conditionsPlaceholder": "z. B. Bluthochdruck, Typ-2-Diabetes", "conditionsHint": "Hilft HealthLog, deine Werte im Kontext einzuordnen, statt Erwartbares zu melden.", "allergiesLabel": "Allergien oder Unverträglichkeiten", "allergiesPlaceholder": "z. B. Penicillin, Laktose", - "privacyNote": "Verschlüsselt gespeichert und nur für besseren Kontext genutzt. Medikamente fragen wir hier nicht ab — die kannst du jederzeit auf der Medikamenten-Seite ergänzen." + "privacyNote": "Verschlüsselt gespeichert und nur für besseren Kontext genutzt. Medikamente fragen wir hier nicht ab, die kannst du jederzeit auf der Medikamenten-Seite ergänzen." }, "ai": { "panelTitle": "So sehen Insights aus", - "panelIntro": "Coach, das tägliche Briefing und die Einschätzungen je Messwert übersetzen deine eigenen Zahlen in Klartext. So sieht das aus — bevor du irgendetwas verbindest.", + "panelIntro": "Coach, das tägliche Briefing und die Einschätzungen je Messwert übersetzen deine eigenen Zahlen in Klartext. So sieht das aus, bevor du irgendetwas verbindest.", "showSample": "Beispiel-Briefing ansehen", "sampleTitle": "Tägliches Briefing", "sampleTag": "Beispiel", "sampleAriaLabel": "Beispielhaftes tägliches Briefing", - "sampleBody": "Gewicht in zwei Wochen um 1,2 kg gesunken. Ruhepuls stabil bei 58 bpm. Blutdruck an 6 von 7 Tagen im Zielbereich — der einzige hohe Wert folgte auf ein spätes, salziges Abendessen.", - "sampleCaption": "Nur ein Beispiel — nicht deine eigenen Daten. So liest sich ein Briefing, sobald Insights aktiv sind.", + "sampleBody": "Gewicht in zwei Wochen um 1,2 kg gesunken. Ruhepuls stabil bei 58 bpm. Blutdruck an 6 von 7 Tagen im Zielbereich; der einzige hohe Wert folgte auf ein spätes, salziges Abendessen.", + "sampleCaption": "Nur ein Beispiel, nicht deine eigenen Daten. So liest sich ein Briefing, sobald Insights aktiv sind.", "ladderTitle": "Drei Wege, es zu aktivieren", - "ladderLocalTitle": "Lokales Modell — KI-Anfragen bleiben in deinem Netzwerk", - "ladderLocalBody": "Richte HealthLog auf Ollama oder LM Studio auf deinem eigenen Rechner aus. Kostenlos und vollständig privat — der ruhige Standard.", + "ladderLocalTitle": "Lokales Modell: KI-Anfragen bleiben in deinem Netzwerk", + "ladderLocalBody": "Richte HealthLog auf Ollama oder LM Studio auf deinem eigenen Rechner aus. Kostenlos und vollständig privat, der ruhige Standard.", "ladderByokTitle": "Eigenen Schlüssel verwenden", "ladderByokBody": "Nutze deinen eigenen OpenAI- oder Anthropic-Schlüssel. Er läuft über dein Konto und deine Abrechnung, und die API-Stufe hält deine Daten standardmäßig aus dem Training heraus.", "ladderOauthTitle": "Mit einem Abo anmelden", - "ladderOauthBody": "Verbinde ein ChatGPT-Konto — keine Kosten pro Token, aber die Bedingungen der Verbraucherstufe können Inhalte fürs Training nutzen. Deshalb eine bewusste Wahl, nie der Standard für deine Gesundheitsdaten.", - "keylessLine": "HealthLog ist auch ohne KI vollständig nutzbar. Deine Kacheln, Diagramme, Trends und Exporte funktionieren alle — KI ergänzt nur den Klartext obendrauf.", + "ladderOauthBody": "Verbinde ein ChatGPT-Konto: keine Kosten pro Token, aber die Bedingungen der Verbraucherstufe können Inhalte fürs Training nutzen. Deshalb eine bewusste Wahl, nie der Standard für deine Gesundheitsdaten.", + "keylessLine": "HealthLog ist auch ohne KI vollständig nutzbar. Deine Kacheln, Diagramme, Trends und Exporte funktionieren alle. KI ergänzt nur den Klartext obendrauf.", "setupCta": "Einrichten (etwa eine Minute)", - "sharedKeyNote": "Diese Instanz stellt bereits einen gemeinsamen KI-Anbieter bereit, deshalb funktionieren Insights für dich sofort — keine Einrichtung nötig.", + "sharedKeyNote": "Diese Instanz stellt bereits einen gemeinsamen KI-Anbieter bereit, deshalb funktionieren Insights für dich sofort, keine Einrichtung nötig.", "offer": { "title": "Die Zusammenfassung dieser Instanz ist bereit.", "body": "Der Betreiber stellt einen Anbieter bereit, der zuletzt innerhalb der letzten 24 Stunden funktioniert hat. Mit einem Tipp schaltest du den Klartext ein; deine Daten gehen dann an diesen einen Anbieter, an niemanden sonst.", @@ -5153,7 +5153,7 @@ "profileDescription": "Größe, Geburtsdatum und Geschlecht schalten personalisierte Zielwerte frei.", "profileCta": "Profil öffnen", "measurementTitle": "Erste Messung hinzufügen", - "measurementDescription": "Ein Messpunkt reicht, um die Kachel zu aktivieren — der Trend zeichnet sich ab dem 5. Eintrag.", + "measurementDescription": "Ein Messpunkt reicht, um die Kachel zu aktivieren. Der Trend zeichnet sich ab dem 5. Eintrag.", "measurementCta": "Messung hinzufügen", "medicationTitle": "Medikament hinzufügen", "medicationDescription": "Verfolge die Therapietreue und erhalte Erinnerungen genau dann, wenn du sie brauchst.", @@ -5162,7 +5162,7 @@ "dataSourceDescription": "Gewicht, Blutdruck, Schlaf und mehr automatisch aus Withings, WHOOP, Oura, Polar, Nightscout, Fitbit oder Apple Health.", "dataSourceCta": "Verbinden", "notificationsTitle": "Benachrichtigungen einrichten", - "notificationsDescription": "Wähle, wie HealthLog dich erinnert — Telegram, ntfy oder Web Push.", + "notificationsDescription": "Wähle, wie HealthLog dich erinnert: Telegram, ntfy oder Web Push.", "notificationsCta": "Benachrichtigungen öffnen", "insightsTitle": "Insights aktivieren (optional)", "insightsDescription": "Füge ein lokales Modell oder deinen eigenen KI-Schlüssel hinzu, um das tägliche Briefing und Coach freizuschalten.", @@ -5388,7 +5388,7 @@ "resetSuccess": "Quellen-Priorität zurückgesetzt", "perMetricToggle": "Pro Metrik anpassen ({count})", "perMetricHelp": "Metriken mit individueller Reihenfolge. Über diese Liste lässt sich eine einzelne Metrik mit einem Klick auf den Standard zurücksetzen, ohne die anderen anzufassen.", - "perMetricEmpty": "Keine individuellen Anpassungen — jede Metrik nutzt die globale Reihenfolge oben.", + "perMetricEmpty": "Keine individuellen Anpassungen. Jede Metrik nutzt die globale Reihenfolge oben.", "resetMetric": "Zurücksetzen", "deviceTypeToggle": "Geräte-Typ-Reihenfolge ({count})", "deviceTypeHelp": "Innerhalb einer Quelle entscheidet die Geräte-Typ-Reihenfolge. Wenn Apple Watch und iPhone beide Schritte aufzeichnen, zählt der höher gereihte Geräte-Typ.", @@ -5452,7 +5452,7 @@ "daysWithData": "{count} von {days} Tagen", "moduleHint": "Die Synchronisierung steuert das Modul „Nährstoffzufuhr“.", "moduleHintLink": "Module verwalten", - "detail": "Nur lesend — die Quell-App besitzt die Werte." + "detail": "Nur lesend, die Quell-App besitzt die Werte." }, "helpDetail": "Die übrigen bleiben für die Audit-Spur gespeichert. Aufgeführt sind nur Quellen, die du verbunden hast oder von denen Daten vorliegen.", "noneInUse": "Noch keine Quelle zum Sortieren. Verbinde eine unter Integrationen oder trage einen Wert ein." @@ -5497,12 +5497,12 @@ "fullBackup": { "title": "Voll-Backup", "description": "Deine gesamte Akte in einer JSON-Datei.", - "scopeNote": "Dokumentmetadaten und die KI-Zusammenfassung, falls vorhanden, sind als Klartext enthalten; die Originaldateien der Dokumente sowie GPS-Routen und Einzelmesswerte von Workouts sind es nicht — lade diese separat aus dem Dokumententresor bzw. dem Workout-Export herunter.", + "scopeNote": "Dokumentmetadaten und die KI-Zusammenfassung, falls vorhanden, sind als Klartext enthalten; die Originaldateien der Dokumente sowie GPS-Routen und Einzelmesswerte von Workouts sind es nicht. Lade diese separat aus dem Dokumententresor bzw. dem Workout-Export herunter.", "encryptToggle": "Mit einer Passphrase verschlüsseln", "passphrasePlaceholder": "Passphrase (mind. 12 Zeichen)", "passphraseHelp": "Leitet den Archivschlüssel per Argon2id ab und versiegelt ihn mit AES-256-GCM. Speichere die Datei mit der Endung .hlx.", - "noRecoveryWarning": "Es gibt keine Wiederherstellung — geht diese Passphrase verloren, lässt sich das Archiv nicht mehr öffnen. Bewahre sie sicher auf.", - "detail": "Gleiche Form wie die wöchentliche automatische Sicherung. Einige Satzarten sind noch nicht enthalten — das Manifest der Datei nennt, was drinsteht.", + "noRecoveryWarning": "Es gibt keine Wiederherstellung. Geht diese Passphrase verloren, lässt sich das Archiv nicht mehr öffnen. Bewahre sie sicher auf.", + "detail": "Gleiche Form wie die wöchentliche automatische Sicherung. Einige Satzarten sind noch nicht enthalten; das Manifest der Datei nennt, was drinsteht.", "contents": "Deine Messwerte, Medikamente, Stimmung, Zyklus, Laborwerte, Krankheitsepisoden, Allergien, Familienanamnese, Nährstoffe, Workouts, dein Gesundheitsprofil und deine eigenen Messgrößen in einer JSON-Datei." } }, @@ -5745,7 +5745,7 @@ "error": "Konnte nicht gespeichert werden. Bitte erneut versuchen.", "toggleable": { "title": "Was du trackst", - "description": "Deaktivierte Module verschwinden aus Navigation, Kacheln und Auswertungen — deine Daten bleiben erhalten." + "description": "Deaktivierte Module verschwinden aus Navigation, Kacheln und Auswertungen, deine Daten bleiben erhalten." }, "manageIn": "In {section} verwalten", "operatorDisabled": "Serverweit deaktiviert", @@ -5865,7 +5865,7 @@ "omitted": "{count} Bereiche stehen nicht in der Liste, weil ihre Erfassung abgeschaltet ist. Schalte ein Modul wieder ein, dann kommt sein Bereich zurück.", "omittedLink": "Module öffnen", "refusal": { - "empty": "Ein Health Score braucht mindestens ein Feld der Gesundheit, das er bewerten kann. Behalte mindestens eines ausgewählt — der Score nennt selbst, worauf er beruht." + "empty": "Ein Health Score braucht mindestens ein Feld der Gesundheit, das er bewerten kann. Behalte mindestens eines ausgewählt. Der Score nennt selbst, worauf er beruht." }, "notice": { "upgrade": { @@ -6048,7 +6048,7 @@ "rawDataWarning": "Ausführlicher Verlauf ist an: Jede Auswertung sendet zusätzlich Tagesdurchschnitte der letzten 90 Tage, Wochendurchschnitte für das Jahr davor und Monatsdurchschnitte bis zu 5 Jahre zurück.", "regenerateInsights": "Reports neu generieren", "regenerateSuccess": "Reports wurden neu generiert", - "regenerateRateLimit": "Bitte warte — du hast das stündliche Limit für Analysen erreicht.", + "regenerateRateLimit": "Bitte warte, du hast das stündliche Limit für Analysen erreicht.", "lastGeneratedAt": "Zuletzt generiert", "ai": { "chatgptConnectedBadge": "ChatGPT verbunden", @@ -6058,11 +6058,11 @@ "deviceCodeHeading": "Verbindung auf chatgpt.com abschließen", "deviceCodeStep1": "Öffne diesen Link auf einem beliebigen Gerät:", "deviceCodeStep2": "Gib diesen Einmalcode ein:", - "deviceCodeStep3": "Bestätige die Verbindung — diese Seite aktualisiert sich automatisch.", + "deviceCodeStep3": "Bestätige die Verbindung. Diese Seite aktualisiert sich automatisch.", "deviceCodeCopy": "kopieren", "deviceCodeWaiting": "Warte auf Bestätigung…", "deviceCodeCancel": "Abbrechen", - "oauthNotConfigured": "ChatGPT-OAuth ist auf dieser Instanz nicht konfiguriert — nutze stattdessen einen eigenen API-Key unten.", + "oauthNotConfigured": "ChatGPT-OAuth ist auf dieser Instanz nicht konfiguriert. Nutze stattdessen einen eigenen API-Key unten.", "modelLabel": "Modell", "modelOptionDefault": "— Standard —", "modelOptionCustom": "Eigenes…", @@ -6070,7 +6070,7 @@ "anthropicKeyLabel": "Anthropic API-Key", "baseUrlLabel": "Base URL", "localKeyLabel": "API-Key (optional)", - "localDescription": "Hier funktioniert jeder OpenAI-kompatible Endpunkt — ein lokales Modell (Ollama, LM Studio) genauso wie ein Gateway wie LiteLLM, OpenRouter oder vLLM. Die Basis-URL endet auf /v1; der API-Schlüssel ist optional.", + "localDescription": "Hier funktioniert jeder OpenAI-kompatible Endpunkt: ein lokales Modell (Ollama, LM Studio) genauso wie ein Gateway wie LiteLLM, OpenRouter oder vLLM. Die Basis-URL endet auf /v1; der API-Schlüssel ist optional.", "savedPreview": "(gespeichert {preview})", "savedShort": "(gespeichert)", "saveCta": "Speichern", @@ -6110,7 +6110,7 @@ "admin-openai": "Admin-OpenAI" }, "compat": { - "description": "Ein vollwertiger Anbieter für jeden Endpunkt, der die OpenAI-API /v1/chat/completions spricht: LiteLLM, OpenRouter, vLLM oder ein anderes Gateway. Die Basis-URL endet auf /v1, der API-Key ist optional, und das Modell ist das, was dein Gateway weiterleitet. Dein OpenAI-Key erreicht diesen Endpunkt nie — dieser Anbieter hat einen eigenen.", + "description": "Ein vollwertiger Anbieter für jeden Endpunkt, der die OpenAI-API /v1/chat/completions spricht: LiteLLM, OpenRouter, vLLM oder ein anderes Gateway. Die Basis-URL endet auf /v1, der API-Key ist optional, und das Modell ist das, was dein Gateway weiterleitet. Dein OpenAI-Key erreicht diesen Endpunkt nie, dieser Anbieter hat einen eigenen.", "keyLabel": "API-Key (optional)", "modelHint": "Der Modellname, den dein Gateway erwartet. Bleibt das Feld leer, wird das für deine anderen Anbieter gespeicherte Modell verwendet; ist auch das leer, wird dieser Anbieter übersprungen." }, @@ -6146,18 +6146,18 @@ "notConfigured": "Der Betreiber hat keinen geteilten OpenAI-Key auf dieser Instanz konfiguriert." }, "testProvider": "Aktiven Provider testen", - "testSuccess": "OK — {provider} ({model})", + "testSuccess": "OK: {provider} ({model})", "testFailedShort": "Test fehlgeschlagen: {message}", - "testUnexpectedResponse": "Verbindung zum KI-Anbieter fehlgeschlagen — unerwartete Antwort vom Server.", - "testReasonCredentials": "Der Anbieter hat die Anmeldedaten abgelehnt — melde dich in den KI-Einstellungen erneut an.", - "testReasonRateLimited": "Der Anbieter hat die Anfrage gedrosselt — versuche es in Kürze erneut.", + "testUnexpectedResponse": "Verbindung zum KI-Anbieter fehlgeschlagen: unerwartete Antwort vom Server.", + "testReasonCredentials": "Der Anbieter hat die Anmeldedaten abgelehnt. Melde dich in den KI-Einstellungen erneut an.", + "testReasonRateLimited": "Der Anbieter hat die Anfrage gedrosselt. Versuche es in Kürze erneut.", "testReasonServerError": "Der KI-Anbieter hat einen Serverfehler zurückgegeben.", - "testReasonBadRequest": "Der Anbieter hat die Anfrage abgelehnt (HTTP {status}) — der Endpunkt hat geantwortet; das Problem liegt also am Anfrageformat oder Modellnamen, nicht an der Verbindung.", + "testReasonBadRequest": "Der Anbieter hat die Anfrage abgelehnt (HTTP {status}). Der Endpunkt hat geantwortet; das Problem liegt also am Anfrageformat oder Modellnamen, nicht an der Verbindung.", "testReasonUnreachable": "Der KI-Anbieter war nicht erreichbar.", "coachMemory": { "title": "Woran sich der Coach erinnert", "description": "Dauerhafte Angaben, die du dem Coach mitgeteilt hast.", - "empty": "Der Coach hat noch keine Angaben gespeichert. Im Gespräch merkt er sich dauerhafte Details, die du teilst — deine Ziele, Beschwerden, Vorlieben — und du kannst sie hier jederzeit löschen.", + "empty": "Der Coach hat noch keine Angaben gespeichert. Im Gespräch merkt er sich dauerhafte Details, die du teilst (deine Ziele, Beschwerden, Vorlieben), und du kannst sie hier jederzeit löschen.", "learnedPrefix": "gelernt {when}", "categoryPreference": "Vorlieben", "categoryCondition": "Beschwerden", @@ -6173,7 +6173,7 @@ "forgetAllConfirmBody": "Dadurch werden alle gespeicherten Angaben entfernt. Der Coach beginnt beim nächsten Gespräch von vorn. Das lässt sich nicht rückgängig machen.", "forgetAllConfirmAction": "Alles vergessen", "cancel": "Abbrechen", - "summaryNote": "Der Coach behält außerdem eine kurze, fortlaufende Zusammenfassung jedes Gesprächs. Dafür gibt es keine Einzelsteuerung — wenn du ein Gespräch löschst, wird auch dessen Zusammenfassung entfernt.", + "summaryNote": "Der Coach behält außerdem eine kurze, fortlaufende Zusammenfassung jedes Gesprächs. Dafür gibt es keine Einzelsteuerung. Wenn du ein Gespräch löschst, wird auch dessen Zusammenfassung entfernt.", "loadError": "Konnte nicht laden, woran sich der Coach erinnert.", "forgotToast": "Angabe vergessen.", "forgotError": "Konnte diese Angabe nicht vergessen. Bitte erneut versuchen.", @@ -6185,7 +6185,7 @@ "coachReminders": { "title": "Deine Erinnerungen", "description": "Dinge, um die du den Coach gebeten hast, später darauf zurückzukommen.", - "empty": "Noch keine Erinnerungen. Bitte den Coach, dich an etwas zu erinnern — dann erscheint es hier.", + "empty": "Noch keine Erinnerungen. Bitte den Coach, dich an etwas zu erinnern, dann erscheint es hier.", "loadError": "Konnte deine Erinnerungen nicht laden.", "dueHeading": "Jetzt fällig", "allHeading": "Gespeichert", @@ -6194,7 +6194,7 @@ "markDone": "Erledigt", "dismiss": "Verwerfen", "deleteAria": "Diese Erinnerung löschen", - "note": "Erinnerungen werden verschlüsselt gespeichert. Lösche eine jederzeit — sie wird aus dem entfernt, was der Coach sehen kann.", + "note": "Erinnerungen werden verschlüsselt gespeichert. Lösche eine jederzeit, sie wird aus dem entfernt, was der Coach sehen kann.", "status": { "proposed": "Vorgeschlagen", "active": "Gespeichert", @@ -6240,15 +6240,15 @@ "autoRead": { "title": "Dokumente automatisch mit KI lesen", "subLabel": "Dein KI-Anbieter liest und indiziert neue Dokumente, ohne dass du jedes einzeln bestätigst.", - "honesty": "Wenn aktiviert, wird jedes hochgeladene Dokument an deinen konfigurierten KI-Anbieter gesendet, um gelesen, beschrieben und für die Suche indiziert zu werden — ohne Bestätigung pro Dokument. Das Einschalten wirkt außerdem rückwirkend: Bereits hochgeladene Dokumente ohne Zusammenfassung werden ebenfalls gesendet, bis zu 200 pro Einschaltvorgang. Das geschieht auf dem Server, und der Inhalt des Dokuments verlässt dabei diese Maschine in Richtung dieses Anbieters. Wenn dein konfigurierter Anbieter eine Abo-Verbindung ist (ein angemeldetes KI-Konto statt eines API-Schlüssels), gelten dessen eigene Datenschutzeinstellungen — Abo-Anbieter dürfen den Inhalt zur Verbesserung ihrer Modelle verwenden, und kein Auftragsverarbeitungsvertrag deckt das ab. Dokumente, die von einem selbst gehosteten lokalen Modell gelesen werden, verlassen deinen Server nie. Standardmäßig aus; aktiviere es nur, wenn du diesen Kompromiss für deine Dokumente akzeptierst.", - "confirm": "Verstanden — aktivieren", + "honesty": "Wenn aktiviert, wird jedes hochgeladene Dokument an deinen konfigurierten KI-Anbieter gesendet, um gelesen, beschrieben und für die Suche indiziert zu werden, ohne Bestätigung pro Dokument. Das Einschalten wirkt außerdem rückwirkend: Bereits hochgeladene Dokumente ohne Zusammenfassung werden ebenfalls gesendet, bis zu 200 pro Einschaltvorgang. Das geschieht auf dem Server, und der Inhalt des Dokuments verlässt dabei diese Maschine in Richtung dieses Anbieters. Wenn dein konfigurierter Anbieter eine Abo-Verbindung ist (ein angemeldetes KI-Konto statt eines API-Schlüssels), gelten dessen eigene Datenschutzeinstellungen: Abo-Anbieter dürfen den Inhalt zur Verbesserung ihrer Modelle verwenden, und kein Auftragsverarbeitungsvertrag deckt das ab. Dokumente, die von einem selbst gehosteten lokalen Modell gelesen werden, verlassen deinen Server nie. Standardmäßig aus; aktiviere es nur, wenn du diesen Kompromiss für deine Dokumente akzeptierst.", + "confirm": "Verstanden, aktivieren", "cancel": "Abbrechen" }, "centralCodex": { "title": "Gemeinsamen KI-Zugang des Servers nutzen", "subLabel": "KI-Anfragen laufen über die gemeinsame Verbindung des Servers, deine eigenen Anbieter dienen als Rückfall.", - "honesty": "Der gemeinsame Zugang ist ein einzelnes angemeldetes KI-Konto, das der Betreiber für alle auf diesem Server verbunden hat — nicht dein eigener Schlüssel. Anfragen darüber werden vom Anbieter standardmäßig zum Training genutzt und von keiner Auftragsverarbeitungsvereinbarung gedeckt, die Stunden- und Wochenlimits des Kontos teilst du dir mit allen anderen, die zugestimmt haben, und deine eigenen Anbieter werden weiterhin zuerst versucht. Aktiviere es nur, wenn du diesen Kompromiss akzeptierst.", - "confirm": "Verstanden — Verbindung nutzen", + "honesty": "Der gemeinsame Zugang ist ein einzelnes angemeldetes KI-Konto, das der Betreiber für alle auf diesem Server verbunden hat, nicht dein eigener Schlüssel. Anfragen darüber werden vom Anbieter standardmäßig zum Training genutzt und von keiner Auftragsverarbeitungsvereinbarung gedeckt, die Stunden- und Wochenlimits des Kontos teilst du dir mit allen anderen, die zugestimmt haben, und deine eigenen Anbieter werden weiterhin zuerst versucht. Aktiviere es nur, wenn du diesen Kompromiss akzeptierst.", + "confirm": "Verstanden, Verbindung nutzen", "cancel": "Abbrechen" }, "consent": { @@ -6324,8 +6324,8 @@ "withingsClientId": "Client-ID", "withingsClientSecret": "Client-Secret", "withingsCredentialsSaved": "Zugangsdaten gespeichert", - "withingsCredentialsSavedPlaceholder": "Gespeichert — neue eingeben zum Ersetzen", - "withingsCredentialsSavedPlaceholderSecret": "Gespeichert — neues eingeben zum Ersetzen", + "withingsCredentialsSavedPlaceholder": "Gespeichert. Neue eingeben zum Ersetzen", + "withingsCredentialsSavedPlaceholderSecret": "Gespeichert. Neues eingeben zum Ersetzen", "withingsSaveCredentials": "Speichern", "configured": "Konfiguriert", "withingsSync": "Jetzt synchronisieren", @@ -6340,7 +6340,7 @@ }, "withingsFullSyncResult": "{count} Messwerte vollständig synchronisiert", "withingsSyncFailed": "Sync fehlgeschlagen", - "withingsOauthConnected": "Withings verbunden — der erste Sync startet im Hintergrund.", + "withingsOauthConnected": "Withings verbunden. Der erste Sync startet im Hintergrund.", "withingsOauthFailed": "Withings-Verbindung fehlgeschlagen", "withingsOauthError": { "csrf1": "Die Sicherheitsprüfung ist fehlgeschlagen, weil das Browser-Cookie fehlte. Starte die Verbindung bitte erneut im selben Browser.", @@ -6365,8 +6365,8 @@ "whoopClientId": "Client-ID", "whoopClientSecret": "Client-Secret", "whoopCredentialsSaved": "Zugangsdaten gespeichert", - "whoopCredentialsSavedPlaceholder": "Gespeichert — neu eingeben zum Ersetzen", - "whoopCredentialsSavedPlaceholderSecret": "Gespeichert — neu eingeben zum Ersetzen", + "whoopCredentialsSavedPlaceholder": "Gespeichert. Neu eingeben zum Ersetzen", + "whoopCredentialsSavedPlaceholderSecret": "Gespeichert. Neu eingeben zum Ersetzen", "whoopSaveCredentials": "Speichern", "whoopSync": "Jetzt synchronisieren", "whoopFullSync": "Alle Daten synchronisieren", @@ -6381,7 +6381,7 @@ "whoopConnect": "Mit WHOOP verbinden", "whoopNoCredentials": "Bitte gib oben deine API-Zugangsdaten ein, um WHOOP zu verbinden.", "whoopBackfillInProgress": "Dein WHOOP-Verlauf wird im Hintergrund importiert…", - "whoopOauthConnected": "WHOOP verbunden — die erste Synchronisierung startet im Hintergrund.", + "whoopOauthConnected": "WHOOP verbunden. Die erste Synchronisierung startet im Hintergrund.", "whoopOauthFailed": "WHOOP-Verbindung fehlgeschlagen", "whoopOauthError": { "csrf1": "Die Sicherheitsprüfung ist fehlgeschlagen, weil das Browser-Cookie fehlte. Bitte starte die Verbindung im selben Browser erneut.", @@ -6395,14 +6395,14 @@ }, "fitbit": "Fitbit", "fitbitTag": "Fitbit & Pixel", - "fitbitDescription": "Verbinde Fitbit, um deine Fitbit- und Pixel-Watch-Werte zu synchronisieren — Gewicht, Herzfrequenz und mehr.", + "fitbitDescription": "Verbinde Fitbit, um deine Fitbit- und Pixel-Watch-Werte zu synchronisieren: Gewicht, Herzfrequenz und mehr.", "fitbitExperimentalBadge": "Experimentell", "fitbitCredentials": "API-Zugangsdaten", "fitbitClientId": "Client-ID", "fitbitClientSecret": "Client-Secret", "fitbitCredentialsSaved": "Zugangsdaten gespeichert", - "fitbitCredentialsSavedPlaceholder": "Gespeichert — neu eingeben zum Ersetzen", - "fitbitCredentialsSavedPlaceholderSecret": "Gespeichert — neu eingeben zum Ersetzen", + "fitbitCredentialsSavedPlaceholder": "Gespeichert. Neu eingeben zum Ersetzen", + "fitbitCredentialsSavedPlaceholderSecret": "Gespeichert. Neu eingeben zum Ersetzen", "fitbitSaveCredentials": "Speichern", "fitbitSync": "Jetzt synchronisieren", "fitbitFullSync": "Alle Daten synchronisieren", @@ -6417,18 +6417,18 @@ "fitbitConnect": "Mit Fitbit verbinden", "fitbitNoCredentials": "Bitte gib oben deine API-Zugangsdaten ein, um Fitbit zu verbinden.", "fitbitBackfillInProgress": "Dein Fitbit-Verlauf wird im Hintergrund importiert…", - "fitbitOauthConnected": "Fitbit verbunden — die erste Synchronisierung startet im Hintergrund.", + "fitbitOauthConnected": "Fitbit verbunden. Die erste Synchronisierung startet im Hintergrund.", "fitbitOauthFailed": "Fitbit-Verbindung fehlgeschlagen", "googleHealth": "Google Health", "googleHealthTag": "Fitbit & Pixel", "googleHealthBetaBadge": "Beta", - "googleHealthDescription": "Verbinde Fitbit, Pixel Watch und Fitbit Air über dein Google-Konto — Gewicht, Herzfrequenz, Schlaf und Aktivität. Das ersetzt die klassische Fitbit-Verbindung, die Google im September 2026 abschaltet.", + "googleHealthDescription": "Verbinde Fitbit, Pixel Watch und Fitbit Air über dein Google-Konto: Gewicht, Herzfrequenz, Schlaf und Aktivität. Das ersetzt die klassische Fitbit-Verbindung, die Google im September 2026 abschaltet.", "googleHealthCredentials": "API-Zugangsdaten", "googleHealthClientId": "Client-ID", "googleHealthClientSecret": "Client-Secret", "googleHealthCredentialsSaved": "Zugangsdaten gespeichert", - "googleHealthCredentialsSavedPlaceholder": "Gespeichert — zum Ersetzen neu eingeben", - "googleHealthCredentialsSavedPlaceholderSecret": "Gespeichert — zum Ersetzen neu eingeben", + "googleHealthCredentialsSavedPlaceholder": "Gespeichert. Zum Ersetzen neu eingeben", + "googleHealthCredentialsSavedPlaceholderSecret": "Gespeichert. Zum Ersetzen neu eingeben", "googleHealthSaveCredentials": "Speichern", "googleHealthSync": "Jetzt synchronisieren", "googleHealthSyncCheckStatus": "Status aktualisieren", @@ -6462,9 +6462,9 @@ "googleHealthConnect": "Mit Google verbinden", "googleHealthNoCredentials": "Bitte gib oben deine API-Zugangsdaten ein, um Google Health zu verbinden.", "googleHealthBackfillInProgress": "Dein Google-Health-Verlauf wird im Hintergrund importiert…", - "googleHealthReauthBanner": "Google hat die Verbindung ablaufen lassen — das passiert regelmäßig, solange deine OAuth-App im Testmodus bleibt. Verbinde neu, um die Synchronisierung fortzusetzen.", + "googleHealthReauthBanner": "Google hat die Verbindung ablaufen lassen. Das passiert regelmäßig, solange deine OAuth-App im Testmodus bleibt. Verbinde neu, um die Synchronisierung fortzusetzen.", "googleHealthReconnect": "Neu verbinden", - "googleHealthOauthConnected": "Google Health verbunden — die erste Synchronisierung startet im Hintergrund.", + "googleHealthOauthConnected": "Google Health verbunden. Die erste Synchronisierung startet im Hintergrund.", "googleHealthOauthFailed": "Verbindung zu Google Health fehlgeschlagen", "googleHealthOauthError": { "csrf1": "Die Sicherheitsprüfung ist fehlgeschlagen, weil das Browser-Cookie fehlte. Bitte starte die Verbindung im selben Browser erneut.", @@ -6499,10 +6499,10 @@ }, "integrationPill": { "connected": "Verbunden", - "errorReconnect": "Fehler — neu verbinden", + "errorReconnect": "Fehler: neu verbinden", "warningServerError": "Sync fehlgeschlagen", "failureCount": "{count}/{threshold}", - "parkedReconnect": "Pausiert — neu verbinden", + "parkedReconnect": "Pausiert: neu verbinden", "notConnected": "Nicht verbunden", "justNow": "gerade eben", "minutesAgo": "vor {count} min", @@ -6536,7 +6536,7 @@ "title": "Messwert-Tokens", "description": "Erzeuge ein Token, damit eine Waage, eine Uhr oder deine Hausautomatisierung Werte eintragen kann.", "detail": "Das Token wird nur einmal angezeigt.", - "scopeNote": "Es kann ausschließlich neue Werte in deine eigene Akte eintragen — deine Daten nicht lesen, nichts ändern oder löschen und kein weiteres Token erstellen. Werte werden als von einem externen Gerät gekennzeichnet, damit du sie später erkennst, und lassen sich jederzeit korrigieren.", + "scopeNote": "Es kann ausschließlich neue Werte in deine eigene Akte eintragen. Es kann deine Daten nicht lesen, nichts ändern oder löschen und kein weiteres Token erstellen. Werte werden als von einem externen Gerät gekennzeichnet, damit du sie später erkennst, und lassen sich jederzeit korrigieren.", "createFailed": "Das Token konnte nicht erstellt werden. Bitte versuche es erneut.", "namePlaceholder": "Name, z. B. Home Assistant" }, @@ -6557,7 +6557,7 @@ "namePlaceholder": "Name, z. B. Paperless-ngx" }, "tokenMintMovedDescription": "Tokens werden dort ausgestellt, wo sie gelten: oben für Messwerte, Trainings und Dokumente, oder im API-Endpoint eines Medikaments für genau dieses Medikament.", - "tokenCreated": "Token erstellt — kopiere ihn jetzt! Er wird nicht erneut angezeigt.", + "tokenCreated": "Token erstellt. Kopiere ihn jetzt! Er wird nicht erneut angezeigt.", "tokenCopy": "Token kopieren", "tokenCopied": "Token in die Zwischenablage kopiert", "tokenCopyFailed": "Token konnte nicht kopiert werden", @@ -6596,7 +6596,7 @@ "deleteAccountCta": "Konto löschen", "deleteAccountConfirmTitle": "Konto endgültig löschen?", "deleteAccountConfirmDescription": "Dein Konto, alle Gesundheitsdaten, Passkeys, Sessions und Audit-Einträge werden unwiderruflich gelöscht. Du wirst danach automatisch abgemeldet.", - "deleteAccountSuccess": "Konto wurde gelöscht — du wirst abgemeldet.", + "deleteAccountSuccess": "Konto wurde gelöscht. Du wirst abgemeldet.", "deleteAccountFailed": "Konto konnte nicht gelöscht werden", "deleteAccountFinal": "Endgültig löschen", "saved": "Gespeichert", @@ -6619,7 +6619,7 @@ "testing": "Teste…", "ok": "Verbunden (Latenz {latency} ms)", "errors": { - "credentials_rejected": "Zugangsdaten abgelehnt — Token prüfen", + "credentials_rejected": "Zugangsdaten abgelehnt. Token prüfen", "rate_limited": "Vom Upstream rate-limitiert", "timeout": "Request hat das Zeitlimit überschritten", "upstream_error": "Upstream hat einen Fehler gemeldet", @@ -6630,7 +6630,7 @@ "private_origin_not_approved": "Ziel im privaten Netz. Der Betreiber muss diesen Origin in NOTIFICATION_PRIVATE_ORIGINS eintragen", "private_origin_not_grantable": "Diese Adresse ist Link-local, eine Metadaten- oder eine unspezifizierte Adresse; keine Betreiber-Freigabe kann sie öffnen. Bitte die Adresse verwenden, auf der das Relay lauscht", "url_invalid": "URL ist ungültig", - "redirected": "Endpunkt leitet weiter — URL prüfen", + "redirected": "Endpunkt leitet weiter. URL prüfen", "endpoint_not_found": "Endpunkt unter der URL nicht gefunden", "credentials_unreadable": "Zugangsdaten nicht entschlüsselbar", "upstream_invalid_json": "Upstream-Antwort ist kein JSON", @@ -6641,7 +6641,7 @@ }, "notificationStatus": { "title": "Zustellstatus", - "description": "Status je Kanal — „Automatisch deaktiviert“ heißt: nach dauerhaften Fehlern gestoppt.", + "description": "Status je Kanal; „Automatisch deaktiviert“ heißt, dass nach dauerhaften Fehlern gestoppt wurde.", "emptyDescription": "Richte unter Einstellungen › Integrationen › Zustellkanäle einen Kanal ein.", "stateActive": "Aktiv", "stateAutoDisabled": "Automatisch deaktiviert", @@ -6667,7 +6667,7 @@ }, "healthRecord": { "title": "Gesundheitsakte exportieren", - "description": "Eine vollständige Akte für die ärztliche Vorlage — als PDF, als FHIR oder beides.", + "description": "Eine vollständige Akte für die ärztliche Vorlage, als PDF, als FHIR oder beides.", "format": "Format", "format_pdf": "PDF", "format_fhir": "Strukturiert (FHIR)", @@ -6699,7 +6699,7 @@ "createTitle": "Neuer Freigabe-Link", "createDescription": "Der Link ist schreibgeschützt und zeitlich begrenzt.", "label": "Bezeichnung", - "labelPlaceholder": "z. B. Dr. Schmidt — Jahres-Check-up", + "labelPlaceholder": "z. B. Dr. Schmidt, Jahres-Check-up", "range": "Tage Verlauf", "rangeHint": "Wie weit das geteilte Zeitfenster zurückreicht.", "expiry": "Läuft ab in (Tagen)", @@ -6719,7 +6719,7 @@ "statusRevoked": "Widerrufen", "statusExpired": "Abgelaufen", "inactiveTitle": "Widerrufen und abgelaufen ({count})", - "shownOnce": "Nur einmal sichtbar. Erfasse QR-Code und Passphrase jetzt — beide lassen sich später nicht wiederherstellen.", + "shownOnce": "Nur einmal sichtbar. Erfasse QR-Code und Passphrase jetzt. Beide lassen sich später nicht wiederherstellen.", "qrAlt": "QR-Code mit Freigabelink und Passphrase", "linkLabel": "Link", "passphraseLabel": "Passphrase", @@ -6730,12 +6730,12 @@ "attachTitle": "Dokumente anhängen", "attachButton": "Dokumente auswählen", "attachCount": "{count} von {max} ausgewählt", - "attachFrozen": "Die Dokumentenauswahl ist nach dem Erstellen des Links fest — Dokumente lassen sich danach weder hinzufügen noch entfernen.", + "attachFrozen": "Die Dokumentenauswahl ist nach dem Erstellen des Links fest. Dokumente lassen sich danach weder hinzufügen noch entfernen.", "attachRemove": "{title} entfernen", "exifNote": "Kamera-Metadaten (EXIF/GPS) werden beim Teilen aus JPEG-, PNG- und WebP-Bildern entfernt. PDF-, TIFF-, HEIC- und Office-Dateien werden unverändert übernommen.", "documentCount": "Angehängte Dokumente: {count}", "qrScanTitle": "Zum Öffnen auf einem anderen Gerät scannen", - "qrScanHint": "Richte eine Handykamera auf den Code, um die geteilte Akte zu öffnen — die Passphrase ist bereits enthalten.", + "qrScanHint": "Richte eine Handykamera auf den Code, um die geteilte Akte zu öffnen. Die Passphrase ist bereits enthalten.", "pickerTitle": "Dokumente anhängen", "pickerDescription": "Durchsuche deinen Tresor und wähle Dokumente zum Teilen. Bis zu {max}.", "pickerSearch": "Dokumente suchen", @@ -6748,7 +6748,7 @@ "statusNeedsReselect": "Inhalt neu wählen", "reselectReason": "Dieser Link lieferte einen Umfang, den niemand gewählt hatte, und wurde deshalb geschlossen. Lege einen neuen an und wähle den Inhalt.", "reselectAction": "Ersatz anlegen", - "createDetail": "Der Token wird nur einmal bei der Erstellung angezeigt — sichere ihn dann; er lässt sich nicht wiederherstellen.", + "createDetail": "Der Token wird nur einmal bei der Erstellung angezeigt. Sichere ihn dann; er lässt sich nicht wiederherstellen.", "activeDescription": "Deine geteilten Links, wann sie ablaufen und wie oft sie geöffnet wurden." }, "genderOther": "Divers", @@ -6757,10 +6757,10 @@ "nightscoutDescription": "Verbinde deine eigene Nightscout-Seite, um kontinuierliche Glukosewerte ins Glukose-Panel zu synchronisieren.", "nightscoutViewData": "Glukose ansehen", "nightscoutUrl": "Nightscout-URL", - "nightscoutUrlSavedPlaceholder": "Gespeichert — neue URL eingeben zum Ersetzen", + "nightscoutUrlSavedPlaceholder": "Gespeichert. Neue URL eingeben zum Ersetzen", "nightscoutToken": "API-Token", "nightscoutTokenOptional": "Optional bei einer öffentlichen Seite", - "nightscoutTokenSavedPlaceholder": "Gespeichert — neuen Token eingeben zum Ersetzen", + "nightscoutTokenSavedPlaceholder": "Gespeichert. Neuen Token eingeben zum Ersetzen", "nightscoutTokenHelp": "Füge einen Zugriffstoken aus deinen Nightscout-Admin-Tools ein. Leer lassen, wenn deine Seite öffentlich lesbar ist.", "nightscoutPrivateOperatorTitle": "Der Zugriff auf ein privates Nightscout benötigt die Freigabe der Serveradministration.", "nightscoutPrivateOperatorDescription": "Bitte die Serveradministration, genau diesen Nightscout-Ursprung freizugeben.", @@ -6781,7 +6781,7 @@ "polarClientId": "Client-ID", "polarClientSecret": "Client-Secret", "polarCredentialsSaved": "Zugangsdaten gespeichert", - "polarCredentialsSavedPlaceholder": "Gespeichert — neu eingeben zum Ersetzen", + "polarCredentialsSavedPlaceholder": "Gespeichert. Neu eingeben zum Ersetzen", "polarSaveCredentials": "Speichern", "polarUnavailable": "Polar ist auf diesem Server nicht konfiguriert. Füge oben deine eigenen Polar-OAuth-Zugangsdaten hinzu oder bitte deinen Administrator, die gemeinsame App zu konfigurieren.", "polarConnect": "Polar verbinden", @@ -6791,7 +6791,7 @@ "polarDisconnect": "Trennen", "polarDisconnectTitle": "Polar trennen?", "polarDisconnectDescription": "Künftige Synchronisierungen stoppen. Bereits importierte Werte bleiben in deinem Verlauf.", - "polarOauthConnected": "Polar verbunden — die erste Synchronisierung startet im Hintergrund.", + "polarOauthConnected": "Polar verbunden. Die erste Synchronisierung startet im Hintergrund.", "polarOauthFailed": "Polar-Verbindung fehlgeschlagen", "polarOauthError": { "csrf1": "Die Sicherheitsprüfung ist fehlgeschlagen, weil das Browser-Cookie fehlte. Bitte starte die Verbindung im selben Browser erneut.", @@ -6810,7 +6810,7 @@ "ouraClientId": "Client-ID", "ouraClientSecret": "Client-Secret", "ouraCredentialsSaved": "Zugangsdaten gespeichert", - "ouraCredentialsSavedPlaceholder": "Gespeichert — neu eingeben zum Ersetzen", + "ouraCredentialsSavedPlaceholder": "Gespeichert. Neu eingeben zum Ersetzen", "ouraSaveCredentials": "Speichern", "ouraUnavailable": "Oura ist auf diesem Server nicht konfiguriert. Füge oben deine eigenen Oura-OAuth-Zugangsdaten hinzu oder bitte deinen Administrator, die gemeinsame App zu konfigurieren.", "ouraConnect": "Oura verbinden", @@ -6820,7 +6820,7 @@ "ouraDisconnect": "Trennen", "ouraDisconnectTitle": "Oura trennen?", "ouraDisconnectDescription": "Künftige Synchronisierungen stoppen. Bereits importierte Werte bleiben in deinem Verlauf.", - "ouraOauthConnected": "Oura verbunden — die erste Synchronisierung startet im Hintergrund.", + "ouraOauthConnected": "Oura verbunden. Die erste Synchronisierung startet im Hintergrund.", "ouraOauthFailed": "Oura-Verbindung fehlgeschlagen", "ouraOauthError": { "csrf1": "Die Sicherheitsprüfung ist fehlgeschlagen, weil das Browser-Cookie fehlte. Bitte starte die Verbindung im selben Browser erneut.", @@ -6851,7 +6851,7 @@ } }, "integrationRedirectGuide": { - "intro": "Die Verbindung läuft über deine eigene {provider}-Entwickler-App — etwa 5 Minuten Einrichtung:", + "intro": "Die Verbindung läuft über deine eigene {provider}-Entwickler-App. Die Einrichtung dauert etwa 5 Minuten:", "step1": "Erstelle eine App im {provider}-Entwicklerportal.", "step2": "Setze deren Weiterleitungs-/Callback-URL auf:", "step3": "Trage die dort erhaltene Client-ID und das Client-Secret oben ein." @@ -6911,7 +6911,7 @@ }, "recovery": { "saveNow": "Speichere diese Wiederherstellungscodes jetzt", - "saveNowHint": "Jeder Code funktioniert einmal. Sie werden nur dieses eine Mal angezeigt — bewahre sie sicher auf. Wenn du deine Authenticator-App verlierst, ist ein Wiederherstellungscode der einzige Weg zurück.", + "saveNowHint": "Jeder Code funktioniert einmal. Sie werden nur dieses eine Mal angezeigt, bewahre sie sicher auf. Wenn du deine Authenticator-App verlierst, ist ein Wiederherstellungscode der einzige Weg zurück.", "download": "Herunterladen", "remainingOne": "{count} Wiederherstellungscode übrig.", "remainingOther": "{count} Wiederherstellungscodes übrig.", @@ -6939,7 +6939,7 @@ }, "passkeyNudge": { "title": "Füge einen Passkey für schnellere Anmeldung hinzu", - "body": "Mit Passkeys meldest du dich per Fingerabdruck, Gesicht oder Geräte-PIN an — ohne Passwort zum Merken." + "body": "Mit Passkeys meldest du dich per Fingerabdruck, Gesicht oder Geräte-PIN an, ohne Passwort zum Merken." }, "trustedDevices": { "title": "Vertrauenswürdige Geräte", @@ -6970,7 +6970,7 @@ "privacy": { "encryption": { "title": "Verschlüsselt gespeichert", - "summary": "Deine sensiblen Daten werden mit {algorithm} verschlüsselt gespeichert — über {columns} Felder in {models} Datensatztypen.", + "summary": "Deine sensiblen Daten werden mit {algorithm} verschlüsselt gespeichert: über {columns} Felder in {models} Datensatztypen.", "statement": "Deine sensiblen Daten werden mit AES-256-GCM verschlüsselt gespeichert." }, "stored": { @@ -6991,7 +6991,7 @@ }, "export": { "title": "Meine Daten herunterladen", - "description": "Deine Datensätze als CSV oder JSON — oder eine vollständige Akte für die Praxis.", + "description": "Deine Datensätze als CSV oder JSON oder eine vollständige Akte für die Praxis.", "openExport": "Export & Backup", "openHealthRecord": "Gesundheitsakte" }, @@ -7014,7 +7014,7 @@ "endpointLabel": "Connector-URL", "connectDescription": "Füge diese URL in die Einrichtung des eigenen Connectors deines Assistenten ein und autorisiere dich mit dem Token unten oder melde dich bei Aufforderung an.", "tokensTitle": "Connector-Tokens", - "tokensDescription": "Erzeuge ein Token für einen Assistenten — nur Lesezugriff, außer du erlaubst unten das Eintragen.", + "tokensDescription": "Erzeuge ein Token für einen Assistenten, nur mit Lesezugriff, außer du erlaubst unten das Eintragen.", "scopeNote": "Neue Tokens können nur deine eigenen Daten lesen. Schreibzugriff (health:write) vergibst du pro Token über den Schalter unten. Admin-Funktionen erreicht ein Token nie.", "writeScopeToggleLabel": "Eintragen erlauben (health:write)", "writeScopeNote": "Fügt den Scope health:write hinzu, damit der Assistent neue Messwerte und Stimmungseinträge in dein Konto eintragen kann. Jeder Schreibvorgang wird zuvor bestätigt. Das Token kann weiterhin keine vorhandenen Einträge löschen oder ändern, keine Medikamente bearbeiten und keine REST- oder Admin-Funktionen erreichen. Für reinen Lesezugriff ausgeschaltet lassen.", @@ -7038,7 +7038,7 @@ "stravaClientId": "Client-ID", "stravaClientSecret": "Client-Secret", "stravaCredentialsSaved": "Zugangsdaten gespeichert", - "stravaCredentialsSavedPlaceholder": "Gespeichert — neue eingeben zum Ersetzen", + "stravaCredentialsSavedPlaceholder": "Gespeichert. Neue eingeben zum Ersetzen", "stravaSaveCredentials": "Speichern", "stravaUnavailable": "Strava ist auf diesem Server nicht konfiguriert. Füge oben deine eigenen Strava-API-Zugangsdaten hinzu oder bitte deinen Administrator, die gemeinsame App zu konfigurieren.", "stravaConnect": "Strava verbinden", @@ -7048,7 +7048,7 @@ "stravaDisconnect": "Trennen", "stravaDisconnectTitle": "Strava trennen?", "stravaDisconnectDescription": "Künftige Synchronisierungen stoppen. Bereits importierte Aktivitäten bleiben in deinem Verlauf.", - "stravaOauthConnected": "Strava verbunden — die erste Synchronisierung startet im Hintergrund.", + "stravaOauthConnected": "Strava verbunden. Die erste Synchronisierung startet im Hintergrund.", "stravaOauthFailed": "Strava-Verbindung fehlgeschlagen", "stravaOauthError": { "csrf1": "Die Sicherheitsprüfung ist fehlgeschlagen, weil das Browser-Cookie fehlte. Bitte starte die Verbindung im selben Browser erneut.", @@ -7102,7 +7102,7 @@ }, "garminInfo": { "title": "Garmin", - "body": "Garmin hat hier keine direkte Verbindung. Verbinde über Apple Health (iOS) oder Google Health Connect (Android). Garmins proprietäre Werte — Body Battery, Training Load, HRV-Status, VO₂max — werden von Garmin an keine der beiden Plattformen weitergegeben.", + "body": "Garmin hat hier keine direkte Verbindung. Verbinde über Apple Health (iOS) oder Google Health Connect (Android). Garmins proprietäre Werte (Body Battery, Training Load, HRV-Status, VO₂max) werden von Garmin an keine der beiden Plattformen weitergegeben.", "docsLink": "Zur Anleitung" }, "glucoseReference": { @@ -7183,33 +7183,33 @@ "loadingStatus": "Status wird geladen…", "systemStatusLoadError": "System-Status konnte nicht geladen werden.", "systemStatusRetry": "Erneut versuchen", - "adminSettingsLoadError": "Admin-Einstellungen konnten nicht geladen werden. Schalter unten zeigen evtl. nicht den Live-Zustand — Seite neu laden.", + "adminSettingsLoadError": "Admin-Einstellungen konnten nicht geladen werden. Schalter unten zeigen evtl. nicht den Live-Zustand. Seite neu laden.", "hostMetrics": { "title": "Host-Auslastung", "load1": "Last (1m)", "memUsedPercent": "Speicher", "diskBusyPercent": "Disk-I/O", "last2hours": "Letzte 2 Stunden", - "empty": "Erfassung läuft — Daten erscheinen in 1–2 Minuten.", + "empty": "Erfassung läuft. Daten erscheinen in 1–2 Minuten.", "loadError": "Host-Metriken konnten nicht geladen werden. Bitte die Seite neu laden." }, "aiServerKey": { "title": "KI-Server-Schlüssel", "description": "Ein Betreiber-Schlüssel für Konten, die keinen eigenen hinterlegt haben.", - "byokHint": "Der eigene Schlüssel (BYOK, ChatGPT-Login oder lokaler Provider) hat immer Vorrang — der Server-Schlüssel ist die letzte Stufe der Provider-Kette.", + "byokHint": "Der eigene Schlüssel (BYOK, ChatGPT-Login oder lokaler Provider) hat immer Vorrang. Der Server-Schlüssel ist die letzte Stufe der Provider-Kette.", "consentHint": "Anfragen über den Server-Schlüssel erfordern die aktive KI-Einwilligung der Person; ohne Einwilligungsbeleg wird nichts gesendet.", "baseUrlHint": "Die Basis-URL bestimmt die API: eine Anthropic-URL wie https://api.anthropic.com/v1 wird erkannt, jeder andere Host wird über die OpenAI-kompatible API angesprochen.", "statusConfigured": "Eingerichtet", "statusNotConfigured": "Nicht eingerichtet", "keyLabel": "API-Schlüssel", "keyPlaceholder": "sk-...", - "keyPlaceholderSet": "Hinterlegt ({preview}) — neuen Schlüssel eingeben, um ihn zu ersetzen", + "keyPlaceholderSet": "Hinterlegt ({preview}). Neuen Schlüssel eingeben, um ihn zu ersetzen", "modelLabel": "Modell", "baseUrlLabel": "Basis-URL", "save": "Speichern", "remove": "Schlüssel entfernen", "removeTitle": "Server-Schlüssel entfernen?", - "removeBody": "Konten ohne eigenen Schlüssel verlieren die KI-Funktionen sofort. Der Schlüssel wird nach dem Speichern nirgends mehr angezeigt — zum Wiederherstellen brauchst du das Original.", + "removeBody": "Konten ohne eigenen Schlüssel verlieren die KI-Funktionen sofort. Der Schlüssel wird nach dem Speichern nirgends mehr angezeigt. Zum Wiederherstellen brauchst du das Original.", "removeConfirm": "Schlüssel entfernen", "saved": "KI-Server-Schlüssel gespeichert", "error": "Speichern des KI-Server-Schlüssels fehlgeschlagen", @@ -7246,7 +7246,7 @@ "title": "Auswertungs-Qualität", "loading": "Feedback-Zusammenfassung wird geladen…", "loadError": "Qualitätszusammenfassung konnte nicht geladen werden. Bitte die Seite neu laden.", - "empty": "Noch kein Feedback. Der Aggregator läuft täglich um 04:00 — sobald Nutzer Empfehlungen bewerten, erscheinen hier die Hilfreich-Quoten.", + "empty": "Noch kein Feedback. Der Aggregator läuft täglich um 04:00. Sobald Nutzer Empfehlungen bewerten, erscheinen hier die Hilfreich-Quoten.", "windowLabel": "Letzte {days} Tage", "generatedAtLabel": "Erstellt", "colSeverity": "Schweregrad", @@ -7261,7 +7261,7 @@ "title": "Coach-Feedback", "loading": "Coach-Feedback-Zusammenfassung wird geladen…", "loadError": "Coach-Feedback-Zusammenfassung konnte nicht geladen werden. Bitte die Seite neu laden.", - "empty": "Noch kein Coach-Feedback. Der Aggregator läuft täglich um 04:00 — sobald Nutzer Coach-Antworten bewerten, erscheinen hier die Hilfreich-Quoten.", + "empty": "Noch kein Coach-Feedback. Der Aggregator läuft täglich um 04:00. Sobald Nutzer Coach-Antworten bewerten, erscheinen hier die Hilfreich-Quoten.", "windowLabel": "Letzte {days} Tage", "generatedAtLabel": "Erstellt", "colPromptVersion": "Prompt-Version", @@ -7280,7 +7280,7 @@ "appSettingsDescription": "Globale Standardwerte für Registrierung, Sprache und Zeitzone neuer Konten.", "registrationEnabled": "Registrierung erlauben", "registrationEnabledDescription": "Wenn deaktiviert, können sich keine neuen Nutzer registrieren.", - "registrationOpenHint": "Die Registrierung ist offen — jeder, der diese Instanz erreichen kann, kann ein Konto anlegen. Schließe sie hier, sobald alle ein Konto haben.", + "registrationOpenHint": "Die Registrierung ist offen: Jeder, der diese Instanz erreichen kann, kann ein Konto anlegen. Schließe sie hier, sobald alle ein Konto haben.", "defaultLanguage": "Standard-Sprache", "defaultLanguageDescription": "Wird für neue Nutzer und als Fallback verwendet.", "defaultUserTimezone": "Standard-Zeitzone für neue Konten", @@ -7294,7 +7294,7 @@ "integrationWebPush": "Web Push", "offlineGeoLabel": "Geodaten", "offlineGeoEnabled": "Offline (GeoLite2)", - "offlineGeoFallback": "Online ({host}) — GeoLite2-Datenbanken einbinden und GEOLITE2_DIR setzen", + "offlineGeoFallback": "Online ({host}). GeoLite2-Datenbanken einbinden und GEOLITE2_DIR setzen", "offlineGeoOff": "Aus", "offlineGeoChosen": "Online ({host})", "apiGlobal": "API-Endpunkte und API-Tokens erlauben.", @@ -7331,7 +7331,7 @@ "webPushVapidGenerating": "Wird erzeugt…", "webPushVapidGenerated": "VAPID-Schlüssel erzeugt. Betreff speichern, um abzuschließen.", "webPushVapidGenerateFailed": "VAPID-Schlüssel konnten nicht erzeugt werden.", - "webPushVapidGenerateConfirm": "VAPID-Schlüssel sind bereits konfiguriert. Ein neues Schlüsselpaar macht alle Browser-Push-Abos ungültig — jedes Gerät muss sich neu anmelden. Fortfahren?", + "webPushVapidGenerateConfirm": "VAPID-Schlüssel sind bereits konfiguriert. Ein neues Schlüsselpaar macht alle Browser-Push-Abos ungültig, jedes Gerät muss sich neu anmelden. Fortfahren?", "webPushVapidGenerateConfirmTitle": "VAPID-Schlüssel neu erzeugen?", "webPushVapidRegenerate": "Neu erzeugen", "configured": "Konfiguriert", @@ -7387,8 +7387,8 @@ "createdToast": "Einladung erstellt", "createError": "Einladung konnte nicht erstellt werden.", "tokenTitle": "Einladungslink", - "tokenOnceHint": "Nur jetzt kopierbar — kopiere den Link oder lass den QR-Code scannen.", - "hashExplainer": "Gespeichert wird nur ein Hash des Links — er kann später nicht erneut angezeigt werden. Geht er verloren: Einladung widerrufen und neu erstellen.", + "tokenOnceHint": "Nur jetzt kopierbar. Kopiere den Link oder lass den QR-Code scannen.", + "hashExplainer": "Gespeichert wird nur ein Hash des Links, er kann später nicht erneut angezeigt werden. Geht er verloren: Einladung widerrufen und neu erstellen.", "copyLink": "Link kopieren", "copiedToast": "Link kopiert", "copyError": "Kopieren fehlgeschlagen.", @@ -7449,7 +7449,7 @@ "tokenName": "Name", "tokenPermissions": "Berechtigungen", "tokenPermissionAll": "Alle", - "tokenPermissionAllTooltip": "Wildcard-Berechtigung — dieses Token kann jede API-Route ansprechen.", + "tokenPermissionAllTooltip": "Wildcard-Berechtigung: Dieses Token kann jede API-Route ansprechen.", "tokenStatus": "Status", "tokenLastUsed": "Zuletzt benutzt", "tokenCreated": "Erstellt", @@ -7627,7 +7627,7 @@ "app-logs": { "title": "App-Logs", "subtitle": "Letzte strukturierte Wide-Events dieses Prozesses anzeigen.", - "processNote": "Es werden nur App-Prozess-Logs angezeigt — Worker-Logs landen in Loki, sofern die Integration konfiguriert ist.", + "processNote": "Es werden nur App-Prozess-Logs angezeigt; Worker-Logs landen in Loki, sofern die Integration konfiguriert ist.", "filterTraceId": "Trace-ID", "filterAction": "Aktion enthält…", "filterLevel": "Level", @@ -7662,7 +7662,7 @@ "loading": "Backups werden geladen…", "loadError": "Backups konnten nicht geladen werden.", "emptyTitle": "Noch keine Backups", - "emptyDescription": "Backups laufen automatisch jeden Sonntag um 03:00 Uhr — oder erstelle jetzt einen ersten Snapshot.", + "emptyDescription": "Backups laufen automatisch jeden Sonntag um 03:00 Uhr, oder erstelle jetzt einen ersten Snapshot.", "colUser": "Nutzer", "colType": "Typ", "typeWeeklyAuto": "Wöchentlich (auto)", @@ -7698,11 +7698,11 @@ "restoreTitle": "Aus Backup wiederherstellen", "restoreDescription": "Dies ersetzt ALLE aktuellen Daten von {username} mit dem Snapshot von {when}. Vorhandene Messungen, Medikamente, Einnahmen, Stimmungseinträge, Benachrichtigungs-Kanäle, Push-Abos und Telegram-Lösch-Aufträge werden entfernt.", "restoreInstanceSettingsLabel": "Instanzweite Einstellungen mitwiederherstellen", - "restoreInstanceSettingsHint": "Registrierung, MFA-Pflicht, Standardsprache, Modulverfügbarkeit, Benachrichtigungs- und KI-Konfiguration — aus dem Snapshot, gültig für alle auf dieser Installation. Leer lassen, um nur dieses Konto wiederherzustellen.", + "restoreInstanceSettingsHint": "Registrierung, MFA-Pflicht, Standardsprache, Modulverfügbarkeit, Benachrichtigungs- und KI-Konfiguration aus dem Snapshot, gültig für alle auf dieser Installation. Leer lassen, um nur dieses Konto wiederherzustellen.", "restorePromptLabel": "Tippe RESTORE zum Fortfahren", "previewTitle": "Inhalt der Sicherung", "previewLoading": "Inhalt wird gelesen…", - "previewUnavailable": "Inhalt konnte nicht gelesen werden — die Wiederherstellung bleibt möglich.", + "previewUnavailable": "Inhalt konnte nicht gelesen werden, die Wiederherstellung bleibt möglich.", "previewStillReading": "Diese Sicherung stammt aus einer früheren Version, deshalb wird ihr Inhalt vollständig gelesen. Bei einem großen Datenbestand dauert das eine Weile. Öffne diesen Dialog in ein paar Minuten noch einmal, dann steht er hier. Die Wiederherstellung hängt nicht davon ab.", "previewEmpty": "Die Datei enthält keine Datensätze.", "previewOther": "Weitere Datensätze", @@ -7745,7 +7745,7 @@ "restoreSkippedMedicationTarget": "Zielwert-Analyt einer Medikation", "restoreSkippedScheduleRevisionLink": "Abfolge der Schema-Zeiträume", "restoreSkippedAccountSetting": "Kontoeinstellung", - "restoreMissingTitle": "Wiederherstellung abgelehnt — die Datei ist unvollständig", + "restoreMissingTitle": "Wiederherstellung abgelehnt: Die Datei ist unvollständig", "restoreMissingDescription": "Das Manifest der Datei sagt, sie enthalte den folgenden Abschnitt, und sie enthält ihn nicht. Es wurde nichts geändert: Eine Wiederherstellung ersetzt eine ganze Datenklasse, ein fehlender Abschnitt hätte sie also geleert.", "restoreMissingRemedy": "Nimm eine Notfall-Sicherung oder exportiere das Konto erneut und lade die neue Datei hoch. Ein Abschnitt, den das Manifest ausdrücklich als weggelassen ausweist, ist etwas anderes und wird normal wiederhergestellt.", "restoreMissingDocuments": "Dokumente", @@ -7869,7 +7869,7 @@ "completed": "Abgeschlossen", "failed": "Fehlgeschlagen" }, - "coverageDetail": "Es werden nur Schlüssel-IDs und Anzahlen gezeigt — niemals Schlüsselmaterial.", + "coverageDetail": "Es werden nur Schlüssel-IDs und Anzahlen gezeigt, niemals Schlüsselmaterial.", "backupsTitle": "Schlüssel, die die Sicherungen noch brauchen", "backupsDescription": "Ein alter Schlüssel bleibt nötig, solange eine Sicherung unten ihn noch aufführt.", "backupsStoredLine": "Schlüssel {key}: {count} gespeicherte Kopien, die älteste vom {when}", @@ -7935,7 +7935,7 @@ "centralCodex": { "title": "Gemeinsame KI-Verbindung", "description": "Verbinde ein angemeldetes ChatGPT-Konto, das jede Nutzerin und jeder Nutzer dieses Servers für KI-Funktionen aktivieren kann.", - "honesty": "Dies ist ein einzelnes gemeinsames, angemeldetes KI-Konto — kein API-Schlüssel. Alle, die zustimmen, senden Anfragen darüber, sodass die Stunden- und Wochenlimits des Kontos unter ihnen geteilt werden; dieselben Limits speisen bereits den Coach. Abo-Anbieter dürfen die Inhalte zur Verbesserung ihrer Modelle verwenden, und keine Auftragsverarbeitungsvereinbarung deckt dies ab — daher ist es nie Standard und steht beim Lesen von Dokumenten hinter Anbietern ohne Training. Verbinde nur ein Konto, das du auf diese Weise teilen möchtest.", + "honesty": "Dies ist ein einzelnes gemeinsames, angemeldetes KI-Konto, kein API-Schlüssel. Alle, die zustimmen, senden Anfragen darüber, sodass die Stunden- und Wochenlimits des Kontos unter ihnen geteilt werden; dieselben Limits speisen bereits den Coach. Abo-Anbieter dürfen die Inhalte zur Verbesserung ihrer Modelle verwenden, und keine Auftragsverarbeitungsvereinbarung deckt dies ab. Daher ist es nie Standard und steht beim Lesen von Dokumenten hinter Anbietern ohne Training. Verbinde nur ein Konto, das du auf diese Weise teilen möchtest.", "statusConnected": "Verbunden", "statusDisconnected": "Nicht verbunden", "statusExpired": "Abgelaufen", @@ -7947,13 +7947,13 @@ "connectedSince": "Verbunden seit {when}", "connected": "Gemeinsame KI-Verbindung verknüpft", "disconnected": "Gemeinsame KI-Verbindung entfernt", - "error": "Etwas ist schiefgelaufen — bitte erneut versuchen" + "error": "Etwas ist schiefgelaufen. Bitte erneut versuchen" }, "failingJobs": { "title": "Hintergrundjobs", "description": "Queues, deren Jobs nach allen Wiederholungen aufgegeben haben.", "none": "In den letzten {hours} Stunden ist kein Job fehlgeschlagen.", - "unavailable": "Keine Job-Queue lesbar — dieses Deployment läuft ohne Hintergrund-Worker.", + "unavailable": "Keine Job-Queue lesbar. Dieses Deployment läuft ohne Hintergrund-Worker.", "countOne": "{count} Fehlschlag", "countFew": "{count} Fehlschläge", "countOther": "{count} Fehlschläge", @@ -8276,7 +8276,7 @@ }, "selfContextComplete": { "title": "Selbstauskunft gepflegt", - "description": "Alle vier Felder der Selbstauskunft ausgefüllt — der Coach kennt deinen Kontext." + "description": "Alle vier Felder der Selbstauskunft ausgefüllt. Der Coach kennt deinen Kontext." }, "sleepLog7": { "title": "7 Tage Schlafprotokoll", @@ -8298,7 +8298,7 @@ }, "hiddenCard": { "title": "Versteckter Erfolg", - "description": "Tracke fleißig weiter — vielleicht stolperst du darüber.", + "description": "Tracke fleißig weiter, vielleicht stolperst du darüber.", "ariaLabel": "Versteckter, gesperrter Erfolg" }, "hiddenUnlockToast": { @@ -8307,7 +8307,7 @@ "dashboardCard": { "title": "Zuletzt freigeschaltet", "viewAll": "Alle anzeigen", - "empty": "Noch keine Erfolge — trage weiter ein, um deinen ersten freizuschalten." + "empty": "Noch keine Erfolge. Trage weiter ein, um deinen ersten freizuschalten." } }, "notifications": { @@ -8490,7 +8490,7 @@ } }, "edit": { - "title": "Zielbereich bearbeiten — {metric}", + "title": "Zielbereich bearbeiten: {metric}", "description": "Passt den Zielbereich an, der in Charts, Insights und im Arztbericht verwendet wird. Werte in {unit}.", "derivedHint": "Diese Karte wird aus anderen Metriken abgeleitet. Bearbeite stattdessen die zugrundeliegenden Ziele (z. B. Blutdruck oder Gewicht).", "minLabel": "Min", @@ -8522,11 +8522,11 @@ "aboveTarget": "{delta} {unit} über Zielbereich", "belowTarget": "{delta} {unit} unter Zielbereich", "diastolic": "Diastolisch", - "glucoseFasting": "Glukose — nüchtern", - "glucosePostprandial": "Glukose — postprandial", - "glucoseRandom": "Glukose — beliebig", - "glucoseBedtime": "Glukose — vor dem Schlafen", - "glucoseUnspecified": "Glukose — ohne Angabe", + "glucoseFasting": "Glukose, nüchtern", + "glucosePostprandial": "Glukose, postprandial", + "glucoseRandom": "Glukose, beliebig", + "glucoseBedtime": "Glukose, vor dem Schlafen", + "glucoseUnspecified": "Glukose, ohne Angabe", "status": { "underweight": "Untergewicht", "normal": "Normal", @@ -8612,7 +8612,7 @@ "askMedicationName": "Bitte Medikament angeben, z. B. genommen Ramipril.", "medicationNotFoundExact": "Medikament nicht gefunden. Bitte Namen exakt wie in HealthLog senden.", "helpHeader": "Verfügbare Befehle:", - "helpBody": "/help — Diese Hilfe anzeigen\n/add — Einnahme erfassen\n/start — Bot starten\n\nTextbefehle:\ngenommen <Name> — Einnahme bestätigen\n\nÜber die Buttons in Erinnerungen:\n• Genommen — Einnahme bestätigen\n• 🕐 1h / 🕐 3h — Erinnerung verschieben\n• ⏭ Überspringen — Einnahme überspringen\n• ✓ Bestätigen — Verpasste Einnahme bestätigen", + "helpBody": "/help: Diese Hilfe anzeigen\n/add: Einnahme erfassen\n/start: Bot starten\n\nTextbefehle:\ngenommen <Name>: Einnahme bestätigen\n\nÜber die Buttons in Erinnerungen:\n• Genommen: Einnahme bestätigen\n• 🕐 1h / 🕐 3h: Erinnerung verschieben\n• ⏭ Überspringen: Einnahme überspringen\n• ✓ Bestätigen: Verpasste Einnahme bestätigen", "measureValuePrompt": "Antworte mit dem Wert, um ihn zu speichern (optional).", "buttonMeasureValue": "Wert…", "measureValueSaved": "Messwert gespeichert.", @@ -8638,7 +8638,7 @@ "lowStockReminders": { "title": "Vorrat niedrig: {medName}", "bodyToday": "Dein Vorrat an {medName} reicht keinen ganzen Tag mehr ({units} Einheiten übrig).", - "bodyReorder": "Dein Vorrat an {medName} ({units} Einheiten) ist um den {runsOutOn} aufgebraucht — bestelle bis zum {reorderBy} nach.", + "bodyReorder": "Dein Vorrat an {medName} ({units} Einheiten) ist um den {runsOutOn} aufgebraucht. Bestelle bis zum {reorderBy} nach.", "bodyLastDose": "Dein Vorrat an {medName} ({units} Einheiten) reicht noch etwa für die letzte Dosis. Aufgebraucht um den {runsOutOn}.", "bodyExpired": "{medName}: kein nutzbarer Bestand mehr. {units} Einheiten sind als abgelaufen markiert.", "bodyAsNeeded": "Von {medName} sind nur noch {units} Einheiten übrig. Bestelle nach, bevor du die nächste Dosis brauchst." @@ -8666,11 +8666,11 @@ "questionConditions": "Hast du chronische Erkrankungen, die der Coach kennen sollte?", "questionFocus": "Gibt es etwas Bestimmtes, worauf der Coach achten soll?", "questionAllergies": "Hast du Allergien oder Unverträglichkeiten?", - "questionAboutMe": "Magst du dem Coach etwas über dich erzählen — Alltag, Ziele, Kontext?" + "questionAboutMe": "Magst du dem Coach etwas über dich erzählen? Alltag, Ziele, Kontext?" }, "clinicianView": { "title": "Geteilte Gesundheitsakte", - "period": "Berichtszeitraum: {start} – {end}", + "period": "Berichtszeitraum: {start}–{end}", "expires": "Dieser Link läuft am {date} ab.", "provenance": "Dies ist eine schreibgeschützte Zusammenfassung, die von der betreffenden Person geteilt wurde, exportiert aus ihren selbst erfassten HealthLog-Daten. Die Werte sind selbst erhoben und können geräteübertragene Messwerte enthalten; behandeln Sie sie als von der Patientin/dem Patienten berichtet, nicht als klinische Untersuchung.", "labs": "Laborwerte", @@ -8694,7 +8694,7 @@ "strain": "Belastungswert", "score": "Wellness-Wert" }, - "footer": "Geteilt aus HealthLog — einem selbst gehosteten Gesundheits-Tracker.", + "footer": "Geteilt aus HealthLog, einem selbst gehosteten Gesundheits-Tracker.", "unlock": { "title": "Passphrase eingeben", "description": "Diese geteilte Gesundheitsakte ist geschützt. Geben Sie die erhaltene Passphrase ein, um sie anzuzeigen.", @@ -8782,10 +8782,10 @@ "generic": "Dein/e {metric} liegt in der Lutealphase etwa {delta} {unit} {dir} als in der Follikelphase.", "dirHigher": "höher", "dirLower": "niedriger", - "empty": "Noch nicht genug Zyklen und Messwerte für ein Phasenmuster. Logge weiter — das füllt sich, je länger deine Historie wird." + "empty": "Noch nicht genug Zyklen und Messwerte für ein Phasenmuster. Logge weiter, das füllt sich, je länger deine Historie wird." }, "crosstab": { - "description": "Wie sich jeder Messwert zwischen deiner Luteal- und Follikelphase vergleicht — auf deinen eigenen Daten.", + "description": "Wie sich jeder Messwert zwischen deiner Luteal- und Follikelphase vergleicht, auf deinen eigenen Daten.", "pairLabel": "{metric}: Luteal- vs. Follikelphase", "detail": "Luteal {lutealAvg} {unit} ({lutealDays} Tage) vs. Follikel {follicularAvg} {unit} ({follicularDays} Tage).", "metricRestingHeartRate": "Ruhepuls", @@ -8822,7 +8822,7 @@ }, "context": { "MENSTRUAL": "Die Hormonspiegel sind jetzt am niedrigsten, weshalb sich diese Tage wie ein ruhiger Neustart anfühlen können. Manche bemerken Krämpfe, leichteren Schlaf oder den Wunsch, einen Gang zurückzuschalten; andere kommen fast unverändert durch. All das liegt im normalen Rahmen, und wie es sich anfühlt, kann von Zyklus zu Zyklus wechseln.", - "FOLLICULAR": "Mit steigendem Östrogen beschreiben viele diese Tage als hell und offen — der Schlaf fällt oft leichter und der Kopf fühlt sich klarer an. Die Basaltemperatur bleibt meist im niedrigeren Bereich, bis kurz vor dem Eisprung. Die Länge dieser Phase schwankt am stärksten — von Person zu Person und von Zyklus zu Zyklus.", + "FOLLICULAR": "Mit steigendem Östrogen beschreiben viele diese Tage als hell und offen: Der Schlaf fällt oft leichter und der Kopf fühlt sich klarer an. Die Basaltemperatur bleibt meist im niedrigeren Bereich, bis kurz vor dem Eisprung. Die Länge dieser Phase schwankt am stärksten, von Person zu Person und von Zyklus zu Zyklus.", "OVULATORY": "Das Östrogen erreicht kurz vor dem Eisprung seinen Höhepunkt, oft begleitet von einem kurzen Stimmungshoch und einem leichten Anstieg der Basaltemperatur in den ein, zwei Tagen danach. Der Zervixschleim wird in diesem Fenster meist klarer und dehnbarer. Ein kurzes Ziehen auf einer Seite bemerken manche; viele spüren gar nichts, und beides ist völlig normal.", "LUTEAL": "Das Progesteron führt durch die zweite Zyklushälfte, und die Basaltemperatur liegt meist etwas höher als zuvor im Zyklus. Manche bemerken im Lauf der Tage Veränderungen bei Schlaf, Appetit, Stimmung oder Energie, während andere durchgehend ausgeglichen bleiben. Das Muster ist persönlich und sieht von Monat zu Monat oft anders aus." }, @@ -8909,8 +8909,8 @@ "ariaUnknown": "Noch kein aktiver Zyklus", "caption": "deines Zyklus", "firstPeriodCta": "Erste Periode erfassen", - "periodOverdue": "Deine Periode ist später als üblich — die Tageszählung pausiert, bis die nächste Periode erfasst ist.", - "periodOverdueDays": "Deine Periode ist {days} Tage später als üblich — die Tageszählung pausiert, bis die nächste Periode erfasst ist.", + "periodOverdue": "Deine Periode ist später als üblich. Die Tageszählung pausiert, bis die nächste Periode erfasst ist.", + "periodOverdueDays": "Deine Periode ist {days} Tage später als üblich. Die Tageszählung pausiert, bis die nächste Periode erfasst ist.", "logPeriodCta": "Periode erfassen" }, "calendar": { @@ -8922,7 +8922,7 @@ "prevMonth": "Vorheriger Monat", "nextMonth": "Nächster Monat", "loading": "Kalender wird geladen…", - "learning": "Wir lernen deinen Zyklus — erfasse mindestens drei volle Zyklen, dann füllen sich fruchtbares Fenster, Eisprung und Phasen. Bis dahin zeigt der Kalender nur, was du erfasst hast.", + "learning": "Wir lernen deinen Zyklus. Erfasse mindestens drei volle Zyklen, dann füllen sich fruchtbares Fenster, Eisprung und Phasen. Bis dahin zeigt der Kalender nur, was du erfasst hast.", "legendSymptom": "Symptome", "legendOvulationConfirmed": "Bestätigter Eisprung", "flowSpotting": "Schmierblutung", @@ -8935,7 +8935,7 @@ "predictions": { "title": "Was als Nächstes kommt", "nextPeriod": "Nächste Periode", - "nextPeriodWindow": "{low} – {high}", + "nextPeriodWindow": "{low}–{high}", "fertileWindow": "Fruchtbares Fenster", "ovulation": "Geschätzter Eisprung", "confidenceHigh": "Hoch", @@ -8944,7 +8944,7 @@ "stillLearning": "Noch am Lernen", "stillLearningBody": "Erfasse mindestens drei vollständige Zyklen, dann werden deine Prognosen genauer. Bis dahin ist dies eine grobe Schätzung.", "rawMode": "Prognose ist aus", - "rawModeBody": "Du hast Prognosen ausgeschaltet — es werden nur deine erfassten Daten gezeigt, ohne Vorhersage.", + "rawModeBody": "Du hast Prognosen ausgeschaltet. Es werden nur deine erfassten Daten gezeigt, ohne Vorhersage.", "none": "Noch keine Prognose. Erfasse eine Periode, um zu starten.", "ovulationConfirmed": "Eisprung (bestätigt)" }, @@ -8977,7 +8977,7 @@ "symptoms": "Symptome", "temperature": "Basaltemperatur", "temperatureDisturbed": "Messwert als gestört markieren", - "temperatureDisturbedHint": "Fieber, Krankheit, Alkohol oder eine späte Messung — wird von der Temperaturauswertung ausgeschlossen.", + "temperatureDisturbedHint": "Fieber, Krankheit, Alkohol oder eine späte Messung: wird von der Temperaturauswertung ausgeschlossen.", "ovulationTest": "Ovulationstest", "mucus": "Zervixschleim", "cervix": "Gebärmutterhals", @@ -9040,7 +9040,7 @@ "remindersDescription": "Perioden-Erinnerungen pro Kanal in den Benachrichtigungseinstellungen aktivieren.", "remindersLink": "Benachrichtigungseinstellungen", "fertileReminder": "Erinnerung an das fruchtbare Fenster", - "fertileReminderDescription": "Erhalte einige Tage vor deinem geschätzten fruchtbaren Fenster einen Hinweis. Standardmäßig aus — aktiviere sie pro Kanal in den Benachrichtigungseinstellungen." + "fertileReminderDescription": "Erhalte einige Tage vor deinem geschätzten fruchtbaren Fenster einen Hinweis. Standardmäßig aus. Aktiviere sie pro Kanal in den Benachrichtigungseinstellungen." }, "testResult": { "POSITIVE": "Positiv", @@ -9073,15 +9073,15 @@ "fieldInfo": { "bbt": "Deine Ruhetemperatur, morgens als Erstes vor dem Aufstehen gemessen. Nach dem Eisprung steigt sie leicht an (etwa 0,2–0,3 °C).", "bbtLabel": "Was ist die Basaltemperatur?", - "mucus": "Der Ausfluss verändert sich im Zyklus — von trocken oder klebrig zu cremig, dann wässrig und spinnbar rund um die fruchtbarsten Tage.", + "mucus": "Der Ausfluss verändert sich im Zyklus: von trocken oder klebrig zu cremig, dann wässrig und spinnbar rund um die fruchtbarsten Tage.", "mucusLabel": "Was ist Zervixschleim?", - "ovulationTest": "Ein Urintest für zu Hause, der den LH-Anstieg erkennt — den Hormonschub etwa 24–36 h vor dem Eisprung. Ein positives Ergebnis markiert die fruchtbarste Phase.", + "ovulationTest": "Ein Urintest für zu Hause, der den LH-Anstieg erkennt, also den Hormonschub etwa 24–36 h vor dem Eisprung. Ein positives Ergebnis markiert die fruchtbarste Phase.", "ovulationTestLabel": "Was ist ein Ovulationstest?", "spotting": "Leichte Blutung außerhalb der Periode.", "spottingLabel": "Was ist Schmierblutung zwischen den Perioden?", "pregnancyTest": "Ergebnis eines Schwangerschaftstests (hCG) für zu Hause.", "pregnancyTestLabel": "Was ist ein Schwangerschaftstest?", - "progesteroneTest": "Ein Test, der bestätigt, dass der Eisprung stattgefunden hat — das Progesteron steigt danach an.", + "progesteroneTest": "Ein Test, der bestätigt, dass der Eisprung stattgefunden hat. Das Progesteron steigt danach an.", "progesteroneTestLabel": "Was ist ein Progesterontest?", "intercourse": "Ob an diesem Tag Geschlechtsverkehr stattgefunden hat.", "intercourseLabel": "Was erfasst Geschlechtsverkehr?", @@ -9134,14 +9134,14 @@ "postpone": { "menuItem": "Verschieben…", "title": "Fälligkeit verschieben", - "description": "Verschiebt nur die aktuelle Fälligkeit — der reguläre Rhythmus bleibt unverändert.", + "description": "Verschiebt nur die aktuelle Fälligkeit, der reguläre Rhythmus bleibt unverändert.", "chip": "+{days} Tage", "dateLabel": "Neues Datum", "confirm": "Verschieben" }, "skip": { "heading": "Diese Fälligkeit überspringen", - "explainer": "Wird ehrlich als übersprungen festgehalten — nicht als erledigt. Das Intervall startet ab heute neu.", + "explainer": "Wird ehrlich als übersprungen festgehalten, nicht als erledigt. Das Intervall startet ab heute neu.", "action": "Überspringen", "confirmTitle": "Fälligkeit überspringen?" }, @@ -9282,7 +9282,7 @@ "localOcr": { "heading": "Scans auf diesem Gerät lesen", "description": "Liest das Foto auf deinem Gerät und sendet nur den erkannten Text an deinen Anbieter.", - "detail": "Nützlich, wenn dein KI-Anbieter keine Bilder lesen kann. Weniger genau — prüfe jeden Wert vor dem Speichern." + "detail": "Nützlich, wenn dein KI-Anbieter keine Bilder lesen kann. Weniger genau, prüfe jeden Wert vor dem Speichern." }, "sort": { "heading": "Sortierung", @@ -9326,7 +9326,7 @@ "sourceRangePlaceholder": "z. B. 3,5 - 5,0 oder < 5", "sourceRangeAdd": "+ Bereich aus dem Befund ergänzen", "sourceRangeHint": "Optional. Gilt nur für diesen Wert; dein gespeicherter Bereich bleibt unverändert.", - "sourceRangeUnparsed": "Wird so übernommen — daraus ließ sich kein Zahlenbereich lesen." + "sourceRangeUnparsed": "Wird so übernommen, daraus ließ sich kein Zahlenbereich lesen." }, "backToLabs": "Zurück zu den Laborwerten", "hasNote": "Notiz", @@ -9344,7 +9344,7 @@ "emptyDescription": "Füge einen Wert hinzu, um diesen Biomarker über die Zeit zu verfolgen.", "title": "Biomarker", "genericDescription": "Ein Laborwert, den du verfolgst. Erfasse Messwerte, um den Verlauf gegenüber dem Referenzbereich zu sehen.", - "valuesTitle": "{marker} — alle Werte", + "valuesTitle": "{marker}: alle Werte", "valuesDescription": "Jeder Messwert für diesen Biomarker. Bearbeite oder entferne einen Eintrag direkt.", "backToMarker": "Zurück zu {marker}", "latestResult": "Letztes Ergebnis" @@ -9364,7 +9364,7 @@ }, "biomarker": { "manageTitle": "Biomarker", - "managerDescription": "Marker einmal definieren — Einheit und Bereich gelten für jede Messung.", + "managerDescription": "Marker einmal definieren; Einheit und Bereich gelten dann für jede Messung.", "define": "Hinzufügen", "defineFirst": "Ersten Biomarker hinzufügen", "defineTitle": "Biomarker hinzufügen", @@ -9383,7 +9383,7 @@ "form": { "seedLabel": "Von einem gängigen Marker starten", "seedPlaceholder": "Marker wählen (optional)", - "seedHint": "Eine Auswahl füllt die Felder unten — passe den Bereich an dein Labor an.", + "seedHint": "Eine Auswahl füllt die Felder unten. Passe den Bereich an dein Labor an.", "name": "Name", "namePlaceholder": "z. B. LDL-Cholesterin", "unit": "Einheit", @@ -9397,7 +9397,7 @@ "upperPlaceholder": "Obere Grenze", "context": "Kontext", "contextPlaceholder": "Optionale Notiz zu diesem Marker", - "rangeHint": "Beide Grenzen sind optional — eine leer lassen für einen offenen Bereich (z. B. LDL < 116).", + "rangeHint": "Beide Grenzen sind optional. Eine leer lassen für einen offenen Bereich (z. B. LDL < 116).", "requiredError": "Name und Einheit sind erforderlich.", "rangeOrderError": "Die untere Grenze darf die obere nicht überschreiten.", "save": "Biomarker speichern", @@ -9453,36 +9453,36 @@ "bloodCount": "Blutbild" }, "desc": { - "total-cholesterol": "Das Gesamtcholesterin ist die Summe des Cholesterins über alle Lipoprotein-Partikel im Blut, einschließlich der LDL-, HDL- und Remnant-Fraktion. Cholesterin selbst ist ein unverzichtbarer Baustein für Zellmembranen, Hormone und Gallensäuren. Als einzelner Wert bleibt es ein grobes Maß, denn sowohl ein hoher HDL- als auch ein hoher LDL-Anteil heben die Summe — deshalb liest man es meist gemeinsam mit den Einzelfraktionen. Erfasst wird es vor allem im Rahmen der langfristigen kardiovaskulären Risikoeinschätzung.", - "ldl": "Das LDL-Cholesterin ist das von Low-Density-Lipoprotein-Partikeln transportierte Cholesterin — die Fraktion, die Cholesterin zu den Geweben bringt, es aber auch in den Gefäßwänden ablagern kann. Über Jahre trägt diese Ablagerung zur arteriosklerotischen Plaque bei, weshalb LDL einer der am genauesten beobachteten Lipidmarker ist. Eine geringere langfristige Belastung geht in der Regel mit einem niedrigeren kardiovaskulären Risiko einher. Bewertet wird es nach Risikokategorie, nicht gegen einen festen Normwert.", + "total-cholesterol": "Das Gesamtcholesterin ist die Summe des Cholesterins über alle Lipoprotein-Partikel im Blut, einschließlich der LDL-, HDL- und Remnant-Fraktion. Cholesterin selbst ist ein unverzichtbarer Baustein für Zellmembranen, Hormone und Gallensäuren. Als einzelner Wert bleibt es ein grobes Maß, denn sowohl ein hoher HDL- als auch ein hoher LDL-Anteil heben die Summe. Deshalb liest man es meist gemeinsam mit den Einzelfraktionen. Erfasst wird es vor allem im Rahmen der langfristigen kardiovaskulären Risikoeinschätzung.", + "ldl": "Das LDL-Cholesterin ist das von Low-Density-Lipoprotein-Partikeln transportierte Cholesterin, also die Fraktion, die Cholesterin zu den Geweben bringt, es aber auch in den Gefäßwänden ablagern kann. Über Jahre trägt diese Ablagerung zur arteriosklerotischen Plaque bei, weshalb LDL einer der am genauesten beobachteten Lipidmarker ist. Eine geringere langfristige Belastung geht in der Regel mit einem niedrigeren kardiovaskulären Risiko einher. Bewertet wird es nach Risikokategorie, nicht gegen einen festen Normwert.", "hdl": "Das HDL-Cholesterin ist das von High-Density-Lipoprotein-Partikeln transportierte Cholesterin, die überschüssiges Cholesterin aus den Geweben aufnehmen und zur Wiederverwertung oder Ausscheidung zur Leber zurückführen. Wegen dieser Transportfunktion wird es oft als die schützende Fraktion bezeichnet. Sehr niedrige Werte gehen tendenziell mit höherem kardiovaskulärem Risiko einher; ein künstliches Anheben hat das Risiko jedoch nicht zuverlässig gesenkt, weshalb man es als Marker und nicht als Zielgröße liest. In der Regel wird es zusammen mit LDL und Triglyzeriden beurteilt.", "triglycerides": "Triglyzeride sind die wichtigste Form von Fett im Blut, die sowohl aus der Nahrung stammt als auch von der Leber gebildet wird, und sie dienen als zentraler Energiespeicher. Nach Mahlzeiten steigen die Werte, daher wird die Probe für die Vergleichbarkeit meist nüchtern entnommen. Dauerhaft hohe Triglyzeride werden mit metabolischem und kardiovaskulärem Risiko in Verbindung gebracht und treten häufig gemeinsam mit Insulinresistenz und niedrigem HDL auf. Sie werden als ein Bestandteil des gesamten Lipidbilds gelesen.", "fasting-glucose": "Der Nüchternblutzucker ist die Zuckerkonzentration im Blut nach einer nächtlichen Nüchternphase und spiegelt wider, wie der Körper seinen Grundblutzucker ohne kürzliche Nahrungsaufnahme hält. Glukose ist der wichtigste unmittelbare Brennstoff des Körpers, und Insulin hält sie normalerweise in einem engen Bereich. Eine Nüchternmessung schließt den Effekt kürzlicher Mahlzeiten aus und ist damit ein Standardscreening dafür, wie die Glukoseregulation funktioniert. Er gehört zu den Markern, mit denen die Stoffwechselgesundheit über die Zeit beurteilt wird.", "hba1c": "Der HbA1c ist der Anteil des Hämoglobins in den roten Blutkörperchen, der an Glukose gebunden ist und sich im Verhältnis zur durchschnittlichen Blutzuckerbelastung anreichert. Da rote Blutkörperchen etwa drei Monate leben, gibt er den durchschnittlichen Blutzucker der vorangegangenen zwei bis drei Monate wieder und nicht einen einzelnen Augenblick. Das macht ihn zu einem stabilen, mahlzeitenunabhängigen Maß der Blutzuckereinstellung. Seine Aussagekraft kann durch Erkrankungen beeinträchtigt sein, die die Lebensdauer der roten Blutkörperchen verändern.", "tsh": "Das TSH (Thyreoidea-stimulierendes Hormon) wird von der Hirnanhangdrüse ausgeschüttet, um die Schilddrüse zur Hormonproduktion anzuregen, und es passt sich nach oben oder unten an, um diese im Gleichgewicht zu halten. Aufgrund dieses Regelkreises ist das TSH das empfindlichste Erstlinien-Screening der Schilddrüsenfunktion: Es bewegt sich meist, bevor die Schilddrüsenhormone selbst abweichen. Ein erhöhter oder erniedrigter Wert deutet auf eine Unter- oder Überfunktion hin und führt in der Regel zur direkten Bestimmung der Schilddrüsenhormone. Schwangerschaft und Alter verschieben den erwarteten Bereich.", - "ft3": "Das freie T3 (Trijodthyronin) ist die ungebundene, biologisch aktive Form des wirksameren Schilddrüsenhormons — der Anteil, der den Geweben zur Verfügung steht. Der größte Teil des zirkulierenden T3 ist an Trägerproteine gebunden und inaktiv, sodass der freie Anteil die tatsächliche Hormonverfügbarkeit widerspiegelt. Gemessen wird es zur Beurteilung der Schilddrüsenfunktion, besonders gemeinsam mit TSH und freiem T4, wenn Befunde unklar sind. Die Werte sind stark assayabhängig und werden im klinischen Zusammenhang gelesen.", + "ft3": "Das freie T3 (Trijodthyronin) ist die ungebundene, biologisch aktive Form des wirksameren Schilddrüsenhormons, also der Anteil, der den Geweben zur Verfügung steht. Der größte Teil des zirkulierenden T3 ist an Trägerproteine gebunden und inaktiv, sodass der freie Anteil die tatsächliche Hormonverfügbarkeit widerspiegelt. Gemessen wird es zur Beurteilung der Schilddrüsenfunktion, besonders gemeinsam mit TSH und freiem T4, wenn Befunde unklar sind. Die Werte sind stark assayabhängig und werden im klinischen Zusammenhang gelesen.", "ft4": "Das freie T4 (Thyroxin) ist die ungebundene Form des wichtigsten Hormons, das die Schilddrüse ins Blut abgibt; es dient als Reservoir, das die Gewebe bei Bedarf in das aktivere T3 umwandeln. Der freie Anteil spiegelt wider, was dem Körper tatsächlich zur Verfügung steht, unabhängig von der Menge der Trägerproteine. In der Regel wird es zusammen mit dem TSH bestimmt, um Probleme der Schilddrüse von Störungen der hypophysären Steuerung zu unterscheiden. Schwangerschaft und bestimmte Medikamente können es verschieben.", - "ferritin": "Ferritin ist das wichtigste Eisenspeicherprotein des Körpers, und sein Blutwert spiegelt grob die gesamten Eisenreserven wider. Ein niedriger Wert deutet auf erschöpfte Speicher hin, ein hoher Wert kann eine Eisenüberladung anzeigen — oder schlicht eine Entzündung, denn Ferritin steigt auch als Akute-Phase-Protein. Aus diesem Grund wird es oft zusammen mit anderen Eisenmarkern und Entzündungszeichen beurteilt. Es ist eines der zentralen Maße zur Einschätzung des Eisenstatus.", - "transferrin-saturation": "Die Transferrinsättigung ist der Prozentsatz des Transferrins — des Proteins, das Eisen durch das Blut transportiert –, der aktuell mit Eisen beladen ist. Sie verknüpft die Menge des zirkulierenden Eisens mit der Eisentransportkapazität und liefert damit eine Momentaufnahme der Eisenverfügbarkeit, die Ferritins Blick auf die Speicher ergänzt. Eine niedrige Sättigung deutet auf einen Eisenmangel hin, ein hoher Wert kann eine Überladung anzeigen. Sie wird zusammen mit Ferritin und dem gesamten Eisenpanel gelesen.", + "ferritin": "Ferritin ist das wichtigste Eisenspeicherprotein des Körpers, und sein Blutwert spiegelt grob die gesamten Eisenreserven wider. Ein niedriger Wert deutet auf erschöpfte Speicher hin, ein hoher Wert kann eine Eisenüberladung anzeigen oder schlicht eine Entzündung, denn Ferritin steigt auch als Akute-Phase-Protein. Aus diesem Grund wird es oft zusammen mit anderen Eisenmarkern und Entzündungszeichen beurteilt. Es ist eines der zentralen Maße zur Einschätzung des Eisenstatus.", + "transferrin-saturation": "Die Transferrinsättigung ist der Prozentsatz des Transferrins (des Proteins, das Eisen durch das Blut transportiert), der aktuell mit Eisen beladen ist. Sie verknüpft die Menge des zirkulierenden Eisens mit der Eisentransportkapazität und liefert damit eine Momentaufnahme der Eisenverfügbarkeit, die Ferritins Blick auf die Speicher ergänzt. Eine niedrige Sättigung deutet auf einen Eisenmangel hin, ein hoher Wert kann eine Überladung anzeigen. Sie wird zusammen mit Ferritin und dem gesamten Eisenpanel gelesen.", "vitamin-d": "Vitamin D wird als 25-Hydroxy-Vitamin-D gemessen, der zirkulierenden Speicherform und dem Standardmarker des gesamten Vitamin-D-Status. Der Körper bildet es in der dem Sonnenlicht ausgesetzten Haut und nimmt einen Teil über die Nahrung auf; es unterstützt den Kalziumhaushalt, die Knochengesundheit und die Immunfunktion. Die Werte schwanken mit Jahreszeit, geografischer Breite, Hauttyp und Nahrungsergänzung. Erfasst wird es, um über die Zeit einzuschätzen, ob die Speicher ausreichend gefüllt sind.", - "vitamin-b12": "Vitamin B12 (Cobalamin) ist ein essenzielles Vitamin, das vor allem aus tierischen Lebensmitteln stammt und größtenteils in der Leber gespeichert wird. Es wird für die Bildung roter Blutkörperchen, die DNA-Synthese und die Gesundheit des Nervensystems benötigt. Ein länger anhaltender Mangel — durch geringe Zufuhr oder gestörte Aufnahme — kann zu einer Blutarmut und nervenbedingten Beschwerden führen. Gemessen wird es zur Beurteilung des Ernährungsstatus, insbesondere dort, wo Zufuhr oder Aufnahme eingeschränkt sein können.", + "vitamin-b12": "Vitamin B12 (Cobalamin) ist ein essenzielles Vitamin, das vor allem aus tierischen Lebensmitteln stammt und größtenteils in der Leber gespeichert wird. Es wird für die Bildung roter Blutkörperchen, die DNA-Synthese und die Gesundheit des Nervensystems benötigt. Ein länger anhaltender Mangel (durch geringe Zufuhr oder gestörte Aufnahme) kann zu einer Blutarmut und nervenbedingten Beschwerden führen. Gemessen wird es zur Beurteilung des Ernährungsstatus, insbesondere dort, wo Zufuhr oder Aufnahme eingeschränkt sein können.", "folate": "Folat (Vitamin B9) ist ein B-Vitamin, das in grünem Blattgemüse, Hülsenfrüchten und angereicherten Lebensmitteln vorkommt und für die Bildung roter Blutkörperchen und die DNA-Synthese zentral ist. Es arbeitet eng mit Vitamin B12 zusammen, und ein Mangel an einem von beiden kann eine ähnliche Form der Blutarmut hervorrufen. Eine ausreichende Folatversorgung ist besonders rund um die frühe Schwangerschaft für die gesunde Entwicklung des Kindes wichtig. Gemessen wird es zur Beurteilung des Ernährungsstatus und der Ursache bestimmter Anämien.", "hs-crp": "Das hochsensitive CRP misst das C-reaktive Protein, einen Marker, den die Leber als Reaktion auf Entzündungen ausschüttet, mit einem Verfahren, das auf die für das kardiovaskuläre Risiko relevanten niedrigen Konzentrationen abgestimmt ist. Anders als das Standard-CRP für akute Infektionen erfasst die hochsensitive Variante die feine, chronische Entzündung, die mit Gefäßerkrankungen verbunden ist. Da jede kürzliche Infektion oder Verletzung den Wert anhebt, wird er außerhalb akuter Erkrankung beurteilt und oft mit einer Wiederholungsprobe bestätigt. Er wird als ein Beitrag zum gesamten kardiovaskulären Risiko gelesen.", "creatinine": "Kreatinin ist ein Abfallprodukt des normalen Muskelstoffwechsels, das die Nieren mit recht gleichbleibender Rate aus dem Blut filtern. Da die Produktion verhältnismäßig konstant ist, dient der Blutwert als praktisches Maß dafür, wie gut die Nieren Abfallstoffe ausscheiden. Die Werte werden auch von Muskelmasse, Flüssigkeitshaushalt und Ernährung beeinflusst, weshalb sie meist gemeinsam mit der geschätzten Filtrationsrate beurteilt werden. Es ist ein zentraler Marker der Nierenfunktion.", "egfr": "Die eGFR (geschätzte glomeruläre Filtrationsrate) schätzt, wie viel Blut die Nieren pro Minute filtern, berechnet aus dem Kreatinin zusammen mit Alter und Geschlecht. Sie übersetzt einen rohen Kreatininwert in ein unmittelbarer verständliches Maß der Nierenfunktion. Eine über die Zeit sinkende eGFR ist der wichtigste Weg, um chronische Nierenveränderungen einzustufen und zu verfolgen. Als Schätzwert wird sie als Trend und nicht als einzelner exakter Zahlenwert gelesen.", "alt": "Die ALT (Alanin-Aminotransferase) ist ein vorwiegend in den Leberzellen konzentriertes Enzym, das ins Blut freigesetzt wird, wenn diese Zellen belastet oder geschädigt sind. Da sie verhältnismäßig leberspezifisch ist, gehört sie zu den wichtigsten Markern, um eine Leberschädigung oder -entzündung zu erkennen. Die Werte können bei Fettleber, Virushepatitis, Alkohol oder bestimmten Medikamenten steigen. In der Regel wird sie zusammen mit der AST und den übrigen Markern des Leberpanels gelesen.", - "ast": "Die AST (Aspartat-Aminotransferase) ist ein Enzym, das in der Leber, aber auch in Muskel, Herz und roten Blutkörperchen vorkommt und bei einer Schädigung dieser Gewebe freigesetzt wird. Da sie weniger leberspezifisch ist als die ALT, werden beide gemeinsam beurteilt — ihr Verhältnis kann Hinweise auf Quelle und Art des Problems geben. Intensive körperliche Belastung oder eine Muskelverletzung können sie unabhängig von der Leber anheben. Sie ist eines der Standardenzyme des Leberpanels.", - "ggt": "Die GGT (Gamma-Glutamyltransferase) ist ein Enzym in der Leber und den Gallenwegen, das besonders bei einem gestörten Gallenfluss oder bei Alkoholexposition ansteigt. Häufig wird sie genutzt, um zu klären, warum ein anderer Lebermarker erhöht ist — etwa um eine Quelle in der Leber oder den Gallenwegen zu unterscheiden. Sie ist empfindlich, aber wenig spezifisch und wird daher im Zusammenhang mit dem übrigen Leberpanel gelesen. Sie ist einer von mehreren Markern zur Beurteilung der Leber- und Gallengesundheit.", + "ast": "Die AST (Aspartat-Aminotransferase) ist ein Enzym, das in der Leber, aber auch in Muskel, Herz und roten Blutkörperchen vorkommt und bei einer Schädigung dieser Gewebe freigesetzt wird. Da sie weniger leberspezifisch ist als die ALT, werden beide gemeinsam beurteilt; ihr Verhältnis kann Hinweise auf Quelle und Art des Problems geben. Intensive körperliche Belastung oder eine Muskelverletzung können sie unabhängig von der Leber anheben. Sie ist eines der Standardenzyme des Leberpanels.", + "ggt": "Die GGT (Gamma-Glutamyltransferase) ist ein Enzym in der Leber und den Gallenwegen, das besonders bei einem gestörten Gallenfluss oder bei Alkoholexposition ansteigt. Häufig wird sie genutzt, um zu klären, warum ein anderer Lebermarker erhöht ist, etwa um eine Quelle in der Leber oder den Gallenwegen zu unterscheiden. Sie ist empfindlich, aber wenig spezifisch und wird daher im Zusammenhang mit dem übrigen Leberpanel gelesen. Sie ist einer von mehreren Markern zur Beurteilung der Leber- und Gallengesundheit.", "sodium": "Natrium ist der wichtigste Elektrolyt in der Flüssigkeit außerhalb der Körperzellen und der zentrale Regler von Flüssigkeitshaushalt und Blutvolumen. Der Körper steuert es eng über Durst, Hormone und die Nieren, sodass der Blutwert eher das Gleichgewicht zwischen Wasser und Salz widerspiegelt als die Zufuhr allein. Abweichende Werte signalisieren meist eine Störung des Wasserhaushalts und nicht des Natriums selbst. Es ist ein Kernbestandteil des grundlegenden Stoffwechsel- und Elektrolytpanels.", "potassium": "Kalium ist der wichtigste Elektrolyt innerhalb der Körperzellen und für die Nervenleitung und den gleichmäßigen Rhythmus des Herzmuskels unverzichtbar. Sein Blutwert wird durch die Nieren und hormonelle Signale in einem engen Bereich gehalten, da sowohl hohe als auch niedrige Werte die elektrische Aktivität des Herzens stören können. Die Werte können durch Nierenfunktion, Flüssigkeitshaushalt und mehrere gängige Medikamente beeinflusst werden. Es ist ein Kernmaß des Elektrolytpanels.", "hemoglobin": "Hämoglobin ist das eisenhaltige Protein in den roten Blutkörperchen, das Sauerstoff in der Lunge bindet und zu den Geweben transportiert. Seine Konzentration ist das wichtigste Maß für die Sauerstofftransportkapazität des Blutes und der zentrale Marker zum Erkennen einer Blutarmut. Niedrige Werte können auf Blutverlust, Eisen- oder Vitaminmangel oder eine verringerte Bildung hinweisen, hohe Werte können auf Flüssigkeitsmangel oder sauerstoffarme Bedingungen folgen. Es ist ein Eckpfeiler des großen Blutbilds.", "hematocrit": "Der Hämatokrit ist der Anteil der roten Blutkörperchen am Blutvolumen, ausgedrückt als Prozentwert. Er bewegt sich eng mit dem Hämoglobin und gibt einen ergänzenden Blick auf die Erythrozytenmasse und die Sauerstofftransportkapazität des Blutes. Der Flüssigkeitshaushalt beeinflusst ihn, da Veränderungen des Plasmavolumens den Anteil verschieben, selbst wenn die Zahl der roten Blutkörperchen stabil bleibt. Er wird zusammen mit dem Hämoglobin und dem übrigen Blutbild gelesen.", "wbc": "Die Leukozytenzahl ist die Gesamtzahl der im Blut zirkulierenden Immunzellen, der mobilen Abwehr des Körpers gegen Infektionen. Sie steigt als Reaktion auf Infektion, Entzündung oder Stress und kann fallen, wenn das Knochenmark unterdrückt ist oder bei manchen Immunerkrankungen. Da sie mehrere unterschiedliche Zelltypen zusammenfasst, wird eine deutliche Veränderung oft durch ein Differenzialblutbild aufgeschlüsselt. Sie ist ein Kernbestandteil des großen Blutbilds.", "platelets": "Thrombozyten sind kleine Zellfragmente im Blut, die sich zusammenlagern und den ersten Pfropf bilden, der eine Blutung aus einem geschädigten Gefäß stoppt. Ihre Zahl spiegelt das Gleichgewicht zwischen Bildung im Knochenmark und Verbrauch oder Abbau wider. Eine niedrige Zahl kann die Blutungsneigung erhöhen, eine hohe Zahl kann auf eine Entzündung oder andere Reize folgen. Sie sind Teil des großen Blutbilds und ein grundlegendes Maß der Gerinnungsfähigkeit.", - "apob": "Apolipoprotein B ist das Strukturprotein, das jedes der atherogenen Lipoprotein-Partikel trägt; seine Messung zählt daher diese Partikel direkt und nicht das von ihnen transportierte Cholesterin. Da auf jedem LDL-, VLDL- und verwandten Partikel genau ein ApoB-Molekül sitzt, kann es kardiovaskuläres Risiko erfassen, das ein LDL-Cholesterinwert übersieht — besonders wenn Partikelzahl und Cholesteringehalt auseinandergehen. Aus diesem Grund wird es zunehmend genutzt, um die lipidbasierte Risikoeinschätzung zu verfeinern. Beurteilt wird es zusammen mit dem üblichen Lipidpanel.", + "apob": "Apolipoprotein B ist das Strukturprotein, das jedes der atherogenen Lipoprotein-Partikel trägt; seine Messung zählt daher diese Partikel direkt und nicht das von ihnen transportierte Cholesterin. Da auf jedem LDL-, VLDL- und verwandten Partikel genau ein ApoB-Molekül sitzt, kann es kardiovaskuläres Risiko erfassen, das ein LDL-Cholesterinwert übersieht, besonders wenn Partikelzahl und Cholesteringehalt auseinandergehen. Aus diesem Grund wird es zunehmend genutzt, um die lipidbasierte Risikoeinschätzung zu verfeinern. Beurteilt wird es zusammen mit dem üblichen Lipidpanel.", "lp-a": "Lipoprotein(a) ist ein LDL-ähnliches Partikel mit einem zusätzlich angehefteten Protein, dessen Spiegel weitgehend genetisch festgelegt ist und ein Leben lang recht stabil bleibt. Ein erhöhtes Lp(a) ist ein unabhängiger, vererbter Risikofaktor für Herz-Kreislauf-Erkrankungen und eine Verengung der Aortenklappe. Da es sich kaum verändert, wird es meist einmal bestimmt, um das lebenslange Risiko einer Person festzulegen, statt es wiederholt zu verfolgen. Es wird in molaren Einheiten angegeben und als Teil des gesamten kardiovaskulären Risikos gelesen.", - "fasting-insulin": "Das Nüchterninsulin ist der Spiegel des Insulins — des Hormons, das Glukose aus dem Blut in die Zellen schleust –, gemessen nach einer nächtlichen Nüchternphase. Zusammen mit dem Nüchternblutzucker hilft es, die Insulinresistenz abzuschätzen, also den Zustand, in dem der Körper mehr Insulin braucht, um den Blutzucker im Bereich zu halten. Ein hohes Nüchterninsulin bei normalem Blutzucker kann ein frühes Zeichen dafür sein, dass dieser Ausgleich im Gange ist. Gelesen wird es als Teil eines Stoffwechselbilds und nicht für sich allein.", - "omega-3-index": "Der Omega-3-Index ist der Anteil von EPA und DHA — den beiden langkettigen marinen Omega-3-Fettsäuren — an den Fettsäuren in den Membranen der roten Blutkörperchen. Da rote Blutkörperchen sich langsam erneuern, spiegelt er die langfristige Omega-3-Zufuhr wider und nicht eine kürzliche Mahlzeit. Ein höherer Index wurde in Beobachtungsstudien mit einem niedrigeren kardiovaskulären Risiko in Verbindung gebracht. Er wird als stabiler Marker des Omega-3-Status verfolgt, der über Monate auf die Ernährung reagiert." + "fasting-insulin": "Das Nüchterninsulin ist der Spiegel des Insulins (des Hormons, das Glukose aus dem Blut in die Zellen schleust), gemessen nach einer nächtlichen Nüchternphase. Zusammen mit dem Nüchternblutzucker hilft es, die Insulinresistenz abzuschätzen, also den Zustand, in dem der Körper mehr Insulin braucht, um den Blutzucker im Bereich zu halten. Ein hohes Nüchterninsulin bei normalem Blutzucker kann ein frühes Zeichen dafür sein, dass dieser Ausgleich im Gange ist. Gelesen wird es als Teil eines Stoffwechselbilds und nicht für sich allein.", + "omega-3-index": "Der Omega-3-Index ist der Anteil von EPA und DHA (den beiden langkettigen marinen Omega-3-Fettsäuren) an den Fettsäuren in den Membranen der roten Blutkörperchen. Da rote Blutkörperchen sich langsam erneuern, spiegelt er die langfristige Omega-3-Zufuhr wider und nicht eine kürzliche Mahlzeit. Ein höherer Index wurde in Beobachtungsstudien mit einem niedrigeren kardiovaskulären Risiko in Verbindung gebracht. Er wird als stabiler Marker des Omega-3-Status verfolgt, der über Monate auf die Ernährung reagiert." }, "apob": "Apolipoprotein B (ApoB)", "lp-a": "Lipoprotein(a)", @@ -9500,7 +9500,7 @@ "acceptImageOnly": "JPEG, PNG oder WebP", "extracting": "Befund wird gelesen…", "readingOnDevice": "Wird auf deinem Gerät gelesen…", - "localModeHint": "Wird auf deinem Gerät gelesen und als Text gesendet. Weniger genau — prüfe jeden Wert.", + "localModeHint": "Wird auf deinem Gerät gelesen und als Text gesendet. Weniger genau, prüfe jeden Wert.", "rangeFromScan": "Referenzbereich aus dem Scan übernommen", "rangeVerify": "Referenzbereich prüfen", "reviewTitle": "Vor dem Speichern prüfen", @@ -9515,12 +9515,12 @@ "dateLabel": "Datum", "refLowLabel": "Referenz unten", "refHighLabel": "Referenz oben", - "newBiomarker": "Neuer Biomarker — wird angelegt", + "newBiomarker": "Neuer Biomarker, wird angelegt", "linksExisting": "Verknüpft mit vorhandenem {name}", "duplicateWarning": "Ein passender Wert existiert bereits", "lowConfidence": "Prüfe diesen Wert", "lowConfidenceBadge": "Geringe Sicherheit", - "valueUnreadable": "Wert unleserlich — bitte manuell eingeben", + "valueUnreadable": "Wert unleserlich, bitte manuell eingeben", "saveSelected": "{count} ausgewählte speichern", "discardAll": "Alle verwerfen", "savedToast": "{count} Laborwerte gespeichert", @@ -9903,7 +9903,7 @@ }, "correlation": { "title": "Wie es verlief", - "learning": "Noch am Lernen — erfasse ein paar weitere Tage, um hier Muster zu sehen.", + "learning": "Noch am Lernen. Erfasse ein paar weitere Tage, um hier Muster zu sehen.", "preOnsetTitle": "Wie es sich ankündigte", "preOnsetBody": "Werte, die vor dem Beginn von deiner Baseline abwichen.", "nadirTitle": "Was sich änderte", @@ -9930,7 +9930,7 @@ "countOne": "Du hast in diesem Zeitraum 1 Episode erfasst.", "countOther": "Du hast in diesem Zeitraum {count} Episoden erfasst.", "typicalGap": "Typische Erholungslücke: {days} Tage zwischen Besserung und normalisierten Werten.", - "typicalGapWithDriver": "Typische Erholungslücke: {days} Tage — du fühlst dich meist besser, bevor sich {vital} normalisiert.", + "typicalGapWithDriver": "Typische Erholungslücke: {days} Tage. Du fühlst dich meist besser, bevor sich {vital} normalisiert.", "typicalGapLearning": "Noch ein paar abgeschlossene Episoden und hier erscheint eine typische Erholungslücke.", "none": "In diesem Zeitraum keine Episoden erfasst.", "analyze": "Erholungslücke analysieren" @@ -9991,8 +9991,8 @@ "stop": "Ich messe genug", "accepted": "Erinnerung gesetzt", "dismissed": "Okay, das schlage ich nicht noch einmal vor", - "stopped": "Verstanden — ich schlage keine Erinnerungen mehr vor", - "failed": "Hat nicht geklappt — bitte erneut versuchen", + "stopped": "Verstanden, ich schlage keine Erinnerungen mehr vor", + "failed": "Hat nicht geklappt. Bitte erneut versuchen", "cadence": { "weightDaily": "Wieg dich täglich, ungefähr zur selben Zeit", "bp722": "Miss deinen Blutdruck eine Woche lang zweimal täglich", @@ -10004,7 +10004,7 @@ "dismiss": "Jetzt nicht", "applied": "Hinzugefügt", "dismissed": "Verworfen", - "failed": "Konnte das nicht hinzufügen — bitte erneut versuchen", + "failed": "Konnte das nicht hinzufügen. Bitte erneut versuchen", "checkup": { "title": "Vorsorge-Erinnerung hinzufügen?" }, @@ -10032,9 +10032,9 @@ "reviewPrefix": "Check-in: {when}", "accept": "Plan übernehmen", "decline": "Ablehnen", - "accepted": "Plan übernommen — der Coach behält ihn im Blick.", + "accepted": "Plan übernommen. Der Coach behält ihn im Blick.", "declined": "Vorschlag abgelehnt.", - "failed": "Das hat nicht geklappt — bitte erneut versuchen.", + "failed": "Das hat nicht geklappt. Bitte erneut versuchen.", "markMet": "Ziel erreicht", "abandon": "Plan beenden", "remove": "Entfernen", @@ -10055,11 +10055,11 @@ } }, "refusal": { - "outOfScope": "Ich kann nur bei den Gesundheitsdaten in deinem Log helfen — Messwerte, Medikamente, Stimmung, Trends. Fragen außerhalb dieses Themas beantworte ich nicht.", - "promptInjection": "In deiner Nachricht stehen Anweisungen, die meine Vorgaben überschreiben sollen. Ich bin der HealthLog-Coach und fasse ausschließlich deine eigenen Gesundheitsdaten zusammen — formuliere deine Frage bitte in diesem Rahmen neu.", + "outOfScope": "Ich kann nur bei den Gesundheitsdaten in deinem Log helfen: Messwerte, Medikamente, Stimmung, Trends. Fragen außerhalb dieses Themas beantworte ich nicht.", + "promptInjection": "In deiner Nachricht stehen Anweisungen, die meine Vorgaben überschreiben sollen. Ich bin der HealthLog-Coach und fasse ausschließlich deine eigenen Gesundheitsdaten zusammen. Formuliere deine Frage bitte in diesem Rahmen neu.", "conversationPoisoned": "Eine frühere Nachricht in dieser Unterhaltung enthält Anweisungen, die meine Vorgaben überschreiben sollen. Beginne bitte eine neue Unterhaltung." }, - "noRecordedData": "Zu deiner Frage sind bei dir keine Messwerte erfasst, also kann ich dir dazu keine Zahl nennen. Sobald du etwas eingetragen hast, frag mich noch einmal — dann rechne ich mit deinen eigenen Werten.", + "noRecordedData": "Zu deiner Frage sind bei dir keine Messwerte erfasst, also kann ich dir dazu keine Zahl nennen. Sobald du etwas eingetragen hast, frag mich noch einmal, dann rechne ich mit deinen eigenen Werten.", "step": { "read": "Prüfe: {domain}", "readWindow": "Prüfe: {domain}, {window}", @@ -10272,7 +10272,7 @@ }, "mentalHealth": { "pageTitle": "Seelisches Wohlbefinden", - "pageDescription": "Vier validierte, freiwillige Selbsttests — aussagekräftig ist der Verlauf, nicht ein einzelner Wert.", + "pageDescription": "Vier validierte, freiwillige Selbsttests. Aussagekräftig ist der Verlauf, nicht ein einzelner Wert.", "attributionLabel": "Quelle", "attributionShow": "Quelle und Lizenz für {instrument}", "choosePrompt": "Check-in auswählen", @@ -10307,7 +10307,7 @@ "2": "Sehr erschwert", "3": "Extrem erschwert" }, - "functionalOptionalHint": "Optional — du kannst auch ohne Antwort auf diese Frage absenden.", + "functionalOptionalHint": "Optional: Du kannst auch ohne Antwort auf diese Frage absenden.", "result": { "title": "Dein Ergebnis", "totalLabel": "Gesamtwert", @@ -10349,7 +10349,7 @@ }, "crisis": { "title": "Du musst das nicht allein durchstehen", - "intro": "Du hast Gedanken angegeben, lieber tot zu sein oder dir etwas anzutun. Es gibt jetzt sofort Unterstützung — sich zu melden ist ein Zeichen von Stärke.", + "intro": "Du hast Gedanken angegeben, lieber tot zu sein oder dir etwas anzutun. Es gibt jetzt sofort Unterstützung. Sich zu melden ist ein Zeichen von Stärke.", "ifDanger": "Wenn du in unmittelbarer Gefahr bist, ruf jetzt {emergency} an.", "resourcesTitle": "Menschen, die helfen können" }, @@ -10497,7 +10497,7 @@ }, "openDetail": "Details anzeigen", "historyLoadError": "Dein Testverlauf konnte nicht geladen werden", - "historyLoadErrorHint": "Das heißt nicht, dass keine Ergebnisse vorliegen — die Liste konnte nicht abgerufen werden. Versuche es erneut.", + "historyLoadErrorHint": "Das heißt nicht, dass keine Ergebnisse vorliegen. Die Liste konnte nicht abgerufen werden. Versuche es erneut.", "privacyNote": "Deine Antworten sind verschlüsselt gespeichert und erreichen den KI-Coach nicht." }, "records": { @@ -11186,7 +11186,7 @@ "genericDescription": "Ein Messwert, den du verfolgst. Erfasse Werte, um ihn über die Zeit zu beobachten.", "emptyTitle": "Noch keine Werte", "emptyDescription": "Erfasse deinen ersten Wert, um diese Metrik darzustellen.", - "valuesTitle": "{metric} — alle Werte", + "valuesTitle": "{metric}: alle Werte", "valuesDescription": "Alle erfassten Werte dieser Metrik.", "backToMetric": "Zurück zu {metric}" } @@ -11233,7 +11233,7 @@ "lastAttemptReason": { "unitMismatch": "Die übermittelten Werte entsprachen nicht den Einheiten, die diese App für diese Nährstoffe erwartet, daher konnten sie nicht gespeichert werden.", "valueOutOfRange": "Die übermittelten Mengen lagen höher, als diese App plausibel speichern kann, daher konnten sie nicht gesichert werden.", - "dayInvalid": "Die Einträge trugen ein Datum, das der Server nicht akzeptieren konnte. Das kann passieren, wenn Uhrzeit oder Zeitzone auf der sendenden Seite falsch eingestellt sind — das lohnt sich zu prüfen.", + "dayInvalid": "Die Einträge trugen ein Datum, das der Server nicht akzeptieren konnte. Das kann passieren, wenn Uhrzeit oder Zeitzone auf der sendenden Seite falsch eingestellt sind. Das lohnt sich zu prüfen.", "upsertFailed": "Diese Einträge haben den Server erreicht, aber ein Problem auf unserer Seite hat verhindert, dass sie gespeichert wurden. Du musst nichts weiter tun.", "unknown": "Diese Einträge sind angekommen, konnten aber nicht gespeichert werden." } @@ -11252,7 +11252,7 @@ "emptyTitle": "Noch keine Mikronährstoffdaten synchronisiert", "loadError": "Deine Nährstoffdaten konnten nicht geladen werden" }, - "sparseNote": "Ein niedriger Wert bedeutet hier meist lückenhafte Erfassung, keinen Mangel — die Tagessummen aus Apple Health spiegeln wider, was deine Apps erfasst haben, nicht die gesamte Nahrungsaufnahme." + "sparseNote": "Ein niedriger Wert bedeutet hier meist lückenhafte Erfassung, keinen Mangel. Die Tagessummen aus Apple Health spiegeln wider, was deine Apps erfasst haben, nicht die gesamte Nahrungsaufnahme." }, "daily": { "line": { @@ -11279,27 +11279,27 @@ }, "syncIssue": { "title": "Synchronisierung braucht Aufmerksamkeit", - "body": "{integration} synchronisiert nicht — verbinde neu, um deine Daten aktuell zu halten." + "body": "{integration} synchronisiert nicht. Verbinde neu, um deine Daten aktuell zu halten." }, "coachCheckin": { "title": "Zeit, einen Plan anzuschauen", - "body": "Es ist etwa eine Woche her, seit du diesen Plan gesetzt hast — behalte ihn, passe ihn an oder lass ihn los. Ganz ohne Druck.", - "bodyPlan": "Vor etwa einer Woche hast du dir vorgenommen: „{plan}“. Behalte es, passe es an oder lass es los — ganz ohne Druck.", + "body": "Es ist etwa eine Woche her, seit du diesen Plan gesetzt hast. Behalte ihn, passe ihn an oder lass ihn los. Ganz ohne Druck.", + "bodyPlan": "Vor etwa einer Woche hast du dir vorgenommen: „{plan}“. Behalte es, passe es an oder lass es los, ganz ohne Druck.", "adjustPrompt": "Ich möchte meinen Check-in-Plan anpassen.", "adjustPromptPlan": "Ich möchte diesen Plan anpassen: „{plan}“" }, "tensionWindow": { "title": "Vielleicht eine angespannte Phase", "body": { - "morning": "Dein Puls lag heute Vormittag über längere Zeit über deinem Ruhewert, während du ruhig warst — möglicherweise etwas Anspannung.", - "afternoon": "Dein Puls lag heute Nachmittag über längere Zeit über deinem Ruhewert, während du ruhig warst — möglicherweise etwas Anspannung.", - "evening": "Dein Puls lag heute Abend über längere Zeit über deinem Ruhewert, während du ruhig warst — möglicherweise etwas Anspannung.", - "night": "Dein Puls lag in der Nacht über längere Zeit über deinem Ruhewert, während du ruhig warst — möglicherweise etwas Anspannung." + "morning": "Dein Puls lag heute Vormittag über längere Zeit über deinem Ruhewert, während du ruhig warst, möglicherweise etwas Anspannung.", + "afternoon": "Dein Puls lag heute Nachmittag über längere Zeit über deinem Ruhewert, während du ruhig warst, möglicherweise etwas Anspannung.", + "evening": "Dein Puls lag heute Abend über längere Zeit über deinem Ruhewert, während du ruhig warst, möglicherweise etwas Anspannung.", + "night": "Dein Puls lag in der Nacht über längere Zeit über deinem Ruhewert, während du ruhig warst, möglicherweise etwas Anspannung." } }, "ecgNewRecording": { "title": "Neue EKG-Aufzeichnung", - "body": "Dein Gerät hat ein neues EKG aufgezeichnet — bereit zum Ansehen.", + "body": "Dein Gerät hat ein neues EKG aufgezeichnet, bereit zum Ansehen.", "bodyVerdict": "Dein Gerät hat ein neues EKG aufgezeichnet und meldet: {verdict}.", "verdict": { "irregular": "einen möglichen unregelmäßigen Rhythmus", @@ -11314,14 +11314,14 @@ }, "body": { "below": "Bis {time} stehst du bei {today} Schritten. An einem üblichen Tag sind es um diese Zeit etwa {typical}.", - "above": "Bis {time} stehst du bei {today} Schritten — mehr als die {typical}, die um diese Zeit für dich üblich sind." + "above": "Bis {time} stehst du bei {today} Schritten, mehr als die {typical}, die um diese Zeit für dich üblich sind." } }, "upcomingVisit": { "title": "Termin steht an", - "bodyToday": "{what} — heute", - "bodyTomorrow": "{what} — morgen", - "bodyDayAfterTomorrow": "{what} — übermorgen" + "bodyToday": "{what}, heute", + "bodyTomorrow": "{what}, morgen", + "bodyDayAfterTomorrow": "{what}, übermorgen" } }, "action": { @@ -11340,7 +11340,7 @@ "scoreLabel": "Gesundheitsscore", "deltaVsBaseline": "{delta} ggü. deinem Ausgangswert", "deltaFlat": "Im Bereich deines Ausgangswerts", - "sleepPending": "Der Schlaf von letzter Nacht fehlt noch — der heutige Wert ist vorläufig.", + "sleepPending": "Der Schlaf von letzter Nacht fehlt noch, der heutige Wert ist vorläufig.", "worthALook": "Einen Blick wert", "allClear": "Heute braucht nichts deine Aufmerksamkeit.", "ringLink": "{metric}-Details öffnen", @@ -11379,11 +11379,11 @@ }, "record": { "title": "Neue Bestmarke: {metric}", - "body": "Heute ein persönlicher Bestwert für {metric} — ganz ruhig festgehalten, du musst nichts tun." + "body": "Heute ein persönlicher Bestwert für {metric}, ganz ruhig festgehalten, du musst nichts tun." }, "returnToBaseline": { "title": "Wieder im Bereich: {metric}", - "body": "{metric} liegt wieder in deinem gewohnten Bereich. Was auch immer es war — es ist vorbei." + "body": "{metric} liegt wieder in deinem gewohnten Bereich. Was auch immer es war, es ist vorbei." }, "sustainedInRange": { "week1": { @@ -11594,7 +11594,7 @@ "errorScope": "So lassen sich diese Bereiche nicht teilen. Wähle mindestens einen Bereich aus oder teile die gesamte Akte.", "errorManageBrowserOnly": "Verwaltenden Zugriff kannst du nur im Browser vergeben.", "errorStepUp": "Bestätige deinen zweiten Faktor und versuche es erneut.", - "errorOffline": "Das hat den Server nicht erreicht. Deine Einladung steht noch hier — prüfe deine Verbindung und versuche es erneut." + "errorOffline": "Das hat den Server nicht erreicht. Deine Einladung steht noch hier. Prüfe deine Verbindung und versuche es erneut." }, "given": { "title": "Wer meine Akte öffnen kann", @@ -11914,7 +11914,7 @@ }, "actionError": { "retry": "Erneut versuchen", - "offline": "Das hat den Server nicht erreicht. Es hat sich nichts geändert — prüfe deine Verbindung und versuche es erneut.", + "offline": "Das hat den Server nicht erreicht. Es hat sich nichts geändert. Prüfe deine Verbindung und versuche es erneut.", "rateLimited": "Zu viele Versuche hintereinander. Warte eine Minute und versuche es erneut.", "acceptExpired": "Diese Einladung ist abgelaufen. Bitte um eine neue.", "acceptWithdrawn": "Diese Einladung wurde zurückgezogen.", @@ -11926,7 +11926,7 @@ "notFound": "Diesen Zugriff gibt es nicht mehr.", "revokeFailed": "Der Zugriff konnte nicht beendet werden.", "renounceFailed": "Der Zugriff konnte nicht zurückgegeben werden.", - "profileNotFound": "Dieses Profil gibt es nicht mehr — es wurde vielleicht schon gelöscht, oder dein Zugriff darauf ist beendet.", + "profileNotFound": "Dieses Profil gibt es nicht mehr. Es wurde vielleicht schon gelöscht, oder dein Zugriff darauf ist beendet.", "deleteProfileFailed": "Das Profil konnte nicht gelöscht werden.", "removeGuardianFailed": "Dieser Zugriff konnte nicht beendet werden." }, @@ -11983,7 +11983,7 @@ "created": "Termin gespeichert", "updated": "Termin aktualisiert", "saveFailed": "Termin konnte nicht gespeichert werden.", - "checkupNotClosed": "Termin gespeichert. Die Vorsorge bleibt offen — dafür reicht deine Freigabe nicht.", + "checkupNotClosed": "Termin gespeichert. Die Vorsorge bleibt offen, dafür reicht deine Freigabe nicht.", "status": { "planned": "Geplant", "done": "Stattgefunden", @@ -12000,7 +12000,7 @@ "dateDerivesStatusHint": "Ein Datum in der Zukunft ist ein gebuchter Termin.", "status": "Status", "practitioner": "Praxis oder Arzt", - "practitionerHint": "Optional — du kannst den Namen später nachtragen.", + "practitionerHint": "Optional, du kannst den Namen später nachtragen.", "practitionerNone": "Keine Angabe", "practitionerSearch": "Name oder Praxis suchen", "practitionerNoMatch": "Kein Eintrag gefunden.", @@ -12058,7 +12058,7 @@ }, "practitioners": { "title": "Praxen und Ärzte", - "description": "Dein eigenes Adressbuch — einmal tippen, überall auswählen.", + "description": "Dein eigenes Adressbuch: einmal tippen, überall auswählen.", "linkLabel": "Adressbuch", "searchPlaceholder": "Name, Praxis oder Fach suchen", "loadError": "Adressbuch konnte nicht geladen werden.", @@ -12260,15 +12260,11 @@ "rugLegend": "Punkte unter der Achse markieren Tage mit Einträgen, ein Ring einen auffälligen Tag.", "sheetExpand": "Auf volle Höhe aufziehen", "sheetShrink": "Verkleinern", - "usualLabel": "Deine 30 Tage davor", "valuesLegend": "Punkt für diesen Tag, Strich für die 30 Tage davor", "valuesAllOne": "Alle Werte", "valuesAllFew": "Alle {count} Werte", "valuesAllOther": "Alle {count} Werte", "valuesFewer": "Weniger Werte", - "countValuesOne": "1 Wert", - "countValuesFew": "{count} Werte", - "countValuesOther": "{count} Werte", "countEntriesOne": "1 Eintrag", "countEntriesFew": "{count} Einträge", "countEntriesOther": "{count} Einträge", @@ -12308,7 +12304,6 @@ "subtitle": "Was wann war, neben deinen Werten.", "standing": "Dauerhaft", "startUnknown": "Beginn unbekannt", - "openDay": "{date} öffnen", "zoom": { "all": "Alles", "year": "12 Monate", diff --git a/messages/en.json b/messages/en.json index 8b2c4bd08..76a96987e 100644 --- a/messages/en.json +++ b/messages/en.json @@ -167,7 +167,7 @@ "anamnesisShiftSchedule": "Work schedule", "anamnesisColFact": "Profile item", "anamnesisColValue": "Recorded value", - "subtitle": "HealthLog — Personal Health Report", + "subtitle": "HealthLog: Personal Health Report", "patient": "Patient", "dateOfBirth": "Date of birth", "gender": "Gender", @@ -213,18 +213,18 @@ "contacts": "Emergency contacts", "notes": "Additional notes" }, - "vitalsTitle": "Vital signs — Summary", + "vitalsTitle": "Vital signs: summary", "colParameter": "Parameter", "colCurrent": "Current", "colAvgPeriod": "Avg. period", "colMin": "Min", "colMax": "Max", "colN": "n", - "bpClassificationTitle": "Blood pressure — ESH classification (2023)", + "bpClassificationTitle": "Blood pressure: ESH classification (2023)", "avgBp": "Average blood pressure", "classification": "Classification", "bmiTitle": "Body Mass Index (BMI)", - "bmiRow": "BMI: {bmi} kg/m² — Classification: {class} (WHO)", + "bmiRow": "BMI: {bmi} kg/m², Classification: {class} (WHO)", "complianceTitle": "Medication adherence", "glp1Title": "GLP-1 therapy", "glp1WeightSummary": "Weight over report period: {start} kg → {end} kg ({delta} kg)", @@ -272,8 +272,8 @@ "typeGlucoseRandom": "Glucose (random)", "typeGlucoseBedtime": "Glucose (bedtime)", "typeGlucoseUnspecified": "Glucose (untagged)", - "glucoseClassificationTitle": "Blood glucose — reference ranges (ADA 2024 / DDG)", - "glucoseRow": "{label}: avg {avg} {unit} (target {rangeMin}–{rangeMax}) — {class}", + "glucoseClassificationTitle": "Blood glucose: reference ranges (ADA 2024 / DDG)", + "glucoseRow": "{label}: avg {avg} {unit} (target {rangeMin}–{rangeMax}), {class}", "glucoseInTarget": "in target", "glucoseBelowTarget": "below target", "glucoseAboveTarget": "above target", @@ -325,7 +325,7 @@ "gmi": "Glucose Management Indicator (GMI)", "eA1c": "Estimated A1C", "cv": "Variability (CV%)", - "spotCaveat": "These are spot-reading estimates from individual measurements, not a continuous-monitor profile — read them as a direction of travel rather than a clinical verdict." + "spotCaveat": "These are spot-reading estimates from individual measurements, not a continuous-monitor profile. Read them as a direction of travel rather than a clinical verdict." }, "illnessTitle": "Conditions & illnesses", "illnessOngoing": "Ongoing", @@ -378,12 +378,12 @@ "backToDashboard": "Back to dashboard" }, "offlineBanner": { - "message": "No connection — changes can't be saved until you're back online.", - "saveFailed": "Couldn't save — you're offline. Please try again once you're back online.", + "message": "No connection: changes can't be saved until you're back online.", + "saveFailed": "Couldn't save, you're offline. Please try again once you're back online.", "showingCached": "Showing your last synced data." }, "demoBanner": { - "message": "Demo mode — changes are not saved." + "message": "Demo mode: changes are not saved." }, "nav": { "dashboard": "Dashboard", @@ -458,10 +458,10 @@ "hasAccount": "Already have an account?", "loginFailed": "Login failed", "registerFailed": "Registration failed", - "invitedBanner": "You have been invited — create your account even while registration is otherwise closed.", + "invitedBanner": "You have been invited. Create your account even while registration is otherwise closed.", "alreadySignedIn": { "title": "You are already signed in", - "body": "You are signed in as {username}. An invitation creates a new account — sign out to accept it.", + "body": "You are signed in as {username}. An invitation creates a new account. Sign out to accept it.", "signOut": "Sign out and accept the invitation" }, "createAccount": "Create account", @@ -775,7 +775,7 @@ "formReset": "Reset form", "saveError": "Error saving", "duplicateTimestamp": "A measurement of this type already exists at the selected timestamp.", - "serverOwnedSource": "Values from a connected source can't be edited — the timestamp and note stay editable.", + "serverOwnedSource": "Values from a connected source can't be edited, but the timestamp and note stay editable.", "deleteError": "Error deleting", "deletedToast": "Measurement deleted", "restoredToast": "Measurement restored", @@ -875,7 +875,7 @@ }, "metricCatalog": { "title": "What HealthLog can track", - "description": "Every metric domain HealthLog supports, whether or not you have data for it yet — and what would supply it.", + "description": "Every metric domain HealthLog supports, whether or not you have data for it yet, and what would supply it.", "statusPresent": "Tracked", "statusAbsent": "Not tracked yet", "statusModuleOff": "Off", @@ -883,11 +883,11 @@ "connectCta": "Connect a source", "viewCta": "View", "ecg": { - "source": "Single-lead ECG strips from a compatible watch — Withings ScanWatch today — synced automatically." + "source": "Single-lead ECG strips from a compatible watch (Withings ScanWatch today), synced automatically." }, "watchdog": { "title": "Automatic screening", - "description": "HealthLog also watches quietly in the background — irregular-rhythm and breathing-disturbance notifications from a connected watch, baseline-drift health-status alerts, and notable shifts between your two most recent lab panels — and surfaces a card only when something stands out. With at least one of those sources connected, no card showing is a good sign, not a missing feature; with none connected yet, there's simply nothing being watched." + "description": "HealthLog also watches quietly in the background: irregular-rhythm and breathing-disturbance notifications from a connected watch, baseline-drift health-status alerts, and notable shifts between your two most recent lab panels. It surfaces a card only when something stands out. With at least one of those sources connected, no card showing is a good sign, not a missing feature; with none connected yet, there's simply nothing being watched." } }, "mood": { @@ -1044,7 +1044,7 @@ "archive": "Archive", "restore": "Restore", "archivedTitle": "Archived tags", - "archivedDescription": "Archived tags stay in your past entries — they only disappear from the picker.", + "archivedDescription": "Archived tags stay in your past entries. They only disappear from the picker.", "archivedEmpty": "Nothing archived.", "purgeTitle": "Delete tag permanently?", "purgeBody": "This removes the tag from {count} past entries. This cannot be undone.", @@ -1069,7 +1069,7 @@ }, "sectionMoreTags": "More tags", "sectionNoteDetails": "Note & details", - "quickTagsHelp": "Your frequent tags — one tap", + "quickTagsHelp": "Your frequent tags, one tap", "quickTagsExpand": "More", "loadError": "Could not load your mood entries.", "sectionLevelA": "State of mind", @@ -1247,8 +1247,8 @@ "dialogDescription": "These medications are due now. Confirm to record all of them as taken.", "confirm": "Take all ({count})", "successToast": "{count} intakes recorded", - "partialToast": "{taken} recorded, {failed} failed – please try again", - "failedToast": "No intake recorded – please try again" + "partialToast": "{taken} recorded, {failed} failed. Please try again", + "failedToast": "No intake recorded. Please try again" }, "logIntake": { "dialogTitle": "Log an intake", @@ -1346,10 +1346,10 @@ "skipped": "Skipped", "intakeToastTaken": "{name} recorded as taken", "intakeToastSkipped": "{name} skipped", - "intakeToastFailed": "Could not record {name} — try again", + "intakeToastFailed": "Could not record {name}. Try again", "intakeUndo": "Undo", "intakeUndone": "Entry reverted", - "intakeUndoFailed": "Could not undo — open the history to fix it", + "intakeUndoFailed": "Could not undo. Open the history to fix it", "glp1LastInjection": "{label}", "glp1NextInjectionDays": "{label} (in {days} days)", "glp1NextInjectionToday": "today", @@ -1431,10 +1431,10 @@ "error": { "empty": "Type a description first.", "tooLong": "Keep the description under 2000 characters.", - "rateLimit": "Too many requests — wait a moment and try again.", - "noProvider": "No AI provider configured — set one up in Settings.", - "budget": "Daily AI budget reached — try again tomorrow.", - "network": "Could not reach the AI provider — please retry.", + "rateLimit": "Too many requests. Wait a moment and try again.", + "noProvider": "No AI provider configured. Set one up in Settings.", + "budget": "Daily AI budget reached. Try again tomorrow.", + "network": "Could not reach the AI provider. Please retry.", "consent": "Reading your description with AI needs your consent first.", "unavailable": "Reading descriptions with AI is not available here right now." } @@ -1450,7 +1450,7 @@ "everyNMonths": "Every N months on a specific day", "yearly": "Once a year", "rolling": "Every N days from when I last took it (flexible)", - "rollingExplainer": "Counts from your last logged intake — pauses if you skip a dose.", + "rollingExplainer": "Counts from your last logged intake; pauses if you skip a dose.", "oneShot": "One-time dose" }, "weekdays": { @@ -1508,7 +1508,7 @@ "night": "Night" }, "max": { - "reached": "Maximum reached — remove a time before adding another." + "reached": "Maximum reached. Remove a time before adding another." } }, "courseWindow": { @@ -1558,7 +1558,7 @@ }, "step3": { "title": "What's the dose?", - "subline": "A tablet, a puff, a drop — depending on the form.", + "subline": "A tablet, a puff, a drop, depending on the form.", "amountLabel": "Amount", "amountPlaceholder": "e.g. 5", "unitLabel": "Unit", @@ -1584,7 +1584,7 @@ }, "dosesPerUnitLabel": "Doses per unit", "dosesPerUnitPlaceholder": "e.g. 4", - "dosesPerUnitHint": "Doses per pen / vial — leave empty for no inventory tracking.", + "dosesPerUnitHint": "Doses per pen / vial. Leave empty for no inventory tracking.", "short": "Dose", "unitsPerDoseLabel": "Units per dose", "unitsPerDoseHint": "e.g. 2 tablets of 2 mg for a 4 mg dose, or ½ a tablet for a split dose" @@ -1596,7 +1596,7 @@ }, "step5": { "title": "How often do you take it?", - "subline": "Pick the cadence — the details follow on the next step.", + "subline": "Pick the cadence. The details follow on the next step.", "short": "Cadence" }, "step6": { @@ -1618,7 +1618,7 @@ }, "step7": { "title": "When do you take it?", - "subline": "One or more times of day — reminders follow this list.", + "subline": "One or more times of day. Reminders follow this list.", "presetsLabel": "Time-of-day presets", "presets": { "morning": "Morning", @@ -1626,7 +1626,7 @@ "evening": "Evening", "night": "Night" }, - "overrideHint": "Optional — set a different dose or unit count just for this time of day. Leave blank to use the medication's default.", + "overrideHint": "Optional: set a different dose or unit count just for this time of day. Leave blank to use the medication's default.", "doseOverrideLabel": "Dose for this time (optional)", "doseOverridePlaceholder": "e.g. half a tablet", "unitsOverrideLabel": "Units consumed at this time", @@ -1634,11 +1634,11 @@ "short": "Times" }, "step8": { - "title": "All done — should HealthLog remind you?", + "title": "All done. Should HealthLog remind you?", "subline": "Review everything below before you save.", "remindersLabel": "Reminders on", - "remindersDescription": "Push, Telegram or ntfy — based on your settings.", - "noChannelHint": "Reminders need a notification channel — none is active right now.", + "remindersDescription": "Push, Telegram or ntfy, based on your settings.", + "noChannelHint": "Reminders need a notification channel, and none is active right now.", "noChannelHintLink": "Set up notifications", "short": "Done" } @@ -1687,7 +1687,7 @@ }, "asNeeded": { "label": "As needed", - "description": "No fixed plan — log an intake whenever you need one (e.g. pain relief)." + "description": "No fixed plan. Log an intake whenever you need one (e.g. pain relief)." } }, "summary": { @@ -1722,7 +1722,7 @@ } }, "errors": { - "submitFailed": "Could not save the medication — please retry." + "submitFailed": "Could not save the medication. Please retry." } }, "doseStrength": { @@ -1742,7 +1742,7 @@ }, "injectionSiteBodyOutlineAriaLabel": "Body outline", "injectionSitePickerAriaLabel": "Injection site picker", - "injectionSiteRecommendedAriaLabel": "{site} — recommended next site", + "injectionSiteRecommendedAriaLabel": "{site}: recommended next site", "injectionSiteLegendAriaLabel": "Marker legend", "injectionSiteLegendRecommended": "Recommended next site", "injectionSiteLegendLastUsed": "Last used site", @@ -1830,7 +1830,7 @@ "cadence": { "oneShotOn": "One-time dose on {date}.", "oneShotPending": "One-time dose pending.", - "asNeeded": "As needed — no fixed plan." + "asNeeded": "As needed, no fixed plan." }, "intake": { "title": "Intake history", @@ -1857,7 +1857,7 @@ "dialogTitle": "Edit intake", "takenAtLabel": "Taken at", "scheduledForHint": "Scheduled: {dateTime}", - "farFromScheduledWarning": "This is far from the scheduled time — check the date.", + "farFromScheduledWarning": "This is far from the scheduled time. Check the date.", "skippedLabel": "Skipped", "save": "Save", "cancel": "Cancel", @@ -1901,10 +1901,10 @@ }, "addDialog": { "title": "Add intake", - "description": "Record a dose — including a backdated or off-schedule one.", + "description": "Record a dose, including a backdated or off-schedule one.", "takenAtLabel": "Taken at", "skippedLabel": "Skipped", - "nudgeHint": "Close to the {slot} slot — on save we ask whether to attribute it.", + "nudgeHint": "Close to the {slot} slot. On save we ask whether to attribute it.", "cancel": "Cancel", "submit": "Save" }, @@ -1953,7 +1953,7 @@ }, "codes": { "label": "Clinical codes (ATC / RxNorm)", - "note": "Optional. Used on the FHIR health-record export. Codes are taken exactly as entered — never guessed.", + "note": "Optional. Used on the FHIR health-record export. Codes are taken exactly as entered, never guessed.", "atcLabel": "ATC", "rxNormLabel": "RxNorm", "saved": "Clinical codes saved", @@ -1973,7 +1973,7 @@ "title": "End medication", "helper": "Stop reminders and mark the medication as ended. History stays visible.", "button": "End", - "dialogTitle": "End {name} — stop reminders, history stays visible", + "dialogTitle": "End {name}? Reminders stop, history stays visible", "dialogBody": "No more reminders. Old entries remain in the timeline.", "toast": "Medication ended", "failed": "Could not end the medication." @@ -2011,7 +2011,7 @@ "copyFailed": "Could not copy.", "tokenCopied": "Token copied", "copyToken": "Copy token", - "mintedHint": "Copy this token now — it is shown only once." + "mintedHint": "Copy this token now. It is shown only once." }, "advanced": { "dataPortability": { @@ -2051,9 +2051,9 @@ "statusTitle": "Status", "nextDoseLabel": "Next dose", "nextDoseNone": "No upcoming dose.", - "nextDoseAsNeeded": "As needed — no planned dose.", + "nextDoseAsNeeded": "As needed, no planned dose.", "nextDoseNotTracked": "Not tracked, kept as a record.", - "pausedHint": "Paused — no reminders.", + "pausedHint": "Paused: no reminders.", "reminderLabel": "Reminder", "reminderOn": "On", "reminderOff": "Off", @@ -2124,7 +2124,7 @@ "packagingDefaultPack": "Default pack size: {units} units", "packagingNoDefaultPack": "No default pack size set", "packagingEdit": "Edit", - "packagingDescription": "Set how many units one dose consumes and how large a new pack usually is — e.g. after a manufacturer switch with a different blister size.", + "packagingDescription": "Set how many units one dose consumes and how large a new pack usually is, e.g. after a manufacturer switch with a different blister size.", "packagingUnitsPerDoseLabel": "Units per dose", "packagingUnitsPerDoseHelper": "E.g. two 2 mg tablets for a 4 mg dose, or 1.5 for one and a half (above 0, up to 100). Doses already recorded stay unchanged.", "packagingDefaultPackLabel": "Default pack size (units)", @@ -2175,11 +2175,11 @@ "hideEras": "Hide earlier eras", "addEra": "Add earlier era", "addEraTitle": "Add earlier era", - "addEraDescription": "Record the times this medication used to be taken at — for example before you adjusted it here.", + "addEraDescription": "Record the times this medication used to be taken at, for example before you adjusted it here.", "editAria": "Edit era", "editEraTitle": "Edit era", "editEraDescription": "Adjust the dose times and the date range of this era.", - "archivedEditHint": "This era was recorded automatically — your change corrects the recorded history; the original is kept internally as a record.", + "archivedEditHint": "This era was recorded automatically. Your change corrects the recorded history; the original is kept internally as a record.", "updatedToast": "Era updated", "updateError": "Could not update the era. It must not overlap other eras and must end before the current plan.", "timesLabel": "Dose times", @@ -2205,7 +2205,7 @@ "saved": "Schedule saved", "failed": "Could not save the schedule", "window": { - "intro": "For each dose, set when an intake still counts as on time — a precise time (±1h) or your own window such as 07:00–09:00.", + "intro": "For each dose, set when an intake still counts as on time: a precise time (±1h) or your own window such as 07:00–09:00.", "explicitToggle": "Custom window", "startLabel": "Window start", "endLabel": "Window end", @@ -2218,10 +2218,10 @@ } }, "logInjectionSiteTitle": "Log injection site", - "logInjectionSiteDescription": "Where did you inject {name}? Optional — you can skip this.", + "logInjectionSiteDescription": "Where did you inject {name}? Optional: you can skip this.", "logInjectionSiteSkip": "Skip", "logInjectionSiteConfirm": "Save site", - "logInjectionSiteNoneAvailable": "No injection site is available — every site is excluded in your settings.", + "logInjectionSiteNoneAvailable": "No injection site is available. Every site is excluded in your settings.", "logInjectionSiteSaveFailed": "Could not save the injection site. Please try again.", "perSlotUnits": "{units} per dose", "trackInjectionSitesToggle": "Track injection sites", @@ -2246,15 +2246,15 @@ "tableStockDoses": "{count} doses", "tableStockRunway": "≈ {days} days left", "cardLowStockRunway": "Supply: ≈ {days} days", - "takeActionFor": "Take – {name}", - "skipActionFor": "Skip – {name}", - "reorderDescription": "Set the order of your medications – it applies to both the card and the table view.", + "takeActionFor": "Take {name}", + "skipActionFor": "Skip {name}", + "reorderDescription": "Set the order of your medications for both the card and the table view.", "reorderSaved": "Order saved", "reorderSaveFailed": "Order could not be saved", "customize": "Customize medications", "efficacy": { "title": "Effect", - "intro": "How the measurements this medication is meant to influence have moved around the time you started it. It shows what lines up in time — an association, not a cause — and never advice about your treatment or dose.", + "intro": "How the measurements this medication is meant to influence have moved around the time you started it. It shows what lines up in time (an association, not a cause) and never advice about your treatment or dose.", "notEligible": "There is no outcome to relate this medication to.", "startFallback": "No start date is set, so the comparison uses your first recorded reading as the reference point.", "noStart": "Set a start date for this medication to compare the readings before and after it began.", @@ -2267,7 +2267,7 @@ "levelShift": "A shift in the level was detected around {date}.", "plateau": { "title": "Weight plateau on the current dose", - "evidence": "Weight moved by {delta} {unit} over the last {window} days ({readings} readings) — {days} days on {dose}." + "evidence": "Weight moved by {delta} {unit} over the last {window} days ({readings} readings), {days} days on {dose}." }, "retarget": { "label": "Not the right measurement?", @@ -2277,16 +2277,16 @@ "error": "Could not save that change. Try again." }, "beforeAfter": { - "summary": "Ø {before} before → Ø {after} since — a change of {delta}.", + "summary": "Ø {before} before → Ø {after} since, a change of {delta}.", "counts": "Based on {beforeCount} readings before and {afterCount} since.", - "needBefore": "Not enough readings before the start yet — about {weeks} weeks are needed before and after to compare.", - "needAfter": "Not enough readings since the start yet — about {weeks} weeks are needed before and after to compare.", + "needBefore": "Not enough readings before the start yet. About {weeks} weeks are needed before and after to compare.", + "needAfter": "Not enough readings since the start yet. About {weeks} weeks are needed before and after to compare.", "needStart": "Set a start date to compare the readings before and after it began.", - "needData": "Not enough readings yet — about {weeks} weeks are needed before and after the start to compare." + "needData": "Not enough readings yet. About {weeks} weeks are needed before and after the start to compare." }, "insights": { "title": "Medication effect", - "subtitle": "What lines up with the measurements your medications target — association only, never a verdict.", + "subtitle": "What lines up with the measurements your medications target: association only, never a verdict.", "link": "Open the effect view", "empty": "Not enough data yet to relate your medications to their target measurements." }, @@ -2320,7 +2320,7 @@ "reasonMissingMedication": "the row names no medication", "reasonUnreadableDosage": "the dosage is not a number", "reasonUnreadableRow": "the row has fewer columns than the header", - "reasonStatusNoDoseInformation": "the file records nothing about that dose — nobody answered and nothing was logged", + "reasonStatusNoDoseInformation": "the file records nothing about that dose; nobody answered and nothing was logged", "reasonStatusReminderEvent": "the row is about a snoozed reminder, which says nothing about the dose", "reasonStatusNotificationNotSent": "the row records that no notification was sent, which is about the app rather than the dose" }, @@ -2392,7 +2392,7 @@ }, "charts": { "loadingLabel": "Loading chart…", - "loadingSlowHint": "Computing analytics — this can take a moment.", + "loadingSlowHint": "Computing analytics. This can take a moment.", "weight": "Weight", "bloodPressure": "Blood Pressure", "pulse": "Pulse", @@ -2480,8 +2480,8 @@ "columnDate": "Date", "noValue": "No value", "captionDay": "One row per day of {metric}, the same points the chart draws.", - "captionWeek": "One row per week of {metric}, the average of that week's days — the same points the chart draws.", - "captionMonth": "One row per month of {metric}, the average of that month's days — the same points the chart draws.", + "captionWeek": "One row per week of {metric}, the average of that week's days, the same points the chart draws.", + "captionMonth": "One row per month of {metric}, the average of that month's days, the same points the chart draws.", "hourlyMeanNote": "{metric} is each day's average, with every hour counting once, so a workout does not outweigh the rest of the day." }, "personalBaseline": "Your normal", @@ -2542,8 +2542,8 @@ }, "tooltipPrior": "Prior period", "unavailable": { - "lastMonth": "Comparison unavailable — no data from last month yet", - "lastYear": "Comparison unavailable — no data from last year yet" + "lastMonth": "Comparison unavailable: no data from last month yet", + "lastYear": "Comparison unavailable: no data from last year yet" }, "notAvailableForCompliance": "Comparison N/A for adherence" }, @@ -2777,7 +2777,7 @@ "emptyDescription": "Generate today's briefing to get a narrative read of your trends.", "emptyAction": "Generate briefing", "loadingLabel": "Synthesising today's briefing", - "refreshFailedHint": "Couldn't refresh the briefing — showing the last one.", + "refreshFailedHint": "Couldn't refresh the briefing. Showing the last one.", "retryAction": "Retry", "failedTitle": "Couldn't generate the briefing", "failedDescription": "The AI provider timed out or returned an error. Try again, or raise the response timeout in AI settings for a slow local model.", @@ -2841,14 +2841,14 @@ } }, "coach": { - "refusalOutOfScope": "I can only help with the health metrics in your log — measurements, medications, mood, trends. I cannot answer questions outside that scope.", - "refusalInjection": "I noticed wording that tries to override my instructions. I am the HealthLog Coach and only summarise your own health data — please rephrase your question in those terms.", + "refusalOutOfScope": "I can only help with the health metrics in your log: measurements, medications, mood, trends. I cannot answer questions outside that scope.", + "refusalInjection": "I noticed wording that tries to override my instructions. I am the HealthLog Coach and only summarise your own health data. Please rephrase your question in those terms.", "errorBudget": "You've reached today's Coach usage limit. The budget refreshes at midnight UTC.", "errorProvider": "The Coach could not reach an Insights provider just now. Please try again in a moment.", "errorDemo": "The Coach doesn't answer in the demo.", - "errorNoProvider": "The Coach reads your logged health data and answers questions about it (not medical advice). HealthLog needs an AI provider for that — connect your own key or a local model.", + "errorNoProvider": "The Coach reads your logged health data and answers questions about it (not medical advice). HealthLog needs an AI provider for that. Connect your own key or a local model.", "errorNoProviderAction": "Connect an AI provider", - "errorNetwork": "No internet connection — try again once you're back online.", + "errorNetwork": "No internet connection. Try again once you're back online.", "prefsSaveError": "Couldn't save your Coach preferences. Please try again.", "errorCredentialExpired": "Your AI provider connection has expired. Reconnect it in Settings to keep the Coach running.", "tagline": "Personal health coach, grounded in your data.", @@ -2867,7 +2867,7 @@ "thinking": "Thinking…", "unverifiedFiguresNotice": "Some figures couldn't be checked against your data and were left out.", "composerPlaceholder": "Ask me anything…", - "nudgeBubbleLabel": "New message from the Coach — open chat", + "nudgeBubbleLabel": "New message from the Coach. Open chat", "fabLabel": "Open the Coach", "readAloud": "Read aloud", "readAloudStop": "Stop reading", @@ -2891,7 +2891,7 @@ "guided": { "offerTitle": "The Coach has {count} follow-up questions for you", "offerTitleOne": "The Coach has a follow-up question for you", - "offerBody": "Short answers sharpen your self-context — one question at a time, right here in the chat.", + "offerBody": "Short answers sharpen your self-context, one question at a time, right here in the chat.", "offerStart": "Answer now", "offerLater": "Later", "offerDismiss": "Don't ask again", @@ -2901,7 +2901,7 @@ "later": "Later", "dismissRemaining": "Don't ask again", "answerPlaceholder": "Type your answer…", - "summaryTitle": "All set — thanks for your answers!", + "summaryTitle": "All set, thanks for your answers!", "summaryAnswered": "{answered} of {total} answered", "summaryAdopted": "{adopted} added to your self-context", "summaryAdoptedNone": "nothing new added to your self-context", @@ -2983,7 +2983,7 @@ "settingsVerbosityBrief": "Brief", "settingsVerbosityDefault": "Default", "settingsVerbosityDetailed": "Detailed", - "settingsVerbosityConciseHint": "The concise tone already keeps replies short — verbosity is pinned to Brief while it is active.", + "settingsVerbosityConciseHint": "The concise tone already keeps replies short, so verbosity is pinned to Brief while it is active.", "settingsSourcesSummary": "The Coach sees {count} of {total} data areas and looks back {window}.", "settingsSourcesSummaryAll": "The Coach sees {count} of {total} data areas and your whole history.", "settingsSourcesPointerLink": "Open Coach settings", @@ -3090,7 +3090,7 @@ "steadyLatestWithin": "Your readings usually sit at {low} {unit}; your latest reading, {date}, was {value} and matches.", "steadyLatestAbove": "Your readings usually sit at {low} {unit}; your latest reading, {date}, was {value}, above that.", "steadyLatestBelow": "Your readings usually sit at {low} {unit}; your latest reading, {date}, was {value}, below that.", - "insufficient": "Still learning your usual range — keep logging for a few more days.", + "insufficient": "Still learning your usual range. Keep logging for a few more days.", "driver": "{note}" }, "scope": { @@ -3104,39 +3104,39 @@ "groupEarlier": "Earlier" }, "seed": { - "bloodPressure": "Walk me through my blood pressure trend over the last 30 days — anything I should keep an eye on?", + "bloodPressure": "Walk me through my blood pressure trend over the last 30 days. Anything I should keep an eye on?", "weight": "How has my weight been trending lately, and is the direction something to act on?", "bmi": "What does my BMI trend tell me, and how should I read it?", - "pulse": "Walk me through my pulse readings — is anything out of the ordinary?", + "pulse": "Walk me through my pulse readings. Is anything out of the ordinary?", "restingHr": "How has my resting heart rate been trending, and what does it say about my fitness?", "hrv": "What is my heart-rate variability telling me about recovery and stress lately?", - "sleep": "Walk me through my recent sleep — duration, consistency, and anything worth changing.", + "sleep": "Walk me through my recent sleep: duration, consistency, and anything worth changing.", "mood": "What patterns do you see in my mood over the last few weeks?", "medications": "How is my medication adherence looking, and is it lined up with how I've been feeling?", "steps": "How active have I been lately based on my steps, and how does it compare to a healthy baseline?", "activeEnergy": "What does my active-energy trend say about my activity level lately?", "cardioFitness": "What does my cardio fitness (VO₂ max) trend mean, and how do I move it in the right direction?", - "bloodGlucose": "Walk me through my recent glucose readings — are they in a healthy range?", + "bloodGlucose": "Walk me through my recent glucose readings. Are they in a healthy range?", "oxygenSaturation": "What does my blood-oxygen (SpO₂) trend tell me?", "respiratoryRate": "What does my respiratory-rate trend say about my health?", - "workouts": "Walk me through my recent workouts — load, frequency, and how I'm recovering between them.", + "workouts": "Walk me through my recent workouts: load, frequency, and how I'm recovering between them.", "recoveryPage": "Why is my recovery where it is right now, and what's driving it?", - "briefing": "Walk me through today's briefing — what should I focus on, and is anything worth acting on?", + "briefing": "Walk me through today's briefing. What should I focus on, and is anything worth acting on?", "healthScore": "Why is my health score {score} out of 100, and what would move it the most?", - "periodWeek": "Walk me through how my last week went across my health metrics — what stands out?", - "periodMonth": "Walk me through how my last month went across my health metrics — what stands out?", + "periodWeek": "Walk me through how my last week went across my health metrics. What stands out?", + "periodMonth": "Walk me through how my last month went across my health metrics. What stands out?", "correlationBpCompliance": "How does my medication adherence relate to my blood pressure? Walk me through what this correlation means for me.", "correlationMoodPulse": "Is there a real link between my mood and my pulse? Help me read this correlation.", "correlationWeightWeekday": "Does my weight follow a weekly pattern? What does this day-of-week correlation tell me?", - "recommendation": "Tell me more about this recommendation: \"{text}\" — why does it apply to me, and what should I do about it?" + "recommendation": "Tell me more about this recommendation: \"{text}\" Why does it apply to me, and what should I do about it?" }, - "assessmentPrompt": "Walk me through my {metric} assessment — what does it mean and what should I do about it?", + "assessmentPrompt": "Walk me through my {metric} assessment. What does it mean and what should I do about it?", "attach": { "menuChooseFromDocuments": "Choose from documents", "menuUploadNew": "Upload new document", "trigger": "Attach documents", "pickerTitle": "Attach documents", - "pickerDescription": "The coach reads only the documents you attach — not your health data.", + "pickerDescription": "The coach reads only the documents you attach, not your health data.", "pickerSearchPlaceholder": "Search documents…", "pickerEmpty": "No documents in your vault yet.", "pickerNotIndexed": "Not yet indexed", @@ -3144,13 +3144,13 @@ "pickerConfirm": "Attach ({count})", "pillRemove": "Remove {title}", "indexing": "Indexing…", - "indexingHint": "A document is still being indexed — you can send once it's ready.", - "fencedHint": "This conversation runs without access to your health data — the coach only reads the attached documents.", + "indexingHint": "A document is still being indexed. You can send once it's ready.", + "fencedHint": "This conversation runs without access to your health data. The coach only reads the attached documents.", "documentsAttachedOne": "1 document attached", "documentsAttachedOther": "{count} documents attached", "railBadge": "Fenced document chat", "uploadError": "Upload failed. Please try again.", - "notFoundError": "That document link is no longer valid — starting a normal chat instead." + "notFoundError": "That document link is no longer valid. Starting a normal chat instead." }, "interrupted": { "note": "This answer was interrupted before it finished.", @@ -3321,7 +3321,7 @@ }, "hrv": { "title": "HRV", - "description": "Heart-rate variability over time — your nervous-system recovery signal, captured during sleep by Apple Watch and other compatible wearables.", + "description": "Heart-rate variability over time: your nervous-system recovery signal, captured during sleep by Apple Watch and other compatible wearables.", "chartTitle": "Heart-rate variability", "emptyState": { "title": "No HRV samples yet", @@ -3330,17 +3330,17 @@ }, "restingHr": { "title": "Resting heart rate", - "description": "The daily floor your heart settles at — distinct from the spot pulse samples on the pulse page. Apple Health surfaces one value per day.", + "description": "The daily floor your heart settles at, distinct from the spot pulse samples on the pulse page. Apple Health surfaces one value per day.", "chartTitle": "Resting heart rate", "emptyState": { "title": "No resting heart rate yet", "description": "Resting heart rate arrives once Apple Watch or a compatible Withings device has worn through one quiet day." }, - "coachPrefill": "I haven't logged any resting heart rate yet — why is the daily resting value different from a spot pulse, and how do I improve it?" + "coachPrefill": "I haven't logged any resting heart rate yet. Why is the daily resting value different from a spot pulse, and how do I improve it?" }, "oxygenSaturation": { "title": "Oxygen saturation", - "description": "Blood oxygen (SpO₂) — clinical normal is 95–100 %, with target zones shaded on the chart.", + "description": "Blood oxygen (SpO₂): clinical normal is 95–100 %, with target zones shaded on the chart.", "chartTitle": "Oxygen saturation", "emptyState": { "title": "No SpO₂ samples yet", @@ -3349,7 +3349,7 @@ }, "bodyTemperature": { "title": "Body temperature", - "description": "Core body temperature trend — Celsius. Skin-temperature readings from Withings live on a separate metric.", + "description": "Core body temperature trend in Celsius. Skin-temperature readings from Withings live on a separate metric.", "chartTitle": "Body temperature", "emptyState": { "title": "No body temperature yet", @@ -3359,7 +3359,7 @@ }, "steps": { "title": "Steps", - "description": "Daily step count — one row per day, sourced from Apple Health or a connected activity device.", + "description": "Daily step count, one row per day, sourced from Apple Health or a connected activity device.", "chartTitle": "Steps per day", "emptyState": { "title": "No step data yet", @@ -3368,7 +3368,7 @@ }, "activeEnergy": { "title": "Active energy", - "description": "Daily active-energy total in kilocalories — one row per day, sourced from Apple Health or Withings activity.", + "description": "Daily active-energy total in kilocalories, one row per day, sourced from Apple Health or Withings activity.", "chartTitle": "Active energy", "emptyState": { "title": "No active-energy data yet", @@ -3388,27 +3388,27 @@ }, "explainer": { "bloodPressureBody": "Blood pressure is the force your blood exerts on the artery walls, written as systolic over diastolic (the peak during a heartbeat over the resting value between beats). Consistently high readings strain the heart and blood vessels over time.", - "pulseBody": "Your pulse is how many times your heart beats per minute. A spot reading reflects what you were doing in the moment — at rest it is typically 60–100 beats per minute, and it rises naturally with movement, stress, or caffeine.", + "pulseBody": "Your pulse is how many times your heart beats per minute. A spot reading reflects what you were doing in the moment. At rest it is typically 60–100 beats per minute, and it rises naturally with movement, stress, or caffeine.", "weightBody": "Body weight is one of the simplest signals of long-term energy balance and overall health. The trend over weeks matters far more than any single reading, which fluctuates with hydration, food, and time of day.", "bmiBody": "BMI is your weight divided by your height squared, giving a single number that places you in a broad weight category. It is a population-level screen, not a diagnosis, and does not distinguish muscle from fat.", "sleepBody": "Sleep duration is how long you actually slept across the night, split into light, deep, and REM stages. Most adults need roughly seven to nine hours; both consistent quantity and quality support recovery, mood, and metabolism.", - "moodBody": "Mood tracking records how you feel over time on a simple scale. Logging it regularly reveals patterns — how sleep, activity, or medication line up with how you feel — that a single day never shows.", + "moodBody": "Mood tracking records how you feel over time on a simple scale. Logging it regularly reveals patterns (how sleep, activity, or medication line up with how you feel) that a single day never shows.", "medicationsBody": "Adherence is how reliably you take your medication as prescribed, shown here as the share of expected doses you actually logged. Steady intake is often what makes a treatment work as intended.", - "restingHrBody": "Resting heart rate is your heart rate when you are completely at rest, usually measured overnight — distinct from your pulse during activity. A lower resting rate generally points to better cardiovascular fitness, and a rising trend can be an early sign of stress or illness. As general guidance, a normal adult resting rate is 60–100 beats per minute (AHA 2024); a trained heart can sit benignly at 40–60.", + "restingHrBody": "Resting heart rate is your heart rate when you are completely at rest, usually measured overnight, distinct from your pulse during activity. A lower resting rate generally points to better cardiovascular fitness, and a rising trend can be an early sign of stress or illness. As general guidance, a normal adult resting rate is 60–100 beats per minute (AHA 2024); a trained heart can sit benignly at 40–60.", "hrvBody": "HRV is the tiny variation in time between consecutive heartbeats. Higher variability usually reflects a well-recovered, adaptable nervous system, while a sustained drop can signal fatigue, stress, or insufficient recovery.", "oxygenSaturationBody": "SpO₂ is the percentage of your red blood cells carrying oxygen. Readings of 95–100% are normal at rest; values that stay below 90% warrant attention, though brief nightly dips are common.", - "bodyTemperatureBody": "Body temperature reflects your core thermal state. As general guidance, the population mean is about 36.6 °C — not 37.0 °C — with a normal oral range of roughly 35.7–37.4 °C and a fever from 38.0 °C (J Gen Intern Med 2019). It swings about 0.5 °C across the day, and sites differ by up to ~1 °C, so tag where you measured. Overnight wrist readings track relative change, not a clinical fever value.", + "bodyTemperatureBody": "Body temperature reflects your core thermal state. As general guidance, the population mean is about 36.6 °C (not 37.0 °C), with a normal oral range of roughly 35.7–37.4 °C and a fever from 38.0 °C (J Gen Intern Med 2019). It swings about 0.5 °C across the day, and sites differ by up to ~1 °C, so tag where you measured. Overnight wrist readings track relative change, not a clinical fever value.", "activeEnergyBody": "Active energy is the calories you burn through movement, on top of the baseline your body uses at rest. It is a direct measure of how physically active your day was.", "workoutsBody": "Workouts are the structured exercise sessions your devices record, with type, duration, and energy. Tracking them shows how regular training accumulates over weeks and how it relates to your other health signals.", - "respiratoryRateBody": "Respiratory rate is the number of breaths you take per minute. As general guidance, at rest most adults breathe 12–20 times a minute (American Lung Association); it is meaningful only truly at rest or asleep. A sustained rise of about +3 above your own nightly baseline can be an early illness signal — clinical escalation cutoffs are hospital tools, not self-alarms.", + "respiratoryRateBody": "Respiratory rate is the number of breaths you take per minute. As general guidance, at rest most adults breathe 12–20 times a minute (American Lung Association); it is meaningful only truly at rest or asleep. A sustained rise of about +3 above your own nightly baseline can be an early illness signal; clinical escalation cutoffs are hospital tools, not self-alarms.", "bodyWaterBody": "Total body water is the share of your body weight made up of fluid, inside and around your cells. It shifts with hydration, food, and activity, so the trend over weeks tells you more than any single reading.", "boneMassBody": "Bone mass is the estimated weight of the mineral in your skeleton. Scale-based estimates are approximate, but a steady or rising trend supports long-term bone strength.", - "fatFreeMassBody": "Fat-free mass is everything in your body that is not fat — muscle, bone, organs, and water. Holding or building it while losing weight usually signals healthier body composition.", - "fatMassBody": "Fat mass is the total weight of fat in your body. Some fat is essential for hormones and energy storage, but too much — especially around the abdomen — raises long-term health risk (WHO 2024).", + "fatFreeMassBody": "Fat-free mass is everything in your body that is not fat: muscle, bone, organs, and water. Holding or building it while losing weight usually signals healthier body composition.", + "fatMassBody": "Fat mass is the total weight of fat in your body. Some fat is essential for hormones and energy storage, but too much, especially around the abdomen, raises long-term health risk (WHO 2024).", "bodyFatBody": "Body fat percentage is the share of your weight that is fat. Healthy ranges depend on sex and age, and home scales estimate it from bioimpedance, so the trend over several weeks says more than a single reading.", "muscleMassBody": "Muscle mass is the estimated weight of the muscle in your body. More muscle supports strength, metabolism, and mobility, and it tends to need active effort to preserve as you age.", "visceralFatBody": "Visceral fat is the fat stored deep in the abdomen around your organs. Unlike fat under the skin, a high level is closely linked to heart disease and type 2 diabetes, so lower is generally better.", - "leanBodyMassBody": "Lean body mass is your total weight minus body fat — muscle, bone, organs, and water combined. Tracking it alongside weight shows whether changes come from muscle or from fat.", + "leanBodyMassBody": "Lean body mass is your total weight minus body fat: muscle, bone, organs, and water combined. Tracking it alongside weight shows whether changes come from muscle or from fat.", "flightsClimbedBody": "Flights climbed counts the floors you go up each day, with one flight roughly ten feet of elevation. It is a simple marker of incidental activity and lower-body effort.", "walkingDistanceBody": "Walking and running distance is the ground you cover on foot each day. It complements step count by reflecting how far you moved, not just how often you stepped.", "walkingSteadinessBody": "Walking steadiness estimates how stable and balanced your gait is, classed from OK to low. A lower level points to a higher chance of a fall and is worth discussing with a clinician.", @@ -3417,36 +3417,36 @@ "doubleSupportTimeBody": "Double support time is the share of each walking cycle when both feet touch the ground at once. A higher percentage usually means a more cautious, less stable gait.", "stepLengthBody": "Step length is the average distance from one footfall to the next. A shorter step over time can reflect fatigue, caution, or a change in mobility.", "walkingSpeedBody": "Walking speed is how fast you move on a level walk. It is a well-studied marker of overall health and mobility, and a steady or rising pace is a good sign.", - "pulseWaveVelocityBody": "Pulse wave velocity measures how fast the pressure wave from each heartbeat travels along your arteries. A faster wave indicates stiffer arteries, which is linked to higher cardiovascular risk. As general guidance, European clinical reference flags carotid-femoral velocity above 10 m/s (ESC/ESH 2018) — but a consumer estimate is a proxy, not interchangeable with that clinical measurement.", + "pulseWaveVelocityBody": "Pulse wave velocity measures how fast the pressure wave from each heartbeat travels along your arteries. A faster wave indicates stiffer arteries, which is linked to higher cardiovascular risk. As general guidance, European clinical reference flags carotid-femoral velocity above 10 m/s (ESC/ESH 2018), but a consumer estimate is a proxy, not interchangeable with that clinical measurement.", "vascularAgeBody": "Vascular age estimates how old your arteries behave compared with your actual age, based on arterial stiffness. A vascular age below your real age suggests healthier blood vessels.", "environmentalAudioBody": "Environmental sound levels track the loudness of the world around you in decibels. Prolonged exposure above about 70 dB can damage hearing over time, so lower daily averages are safer.", "headphoneAudioBody": "Headphone audio levels track how loudly you listen through earbuds or headphones, in decibels. Keeping the volume down and taking breaks protects your hearing over the long run.", "audioEventsBody": "Loud sound events flag moments when noise around you reached a level that can harm hearing with enough exposure. Frequent events are a cue to seek quieter surroundings or hearing protection.", "daylightBody": "Time in daylight is how long you spend in outdoor light each day. Regular daylight supports a healthy sleep-wake rhythm and mood (CDC 2024), and time outdoors is linked to eye health.", - "bloodGlucoseBody": "Blood glucose is the amount of sugar in your blood, the body's main energy source. It rises after eating and settles between meals. As general guidance for adults without diabetes, a fasting reading under {prediabetesFrom} {unit} is normal, {prediabetesFrom}–{prediabetesTo} is prediabetes, and {diabetesFrom} or above falls in the diabetes range (ADA 2024). A single high reading does not diagnose — a clinician confirms with a repeat test, and people managing diabetes use different, clinician-set targets.", + "bloodGlucoseBody": "Blood glucose is the amount of sugar in your blood, the body's main energy source. It rises after eating and settles between meals. As general guidance for adults without diabetes, a fasting reading under {prediabetesFrom} {unit} is normal, {prediabetesFrom}–{prediabetesTo} is prediabetes, and {diabetesFrom} or above falls in the diabetes range (ADA 2024). A single high reading does not diagnose; a clinician confirms with a repeat test, and people managing diabetes use different, clinician-set targets.", "skinTemperatureBody": "Skin temperature here is the small nightly change in your wrist temperature from your own baseline, not an absolute fever reading. Shifts can track sleep, environment, illness, or menstrual-cycle phase.", - "cardioFitnessBody": "VO₂ max is how much oxygen your body can use at peak effort — the best lab index of aerobic fitness, which wearables estimate indirectly. A higher or rising trend is a strong sign of cardiovascular health.", + "cardioFitnessBody": "VO₂ max is how much oxygen your body can use at peak effort, the best lab index of aerobic fitness, which wearables estimate indirectly. A higher or rising trend is a strong sign of cardiovascular health.", "cardioRecoveryBody": "Cardio recovery is how many beats per minute your heart rate falls in the first minute after you stop hard exercise. A bigger drop means your heart settles down faster, which is a sign of good fitness.", "wristTemperatureBody": "Wrist temperature is measured while you sleep and reported as the difference from your personal baseline, not an absolute value. A steady reading is normal, while a sustained rise can hint at illness, intense training, or a menstrual-cycle change.", "fallsBody": "This counts the hard falls your wearable detects. Zero is the goal; a rising count is a mobility-risk signal worth raising with a clinician, especially for older adults (CDC STEADI 2024).", - "sixMinuteWalkBody": "This is an estimate of how far you could walk in six minutes — a long-standing clinical test of mobility and cardiopulmonary endurance. The wearable figure is a proxy, not the supervised clinical test; a steady or rising trend is the useful read.", - "stairAscentSpeedBody": "This is how fast you climb a flight of stairs. It is a sensitive marker of leg strength and mobility — a steady or rising pace is a good sign, and a falling one is worth watching.", - "stairDescentSpeedBody": "This is how fast you go down a flight of stairs. Together with ascent speed it tracks leg control and balance — a steady pace is a good sign, and a falling one is worth watching.", + "sixMinuteWalkBody": "This is an estimate of how far you could walk in six minutes, a long-standing clinical test of mobility and cardiopulmonary endurance. The wearable figure is a proxy, not the supervised clinical test; a steady or rising trend is the useful read.", + "stairAscentSpeedBody": "This is how fast you climb a flight of stairs. It is a sensitive marker of leg strength and mobility. A steady or rising pace is a good sign, and a falling one is worth watching.", + "stairDescentSpeedBody": "This is how fast you go down a flight of stairs. Together with ascent speed it tracks leg control and balance. A steady pace is a good sign, and a falling one is worth watching.", "breathingDisturbancesBody": "A wearable can estimate how often your breathing was interrupted during sleep. A lower index is better; a level flagged as elevated, especially across many nights, is worth raising with a clinician. It is a screening proxy, not a sleep-apnea diagnosis.", - "stepsBody": "Step count is the total number of steps you take each day — the simplest measure of everyday movement. A steady habit matters more than any single big day, and the round 10,000 target is a marketing slogan, not research.", - "readinessBody": "Readiness is a single daily read on how prepared your body is to take on the day, blending resting heart rate, heart-rate variability, and sleep. It is a device proxy benchmarked against your own baseline, not a clinical measure — a higher score means recovered, a lower one is a gentle cue to ease off.", - "sleepScoreBody": "Your sleep score distils a whole night into one number — duration, efficiency, regularity, and the balance of light, deep, and REM. Watch the pattern across weeks rather than chasing a perfect score on any single night.", + "stepsBody": "Step count is the total number of steps you take each day, the simplest measure of everyday movement. A steady habit matters more than any single big day, and the round 10,000 target is a marketing slogan, not research.", + "readinessBody": "Readiness is a single daily read on how prepared your body is to take on the day, blending resting heart rate, heart-rate variability, and sleep. It is a device proxy benchmarked against your own baseline, not a clinical measure. A higher score means recovered, a lower one is a gentle cue to ease off.", + "sleepScoreBody": "Your sleep score distils a whole night into one number: duration, efficiency, regularity, and the balance of light, deep, and REM. Watch the pattern across weeks rather than chasing a perfect score on any single night.", "recoveryBody": "Recovery reflects how well your body has bounced back, drawing on overnight signals like heart-rate variability and resting heart rate. It is a device-derived proxy read against your own baseline, not a clinical measure, and is not comparable across devices. A strong score is a green light to push; a softer one suggests your system is still rebuilding.", "strainBody": "Strain captures how much cardiovascular and physical load you have put on your body, from workouts to an active day on your feet. It is a device-derived index judged against your own typical effort, not a clinical measure, and the headline number is not comparable across devices.", - "stressBody": "Stress here is a device heuristic derived from heart-rate-variability patterns, not a cortisol measurement or how you consciously feel — and not a clinical stress score. Read it against your own baseline; it is not comparable across devices. A lower score points to a calm, well-regulated state; a higher one is an invitation to build in recovery.", - "recoveryPageBody": "Recovery brings together the overnight signals your wearable records — recharge, strain, load and your day's heart-rate and energy totals — to show how well your body has bounced back. Read the pattern across days rather than any single number; a softer reading is an invitation to ease off, not an alarm.", + "stressBody": "Stress here is a device heuristic derived from heart-rate-variability patterns, not a cortisol measurement or how you consciously feel, and not a clinical stress score. Read it against your own baseline; it is not comparable across devices. A lower score points to a calm, well-regulated state; a higher one is an invitation to build in recovery.", + "recoveryPageBody": "Recovery brings together the overnight signals your wearable records (recharge, strain, load and your day's heart-rate and energy totals) to show how well your body has bounced back. Read the pattern across days rather than any single number; a softer reading is an invitation to ease off, not an alarm.", "pulsePressureBody": "Pulse pressure is the gap between your systolic and diastolic readings (systolic minus diastolic). As general guidance, about 40 mmHg is typical at rest; a wide gap above roughly 60 mmHg in middle age can reflect stiffening arteries, while a narrow gap under about 25 mmHg can accompany low stroke volume (StatPearls/NIH 2023). It is a discussion prompt, not a diagnosis.", "meanArterialPressureBody": "Mean arterial pressure is the average pressure your organs see across a heartbeat, roughly the diastolic plus a third of the gap to systolic. As general guidance, a resting value sits around 70–100 mmHg (StatPearls/NIH 2023). The often-cited ~60 mmHg floor is an acute-care concept, not a consumer self-alarm.", - "cycleEducationBody": "Your cycle runs through four phases driven by shifting hormones, and its length and regularity are an accessible window on overall health. As general guidance, adult cycles typically run 21–35 days (clinical references cite 24–38), with bleeding around five days (ACOG 2015). The luteal phase is the steady anchor, so ovulation is best estimated by counting back from your next expected period — never a fixed 'day 14'. A predicted fertile window is an estimate that needs several recorded cycles and stays approximate, and basal body temperature confirms ovulation after the fact rather than predicting it. This is not a contraceptive method.", + "cycleEducationBody": "Your cycle runs through four phases driven by shifting hormones, and its length and regularity are an accessible window on overall health. As general guidance, adult cycles typically run 21–35 days (clinical references cite 24–38), with bleeding around five days (ACOG 2015). The luteal phase is the steady anchor, so ovulation is best estimated by counting back from your next expected period, never a fixed 'day 14'. A predicted fertile window is an estimate that needs several recorded cycles and stays approximate, and basal body temperature confirms ovulation after the fact rather than predicting it. This is not a contraceptive method.", "sleepHygieneBody": "A few evidence-based habits support sleep: keep consistent bed and wake times including weekends, get bright morning daylight and dim your evenings, keep the room cool, dark and quiet, and avoid afternoon caffeine, late alcohol and large late meals (CDC 2024). Regularity predicts health at least as strongly as duration, and a wearable's total sleep time is far more trustworthy than its deep, light and REM split." }, "bpDerived": { - "pulsePressure": "Pulse pressure (the gap between your readings) is about {value} mmHg — roughly 40 is typical at rest.", + "pulsePressure": "Pulse pressure (the gap between your readings) is about {value} mmHg; roughly 40 is typical at rest.", "meanArterialPressure": "Mean arterial pressure (the average your organs see) is about {value} mmHg, normally around 70–100.", "caveat": "These are derived from your latest reading as general guidance, not a diagnosis." }, @@ -3458,7 +3458,7 @@ "mean": "Mean" }, "showAllValues": "Show all readings", - "valuesPageTitle": "{metric} — all readings", + "valuesPageTitle": "{metric}: all readings", "valuesPageDescription": "Every reading behind this metric. Edit or remove an entry directly.", "diversity": { "trigger": "Measurement tip", @@ -3498,11 +3498,11 @@ "inBed": "In bed", "nap": "Nap", "napCount": "{count} naps", - "unavailable": "No stage data yet — sleep stages appear here as soon as a connected source delivers them." + "unavailable": "No stage data yet. Sleep stages appear here as soon as a connected source delivers them." }, "empty": { "title": "No sleep data yet", - "description": "Connect a source like Apple Health or a wearable — or log sleep manually — and this view fills in automatically.", + "description": "Connect a source like Apple Health or a wearable, or log sleep manually, and this view fills in automatically.", "action": "Manage devices" }, "debt": { @@ -3511,21 +3511,21 @@ "caption": "Outstanding balance over the last {nights} nights", "clearValue": "All caught up", "clearCaption": "Nothing outstanding over the last {nights} nights", - "learning": "Still learning your sleep — {counted} nights so far, {remaining} more to read a reliable balance.", + "learning": "Still learning your sleep: {counted} nights so far, {remaining} more to read a reliable balance.", "computedInfo": "This is HealthLog's own estimate: a rolling balance of need minus sleep over recent nights, with catch-up sleep paying it down. It can differ from a wearable's native sleep-debt figure, which uses its own need model." }, "average": { "title": "Average per night", "value": "{hours}h {minutes}m", "caption": "Mean sleep across the last {nights} nights", - "learning": "Still learning your sleep — {counted} nights so far, {remaining} more for a reliable average." + "learning": "Still learning your sleep: {counted} nights so far, {remaining} more for a reliable average." }, "chronotype": { "title": "Chronotype", - "learning": "Still learning your rhythm — {counted} of {total} free nights. A chronotype needs a few alarm-free mornings before it means anything.", + "learning": "Still learning your rhythm: {counted} of {total} free nights. A chronotype needs a few alarm-free mornings before it means anything.", "advancedToggle": "Advanced", "socialJetlagValue": "{hours}h {minutes}m social jetlag", - "socialJetlagCaption": "The gap between your work-day and free-day sleep timing — like a small weekly time-zone shift.", + "socialJetlagCaption": "The gap between your work-day and free-day sleep timing, like a small weekly time-zone shift.", "msfScValue": "Corrected mid-sleep {clock}", "msfScCaption": "Adjusted for the sleep you catch up on at the weekend (MSFsc).", "dayTypeNote": "Free days are assumed to be weekends until day-type tracking is added.", @@ -3732,11 +3732,11 @@ "clinical": { "title": "Glucose overview", "subtitle": "A read on your last {days} days, from {count} readings.", - "spotCaveat": "These are spot-reading estimates from individual measurements, not a continuous-monitor profile — read them as a direction of travel rather than a clinical verdict.", + "spotCaveat": "These are spot-reading estimates from individual measurements, not a continuous-monitor profile. Read them as a direction of travel rather than a clinical verdict.", "labsLink": "Lab results? Log a blood-draw HbA1c or fasting glucose under Labs.", "learningTitle": "Still learning your glucose", - "learningBody": "So far that's {count} over {days}. A little more history and a fuller picture comes into focus — keep logging, or let a connected device fill it in.", - "learningBodyEmpty": "Once a handful of readings come in — logged by you or synced from a device — your time-in-range, average, and variability take shape here.", + "learningBody": "So far that's {count} over {days}. A little more history and a fuller picture comes into focus. Keep logging, or let a connected device fill it in.", + "learningBodyEmpty": "Once a handful of readings come in (logged by you or synced from a device), your time-in-range, average, and variability take shape here.", "readingsCount": "{count} readings", "readingsCountOne": "1 reading", "daysCount": "{days} days", @@ -3774,7 +3774,7 @@ "intro": "Research-grade composites for a closer look. Each folds your readings into a single risk-weighted number.", "jIndex": { "label": "J-index", - "help": "A single score blending your average and its spread — lower reads as tighter control." + "help": "A single score blending your average and its spread; lower reads as tighter control." }, "lbgi": { "label": "Low-glucose risk (LBGI)", @@ -3891,7 +3891,7 @@ "navSkinTemperature": "Skin temp", "pulseWaveVelocity": { "title": "Pulse Wave Velocity", - "description": "Your arterial pulse-wave velocity over time, in m/s — higher values suggest stiffer arteries.", + "description": "Your arterial pulse-wave velocity over time, in m/s. Higher values suggest stiffer arteries.", "chartTitle": "Pulse wave velocity", "emptyState": { "title": "No pulse-wave-velocity data yet", @@ -4084,7 +4084,7 @@ "inTargetCaption": "of recent days in your good-mood range", "narrative": { "title": "What stands out", - "weekdayDip": "Your mood dips most on {weekday} — {delta} below your week.", + "weekdayDip": "Your mood dips most on {weekday}, {delta} below your week.", "weekdayPeak": "{weekday} is consistently your best day, averaging {value}.", "trendUp": "Your mood is trending up over the last {days} days (+{delta} vs the prior period).", "trendDown": "Your mood is trending down over the last {days} days (-{delta} vs the prior period).", @@ -4093,7 +4093,7 @@ "tagLift": "Days tagged \"{tag}\" average {delta} above your overall mood.", "tagDrop": "Days tagged \"{tag}\" run {delta} below your average.", "inTarget": "You've been in your good-mood range {pct}% of the last 30 days.", - "streak": "You've logged your mood {days} days in a row — keep it up.", + "streak": "You've logged your mood {days} days in a row. Keep it up.", "timeOfDay": "You feel best in the {bucket}, averaging {value}." }, "timeOfDay": { @@ -4164,7 +4164,7 @@ "title": "What stands out", "subheading": "Discovered relationships", "footer": "Surfaced from {tested} day-to-day pairs tested across all your metrics, after the false-discovery correction.", - "disclaimer": "Statistically filtered, but still observational — a pattern worth watching, not a cause.", + "disclaimer": "Statistically filtered, but still observational: a pattern worth watching, not a cause.", "moodUp": "Higher {factor} tends to go with higher next-day mood in your data.", "moodDown": "Higher {factor} tends to go with lower next-day mood in your data.", "outcomeUp": "Higher mood tends to go with higher next-day {factor} in your data.", @@ -4203,8 +4203,8 @@ "deviationAbove": "Your own rating sits {amount} points above that range.", "deviationBelow": "Your own rating sits {amount} points below that range.", "weightedTitle": "What weighed most in this day's comparison", - "weightedUp": "{label} — counted towards a higher expected value", - "weightedDown": "{label} — counted towards a lower expected value", + "weightedUp": "{label}: counted towards a higher expected value", + "weightedDown": "{label}: counted towards a lower expected value", "caveat": "This is a comparison with your own past days, not a statement about how a day came to go the way it did.", "learning": "Learning phase: {entries} of {threshold} days recorded. A comparison appears once there are enough of them.", "noPattern": "Nothing in the {entries} days recorded so far is steady enough to compare a day against. When you also capture a day's context, more of it becomes comparable.", @@ -4221,7 +4221,7 @@ }, "scoreRing": { "aria": "Score {score} out of 100, {band}", - "ariaProvisional": "Score not available yet — not enough data", + "ariaProvisional": "Score not available yet, not enough data", "provisionalCaption": "Not enough data yet", "band": { "green": "good", @@ -4245,7 +4245,7 @@ "loadingLabel": "Loading your vitals", "loadError": "Could not load your vitals right now.", "infoLabel": "How is this calculated?", - "building": "Building your typical range — {count} of {target} days", + "building": "Building your typical range: {count} of {target} days", "typicalRange": "Typical for you: {low}–{high}", "fitnessYounger": "Cardio fitness of someone ~{years} yr younger", "fitnessOlder": "Cardio fitness ~{years} yr above your age", @@ -4297,7 +4297,7 @@ "READINESS": { "title": "Readiness", "description": "A daily wellness proxy from how your signals sit against your own baseline.", - "method": "A 0–100 blend of resting-HR deviation, HRV (SDNN) deviation, sleep adequacy, respiratory-rate stability and mood stability — each measured against your personal baseline. Weights renormalise over the components your data supports. A wellness proxy, not a recovery or clinical score.", + "method": "A 0–100 blend of resting-HR deviation, HRV (SDNN) deviation, sleep adequacy, respiratory-rate stability and mood stability, each measured against your personal baseline. Weights renormalise over the components your data supports. A wellness proxy, not a recovery or clinical score.", "component": { "rhr": "Resting heart rate", "hrv": "HRV (SDNN)", @@ -4307,28 +4307,28 @@ } }, "VITALS_BASELINE": { - "method": "Your personal typical range is the median of your daily values over the window, ± a robust spread (median absolute deviation, scaled). It tracks YOUR readings, not a population norm — so a value inside the band is typical for you." + "method": "Your personal typical range is the median of your daily values over the window, ± a robust spread (median absolute deviation, scaled). It tracks YOUR readings, not a population norm, so a value inside the band is typical for you." }, "HRV_BALANCE": { "method": "Your recent HRV (SDNN) average placed against your own rolling baseline (median ± a robust spread). Balanced means it sits inside your personal range; the band is built from your data, never a population cut-off." }, "BMI": { - "method": "Weight ÷ height², classified against the WHO adult categories (underweight / normal / overweight / obese). A screening ratio only — it does not distinguish muscle from fat." + "method": "Weight ÷ height², classified against the WHO adult categories (underweight / normal / overweight / obese). A screening ratio only; it does not distinguish muscle from fat." }, "FITNESS_AGE": { - "method": "Your VO₂max placed against age- and sex-referenced cardiorespiratory-fitness percentiles, expressed as a fitness-age delta. The VO₂max is your device's estimate — never recomputed here." + "method": "Your VO₂max placed against age- and sex-referenced cardiorespiratory-fitness percentiles, expressed as a fitness-age delta. The VO₂max is your device's estimate, never recomputed here." }, "VASCULAR_AGE_DELTA": { "method": "Your device's vascular-age / pulse-wave-velocity estimate compared with your chronological age, expressed as a delta in years. The estimate is the device's; HealthLog only re-frames it.", - "caveat": "Your device's own estimate, re-framed — descriptive, not a clinical vascular assessment.", + "caveat": "Your device's own estimate, re-framed: descriptive, not a clinical vascular assessment.", "description": "How your device's vascular-age estimate sits against your chronological age." }, "COINCIDENT_DEVIATION": { "method": "A flag raised when two or more of your vitals sit outside their personal typical range on the same day. Each band is the robust median ± k·MAD of your own history, so it adapts to you rather than to a population cut-off.", - "caveat": "An awareness flag from your own baselines — descriptive, not a diagnosis or a clinical alert." + "caveat": "An awareness flag from your own baselines: descriptive, not a diagnosis or a clinical alert." }, "RECOVERY_SCORE": { - "method": "A nightly 0–100 recovery proxy blended from your HRV, resting heart rate and sleep against your own baseline. Higher means better-recovered. Computed once each night and read back here — never recomputed on the fly.", + "method": "A nightly 0–100 recovery proxy blended from your HRV, resting heart rate and sleep against your own baseline. Higher means better-recovered. Computed once each night and read back here, never recomputed on the fly.", "description": "A nightly recovery proxy from your HRV, resting heart rate and sleep." }, "STRESS_SCORE": { @@ -4337,31 +4337,31 @@ }, "STRAIN_SCORE": { "method": "A nightly 0–100 strain proxy from your heart-rate-weighted activity load (a TRIMP-style training-impulse model). Higher means a harder day.", - "anchorPersonal": "Anchored to your own recent training-day load — scored relative to your typical effort, so a genuinely hard day for you reads high.", + "anchorPersonal": "Anchored to your own recent training-day load, scored relative to your typical effort, so a genuinely hard day for you reads high.", "anchorPopulation": "Scored against a general reference while you build training history; once you have enough it switches to your own typical effort.", "description": "A nightly activity-load proxy from your heart-rate-weighted effort, relative to your typical effort.", "deviceCaption": "Your device's day strain: {value} of {max}", "deviceSource": "Until HealthLog has computed its own value overnight, the card shows your device's day strain, rescaled to 0–100." }, "WRIST_TEMPERATURE_BASELINE": { - "method": "Your typical overnight wrist temperature is the median of your nightly readings over the window, ± a robust spread (median absolute deviation, scaled). It tracks YOUR readings — last night is shown as a deviation from your own baseline, not a population norm.", - "caveat": "A personal-deviation band only — descriptive, not an illness, fever or cycle-phase signal. Interpret it yourself." + "method": "Your typical overnight wrist temperature is the median of your nightly readings over the window, ± a robust spread (median absolute deviation, scaled). It tracks YOUR readings: last night is shown as a deviation from your own baseline, not a population norm.", + "caveat": "A personal-deviation band only: descriptive, not an illness, fever or cycle-phase signal. Interpret it yourself." }, "STAIR_ASCENT_SPEED_BASELINE": { - "method": "Your typical stair-climbing pace is the median of your daily values over the window, ± a robust spread (median absolute deviation, scaled). The band is built from your data — there is no population stair-speed cut-off, because pace depends on stair geometry and leg length.", - "caveat": "A personal mobility-trend band — descriptive, not a frailty or fall-risk assessment." + "method": "Your typical stair-climbing pace is the median of your daily values over the window, ± a robust spread (median absolute deviation, scaled). The band is built from your data. There is no population stair-speed cut-off, because pace depends on stair geometry and leg length.", + "caveat": "A personal mobility-trend band: descriptive, not a frailty or fall-risk assessment." }, "STAIR_DESCENT_SPEED_BASELINE": { - "method": "Your typical stair-descent pace is the median of your daily values over the window, ± a robust spread (median absolute deviation, scaled). The band is built from your data — there is no population stair-speed cut-off, because pace depends on stair geometry and leg length.", - "caveat": "A personal mobility-trend band — descriptive, not a frailty or fall-risk assessment." + "method": "Your typical stair-descent pace is the median of your daily values over the window, ± a robust spread (median absolute deviation, scaled). The band is built from your data. There is no population stair-speed cut-off, because pace depends on stair geometry and leg length.", + "caveat": "A personal mobility-trend band: descriptive, not a frailty or fall-risk assessment." }, "SIX_MINUTE_WALK_BAND": { - "method": "Your device's ESTIMATED six-minute-walk distance placed against the Enright & Sherrill reference for your age, height, weight and sex, as a percent of predicted. The distance is the device's estimate — never recomputed here. Without your age, height, weight and sex the percent is hidden and only the distance and trend are shown.", - "caveat": "An estimate re-framed against a published reference — a functional-capacity awareness signal, not a clinical 6-minute-walk test or a diagnosis. The reference was established for ages 40–80; outside that range the predicted value is an extrapolation." + "method": "Your device's ESTIMATED six-minute-walk distance placed against the Enright & Sherrill reference for your age, height, weight and sex, as a percent of predicted. The distance is the device's estimate, never recomputed here. Without your age, height, weight and sex the percent is hidden and only the distance and trend are shown.", + "caveat": "An estimate re-framed against a published reference: a functional-capacity awareness signal, not a clinical 6-minute-walk test or a diagnosis. The reference was established for ages 40–80; outside that range the predicted value is an extrapolation." }, "TRAJECTORY": { "method": "A least-squares line fitted to your recent daily values and projected forward over a short horizon, with the textbook prediction interval that widens the further it reaches. Computed only when the recent trend is strong enough and your history is long and current enough; otherwise no line is drawn.", - "caveat": "A projection of your own recent trend — not a prediction, a target, or a clinical forecast. It holds only if the recent pattern continues; the shaded band shows how quickly that certainty fades." + "caveat": "A projection of your own recent trend, not a prediction, a target, or a clinical forecast. It holds only if the recent pattern continues; the shaded band shows how quickly that certainty fades." }, "SAME_TIME_BASELINE": { "method": "Your running total for today set against the median of the same local hour across your last four weeks, with a robust median ± MAD band around it. Only days with enough recorded detail count towards it, and no comparison is shown until at least fourteen of them are in hand.", @@ -4388,31 +4388,31 @@ "allClear": "All your vitals are within their personal range today.", "allClearMeta": "Checked {count} of your vitals against your own typical range.", "watch": "One vital is outside its usual range today.", - "watchVital": "Outside range: {vital}. Often just a one-off — worth a glance over the next few days.", + "watchVital": "Outside range: {vital}. Often just a one-off, worth a glance over the next few days.", "firedHeadline": "{count} of your vitals are outside their personal range today.", - "factors": "Possible factors — never a cause: a hard workout, poor sleep, alcohol, altitude, stress, or illness. This is awareness from your own baselines, not a diagnosis.", - "building": "Building your personal baselines — track a few more days and this will appear.", + "factors": "Possible factors (never a cause): a hard workout, poor sleep, alcohol, altitude, stress, or illness. This is awareness from your own baselines, not a diagnosis.", + "building": "Building your personal baselines. Track a few more days and this will appear.", "illnessExplained": "These shifts likely reflect the condition you logged." }, "trajectory": { "cardTitle": "Short-horizon projection", - "headline": "If this pattern continues — the next {days} days", + "headline": "If this pattern continues: the next {days} days", "range": "Projected around {low}–{high} {unit} in {days} days.", "caveat": "A projection of your own recent trend, not a prediction. The shaded band widens to show how quickly the uncertainty grows.", - "insufficient": "Not enough of a clear trend to project yet — keep tracking and a projection will appear once the recent pattern is strong enough.", + "insufficient": "Not enough of a clear trend to project yet. Keep tracking and a projection will appear once the recent pattern is strong enough.", "daysNeeded": "About {count} more days of tracking needed before a projection can appear." }, "sameTime": { "sectionTitle": "Today so far", "sectionSubtitle": "Your running totals against what is usual for you at this hour", - "learning": "Learning your usual day — {count} of {target} days", + "learning": "Learning your usual day: {count} of {target} days", "framing": "Typical by {time}: {typical} {unit}", "comparisonLabel": "Your typical day" } }, "cardioFitness": { "title": "Cardio Fitness", - "description": "Your VO₂ max over time — the headline measure of aerobic fitness.", + "description": "Your VO₂ max over time, the headline measure of aerobic fitness.", "chartTitle": "VO₂ max (mL/(kg·min))", "emptyState": { "title": "No cardio-fitness data yet", @@ -4492,7 +4492,7 @@ "navBreathingDisturbances": "Breathing", "rhythmEvents": { "sectionTitle": "Device health notifications", - "sectionIntro": "Notifications your watch sent on its own. HealthLog only shows these — it does not detect, confirm, or interpret them.", + "sectionIntro": "Notifications your watch sent on its own. HealthLog only shows these. It does not detect, confirm, or interpret them.", "loadError": "Could not load your device notifications.", "disclaimer": "These are alerts your device produced using its own built-in detection. They are shown here for your awareness only. This is not a medical assessment by HealthLog, and HealthLog does not diagnose any condition. If a notification concerns you, talk to your doctor.", "event": { @@ -4537,13 +4537,13 @@ "detail": "Hidden detail pages are also removed from the top navigation." }, "customize": "Customize Insights", - "regenerateRateLimited": "Refresh limit reached — please try again later.", - "regenerateUnavailable": "No fresh analysis arrived — please try again later.", - "regenerateError": "Still refreshing — please try again in a moment.", + "regenerateRateLimited": "Refresh limit reached. Please try again later.", + "regenerateUnavailable": "No fresh analysis arrived. Please try again later.", + "regenerateError": "Still refreshing. Please try again in a moment.", "regenerateSettling": "Your assessment is still being prepared", "regenerateSettleFailed": "The refresh could not be completed. Please try again later.", "deviceScore": { - "learning": "Still learning your baseline — a few more nights will fill in the trend.", + "learning": "Still learning your baseline. A few more nights will fill in the trend.", "average": "30-day average {value}", "unitScore": "score", "unitMinutes": "min", @@ -4556,14 +4556,14 @@ }, "recovery": { "title": "Recovery", - "description": "How well your body has bounced back — the recovery, strain and load signals your wearable records overnight.", + "description": "How well your body has bounced back: the recovery, strain and load signals your wearable records overnight.", "scoreCrossLink": "See the composite recovery score", "emptyTitle": "No recovery data yet", "empty": "No recovery data yet. Connect a WHOOP, Polar or Oura account and these scores fill in once your device syncs.", "block": { - "ansChargeExplainer": "How charged your autonomic nervous system is for the day ahead — a recharge reading drawn from your overnight heart and breathing signals.", + "ansChargeExplainer": "How charged your autonomic nervous system is for the day ahead, a recharge reading drawn from your overnight heart and breathing signals.", "dayStrainExplainer": "The day's whole-body cardiovascular load on your device's strain scale. Read it against your recovery, not as a goal on its own.", - "workoutStrainExplainer": "How demanding a single workout was on the same strain scale — the cardiovascular cost of that session.", + "workoutStrainExplainer": "How demanding a single workout was on the same strain scale: the cardiovascular cost of that session.", "cardioLoadExplainer": "A training-load proxy that tracks the acute cardiovascular load you have built up. Compare it with your own recent days.", "averageHeartRateExplainer": "Your average heart rate across the whole day or cycle, as reported by your wearable.", "maxHeartRateExplainer": "Your peak heart rate across the whole day or cycle, as reported by your wearable.", @@ -4576,7 +4576,7 @@ }, "resilience": { "explainer": "How well your body is balancing daily strain with recovery, read from your overnight signals across recent days.", - "learning": "Still learning your resilience — a few more days will settle the band.", + "learning": "Still learning your resilience. A few more days will settle the band.", "band": { "limited": "Limited", "adequate": "Adequate", @@ -4621,7 +4621,7 @@ "nights": "{count} nights tracked", "indexLine": "recent average index {value}", "eventsFlagged": "{count} events flagged by your device", - "disclaimer": "This is a screening signal, not a diagnosis — discuss with a clinician." + "disclaimer": "This is a screening signal, not a diagnosis. Discuss with a clinician." }, "labsChanges": { "sectionTitle": "Since your last panel", @@ -4637,14 +4637,14 @@ "navWaistToHeight": "Waist-to-height", "gripStrength": { "title": "Grip strength", - "description": "Maximal handgrip force — a robust proxy for whole-body strength. Below the sex-specific cut-off (men 27 kg, women 16 kg) flags probable sarcopenia; your own trend leads the read.", + "description": "Maximal handgrip force, a robust proxy for whole-body strength. Below the sex-specific cut-off (men 27 kg, women 16 kg) flags probable sarcopenia; your own trend leads the read.", "chartTitle": "Grip strength", "emptyState": { "title": "No grip strength yet", - "description": "Log a reading from a hand dynamometer — record the best of a few squeezes — and the trend will appear here.", + "description": "Log a reading from a hand dynamometer (record the best of a few squeezes) and the trend will appear here.", "cta": "Log grip strength" }, - "coachPrefill": "I haven't logged any grip strength yet — what does it tell me about my muscle health, and how do I measure and improve it?" + "coachPrefill": "I haven't logged any grip strength yet. What does it tell me about my muscle health, and how do I measure and improve it?" }, "pain": { "title": "Pain (0–10)", @@ -4655,29 +4655,29 @@ "description": "Log how your pain feels right now on the 0–10 scale and the trend will appear here.", "cta": "Log a pain score" }, - "coachPrefill": "I haven't logged any pain scores yet — how should I track pain on the 0–10 scale, and what counts as a meaningful change?" + "coachPrefill": "I haven't logged any pain scores yet. How should I track pain on the 0–10 scale, and what counts as a meaningful change?" }, "waist": { "title": "Waist circumference", - "description": "Waist girth in centimetres — a marker of central fat. The WHO increased-risk threshold is sex-specific (men 94 cm, women 80 cm); your own trend leads the read.", + "description": "Waist girth in centimetres, a marker of central fat. The WHO increased-risk threshold is sex-specific (men 94 cm, women 80 cm); your own trend leads the read.", "chartTitle": "Waist circumference", "emptyState": { "title": "No waist measurements yet", "description": "Measure your waist at the midpoint between the lowest rib and the hip bone, at the end of a normal breath, and log it here.", "cta": "Log waist circumference" }, - "coachPrefill": "I haven't logged any waist measurements yet — how do I measure my waist correctly, and what does the number mean for my health?" + "coachPrefill": "I haven't logged any waist measurements yet. How do I measure my waist correctly, and what does the number mean for my health?" }, "waistToHeight": { "title": "Waist-to-height ratio", - "description": "Your waist divided by your height — the ancestry-robust single number. Keeping it under 0.5 (waist below half your height) is the simple target.", + "description": "Your waist divided by your height, the ancestry-robust single number. Keeping it under 0.5 (waist below half your height) is the simple target.", "chartTitle": "Waist-to-height ratio", "emptyState": { "title": "No waist-to-height ratio yet", "description": "Log a waist-to-height ratio and the trend will appear here. The rule of thumb: keep your waist under half your height.", "cta": "Log waist-to-height ratio" }, - "coachPrefill": "I haven't logged a waist-to-height ratio yet — why is it a useful number, and how do I keep it under 0.5?" + "coachPrefill": "I haven't logged a waist-to-height ratio yet. Why is it a useful number, and how do I keep it under 0.5?" }, "ecg": { "sectionTitle": "ECG recordings", @@ -4720,7 +4720,7 @@ "intradayPulse": { "title": "Pulse through the day", "caption": "Averaged in 10-minute steps.", - "hourlyNote": "Showing this day's hourly average — recent days show the full 10-minute detail.", + "hourlyNote": "Showing this day's hourly average; recent days show the full 10-minute detail.", "empty": "Not enough heart-rate readings for this day to show its shape yet.", "coverageOne": "Based on 1 reading across {hours}h.", "coverageMany": "Based on {count} readings across {hours}h.", @@ -4729,10 +4729,10 @@ "previousDay": "Previous day", "nextDay": "Next day", "tension": { - "morning": "A sustained elevated-at-rest stretch this morning — possibly some tension.", - "afternoon": "A sustained elevated-at-rest stretch this afternoon — possibly some tension.", - "evening": "A sustained elevated-at-rest stretch this evening — possibly some tension.", - "night": "A sustained elevated-at-rest stretch overnight — possibly some tension." + "morning": "A sustained elevated-at-rest stretch this morning, possibly some tension.", + "afternoon": "A sustained elevated-at-rest stretch this afternoon, possibly some tension.", + "evening": "A sustained elevated-at-rest stretch this evening, possibly some tension.", + "night": "A sustained elevated-at-rest stretch overnight, possibly some tension." } }, "navEcg": "ECG", @@ -4785,14 +4785,14 @@ "metricBodyFat": "Body fat", "metricSleep": "Sleep duration", "metricSteps": "Daily steps", - "metricGlucoseFasting": "Glucose — fasting", - "metricGlucosePostprandial": "Glucose — post-meal", - "metricGlucoseRandom": "Glucose — random", - "metricGlucoseBedtime": "Glucose — bedtime", + "metricGlucoseFasting": "Glucose (fasting)", + "metricGlucosePostprandial": "Glucose (post-meal)", + "metricGlucoseRandom": "Glucose (random)", + "metricGlucoseBedtime": "Glucose (bedtime)", "metricBodyWater": "Body water", "metricBoneMass": "Bone mass", "metricOxygenSaturation": "Oxygen saturation (SpO₂)", - "unsetExplanation": "No override — using computed default.", + "unsetExplanation": "No override, using computed default.", "cardTitle": "Ranges per metric" }, "onboarding": { @@ -4806,11 +4806,11 @@ "steps": { "dashboardOverview": { "title": "Your dashboard", - "body": "The dashboard pulls every module together at a glance. Long-press a tile to reorder or hide it (Settings → Dashboard layout). Each tile is only as telling as the data behind it — the modules ahead fill them." + "body": "The dashboard pulls every module together at a glance. Long-press a tile to reorder or hide it (Settings → Dashboard layout). Each tile is only as telling as the data behind it, and the modules ahead fill them." }, "quickAdd": { "title": "Logged in seconds", - "body": "Use “+ Add” to log any reading in seconds — weight, blood pressure, pulse, glucose. Hidden strength: backdate readings you forgot to enter. Everything you log here feeds trends, the health score, and the AI insights." + "body": "Use “+ Add” to log any reading in seconds: weight, blood pressure, pulse, glucose. Hidden strength: backdate readings you forgot to enter. Everything you log here feeds trends, the health score, and the AI insights." }, "measurements": { "title": "Readings & target ranges", @@ -4822,7 +4822,7 @@ }, "labs": { "title": "Lab values", - "body": "Labs captures biomarkers with reference ranges — blood count, cholesterol, HbA1c. Strength: import and FHIR export. Out-of-range lab values resurface as evidence in the insights and the doctor report." + "body": "Labs captures biomarkers with reference ranges: blood count, cholesterol, HbA1c. Strength: import and FHIR export. Out-of-range lab values resurface as evidence in the insights and the doctor report." }, "illness": { "title": "Illness journal", @@ -4838,31 +4838,31 @@ }, "mood": { "title": "Mood", - "body": "Mood captures how you feel plus tags in two seconds. Strength: your own tags. Mood trends correlate with sleep, medications, and cycle — the Coach spots the patterns." + "body": "Mood captures how you feel plus tags in two seconds. Strength: your own tags. Mood trends correlate with sleep, medications, and cycle, and the Coach spots the patterns." }, "insights": { "title": "Insights", - "body": "Insights is the heart of it: evidence-based, dynamic analysis instead of generic tips — every statement points at your real data. Hidden: the layout is customizable. Insights pulls together everything the modules above provide." + "body": "Insights is the heart of it: evidence-based, dynamic analysis instead of generic tips. Every statement points at your real data. Hidden: the layout is customizable. Insights pulls together everything the modules above provide." }, "coach": { "title": "Coach", - "body": "The Coach answers questions about your data in a dialogue, using your history, medications, and lab values as context. Pick your AI provider yourself (your own key or local). It recomputes nothing — it reads the same numbers as the dashboard." + "body": "The Coach answers questions about your data in a dialogue, using your history, medications, and lab values as context. Pick your AI provider yourself (your own key or local). It recomputes nothing; it reads the same numbers as the dashboard." }, "integrations": { "title": "Integrations", - "body": "Integrations sync Withings, WHOOP, Polar, Oura, and Apple Health automatically. Weight, sleep, and recovery fill in without manual typing — and feed the insights and Coach in turn." + "body": "Integrations sync Withings, WHOOP, Polar, Oura, and Apple Health automatically. Weight, sleep, and recovery fill in without manual typing and feed the insights and Coach in turn." }, "export": { "title": "Doctor report", - "body": "The doctor report bundles readings, medications, lab values, and checkups as PDF or FHIR for the appointment. This is where every module converges — a complete report only comes from well-kept data." + "body": "The doctor report bundles readings, medications, lab values, and checkups as PDF or FHIR for the appointment. This is where every module converges: a complete report only comes from well-kept data." }, "achievements": { "title": "Achievements", - "body": "Achievements reward consistency — streaks and milestones. A small motivation loop that makes sticking with it easier." + "body": "Achievements reward consistency: streaks and milestones. A small motivation loop that makes sticking with it easier." }, "wrapUp": { "title": "That’s the tour", - "body": "This walkthrough runs once — it won't reopen on its own. Everything it covered stays put, and you can turn features on or off any time under Settings → Modules." + "body": "This walkthrough runs once and won't reopen on its own. Everything it covered stays put, and you can turn features on or off any time under Settings → Modules." } } }, @@ -4893,7 +4893,7 @@ "title": "You're all set", "body": "Welcome aboard. Your dashboard is ready.", "returnCta": "Open dashboard", - "learning": "Some insights — glucose, sleep rhythm, blood-pressure trends, cycle — sharpen over the first week or two as your data builds up. Empty tiles now just mean we're still learning your baseline.", + "learning": "Some insights (glucose, sleep rhythm, blood-pressure trends, cycle) sharpen over the first week or two as your data builds up. Empty tiles now just mean we're still learning your baseline.", "connectCta": "Connect a device", "logCta": "Log your first measurement", "importCta": "Import existing history", @@ -4910,33 +4910,33 @@ "anamnesis": { "title": "About your health (optional)", "subtitle": "A little context so HealthLog reads your numbers more fairly.", - "intro": "Share as much or as little as you like — every field is optional and you can edit it anytime in Settings.", + "intro": "Share as much or as little as you like. Every field is optional and you can edit it anytime in Settings.", "conditionsLabel": "Ongoing conditions", "conditionsPlaceholder": "e.g. high blood pressure, type 2 diabetes", "conditionsHint": "Helps HealthLog frame your readings in context rather than flagging the expected.", "allergiesLabel": "Allergies or intolerances", "allergiesPlaceholder": "e.g. penicillin, lactose", - "privacyNote": "Stored encrypted and used only to give you better context. We don't ask for your medications here — add those anytime from the Medications page." + "privacyNote": "Stored encrypted and used only to give you better context. We don't ask for your medications here. Add those anytime from the Medications page." }, "ai": { "panelTitle": "See what insights look like", - "panelIntro": "Coach, the daily briefing and the per-metric reads turn your own numbers into plain language. Here's the shape of it — before you connect anything.", + "panelIntro": "Coach, the daily briefing and the per-metric reads turn your own numbers into plain language. Here's the shape of it, before you connect anything.", "showSample": "See a sample briefing", "sampleTitle": "Daily Briefing", "sampleTag": "Example", "sampleAriaLabel": "Example daily briefing", - "sampleBody": "Weight down 1.2 kg over two weeks. Resting pulse steady at 58 bpm. Blood pressure in range on 6 of 7 days — the one high reading followed a late, salty dinner.", - "sampleCaption": "Example only — not your own data. This is what a briefing reads like once insights are on.", + "sampleBody": "Weight down 1.2 kg over two weeks. Resting pulse steady at 58 bpm. Blood pressure in range on 6 of 7 days; the one high reading followed a late, salty dinner.", + "sampleCaption": "Example only, not your own data. This is what a briefing reads like once insights are on.", "ladderTitle": "Three ways to turn it on", - "ladderLocalTitle": "Local model — AI requests stay on your network", - "ladderLocalBody": "Point HealthLog at Ollama or LM Studio on your own machine. Free and fully private — the calm default.", + "ladderLocalTitle": "Local model: AI requests stay on your network", + "ladderLocalBody": "Point HealthLog at Ollama or LM Studio on your own machine. Free and fully private, the calm default.", "ladderByokTitle": "Bring your own key", "ladderByokBody": "Use your own OpenAI or Anthropic key. It runs under your account and billing, and the API tier keeps your data out of training by default.", "ladderOauthTitle": "Sign in with a subscription", - "ladderOauthBody": "Connect a ChatGPT account — no per-token cost, but the consumer tier's terms may use content for training, so it's a deliberate choice, never the default for your health data.", - "keylessLine": "HealthLog is fully useful without AI. Your tiles, charts, trends and exports all work — AI only adds the plain-language read on top.", + "ladderOauthBody": "Connect a ChatGPT account. No per-token cost, but the consumer tier's terms may use content for training, so it's a deliberate choice, never the default for your health data.", + "keylessLine": "HealthLog is fully useful without AI. Your tiles, charts, trends and exports all work. AI only adds the plain-language read on top.", "setupCta": "Set it up (about a minute)", - "sharedKeyNote": "This instance already provides a shared AI provider, so insights work for you right now — no setup needed.", + "sharedKeyNote": "This instance already provides a shared AI provider, so insights work for you right now, no setup needed.", "offer": { "title": "This instance can write your summary in plain language.", "body": "The operator provides a provider that last worked within the past 24 hours. One tap turns the plain-language read on; your data then goes to that one provider and to nobody else.", @@ -5153,7 +5153,7 @@ "profileDescription": "Height, date of birth and gender unlock personalised targets.", "profileCta": "Open profile", "measurementTitle": "Log your first measurement", - "measurementDescription": "One reading unlocks the tile — the trend itself draws from your 5th reading.", + "measurementDescription": "One reading unlocks the tile; the trend itself draws from your 5th reading.", "measurementCta": "Add measurement", "medicationTitle": "Add a medication", "medicationDescription": "Track adherence and get reminders right when you need them.", @@ -5162,7 +5162,7 @@ "dataSourceDescription": "Auto-sync weight, BP, sleep and more from Withings, WHOOP, Oura, Polar, Nightscout, Fitbit or Apple Health.", "dataSourceCta": "Connect", "notificationsTitle": "Configure notifications", - "notificationsDescription": "Choose how HealthLog should remind you — Telegram, ntfy or Web Push.", + "notificationsDescription": "Choose how HealthLog should remind you: Telegram, ntfy or Web Push.", "notificationsCta": "Open notifications", "insightsTitle": "Turn on insights (optional)", "insightsDescription": "Add a local model or your own AI key to unlock the daily briefing and Coach.", @@ -5388,7 +5388,7 @@ "resetSuccess": "Source priority reset to defaults", "perMetricToggle": "Per-metric overrides ({count})", "perMetricHelp": "Metrics you have customised away from the default ladder. Use this list to roll any single metric back to its constant default without touching the rest.", - "perMetricEmpty": "No per-metric overrides set — every metric uses the global ladder above.", + "perMetricEmpty": "No per-metric overrides set. Every metric uses the global ladder above.", "resetMetric": "Reset", "deviceTypeToggle": "Device-type priority ({count})", "deviceTypeHelp": "Within a source, which device wins. When an Apple Watch and an iPhone both record steps, the higher-ranked device-type counts as the canonical reading.", @@ -5452,7 +5452,7 @@ "daysWithData": "{count} of {days} days", "moduleHint": "Syncing is controlled by the Nutrient intake module.", "moduleHintLink": "Manage modules", - "detail": "Read-only — the source app owns the numbers." + "detail": "Read-only: the source app owns the numbers." }, "helpDetail": "The others stay stored for the audit trail. Only sources you have connected or hold data from are listed.", "noneInUse": "No source to rank yet. Connect one under Integrations or record a value." @@ -5497,12 +5497,12 @@ "fullBackup": { "title": "Full backup", "description": "Your whole record in one JSON file.", - "scopeNote": "Document metadata and the AI-generated summary, if one exists, are included as plain text; original document files and workout GPS/sample data are not — download those separately from the vault or the workout export.", + "scopeNote": "Document metadata and the AI-generated summary, if one exists, are included as plain text; original document files and workout GPS/sample data are not. Download those separately from the vault or the workout export.", "encryptToggle": "Encrypt with a passphrase", "passphrasePlaceholder": "Passphrase (min. 12 characters)", "passphraseHelp": "Derives the archive key with Argon2id and seals it with AES-256-GCM. Save the file with a .hlx extension.", - "noRecoveryWarning": "There is no recovery — if you lose this passphrase, the archive cannot be opened. Keep it somewhere safe.", - "detail": "Same shape as the weekly auto-backup. Some record types are not carried yet — the file's manifest names what is in it.", + "noRecoveryWarning": "There is no recovery. If you lose this passphrase, the archive cannot be opened. Keep it somewhere safe.", + "detail": "Same shape as the weekly auto-backup. Some record types are not carried yet; the file's manifest names what is in it.", "contents": "Your measurements, medications, mood, cycle, labs, illness episodes, allergies, family history, nutrients, workouts, health profile and custom metrics in one JSON file." } }, @@ -5745,7 +5745,7 @@ "error": "Couldn't save. Please try again.", "toggleable": { "title": "What you track", - "description": "Disabled modules drop out of the navigation, tiles, and insights — your data stays untouched." + "description": "Disabled modules drop out of the navigation, tiles and insights, while your data stays untouched." }, "manageIn": "Manage in {section}", "operatorDisabled": "Disabled server-wide", @@ -5865,7 +5865,7 @@ "omitted": "{count} pillars are not listed because their tracking is switched off. Turn a module back on and its pillar comes back.", "omittedLink": "Open modules", "refusal": { - "empty": "A health score needs at least one area of health to score. Keep one selected — the score will say which areas it is built from." + "empty": "A health score needs at least one area of health to score. Keep one selected; the score will say which areas it is built from." }, "notice": { "upgrade": { @@ -6048,7 +6048,7 @@ "rawDataWarning": "Detailed history is on: every analysis also sends daily averages for the last 90 days, weekly averages for the year before, and monthly averages back to 5 years.", "regenerateInsights": "Regenerate reports", "regenerateSuccess": "Reports regenerated successfully", - "regenerateRateLimit": "Please wait — you've hit the hourly limit for analyses.", + "regenerateRateLimit": "Please wait: you've hit the hourly limit for analyses.", "lastGeneratedAt": "Last generated", "ai": { "chatgptConnectedBadge": "ChatGPT connected", @@ -6058,11 +6058,11 @@ "deviceCodeHeading": "Finish connecting on chatgpt.com", "deviceCodeStep1": "Open this link on any device:", "deviceCodeStep2": "Enter this one-time code:", - "deviceCodeStep3": "Approve the connection — this page updates automatically.", + "deviceCodeStep3": "Approve the connection. This page updates automatically.", "deviceCodeCopy": "copy", "deviceCodeWaiting": "Waiting for approval…", "deviceCodeCancel": "Cancel", - "oauthNotConfigured": "ChatGPT OAuth is not configured on this instance — use your own API key below instead.", + "oauthNotConfigured": "ChatGPT OAuth is not configured on this instance. Use your own API key below instead.", "modelLabel": "Model", "modelOptionDefault": "— Default —", "modelOptionCustom": "Custom…", @@ -6070,7 +6070,7 @@ "anthropicKeyLabel": "Anthropic API key", "baseUrlLabel": "Base URL", "localKeyLabel": "API key (optional)", - "localDescription": "Any OpenAI-compatible endpoint works here — a local model (Ollama, LM Studio) as well as a gateway such as LiteLLM, OpenRouter or vLLM. The base URL ends with /v1; the API key is optional.", + "localDescription": "Any OpenAI-compatible endpoint works here: a local model (Ollama, LM Studio) as well as a gateway such as LiteLLM, OpenRouter or vLLM. The base URL ends with /v1; the API key is optional.", "savedPreview": "(saved {preview})", "savedShort": "(saved)", "saveCta": "Save", @@ -6110,7 +6110,7 @@ "admin-openai": "Admin-provided OpenAI" }, "compat": { - "description": "A first-class provider for any endpoint that speaks the OpenAI /v1/chat/completions API: LiteLLM, OpenRouter, vLLM or another gateway. The base URL ends with /v1, the API key is optional, and the model is whatever your gateway routes. Your OpenAI key never reaches this endpoint — this provider has its own.", + "description": "A first-class provider for any endpoint that speaks the OpenAI /v1/chat/completions API: LiteLLM, OpenRouter, vLLM or another gateway. The base URL ends with /v1, the API key is optional, and the model is whatever your gateway routes. Your OpenAI key never reaches this endpoint; this provider has its own.", "keyLabel": "API key (optional)", "modelHint": "The model name your gateway expects. Left blank, the model saved for your other providers is used; with neither set, this provider is skipped." }, @@ -6146,18 +6146,18 @@ "notConfigured": "The operator has not configured a shared OpenAI key on this instance." }, "testProvider": "Test active provider", - "testSuccess": "OK — {provider} ({model})", + "testSuccess": "OK: {provider} ({model})", "testFailedShort": "Test failed: {message}", - "testUnexpectedResponse": "AI provider connection failed — unexpected response from the server.", - "testReasonCredentials": "Provider rejected the credentials — re-authenticate in AI settings.", - "testReasonRateLimited": "Provider rate-limited the request — try again shortly.", + "testUnexpectedResponse": "AI provider connection failed: unexpected response from the server.", + "testReasonCredentials": "Provider rejected the credentials. Re-authenticate in AI settings.", + "testReasonRateLimited": "Provider rate-limited the request. Try again shortly.", "testReasonServerError": "The AI provider returned a server error.", - "testReasonBadRequest": "The provider rejected the request (HTTP {status}) — the endpoint answered, so this is a request-shape or model-name problem, not connectivity.", + "testReasonBadRequest": "The provider rejected the request (HTTP {status}). The endpoint answered, so this is a request-shape or model-name problem, not connectivity.", "testReasonUnreachable": "Could not reach the AI provider.", "coachMemory": { "title": "What the Coach remembers", "description": "Durable facts you have told the Coach.", - "empty": "The Coach has not stored any facts yet. As you chat, it remembers durable details you share — your goals, conditions, preferences — and you can clear them here at any time.", + "empty": "The Coach has not stored any facts yet. As you chat, it remembers durable details you share (your goals, conditions, preferences), and you can clear them here at any time.", "learnedPrefix": "learned {when}", "categoryPreference": "Preferences", "categoryCondition": "Conditions", @@ -6173,7 +6173,7 @@ "forgetAllConfirmBody": "This removes every stored fact. The Coach will start fresh the next time you chat. This cannot be undone.", "forgetAllConfirmAction": "Forget everything", "cancel": "Cancel", - "summaryNote": "The Coach may also keep a short rolling summary of each conversation. There is no per-item control for it — deleting a conversation removes its summary.", + "summaryNote": "The Coach may also keep a short rolling summary of each conversation. There is no per-item control for it; deleting a conversation removes its summary.", "loadError": "Could not load what the Coach remembers.", "forgotToast": "Fact forgotten.", "forgotError": "Could not forget that fact. Please try again.", @@ -6194,7 +6194,7 @@ "markDone": "Done", "dismiss": "Dismiss", "deleteAria": "Delete this reminder", - "note": "Reminders are stored encrypted. Delete one any time — it is removed from what the Coach can see.", + "note": "Reminders are stored encrypted. Delete one any time and it is removed from what the Coach can see.", "status": { "proposed": "Suggested", "active": "Saved", @@ -6240,15 +6240,15 @@ "autoRead": { "title": "Read documents automatically with AI", "subLabel": "Your AI provider reads and indexes each new document without a tap per document.", - "honesty": "When on, each document you upload is sent to your configured AI provider to be read, described, and indexed for search — with no per-document confirmation. Turning it on also reaches backwards: documents you have already uploaded that carry no summary yet are sent too, up to 200 each time you switch it on. This happens on the server and the document's contents leave this machine to that provider. If your configured provider is a subscription connection (a signed-in AI account rather than an API key), that provider's own data settings apply — subscription providers may use the content to improve their models, and no data-processing agreement covers it. Documents read by a self-hosted local model never leave your server. Off by default; turn it on only if you accept this trade for your documents.", - "confirm": "I understand — turn on", + "honesty": "When on, each document you upload is sent to your configured AI provider to be read, described, and indexed for search, with no per-document confirmation. Turning it on also reaches backwards: documents you have already uploaded that carry no summary yet are sent too, up to 200 each time you switch it on. This happens on the server and the document's contents leave this machine to that provider. If your configured provider is a subscription connection (a signed-in AI account rather than an API key), that provider's own data settings apply: subscription providers may use the content to improve their models, and no data-processing agreement covers it. Documents read by a self-hosted local model never leave your server. Off by default; turn it on only if you accept this trade for your documents.", + "confirm": "I understand, turn on", "cancel": "Cancel" }, "centralCodex": { "title": "Use the server's shared AI access", "subLabel": "Send AI requests through the server's shared connection, with your own providers as the fallback.", - "honesty": "The shared access is a single signed-in AI account the operator connected for everyone on this server — not your own key. Requests you make on it are trained on by the provider by default and no data-processing agreement covers them, the account's hourly and weekly limits are shared with every other user who opted in, and your own configured providers are still tried first. Turn it on only if you accept this trade.", - "confirm": "I understand — use connection", + "honesty": "The shared access is a single signed-in AI account the operator connected for everyone on this server, not your own key. Requests you make on it are trained on by the provider by default and no data-processing agreement covers them, the account's hourly and weekly limits are shared with every other user who opted in, and your own configured providers are still tried first. Turn it on only if you accept this trade.", + "confirm": "I understand, use connection", "cancel": "Cancel" }, "consent": { @@ -6324,8 +6324,8 @@ "withingsClientId": "Client ID", "withingsClientSecret": "Client Secret", "withingsCredentialsSaved": "Credentials saved", - "withingsCredentialsSavedPlaceholder": "Saved — enter new to replace", - "withingsCredentialsSavedPlaceholderSecret": "Saved — enter new to replace", + "withingsCredentialsSavedPlaceholder": "Saved. Enter new to replace", + "withingsCredentialsSavedPlaceholderSecret": "Saved. Enter new to replace", "withingsSaveCredentials": "Save", "configured": "Configured", "withingsSync": "Sync now", @@ -6340,7 +6340,7 @@ }, "withingsFullSyncResult": "{count} measurements fully synchronized", "withingsSyncFailed": "Sync failed", - "withingsOauthConnected": "Withings connected — the first sync starts in the background.", + "withingsOauthConnected": "Withings connected. The first sync starts in the background.", "withingsOauthFailed": "Withings connection failed", "withingsOauthError": { "csrf1": "The security check failed because the browser cookie was missing. Please start the connection again in the same browser.", @@ -6365,8 +6365,8 @@ "whoopClientId": "Client ID", "whoopClientSecret": "Client Secret", "whoopCredentialsSaved": "Credentials saved", - "whoopCredentialsSavedPlaceholder": "Saved — enter new to replace", - "whoopCredentialsSavedPlaceholderSecret": "Saved — enter new to replace", + "whoopCredentialsSavedPlaceholder": "Saved. Enter new to replace", + "whoopCredentialsSavedPlaceholderSecret": "Saved. Enter new to replace", "whoopSaveCredentials": "Save", "whoopSync": "Sync now", "whoopFullSync": "Sync all data", @@ -6381,7 +6381,7 @@ "whoopConnect": "Connect with WHOOP", "whoopNoCredentials": "Please enter your API credentials above to connect WHOOP.", "whoopBackfillInProgress": "Importing your WHOOP history in the background…", - "whoopOauthConnected": "WHOOP connected — the first sync starts in the background.", + "whoopOauthConnected": "WHOOP connected. The first sync starts in the background.", "whoopOauthFailed": "WHOOP connection failed", "whoopOauthError": { "csrf1": "The security check failed because the browser cookie was missing. Please start the connection again in the same browser.", @@ -6395,14 +6395,14 @@ }, "fitbit": "Fitbit", "fitbitTag": "Fitbit & Pixel", - "fitbitDescription": "Connect Fitbit to sync your Fitbit and Pixel Watch vitals — weight, heart rate, and more.", + "fitbitDescription": "Connect Fitbit to sync your Fitbit and Pixel Watch vitals: weight, heart rate, and more.", "fitbitExperimentalBadge": "Experimental", "fitbitCredentials": "API Credentials", "fitbitClientId": "Client ID", "fitbitClientSecret": "Client Secret", "fitbitCredentialsSaved": "Credentials saved", - "fitbitCredentialsSavedPlaceholder": "Saved — enter new to replace", - "fitbitCredentialsSavedPlaceholderSecret": "Saved — enter new to replace", + "fitbitCredentialsSavedPlaceholder": "Saved. Enter new to replace", + "fitbitCredentialsSavedPlaceholderSecret": "Saved. Enter new to replace", "fitbitSaveCredentials": "Save", "fitbitSync": "Sync now", "fitbitFullSync": "Sync all data", @@ -6417,18 +6417,18 @@ "fitbitConnect": "Connect with Fitbit", "fitbitNoCredentials": "Please enter your API credentials above to connect Fitbit.", "fitbitBackfillInProgress": "Importing your Fitbit history in the background…", - "fitbitOauthConnected": "Fitbit connected — the first sync starts in the background.", + "fitbitOauthConnected": "Fitbit connected. The first sync starts in the background.", "fitbitOauthFailed": "Fitbit connection failed", "googleHealth": "Google Health", "googleHealthTag": "Fitbit & Pixel", "googleHealthBetaBadge": "Beta", - "googleHealthDescription": "Connect Fitbit, Pixel Watch and Fitbit Air through your Google account — weight, heart rate, sleep and activity. This replaces the classic Fitbit connection, which Google retires in September 2026.", + "googleHealthDescription": "Connect Fitbit, Pixel Watch and Fitbit Air through your Google account: weight, heart rate, sleep and activity. This replaces the classic Fitbit connection, which Google retires in September 2026.", "googleHealthCredentials": "API Credentials", "googleHealthClientId": "Client ID", "googleHealthClientSecret": "Client Secret", "googleHealthCredentialsSaved": "Credentials saved", - "googleHealthCredentialsSavedPlaceholder": "Saved — enter new to replace", - "googleHealthCredentialsSavedPlaceholderSecret": "Saved — enter new to replace", + "googleHealthCredentialsSavedPlaceholder": "Saved. Enter new to replace", + "googleHealthCredentialsSavedPlaceholderSecret": "Saved. Enter new to replace", "googleHealthSaveCredentials": "Save", "googleHealthSync": "Sync now", "googleHealthSyncCheckStatus": "Refresh status", @@ -6462,9 +6462,9 @@ "googleHealthConnect": "Connect with Google", "googleHealthNoCredentials": "Please enter your API credentials above to connect Google Health.", "googleHealthBackfillInProgress": "Importing your Google Health history in the background…", - "googleHealthReauthBanner": "Google has expired the connection — this happens periodically while your OAuth app stays in Testing mode. Reconnect to resume syncing.", + "googleHealthReauthBanner": "Google has expired the connection. This happens periodically while your OAuth app stays in Testing mode. Reconnect to resume syncing.", "googleHealthReconnect": "Reconnect", - "googleHealthOauthConnected": "Google Health connected — the first sync starts in the background.", + "googleHealthOauthConnected": "Google Health connected. The first sync starts in the background.", "googleHealthOauthFailed": "Google Health connection failed", "googleHealthOauthError": { "csrf1": "The security check failed because the browser cookie was missing. Please start the connection again in the same browser.", @@ -6499,10 +6499,10 @@ }, "integrationPill": { "connected": "Connected", - "errorReconnect": "Error — reconnect", + "errorReconnect": "Error: reconnect", "warningServerError": "Sync failing", "failureCount": "{count}/{threshold}", - "parkedReconnect": "Paused — reconnect", + "parkedReconnect": "Paused: reconnect", "notConnected": "Not connected", "justNow": "just now", "minutesAgo": "{count} min ago", @@ -6536,7 +6536,7 @@ "title": "Measurement tokens", "description": "Mint a token so a scale, a watch bridge or your home automation can add readings.", "detail": "The token is shown once.", - "scopeNote": "It can only add new readings to your own record — it cannot read your data, change or delete anything, or create another token. Readings are marked as coming from an external device, so you can tell them apart later, and you can still correct them yourself.", + "scopeNote": "It can only add new readings to your own record. It cannot read your data, change or delete anything, or create another token. Readings are marked as coming from an external device, so you can tell them apart later, and you can still correct them yourself.", "createFailed": "The token could not be created. Please try again.", "namePlaceholder": "Name, e.g. Home Assistant" }, @@ -6557,7 +6557,7 @@ "namePlaceholder": "Name, e.g. Paperless-ngx" }, "tokenMintMovedDescription": "Tokens are issued where they apply: above for measurements, workouts and documents, or in a medication's own API endpoint for that one medication.", - "tokenCreated": "Token created — copy it now! It won't be shown again.", + "tokenCreated": "Token created. Copy it now! It won't be shown again.", "tokenCopy": "Copy token", "tokenCopied": "Token copied to clipboard", "tokenCopyFailed": "Could not copy the token", @@ -6596,7 +6596,7 @@ "deleteAccountCta": "Delete account", "deleteAccountConfirmTitle": "Delete account permanently?", "deleteAccountConfirmDescription": "Your account, all health data, passkeys, sessions, and audit entries will be permanently deleted. You will be signed out immediately after.", - "deleteAccountSuccess": "Account deleted — signing you out.", + "deleteAccountSuccess": "Account deleted. Signing you out.", "deleteAccountFailed": "Account could not be deleted", "deleteAccountFinal": "Delete permanently", "saved": "Saved", @@ -6619,7 +6619,7 @@ "testing": "Testing…", "ok": "Connected (latency {latency} ms)", "errors": { - "credentials_rejected": "Credentials rejected — check your token", + "credentials_rejected": "Credentials rejected. Check your token", "rate_limited": "Rate-limited by the upstream", "timeout": "Request timed out", "upstream_error": "Upstream returned an error", @@ -6630,7 +6630,7 @@ "private_origin_not_approved": "Private network target. The operator has to list this origin in NOTIFICATION_PRIVATE_ORIGINS", "private_origin_not_grantable": "This address is link-local, a metadata or an unspecified address; no operator grant can open it. Use the address the relay listens on", "url_invalid": "URL is invalid", - "redirected": "Endpoint redirects — check the URL", + "redirected": "Endpoint redirects. Check the URL", "endpoint_not_found": "Endpoint not found at the URL", "credentials_unreadable": "Credentials cannot be decrypted", "upstream_invalid_json": "Upstream sent invalid JSON", @@ -6641,7 +6641,7 @@ }, "notificationStatus": { "title": "Delivery status", - "description": "State of each channel — “Auto-disabled” means retries stopped after permanent errors.", + "description": "State of each channel; “Auto-disabled” means retries stopped after permanent errors.", "emptyDescription": "Set up a channel under Settings › Integrations › Delivery channels.", "stateActive": "Active", "stateAutoDisabled": "Auto-disabled", @@ -6667,7 +6667,7 @@ }, "healthRecord": { "title": "Export health record", - "description": "A complete record for your doctor — as a PDF, as FHIR, or both.", + "description": "A complete record for your doctor: as a PDF, as FHIR, or both.", "format": "Format", "format_pdf": "PDF", "format_fhir": "Structured (FHIR)", @@ -6699,7 +6699,7 @@ "createTitle": "New share link", "createDescription": "The link is read-only and time-boxed.", "label": "Label", - "labelPlaceholder": "e.g. Dr. Smith — annual check-up", + "labelPlaceholder": "e.g. Dr. Smith, annual check-up", "range": "Days of history", "rangeHint": "How far back the shared window reaches.", "expiry": "Expires in (days)", @@ -6719,7 +6719,7 @@ "statusRevoked": "Revoked", "statusExpired": "Expired", "inactiveTitle": "Revoked and expired ({count})", - "shownOnce": "Shown once only. Capture the QR code and passphrase now — neither can be recovered later.", + "shownOnce": "Shown once only. Capture the QR code and passphrase now; neither can be recovered later.", "qrAlt": "QR code containing the share link and passphrase", "linkLabel": "Link", "passphraseLabel": "Passphrase", @@ -6730,12 +6730,12 @@ "attachTitle": "Attach documents", "attachButton": "Choose documents", "attachCount": "{count} of {max} selected", - "attachFrozen": "The document set is fixed once you create the link — documents can't be added or removed afterwards.", + "attachFrozen": "The document set is fixed once you create the link. Documents can't be added or removed afterwards.", "attachRemove": "Remove {title}", "exifNote": "Camera metadata (EXIF/GPS) is removed from JPEG, PNG and WebP images when shared. PDF, TIFF, HEIC and Office files pass through unchanged.", "documentCount": "Attached documents: {count}", "qrScanTitle": "Scan to open on another device", - "qrScanHint": "Point a phone camera at the code to open the shared record — the passphrase is already included.", + "qrScanHint": "Point a phone camera at the code to open the shared record. The passphrase is already included.", "pickerTitle": "Attach documents", "pickerDescription": "Search your vault and select documents to share. Up to {max}.", "pickerSearch": "Search documents", @@ -6748,7 +6748,7 @@ "statusNeedsReselect": "Pick contents again", "reselectReason": "This link served a scope that was never chosen, so it was closed. Create a new one and pick what it should contain.", "reselectAction": "Create a replacement", - "createDetail": "The token is shown once on creation — store it then; it cannot be recovered.", + "createDetail": "The token is shown once on creation. Store it then; it cannot be recovered.", "activeDescription": "Links you have shared, when they expire and how often they were opened." }, "genderOther": "Other", @@ -6757,10 +6757,10 @@ "nightscoutDescription": "Connect your own Nightscout site to sync continuous glucose readings into the glucose panel.", "nightscoutViewData": "View your glucose", "nightscoutUrl": "Nightscout URL", - "nightscoutUrlSavedPlaceholder": "Saved — enter a new URL to replace it", + "nightscoutUrlSavedPlaceholder": "Saved. Enter a new URL to replace it", "nightscoutToken": "API token", "nightscoutTokenOptional": "Optional for a public site", - "nightscoutTokenSavedPlaceholder": "Saved — enter a new token to replace it", + "nightscoutTokenSavedPlaceholder": "Saved. Enter a new token to replace it", "nightscoutTokenHelp": "Paste an access token from your Nightscout admin tools. Leave empty if your site is publicly readable.", "nightscoutPrivateOperatorTitle": "Private Nightscout access requires server operator approval.", "nightscoutPrivateOperatorDescription": "Ask your server operator to approve this exact Nightscout origin.", @@ -6781,7 +6781,7 @@ "polarClientId": "Client ID", "polarClientSecret": "Client Secret", "polarCredentialsSaved": "Credentials saved", - "polarCredentialsSavedPlaceholder": "Saved — enter new to replace", + "polarCredentialsSavedPlaceholder": "Saved. Enter new to replace", "polarSaveCredentials": "Save", "polarUnavailable": "Polar is not configured on this server. Add your own Polar OAuth credentials above, or ask your administrator to configure the shared app.", "polarConnect": "Connect Polar", @@ -6791,7 +6791,7 @@ "polarDisconnect": "Disconnect", "polarDisconnectTitle": "Disconnect Polar?", "polarDisconnectDescription": "Future syncs stop. Readings already imported stay in your history.", - "polarOauthConnected": "Polar connected — the first sync starts in the background.", + "polarOauthConnected": "Polar connected. The first sync starts in the background.", "polarOauthFailed": "Polar connection failed", "polarOauthError": { "csrf1": "The security check failed because the browser cookie was missing. Please start the connection again in the same browser.", @@ -6810,7 +6810,7 @@ "ouraClientId": "Client ID", "ouraClientSecret": "Client Secret", "ouraCredentialsSaved": "Credentials saved", - "ouraCredentialsSavedPlaceholder": "Saved — enter new to replace", + "ouraCredentialsSavedPlaceholder": "Saved. Enter new to replace", "ouraSaveCredentials": "Save", "ouraUnavailable": "Oura is not configured on this server. Add your own Oura OAuth credentials above, or ask your administrator to configure the shared app.", "ouraConnect": "Connect Oura", @@ -6820,7 +6820,7 @@ "ouraDisconnect": "Disconnect", "ouraDisconnectTitle": "Disconnect Oura?", "ouraDisconnectDescription": "Future syncs stop. Readings already imported stay in your history.", - "ouraOauthConnected": "Oura connected — the first sync starts in the background.", + "ouraOauthConnected": "Oura connected. The first sync starts in the background.", "ouraOauthFailed": "Oura connection failed", "ouraOauthError": { "csrf1": "The security check failed because the browser cookie was missing. Please start the connection again in the same browser.", @@ -6851,7 +6851,7 @@ } }, "integrationRedirectGuide": { - "intro": "This connects through your own {provider} developer app — about 5 minutes to set up:", + "intro": "This connects through your own {provider} developer app, about 5 minutes to set up:", "step1": "Create an app in the {provider} developer portal.", "step2": "Set its redirect / callback URL to:", "step3": "Paste the client ID and client secret it gives you above." @@ -6911,7 +6911,7 @@ }, "recovery": { "saveNow": "Save these recovery codes now", - "saveNowHint": "Each code works once. They are shown only this time — store them somewhere safe. If you lose your authenticator, a recovery code is the only way back in.", + "saveNowHint": "Each code works once. They are shown only this time. Store them somewhere safe. If you lose your authenticator, a recovery code is the only way back in.", "download": "Download", "remainingOne": "{count} recovery code remaining.", "remainingOther": "{count} recovery codes remaining.", @@ -6939,7 +6939,7 @@ }, "passkeyNudge": { "title": "Add a passkey for faster sign-in", - "body": "Passkeys let you sign in with your fingerprint, face, or device PIN — no password to remember." + "body": "Passkeys let you sign in with your fingerprint, face, or device PIN, no password to remember." }, "trustedDevices": { "title": "Trusted devices", @@ -7014,7 +7014,7 @@ "endpointLabel": "Connector URL", "connectDescription": "Paste this URL into your assistant's custom-connector setup, then authorize with the token below or sign in when prompted.", "tokensTitle": "Connector tokens", - "tokensDescription": "Mint a token to connect an assistant — read-only unless you allow logging below.", + "tokensDescription": "Mint a token to connect an assistant, read-only unless you allow logging below.", "scopeNote": "New tokens can only read your own records. Write access (health:write) is granted per token with the toggle below. A token can never reach admin functions.", "writeScopeToggleLabel": "Allow logging (health:write)", "writeScopeNote": "Adds the health:write scope so the assistant can log new measurements and mood entries to your account. Every write is confirmed first. The token still can't delete or edit existing entries, change medications, or reach REST or admin functions. Leave off for read-only access.", @@ -7038,7 +7038,7 @@ "stravaClientId": "Client ID", "stravaClientSecret": "Client Secret", "stravaCredentialsSaved": "Credentials saved", - "stravaCredentialsSavedPlaceholder": "Saved — enter new to replace", + "stravaCredentialsSavedPlaceholder": "Saved. Enter new to replace", "stravaSaveCredentials": "Save", "stravaUnavailable": "Strava is not configured on this server. Add your own Strava API credentials above, or ask your administrator to configure the shared app.", "stravaConnect": "Connect Strava", @@ -7048,7 +7048,7 @@ "stravaDisconnect": "Disconnect", "stravaDisconnectTitle": "Disconnect Strava?", "stravaDisconnectDescription": "Future syncs stop. Activities already imported stay in your history.", - "stravaOauthConnected": "Strava connected — the first sync starts in the background.", + "stravaOauthConnected": "Strava connected. The first sync starts in the background.", "stravaOauthFailed": "Strava connection failed", "stravaOauthError": { "csrf1": "The security check failed because the browser cookie was missing. Please start the connection again in the same browser.", @@ -7102,7 +7102,7 @@ }, "garminInfo": { "title": "Garmin", - "body": "Garmin has no direct connection here. Connect via Apple Health (iOS) or Google Health Connect (Android). Garmin's proprietary scores — Body Battery, Training Load, HRV Status, VO₂ max — are not shared by Garmin to either platform.", + "body": "Garmin has no direct connection here. Connect via Apple Health (iOS) or Google Health Connect (Android). Garmin's proprietary scores (Body Battery, Training Load, HRV Status, VO₂ max) are not shared by Garmin to either platform.", "docsLink": "Read the guide" }, "glucoseReference": { @@ -7183,27 +7183,27 @@ "loadingStatus": "Loading status…", "systemStatusLoadError": "Failed to load system status.", "systemStatusRetry": "Retry", - "adminSettingsLoadError": "Failed to load admin settings. Toggles below may not reflect the live state — refresh the page.", + "adminSettingsLoadError": "Failed to load admin settings. Toggles below may not reflect the live state. Refresh the page.", "hostMetrics": { "title": "Host load", "load1": "Load (1m)", "memUsedPercent": "Memory", "diskBusyPercent": "Disk I/O", "last2hours": "Last 2 hours", - "empty": "Sampling started — data appears in 1–2 minutes.", + "empty": "Sampling started. Data appears in 1–2 minutes.", "loadError": "Failed to load host metrics. Try refreshing the page." }, "aiServerKey": { "title": "AI server key", "description": "An operator key for accounts that have not configured one of their own.", - "byokHint": "A user's own key (BYOK, ChatGPT login or local provider) always takes precedence — the server key is the last step in the provider chain.", + "byokHint": "A user's own key (BYOK, ChatGPT login or local provider) always takes precedence; the server key is the last step in the provider chain.", "consentHint": "Requests over the server key require the user's active AI consent; without a consent receipt nothing is sent.", "baseUrlHint": "The base URL selects the API: an Anthropic URL such as https://api.anthropic.com/v1 is understood, any other host is called on the OpenAI-compatible API.", "statusConfigured": "Configured", "statusNotConfigured": "Not configured", "keyLabel": "API key", "keyPlaceholder": "sk-...", - "keyPlaceholderSet": "Stored ({preview}) — enter a new key to replace it", + "keyPlaceholderSet": "Stored ({preview}). Enter a new key to replace it", "modelLabel": "Model", "baseUrlLabel": "Base URL", "save": "Save", @@ -7246,7 +7246,7 @@ "title": "Insights Quality", "loading": "Loading feedback summary…", "loadError": "Failed to load Insights quality summary. Try refreshing the page.", - "empty": "No feedback yet. The aggregator runs daily at 04:00 — once users start rating recommendations, helpful-rate bands appear here.", + "empty": "No feedback yet. The aggregator runs daily at 04:00. Once users start rating recommendations, helpful-rate bands appear here.", "windowLabel": "Last {days} days", "generatedAtLabel": "Generated", "colSeverity": "Severity", @@ -7261,7 +7261,7 @@ "title": "Coach Feedback", "loading": "Loading Coach feedback summary…", "loadError": "Failed to load Coach feedback summary. Try refreshing the page.", - "empty": "No Coach feedback yet. The aggregator runs daily at 04:00 — once users rate Coach replies, helpful-rate bands appear here.", + "empty": "No Coach feedback yet. The aggregator runs daily at 04:00. Once users rate Coach replies, helpful-rate bands appear here.", "windowLabel": "Last {days} days", "generatedAtLabel": "Generated", "colPromptVersion": "Prompt version", @@ -7280,7 +7280,7 @@ "appSettingsDescription": "Global defaults for registration, language, and the timezone of new accounts.", "registrationEnabled": "Allow registration", "registrationEnabledDescription": "When disabled, new users cannot register.", - "registrationOpenHint": "Registration is open — anyone who can reach this instance can create an account. Close it here once everyone who needs an account has one.", + "registrationOpenHint": "Registration is open: anyone who can reach this instance can create an account. Close it here once everyone who needs an account has one.", "defaultLanguage": "Default language", "defaultLanguageDescription": "Used for new users and as fallback.", "defaultUserTimezone": "Default timezone for new accounts", @@ -7294,7 +7294,7 @@ "integrationWebPush": "Web Push", "offlineGeoLabel": "Geo data", "offlineGeoEnabled": "Offline (GeoLite2)", - "offlineGeoFallback": "Online ({host}) — mount GeoLite2 databases and set GEOLITE2_DIR", + "offlineGeoFallback": "Online ({host}). Mount GeoLite2 databases and set GEOLITE2_DIR", "offlineGeoOff": "Off", "offlineGeoChosen": "Online ({host})", "apiGlobal": "Allow API endpoints and API tokens.", @@ -7331,7 +7331,7 @@ "webPushVapidGenerating": "Generating…", "webPushVapidGenerated": "VAPID keys generated. Save the subject to finish.", "webPushVapidGenerateFailed": "Could not generate VAPID keys.", - "webPushVapidGenerateConfirm": "VAPID keys are already configured. Generating a new pair invalidates every browser push subscription — each device must re-subscribe. Continue?", + "webPushVapidGenerateConfirm": "VAPID keys are already configured. Generating a new pair invalidates every browser push subscription, and each device must re-subscribe. Continue?", "webPushVapidGenerateConfirmTitle": "Regenerate VAPID keys?", "webPushVapidRegenerate": "Regenerate", "configured": "Configured", @@ -7387,7 +7387,7 @@ "createdToast": "Invite created", "createError": "Could not create the invite.", "tokenTitle": "Invite link", - "tokenOnceHint": "Copyable only now — copy the link or have the QR code scanned.", + "tokenOnceHint": "Copyable only now. Copy the link or have the QR code scanned.", "hashExplainer": "Only a hash of the link is stored, so it cannot be shown again later. If it gets lost, revoke the invite and create a new one.", "copyLink": "Copy link", "copiedToast": "Link copied", @@ -7449,7 +7449,7 @@ "tokenName": "Name", "tokenPermissions": "Permissions", "tokenPermissionAll": "All", - "tokenPermissionAllTooltip": "Wildcard permission — this token can call every API route.", + "tokenPermissionAllTooltip": "Wildcard permission: this token can call every API route.", "tokenStatus": "Status", "tokenLastUsed": "Last used", "tokenCreated": "Created", @@ -7627,7 +7627,7 @@ "app-logs": { "title": "App logs", "subtitle": "Tail the most recent structured wide-events emitted by this process.", - "processNote": "Showing app-process logs only — worker-process logs go to Loki when that integration is configured.", + "processNote": "Showing app-process logs only; worker-process logs go to Loki when that integration is configured.", "filterTraceId": "Trace ID", "filterAction": "Action contains…", "filterLevel": "Level", @@ -7662,7 +7662,7 @@ "loading": "Loading backups…", "loadError": "Failed to load backups.", "emptyTitle": "No backups yet", - "emptyDescription": "Backups run automatically every Sunday at 03:00 — or trigger one now to create the first snapshot.", + "emptyDescription": "Backups run automatically every Sunday at 03:00, or trigger one now to create the first snapshot.", "colUser": "User", "colType": "Type", "typeWeeklyAuto": "Weekly (auto)", @@ -7698,11 +7698,11 @@ "restoreTitle": "Restore from backup", "restoreDescription": "This will replace ALL current data for {username} with the snapshot from {when}. Existing measurements, medications, intake events, mood entries, notification channels, push subscriptions and queued Telegram deletions will be deleted.", "restoreInstanceSettingsLabel": "Also restore instance settings", - "restoreInstanceSettingsHint": "Registration, MFA requirement, default locale, module availability, notification and AI configuration — taken from the snapshot and applied to everybody on this installation. Leave it clear to restore this account alone.", + "restoreInstanceSettingsHint": "Registration, MFA requirement, default locale, module availability, notification and AI configuration, taken from the snapshot and applied to everybody on this installation. Leave it clear to restore this account alone.", "restorePromptLabel": "Type RESTORE to continue", "previewTitle": "What this backup contains", "previewLoading": "Reading contents…", - "previewUnavailable": "Contents could not be read — restoring is still possible.", + "previewUnavailable": "Contents could not be read. Restoring is still possible.", "previewStillReading": "This backup was made by an earlier version, so its contents are being read in full, which takes a while for a large record. Open this dialog again in a few minutes to see them. Restoring does not depend on it.", "previewEmpty": "The file contains no records.", "previewOther": "Other records", @@ -7745,7 +7745,7 @@ "restoreSkippedMedicationTarget": "Medication target analyte", "restoreSkippedScheduleRevisionLink": "Schedule era succession", "restoreSkippedAccountSetting": "Account setting", - "restoreMissingTitle": "Restore refused — the file is incomplete", + "restoreMissingTitle": "Restore refused: the file is incomplete", "restoreMissingDescription": "The file's own manifest says it carries the section below, and it does not. Nothing was changed: a restore replaces a whole class of records, so putting back a section that is not in the file would have emptied it.", "restoreMissingRemedy": "Use a disaster-recovery snapshot, or export the account again and upload the new file. A section the manifest declares as omitted is a different thing and restores normally.", "restoreMissingDocuments": "Documents", @@ -7869,7 +7869,7 @@ "completed": "Completed", "failed": "Failed" }, - "coverageDetail": "Only key ids and counts are shown — never key material.", + "coverageDetail": "Only key ids and counts are shown, never key material.", "backupsTitle": "Keys the backups still need", "backupsDescription": "A retired key stays needed while any backup below still lists it.", "backupsStoredLine": "Key {key}: {count} stored copies, the oldest from {when}", @@ -7935,7 +7935,7 @@ "centralCodex": { "title": "Shared AI connection", "description": "Connect one signed-in ChatGPT account that any user on this server can opt into for AI features.", - "honesty": "This is a single shared, signed-in AI account — not an API key. Every user who opts in sends requests through it, so the account's hourly and weekly limits are shared across all of them, and the same limits already feed the Coach. Subscription providers may use the content to improve their models and no data-processing agreement covers it, so it is never the default and stays below no-training providers for document reads. Only connect an account you are comfortable sharing this way.", + "honesty": "This is a single shared, signed-in AI account, not an API key. Every user who opts in sends requests through it, so the account's hourly and weekly limits are shared across all of them, and the same limits already feed the Coach. Subscription providers may use the content to improve their models and no data-processing agreement covers it, so it is never the default and stays below no-training providers for document reads. Only connect an account you are comfortable sharing this way.", "statusConnected": "Connected", "statusDisconnected": "Not connected", "statusExpired": "Expired", @@ -7947,13 +7947,13 @@ "connectedSince": "Connected since {when}", "connected": "Shared AI connection linked", "disconnected": "Shared AI connection removed", - "error": "Something went wrong — please try again" + "error": "Something went wrong. Please try again" }, "failingJobs": { "title": "Background jobs", "description": "Queues whose jobs gave up after exhausting their retries.", "none": "No job has failed in the last {hours} hours.", - "unavailable": "No job queue to read — this deployment runs without the background worker.", + "unavailable": "No job queue to read. This deployment runs without the background worker.", "countOne": "{count} failure", "countFew": "{count} failures", "countOther": "{count} failures", @@ -8276,7 +8276,7 @@ }, "selfContextComplete": { "title": "Self-report maintained", - "description": "All four self-report fields filled in — the Coach knows your context." + "description": "All four self-report fields filled in. The Coach knows your context." }, "sleepLog7": { "title": "Sleep log for 7 days", @@ -8298,7 +8298,7 @@ }, "hiddenCard": { "title": "Hidden achievement", - "description": "Keep tracking — you might just stumble across it.", + "description": "Keep tracking. You might just stumble across it.", "ariaLabel": "Hidden locked achievement" }, "hiddenUnlockToast": { @@ -8307,7 +8307,7 @@ "dashboardCard": { "title": "Recent unlocks", "viewAll": "View all", - "empty": "No achievements yet — keep logging to unlock your first." + "empty": "No achievements yet. Keep logging to unlock your first." } }, "notifications": { @@ -8490,7 +8490,7 @@ } }, "edit": { - "title": "Edit target range — {metric}", + "title": "Edit target range: {metric}", "description": "Adjust the in-range band used across charts, insights and the doctor report. Values are in {unit}.", "derivedHint": "This card is derived from other metrics. Edit the underlying targets (e.g. blood pressure or weight) instead.", "minLabel": "Min", @@ -8522,11 +8522,11 @@ "aboveTarget": "{delta} {unit} above target", "belowTarget": "{delta} {unit} below target", "diastolic": "Diastolic", - "glucoseFasting": "Glucose — fasting", - "glucosePostprandial": "Glucose — post-meal", - "glucoseRandom": "Glucose — random", - "glucoseBedtime": "Glucose — bedtime", - "glucoseUnspecified": "Glucose — untagged", + "glucoseFasting": "Glucose (fasting)", + "glucosePostprandial": "Glucose (post-meal)", + "glucoseRandom": "Glucose (random)", + "glucoseBedtime": "Glucose (bedtime)", + "glucoseUnspecified": "Glucose (untagged)", "status": { "underweight": "Underweight", "normal": "Normal", @@ -8612,7 +8612,7 @@ "askMedicationName": "Please specify a medication, e.g. taken Ramipril.", "medicationNotFoundExact": "Medication not found. Please send the name exactly as in HealthLog.", "helpHeader": "Available commands:", - "helpBody": "/help — show this help\n/add — record an intake\n/start — start the bot\n\nText commands:\ntaken <name> — confirm an intake\n\nButtons in reminders:\n• Taken — confirm intake\n• 🕐 1h / 🕐 3h — postpone reminder\n• ⏭ Skip — skip intake\n• ✓ Confirm — confirm a missed intake", + "helpBody": "/help: show this help\n/add: record an intake\n/start: start the bot\n\nText commands:\ntaken <name>: confirm an intake\n\nButtons in reminders:\n• Taken: confirm intake\n• 🕐 1h / 🕐 3h: postpone reminder\n• ⏭ Skip: skip intake\n• ✓ Confirm: confirm a missed intake", "measureValuePrompt": "Reply with the value to log it (optional).", "buttonMeasureValue": "Value…", "measureValueSaved": "Reading saved.", @@ -8637,9 +8637,9 @@ }, "lowStockReminders": { "title": "Low supply: {medName}", - "bodyToday": "{medName}: {units} units left — less than one day of supply.", - "bodyReorder": "{medName}: {units} units left. Supply runs out around {runsOutOn} — reorder by {reorderBy}.", - "bodyLastDose": "{medName}: {units} units left — about your final dose. Supply runs out around {runsOutOn}.", + "bodyToday": "{medName}: {units} units left, less than one day of supply.", + "bodyReorder": "{medName}: {units} units left. Supply runs out around {runsOutOn}. Reorder by {reorderBy}.", + "bodyLastDose": "{medName}: {units} units left, about your final dose. Supply runs out around {runsOutOn}.", "bodyExpired": "{medName}: no usable supply left. {units} units are marked expired.", "bodyAsNeeded": "{medName}: only {units} units left. Reorder before you need the next dose." }, @@ -8666,11 +8666,11 @@ "questionConditions": "Do you have any chronic conditions the Coach should know about?", "questionFocus": "Is there anything specific the Coach should pay attention to?", "questionAllergies": "Do you have any allergies or intolerances?", - "questionAboutMe": "Want to tell the Coach a bit about yourself — routines, goals, context?" + "questionAboutMe": "Want to tell the Coach a bit about yourself: routines, goals, context?" }, "clinicianView": { "title": "Shared health record", - "period": "Reporting period: {start} – {end}", + "period": "Reporting period: {start}–{end}", "expires": "This link expires on {date}.", "provenance": "This is a read-only summary shared by the person it belongs to, exported from their self-tracked HealthLog data. Values are self-recorded and may include device-synced readings; treat them as patient-reported, not as a clinical examination.", "labs": "Lab values", @@ -8694,7 +8694,7 @@ "strain": "Strain score", "score": "Wellness score" }, - "footer": "Shared from HealthLog — a self-hosted personal health tracker.", + "footer": "Shared from HealthLog, a self-hosted personal health tracker.", "unlock": { "title": "Enter passphrase", "description": "This shared health record is protected. Enter the passphrase you were given to view it.", @@ -8782,7 +8782,7 @@ "generic": "Your {metric} runs about {delta} {unit} {dir} in your luteal phase than your follicular phase.", "dirHigher": "higher", "dirLower": "lower", - "empty": "Not enough cycles and readings yet to surface a phase pattern. Keep logging — this fills in as your history grows." + "empty": "Not enough cycles and readings yet to surface a phase pattern. Keep logging; this fills in as your history grows." }, "crosstab": { "description": "How each measurement compares between your luteal and follicular phases, on your own data.", @@ -8822,7 +8822,7 @@ }, "context": { "MENSTRUAL": "Hormone levels are at their lowest, which is why these days can feel like a quiet reset. Some people notice cramps, lighter sleep or a wish to slow down; others sail through with little change. All of that sits within the normal range, and how it feels can shift from one cycle to the next.", - "FOLLICULAR": "With oestrogen on the rise, many people describe these days as bright and open — sleep often comes more easily and the mind feels clearer. Basal body temperature usually stays in its lower band until just before ovulation. The length of this phase varies most from person to person, and from cycle to cycle.", + "FOLLICULAR": "With oestrogen on the rise, many people describe these days as bright and open: sleep often comes more easily and the mind feels clearer. Basal body temperature usually stays in its lower band until just before ovulation. The length of this phase varies most from person to person, and from cycle to cycle.", "OVULATORY": "Oestrogen peaks just before the egg is released, often alongside a brief lift in mood and a small rise in basal body temperature in the day or two that follow. Cervical fluid tends to become clearer and more stretchy around this window. A short twinge on one side is something some people notice; many feel nothing at all, and both are perfectly normal.", "LUTEAL": "Progesterone leads the second half and basal body temperature usually settles a little higher than earlier in the cycle. Some people notice shifts in sleep, appetite, mood or energy as the days go on, while others feel steady throughout. The pattern is personal, and it often looks different from one month to the next." }, @@ -8909,8 +8909,8 @@ "ariaUnknown": "No active cycle yet", "caption": "of your cycle", "firstPeriodCta": "Log my first period", - "periodOverdue": "Your period is later than usual — the day count pauses until the next period is logged.", - "periodOverdueDays": "Your period is {days} days later than usual — the day count pauses until the next period is logged.", + "periodOverdue": "Your period is later than usual. The day count pauses until the next period is logged.", + "periodOverdueDays": "Your period is {days} days later than usual. The day count pauses until the next period is logged.", "logPeriodCta": "Log period" }, "calendar": { @@ -8922,7 +8922,7 @@ "prevMonth": "Previous month", "nextMonth": "Next month", "loading": "Loading your calendar…", - "learning": "Learning your cycle — log at least three full cycles and the fertile window, ovulation and phases fill in. Until then the calendar shows only what you've logged.", + "learning": "Learning your cycle. Log at least three full cycles and the fertile window, ovulation and phases fill in. Until then the calendar shows only what you've logged.", "legendSymptom": "Symptoms", "legendOvulationConfirmed": "Confirmed ovulation", "flowSpotting": "spotting", @@ -8935,7 +8935,7 @@ "predictions": { "title": "What comes next", "nextPeriod": "Next period", - "nextPeriodWindow": "{low} – {high}", + "nextPeriodWindow": "{low}–{high}", "fertileWindow": "Fertile window", "ovulation": "Estimated ovulation", "confidenceHigh": "High", @@ -8944,7 +8944,7 @@ "stillLearning": "Still learning", "stillLearningBody": "Log at least three full cycles and your predictions sharpen. Until then this is a rough estimate.", "rawMode": "Prediction is off", - "rawModeBody": "You turned predictions off — only your logged data is shown, with no forecast.", + "rawModeBody": "You turned predictions off. Only your logged data is shown, with no forecast.", "none": "No prediction yet. Log a period to get started.", "ovulationConfirmed": "Ovulation (confirmed)" }, @@ -8977,7 +8977,7 @@ "symptoms": "Symptoms", "temperature": "Basal body temperature", "temperatureDisturbed": "Mark reading as disturbed", - "temperatureDisturbedHint": "Fever, illness, alcohol or a late measurement — excluded from the temperature evaluation.", + "temperatureDisturbedHint": "Fever, illness, alcohol or a late measurement: excluded from the temperature evaluation.", "ovulationTest": "Ovulation test", "mucus": "Cervical mucus", "cervix": "Cervix", @@ -9045,7 +9045,7 @@ "remindersDescription": "Turn period reminders on per channel in notification settings.", "remindersLink": "Notification settings", "fertileReminder": "Fertile-window reminder", - "fertileReminderDescription": "Get a heads-up a few days before your estimated fertile window. Off by default — turn it on per channel in notification settings." + "fertileReminderDescription": "Get a heads-up a few days before your estimated fertile window. Off by default; turn it on per channel in notification settings." }, "contraceptive": { "NONE": "None", @@ -9073,15 +9073,15 @@ "fieldInfo": { "bbt": "Your resting temperature, taken first thing in the morning before getting up. It rises slightly (about 0.2–0.3 °C) after ovulation.", "bbtLabel": "What is basal body temperature?", - "mucus": "Vaginal discharge changes across the cycle — from dry or sticky to creamy, then watery and egg-white-like around the most fertile days.", + "mucus": "Vaginal discharge changes across the cycle, from dry or sticky to creamy, then watery and egg-white-like around the most fertile days.", "mucusLabel": "What is cervical mucus?", - "ovulationTest": "A home urine test that detects the LH surge — the hormone spike about 24–36 h before ovulation. A positive flags the most fertile window.", + "ovulationTest": "A home urine test that detects the LH surge, the hormone spike about 24–36 h before ovulation. A positive flags the most fertile window.", "ovulationTestLabel": "What is an ovulation test?", "spotting": "Light bleeding outside the period.", "spottingLabel": "What is spotting between periods?", "pregnancyTest": "Result of a home pregnancy (hCG) test.", "pregnancyTestLabel": "What is a pregnancy test?", - "progesteroneTest": "A test confirming ovulation has occurred — progesterone rises afterward.", + "progesteroneTest": "A test confirming ovulation has occurred; progesterone rises afterward.", "progesteroneTestLabel": "What is a progesterone test?", "intercourse": "Whether sexual intercourse took place on this day.", "intercourseLabel": "What does intercourse track?", @@ -9134,14 +9134,14 @@ "postpone": { "menuItem": "Postpone…", "title": "Postpone due date", - "description": "Only moves the current due date — the regular rhythm stays unchanged.", + "description": "Only moves the current due date; the regular rhythm stays unchanged.", "chip": "+{days} days", "dateLabel": "New date", "confirm": "Postpone" }, "skip": { "heading": "Skip this due date", - "explainer": "Recorded honestly as skipped — not as done. The interval restarts from today.", + "explainer": "Recorded honestly as skipped, not as done. The interval restarts from today.", "action": "Skip", "confirmTitle": "Skip this due date?" }, @@ -9282,7 +9282,7 @@ "localOcr": { "heading": "Read scans on this device", "description": "Reads the photo on your device and sends only the extracted text to your provider.", - "detail": "Useful when your AI provider cannot read images. Less accurate — review every value before saving." + "detail": "Useful when your AI provider cannot read images. Less accurate: review every value before saving." }, "sort": { "heading": "Sort order", @@ -9326,7 +9326,7 @@ "sourceRangePlaceholder": "e.g. 3.5 - 5.0 or < 5", "sourceRangeAdd": "+ Add the range from the report", "sourceRangeHint": "Optional. Applies to this reading only; your saved range stays as it is.", - "sourceRangeUnparsed": "Kept as written — no numeric range read from it." + "sourceRangeUnparsed": "Kept as written, no numeric range read from it." }, "backToLabs": "Back to lab results", "hasNote": "Note", @@ -9344,7 +9344,7 @@ "emptyDescription": "Add a value to start tracking this biomarker over time.", "title": "Biomarker", "genericDescription": "A lab biomarker you track. Add readings to follow how it trends against its reference range.", - "valuesTitle": "{marker} — all readings", + "valuesTitle": "{marker}: all readings", "valuesDescription": "Every reading for this biomarker. Edit or remove an entry directly.", "backToMarker": "Back to {marker}", "latestResult": "Latest result" @@ -9364,7 +9364,7 @@ }, "biomarker": { "manageTitle": "Biomarkers", - "managerDescription": "Define a marker once — its unit and range are reused for every reading.", + "managerDescription": "Define a marker once; its unit and range are reused for every reading.", "define": "Define", "defineFirst": "Define your first biomarker", "defineTitle": "Define biomarker", @@ -9383,7 +9383,7 @@ "form": { "seedLabel": "Start from a common marker", "seedPlaceholder": "Choose a marker (optional)", - "seedHint": "Picking one fills the fields below — adjust the range to match your lab.", + "seedHint": "Picking one fills the fields below. Adjust the range to match your lab.", "name": "Name", "namePlaceholder": "e.g. LDL cholesterol", "unit": "Unit", @@ -9397,7 +9397,7 @@ "upperPlaceholder": "Upper bound", "context": "Context", "contextPlaceholder": "Optional note about this marker", - "rangeHint": "Either bound is optional — leave one blank for an open-ended range (e.g. LDL < 116).", + "rangeHint": "Either bound is optional. Leave one blank for an open-ended range (e.g. LDL < 116).", "requiredError": "Name and unit are required.", "rangeOrderError": "The lower bound must not exceed the upper bound.", "save": "Save biomarker", @@ -9453,7 +9453,7 @@ "bloodCount": "Blood count" }, "desc": { - "total-cholesterol": "Total cholesterol is the sum of the cholesterol carried across all lipoprotein particles in the blood, including the LDL, HDL, and remnant fractions. Cholesterol itself is an essential building block for cell membranes, hormones, and bile acids. As a single number it is a coarse summary, because both a healthy HDL share and a high LDL share lift the total — so it is usually read alongside the individual fractions. It is tracked mainly as part of long-term cardiovascular risk assessment.", + "total-cholesterol": "Total cholesterol is the sum of the cholesterol carried across all lipoprotein particles in the blood, including the LDL, HDL, and remnant fractions. Cholesterol itself is an essential building block for cell membranes, hormones, and bile acids. As a single number it is a coarse summary, because both a healthy HDL share and a high LDL share lift the total, so it is usually read alongside the individual fractions. It is tracked mainly as part of long-term cardiovascular risk assessment.", "ldl": "LDL cholesterol is the cholesterol carried by low-density lipoprotein particles, the fraction that delivers cholesterol to tissues but can also deposit it in artery walls. Over years this deposition contributes to atherosclerotic plaque, which is why LDL is one of the most closely watched lipid markers. Lower long-term exposure generally tracks with lower cardiovascular risk. It is interpreted by risk category rather than against one fixed normal value.", "hdl": "HDL cholesterol is the cholesterol carried by high-density lipoprotein particles, which collect surplus cholesterol from tissues and return it to the liver for recycling or removal. Because of this transport role it is often described as the protective fraction. Very low levels tend to accompany higher cardiovascular risk, though raising it artificially has not reliably reduced risk, so it is read as a marker rather than a target. It is usually interpreted together with LDL and triglycerides.", "triglycerides": "Triglycerides are the main form of fat circulating in the blood, supplied both by the diet and produced by the liver, and they serve as a key energy store. Levels rise after meals, so the sample is usually taken fasting for comparability. Persistently high triglycerides are associated with metabolic and cardiovascular risk and often travel with insulin resistance and low HDL. They are read as one component of the overall lipid picture.", @@ -9462,27 +9462,27 @@ "tsh": "TSH (thyroid-stimulating hormone) is released by the pituitary gland to signal the thyroid to produce its hormones, and it adjusts up or down to keep them in balance. Because of this feedback loop, TSH is the most sensitive first-line screen of thyroid function: it tends to move before the thyroid hormones themselves drift. A raised or lowered TSH points toward an under- or over-active thyroid and usually prompts measurement of the thyroid hormones directly. Pregnancy and age shift the expected range.", "ft3": "Free T3 (triiodothyronine) is the unbound, biologically active form of the more potent thyroid hormone, the fraction available to act on tissues. Most circulating T3 is bound to carrier proteins and inactive, so the free portion is what reflects true hormone availability. It is measured to characterise thyroid function, especially alongside TSH and free T4 when results are unclear. Levels are strongly assay-dependent and read in clinical context.", "ft4": "Free T4 (thyroxine) is the unbound form of the main hormone the thyroid releases into the blood, serving as a reservoir that tissues convert to the more active T3 as needed. The free fraction reflects what is actually available to the body, independent of carrier-protein levels. It is usually measured together with TSH to separate thyroid-gland problems from pituitary signalling. Pregnancy and certain medications can shift it.", - "ferritin": "Ferritin is the body's main iron-storage protein, and its blood level broadly mirrors total iron reserves. A low value points toward depleted stores, while a high value can reflect iron overload — or simply inflammation, because ferritin also rises as an acute-phase reactant. For that reason it is often interpreted alongside other iron markers and signs of inflammation. It is one of the core measures used to assess iron status.", - "transferrin-saturation": "Transferrin saturation is the percentage of transferrin — the protein that ferries iron through the blood — that is currently loaded with iron. It links the amount of iron in transit to the body's iron-carrying capacity, giving a snapshot of iron availability that complements ferritin's view of storage. A low saturation suggests iron is in short supply, while a high value can indicate overload. It is read together with ferritin and the full iron panel.", + "ferritin": "Ferritin is the body's main iron-storage protein, and its blood level broadly mirrors total iron reserves. A low value points toward depleted stores, while a high value can reflect iron overload, or simply inflammation, because ferritin also rises as an acute-phase reactant. For that reason it is often interpreted alongside other iron markers and signs of inflammation. It is one of the core measures used to assess iron status.", + "transferrin-saturation": "Transferrin saturation is the percentage of transferrin (the protein that ferries iron through the blood) that is currently loaded with iron. It links the amount of iron in transit to the body's iron-carrying capacity, giving a snapshot of iron availability that complements ferritin's view of storage. A low saturation suggests iron is in short supply, while a high value can indicate overload. It is read together with ferritin and the full iron panel.", "vitamin-d": "Vitamin D is measured as 25-hydroxyvitamin D, the circulating storage form and the standard marker of overall vitamin D status. The body makes it in skin exposed to sunlight and absorbs some from food, and it supports calcium balance, bone health, and immune function. Levels vary with season, latitude, skin tone, and supplementation. It is tracked to gauge whether stores are adequate over time.", - "vitamin-b12": "Vitamin B12 (cobalamin) is an essential vitamin obtained mainly from animal-source foods and stored largely in the liver. It is required for red-blood-cell formation, DNA synthesis, and the health of the nervous system. Prolonged shortfall — from low intake or impaired absorption — can lead to anaemia and nerve-related symptoms. It is measured to assess nutritional status, particularly where intake or absorption may be limited.", + "vitamin-b12": "Vitamin B12 (cobalamin) is an essential vitamin obtained mainly from animal-source foods and stored largely in the liver. It is required for red-blood-cell formation, DNA synthesis, and the health of the nervous system. Prolonged shortfall, from low intake or impaired absorption, can lead to anaemia and nerve-related symptoms. It is measured to assess nutritional status, particularly where intake or absorption may be limited.", "folate": "Folate (vitamin B9) is a B-vitamin found in leafy greens, legumes, and fortified foods, central to red-blood-cell formation and DNA synthesis. It works closely with vitamin B12, and a shortfall in either can produce a similar type of anaemia. Adequate folate is especially important around early pregnancy for healthy fetal development. It is measured to assess nutritional status and the cause of certain anaemias.", "hs-crp": "High-sensitivity CRP measures C-reactive protein, a marker the liver releases in response to inflammation, using an assay refined to detect the low concentrations relevant to cardiovascular risk. Unlike standard CRP used for acute infection, the high-sensitivity version captures the subtle, chronic inflammation linked to vascular disease. Because any recent infection or injury can raise it, it is interpreted away from acute illness and often confirmed with a repeat sample. It is read as one contributor to overall cardiovascular risk.", "creatinine": "Creatinine is a waste product of normal muscle metabolism that the kidneys filter out of the blood at a fairly steady rate. Because production is relatively constant, its blood level serves as a practical gauge of how well the kidneys are clearing waste. Values are also influenced by muscle mass, hydration, and diet, so it is usually interpreted alongside the estimated filtration rate. It is a core marker of kidney function.", "egfr": "eGFR (estimated glomerular filtration rate) estimates how much blood the kidneys filter each minute, calculated from creatinine together with age and sex. It translates a raw creatinine value into a more directly interpretable measure of kidney function. A declining eGFR over time is the main way chronic kidney changes are staged and tracked. As an estimate it is read as a trend rather than a single exact figure.", "alt": "ALT (alanine aminotransferase) is an enzyme concentrated in liver cells, released into the blood when those cells are stressed or damaged. Because it is relatively liver-specific, it is one of the primary markers used to detect liver injury or inflammation. Levels can rise with fatty liver, viral hepatitis, alcohol, or certain medications. It is usually read together with AST and the other liver-panel markers.", - "ast": "AST (aspartate aminotransferase) is an enzyme found in the liver but also in muscle, heart, and red blood cells, released when any of those tissues is injured. Because it is less liver-specific than ALT, the two are interpreted together — their ratio can hint at the source and nature of the problem. Vigorous exercise or muscle injury can raise it independently of the liver. It is one of the standard liver-panel enzymes.", - "ggt": "GGT (gamma-glutamyl transferase) is an enzyme found in the liver and the bile ducts that rises particularly when bile flow is obstructed or with alcohol exposure. It is often used to clarify why another liver marker is elevated — for example, to distinguish a liver or bile-duct source. It is sensitive but not very specific, so it is read in context with the rest of the liver panel. It is one of several markers used to assess liver and biliary health.", + "ast": "AST (aspartate aminotransferase) is an enzyme found in the liver but also in muscle, heart, and red blood cells, released when any of those tissues is injured. Because it is less liver-specific than ALT, the two are interpreted together; their ratio can hint at the source and nature of the problem. Vigorous exercise or muscle injury can raise it independently of the liver. It is one of the standard liver-panel enzymes.", + "ggt": "GGT (gamma-glutamyl transferase) is an enzyme found in the liver and the bile ducts that rises particularly when bile flow is obstructed or with alcohol exposure. It is often used to clarify why another liver marker is elevated, for example, to distinguish a liver or bile-duct source. It is sensitive but not very specific, so it is read in context with the rest of the liver panel. It is one of several markers used to assess liver and biliary health.", "sodium": "Sodium is the principal electrolyte in the fluid outside the body's cells and the main driver of fluid balance and blood volume. The body regulates it tightly through thirst, hormones, and the kidneys, so its blood level reflects the balance between water and salt more than dietary intake alone. Abnormal values usually signal a disturbance of water balance rather than of sodium itself. It is a core part of the basic metabolic and electrolyte panel.", "potassium": "Potassium is the main electrolyte inside the body's cells and is essential for nerve signalling and the steady rhythm of the heart muscle. Its blood level is held within a narrow range by the kidneys and hormonal signals, because both high and low values can disturb the heart's electrical activity. Levels can be affected by kidney function, hydration, and several common medications. It is a core measure in the electrolyte panel.", "hemoglobin": "Haemoglobin is the iron-containing protein in red blood cells that binds oxygen in the lungs and carries it to the tissues. Its concentration is the main measure of the blood's oxygen-carrying capacity and the central marker for detecting anaemia. Low values can reflect blood loss, iron or vitamin shortfalls, or reduced production, while high values can follow dehydration or low-oxygen conditions. It is a cornerstone of the complete blood count.", "hematocrit": "Haematocrit is the proportion of blood volume made up of red blood cells, expressed as a percentage. It moves closely with haemoglobin and gives a complementary view of red-cell mass and the blood's oxygen-carrying capacity. Hydration affects it, since plasma-volume changes shift the proportion even when red-cell numbers are stable. It is read alongside haemoglobin and the rest of the blood count.", "wbc": "The white blood cell count is the total number of immune cells circulating in the blood, the body's mobile defence against infection. It rises in response to infection, inflammation, or stress and can fall when the bone marrow is suppressed or in some immune conditions. Because it sums several distinct cell types, a notable change is often followed up with a differential that breaks it down. It is a core component of the complete blood count.", "platelets": "Platelets are small cell fragments in the blood that clump together and form the initial plug that stops bleeding from a damaged vessel. Their count reflects the balance between production in the bone marrow and consumption or breakdown. A low count can raise bleeding tendency, while a high count can follow inflammation or other stimuli. It is part of the complete blood count and a basic gauge of clotting capacity.", - "apob": "Apolipoprotein B is the structural protein carried by each of the atherogenic lipoprotein particles, so measuring it counts those particles directly rather than the cholesterol they carry. Because one ApoB molecule sits on each LDL, VLDL, and related particle, it can capture cardiovascular risk that an LDL-cholesterol value misses — particularly when particle number and cholesterol content diverge. For this reason it is increasingly used to refine lipid-based risk assessment. It is interpreted alongside the standard lipid panel.", + "apob": "Apolipoprotein B is the structural protein carried by each of the atherogenic lipoprotein particles, so measuring it counts those particles directly rather than the cholesterol they carry. Because one ApoB molecule sits on each LDL, VLDL, and related particle, it can capture cardiovascular risk that an LDL-cholesterol value misses, particularly when particle number and cholesterol content diverge. For this reason it is increasingly used to refine lipid-based risk assessment. It is interpreted alongside the standard lipid panel.", "lp-a": "Lipoprotein(a) is an LDL-like particle with an extra attached protein, and its level is largely set by genetics and stays fairly stable through life. Elevated Lp(a) is an independent, inherited risk factor for cardiovascular disease and aortic-valve narrowing. Because it changes little, it is usually measured once to establish a person's lifelong risk rather than tracked repeatedly. It is reported in molar units and read as part of overall cardiovascular risk.", - "fasting-insulin": "Fasting insulin is the level of insulin — the hormone that moves glucose from the blood into cells — measured after an overnight fast. Paired with fasting glucose, it helps estimate insulin resistance, the state in which the body needs more insulin to keep glucose in range. A high fasting insulin alongside normal glucose can be an early sign that this compensation is under way. It is read as part of a metabolic-health picture rather than in isolation.", - "omega-3-index": "The omega-3 index is the share of EPA and DHA — the two long-chain marine omega-3 fatty acids — among the fatty acids in red-blood-cell membranes. Because red cells turn over slowly, it reflects long-term omega-3 intake rather than a recent meal. A higher index has been associated in observational studies with lower cardiovascular risk. It is tracked as a stable marker of omega-3 status that responds to diet over months." + "fasting-insulin": "Fasting insulin is the level of insulin (the hormone that moves glucose from the blood into cells) measured after an overnight fast. Paired with fasting glucose, it helps estimate insulin resistance, the state in which the body needs more insulin to keep glucose in range. A high fasting insulin alongside normal glucose can be an early sign that this compensation is under way. It is read as part of a metabolic-health picture rather than in isolation.", + "omega-3-index": "The omega-3 index is the share of EPA and DHA (the two long-chain marine omega-3 fatty acids) among the fatty acids in red-blood-cell membranes. Because red cells turn over slowly, it reflects long-term omega-3 intake rather than a recent meal. A higher index has been associated in observational studies with lower cardiovascular risk. It is tracked as a stable marker of omega-3 status that responds to diet over months." }, "apob": "Apolipoprotein B (ApoB)", "lp-a": "Lipoprotein(a)", @@ -9500,7 +9500,7 @@ "acceptImageOnly": "JPEG, PNG, or WebP", "extracting": "Reading your report…", "readingOnDevice": "Reading on your device…", - "localModeHint": "Read on your device, then sent as text. Less accurate — review every value.", + "localModeHint": "Read on your device, then sent as text. Less accurate: review every value.", "rangeFromScan": "Reference range taken from the scan", "rangeVerify": "Verify the reference range", "reviewTitle": "Review before saving", @@ -9515,12 +9515,12 @@ "dateLabel": "Date", "refLowLabel": "Reference low", "refHighLabel": "Reference high", - "newBiomarker": "New biomarker — will be created", + "newBiomarker": "New biomarker, will be created", "linksExisting": "Links to existing {name}", "duplicateWarning": "A matching reading already exists", "lowConfidence": "Please double-check this value", "lowConfidenceBadge": "Low confidence", - "valueUnreadable": "Value unreadable — enter it manually", + "valueUnreadable": "Value unreadable. Enter it manually", "saveSelected": "Save {count} selected", "discardAll": "Discard all", "savedToast": "{count} lab results saved", @@ -9903,7 +9903,7 @@ }, "correlation": { "title": "How it unfolded", - "learning": "Still learning — log a few more days to see patterns here.", + "learning": "Still learning. Log a few more days to see patterns here.", "preOnsetTitle": "How it announced itself", "preOnsetBody": "Signals that drifted from your baseline before you marked the onset.", "nadirTitle": "What changed", @@ -9930,7 +9930,7 @@ "countOne": "You logged 1 episode in this period.", "countOther": "You logged {count} episodes in this period.", "typicalGap": "Typical recovery gap: {days} days between feeling better and your numbers settling.", - "typicalGapWithDriver": "Typical recovery gap: {days} days — you tend to feel better before your {vital} settles.", + "typicalGapWithDriver": "Typical recovery gap: {days} days; you tend to feel better before your {vital} settles.", "typicalGapLearning": "A few more resolved episodes and a typical recovery gap will appear here.", "none": "No episodes logged in this period.", "analyze": "Analyse the recovery gap" @@ -9991,8 +9991,8 @@ "stop": "I measure enough", "accepted": "Reminder set", "dismissed": "Okay, I won't suggest this again", - "stopped": "Got it — I'll stop suggesting reminders", - "failed": "Couldn't set that up — please try again", + "stopped": "Got it, I'll stop suggesting reminders", + "failed": "Couldn't set that up. Please try again", "cadence": { "weightDaily": "Weigh yourself daily, around the same time", "bp722": "Measure your blood pressure twice a day for a week", @@ -10004,7 +10004,7 @@ "dismiss": "Not now", "applied": "Added", "dismissed": "Dismissed", - "failed": "Couldn't add that — please try again", + "failed": "Couldn't add that. Please try again", "checkup": { "title": "Add a check-up reminder?" }, @@ -10032,9 +10032,9 @@ "reviewPrefix": "Check-in: {when}", "accept": "Accept plan", "decline": "Decline", - "accepted": "Plan accepted — the Coach will keep it in mind.", + "accepted": "Plan accepted. The Coach will keep it in mind.", "declined": "Proposal declined.", - "failed": "That didn't work — please try again.", + "failed": "That didn't work. Please try again.", "markMet": "Goal met", "abandon": "End plan", "remove": "Remove", @@ -10055,8 +10055,8 @@ } }, "refusal": { - "outOfScope": "I can only help with the health metrics in your log — measurements, medications, mood, trends. I cannot answer questions outside that scope.", - "promptInjection": "I noticed wording that tries to override my instructions. I am the HealthLog Coach and only summarise your own health data — please rephrase your question in those terms.", + "outOfScope": "I can only help with the health metrics in your log: measurements, medications, mood, trends. I cannot answer questions outside that scope.", + "promptInjection": "I noticed wording that tries to override my instructions. I am the HealthLog Coach and only summarise your own health data. Please rephrase your question in those terms.", "conversationPoisoned": "An earlier message in this conversation contains wording that overrides my instructions. Please start a new conversation." }, "noRecordedData": "I don't have any recorded readings for what you asked about, so there is nothing I can give you a figure from. Once you log some, ask me again and I'll work from your own numbers.", @@ -10272,7 +10272,7 @@ }, "mentalHealth": { "pageTitle": "Mental wellbeing", - "pageDescription": "Four validated, voluntary self-checks — the trend over time says more than any single score.", + "pageDescription": "Four validated, voluntary self-checks. The trend over time says more than any single score.", "attributionLabel": "Attribution", "attributionShow": "Source and licence for {instrument}", "choosePrompt": "Choose a check-in", @@ -10307,7 +10307,7 @@ "2": "Very difficult", "3": "Extremely difficult" }, - "functionalOptionalHint": "Optional — you can submit without answering this question.", + "functionalOptionalHint": "Optional: you can submit without answering this question.", "result": { "title": "Your result", "totalLabel": "Total score", @@ -10360,9 +10360,9 @@ "3": "Trouble falling or staying asleep, or sleeping too much", "4": "Feeling tired or having little energy", "5": "Poor appetite or overeating", - "6": "Feeling bad about yourself — or that you are a failure or have let yourself or your family down", + "6": "Feeling bad about yourself, or that you are a failure or have let yourself or your family down", "7": "Trouble concentrating on things, such as reading the newspaper or watching television", - "8": "Moving or speaking so slowly that other people could have noticed. Or the opposite — being so fidgety or restless that you have been moving around a lot more than usual", + "8": "Moving or speaking so slowly that other people could have noticed. Or the opposite: being so fidgety or restless that you have been moving around a lot more than usual", "9": "Thoughts that you would be better off dead, or of hurting yourself in some way" }, "gad7": { @@ -10497,7 +10497,7 @@ }, "openDetail": "Show details", "historyLoadError": "Your assessment history could not be loaded", - "historyLoadErrorHint": "This does not mean you have no results — the list could not be fetched. Try again.", + "historyLoadErrorHint": "This does not mean you have no results; the list could not be fetched. Try again.", "privacyNote": "Your answers are stored encrypted and never reach the AI Coach." }, "records": { @@ -11186,7 +11186,7 @@ "genericDescription": "A measurement you track. Add values to follow it over time.", "emptyTitle": "No values yet", "emptyDescription": "Add your first value to start charting this metric.", - "valuesTitle": "{metric} — all values", + "valuesTitle": "{metric}: all values", "valuesDescription": "Every logged value for this metric.", "backToMetric": "Back to {metric}" } @@ -11233,7 +11233,7 @@ "lastAttemptReason": { "unitMismatch": "The values that arrived didn't match the units this app expects for these nutrients, so they couldn't be stored.", "valueOutOfRange": "The amounts that arrived were higher than this app can plausibly store, so they couldn't be saved.", - "dayInvalid": "The entries carried a date the server couldn't accept. This can happen when the clock or time zone on the sending side is wrong — it's worth checking.", + "dayInvalid": "The entries carried a date the server couldn't accept. This can happen when the clock or time zone on the sending side is wrong, so it's worth checking.", "upsertFailed": "These entries reached the server, but a problem on this end kept them from being saved. There's nothing you need to do.", "unknown": "These entries arrived but couldn't be stored." } @@ -11252,7 +11252,7 @@ "emptyTitle": "No micronutrient data synced yet", "loadError": "Your nutrient data could not be loaded" }, - "sparseNote": "A low number here usually means sparse logging, not a deficiency — Apple Health day totals reflect what your apps logged, not total dietary intake." + "sparseNote": "A low number here usually means sparse logging, not a deficiency. Apple Health day totals reflect what your apps logged, not total dietary intake." }, "daily": { "line": { @@ -11279,27 +11279,27 @@ }, "syncIssue": { "title": "Sync needs attention", - "body": "{integration} isn't syncing — reconnect to keep your data current." + "body": "{integration} isn't syncing. Reconnect to keep your data current." }, "coachCheckin": { "title": "Time to check in on a plan", - "body": "It's been about a week since you set this plan — keep it, adjust it, or let it go. No pressure either way.", - "bodyPlan": "About a week ago you set: “{plan}”. Keep it, adjust it, or let it go — no pressure either way.", + "body": "It's been about a week since you set this plan. Keep it, adjust it, or let it go. No pressure either way.", + "bodyPlan": "About a week ago you set: “{plan}”. Keep it, adjust it, or let it go. No pressure either way.", "adjustPrompt": "I'd like to adjust my check-in plan.", "adjustPromptPlan": "I'd like to adjust this plan: “{plan}”" }, "tensionWindow": { "title": "Possible tension today", "body": { - "morning": "Your heart rate sat above its resting baseline for a sustained stretch this morning while you were still — possibly some tension.", - "afternoon": "Your heart rate sat above its resting baseline for a sustained stretch this afternoon while you were still — possibly some tension.", - "evening": "Your heart rate sat above its resting baseline for a sustained stretch this evening while you were still — possibly some tension.", - "night": "Your heart rate sat above its resting baseline for a sustained stretch overnight while you were still — possibly some tension." + "morning": "Your heart rate sat above its resting baseline for a sustained stretch this morning while you were still, possibly some tension.", + "afternoon": "Your heart rate sat above its resting baseline for a sustained stretch this afternoon while you were still, possibly some tension.", + "evening": "Your heart rate sat above its resting baseline for a sustained stretch this evening while you were still, possibly some tension.", + "night": "Your heart rate sat above its resting baseline for a sustained stretch overnight while you were still, possibly some tension." } }, "ecgNewRecording": { "title": "New ECG recording", - "body": "Your device recorded a new ECG — it's ready to view.", + "body": "Your device recorded a new ECG. It's ready to view.", "bodyVerdict": "Your device recorded a new ECG and reported: {verdict}.", "verdict": { "irregular": "a possible irregular rhythm", @@ -11319,9 +11319,9 @@ }, "upcomingVisit": { "title": "Appointment coming up", - "bodyToday": "{what} — today", - "bodyTomorrow": "{what} — tomorrow", - "bodyDayAfterTomorrow": "{what} — the day after tomorrow" + "bodyToday": "{what} today", + "bodyTomorrow": "{what} tomorrow", + "bodyDayAfterTomorrow": "{what} the day after tomorrow" } }, "action": { @@ -11340,7 +11340,7 @@ "scoreLabel": "Health score", "deltaVsBaseline": "{delta} vs your baseline", "deltaFlat": "In line with your baseline", - "sleepPending": "Last night's sleep isn't in yet — today's read is provisional.", + "sleepPending": "Last night's sleep isn't in yet, so today's read is provisional.", "worthALook": "Worth a look", "allClear": "Nothing needs your attention today.", "ringLink": "Open {metric} details", @@ -11379,7 +11379,7 @@ }, "record": { "title": "A new {metric} best", - "body": "A personal best for your {metric} today — quietly noted, nothing to do." + "body": "A personal best for your {metric} today. Quietly noted, nothing to do." }, "returnToBaseline": { "title": "Back in range: {metric}", @@ -11541,7 +11541,7 @@ "canManage": "Can read the record, add to it, and change or remove what is in it", "entireRecord": "Covers the entire record", "sections": "Covers: {sections}", - "noSections": "Covers nothing — this access opens no part of the record", + "noSections": "Covers nothing: this access opens no part of the record", "invited": "Invited", "accepted": "Accepted", "expires": "Lapses", @@ -11594,7 +11594,7 @@ "errorScope": "Those sections cannot be shared like that. Pick at least one section, or share the entire record.", "errorManageBrowserOnly": "Manage access can only be offered in a browser.", "errorStepUp": "Confirm your second factor, then try again.", - "errorOffline": "That did not reach the server. Your invitation is still here — check your connection and try again." + "errorOffline": "That did not reach the server. Your invitation is still here. Check your connection and try again." }, "given": { "title": "Who can open my record", @@ -11914,7 +11914,7 @@ }, "actionError": { "retry": "Try again", - "offline": "That did not reach the server. Nothing has changed — check your connection and try again.", + "offline": "That did not reach the server. Nothing has changed. Check your connection and try again.", "rateLimited": "Too many attempts in a row. Wait a minute and try again.", "acceptExpired": "That invitation has lapsed. Ask for a new one.", "acceptWithdrawn": "That invitation was withdrawn.", @@ -11926,7 +11926,7 @@ "notFound": "That access is no longer there.", "revokeFailed": "The access could not be ended.", "renounceFailed": "The access could not be handed back.", - "profileNotFound": "That profile is not there any more — it may already have been deleted, or your access to it may have ended.", + "profileNotFound": "That profile is not there any more. It may already have been deleted, or your access to it may have ended.", "deleteProfileFailed": "The profile could not be deleted.", "removeGuardianFailed": "That access could not be ended." }, @@ -11983,7 +11983,7 @@ "created": "Visit saved", "updated": "Visit updated", "saveFailed": "The visit could not be saved.", - "checkupNotClosed": "Visit saved. The checkup stays open — your access does not cover that.", + "checkupNotClosed": "Visit saved. The checkup stays open; your access does not cover that.", "status": { "planned": "Planned", "done": "Attended", @@ -12000,7 +12000,7 @@ "dateDerivesStatusHint": "A date in the future is a booked appointment.", "status": "Status", "practitioner": "Practice or doctor", - "practitionerHint": "Optional — you can add the name later.", + "practitionerHint": "Optional: you can add the name later.", "practitionerNone": "Not specified", "practitionerSearch": "Search name or practice", "practitionerNoMatch": "No entry found.", @@ -12058,7 +12058,7 @@ }, "practitioners": { "title": "Practices and doctors", - "description": "Your own address book — type a practice once, pick it everywhere.", + "description": "Your own address book: type a practice once, pick it everywhere.", "linkLabel": "Address book", "searchPlaceholder": "Search name, practice or specialty", "loadError": "The address book could not be loaded.", @@ -12260,15 +12260,11 @@ "rugLegend": "Dots under the axis mark days with entries, a ring marks a notable day.", "sheetExpand": "Expand to full height", "sheetShrink": "Shrink", - "usualLabel": "Your 30 days before", "valuesLegend": "Dot for this day, bar for the 30 days before", "valuesAllOne": "All values", "valuesAllFew": "All {count} values", "valuesAllOther": "All {count} values", "valuesFewer": "Fewer values", - "countValuesOne": "1 value", - "countValuesFew": "{count} values", - "countValuesOther": "{count} values", "countEntriesOne": "1 entry", "countEntriesFew": "{count} entries", "countEntriesOther": "{count} entries", @@ -12308,7 +12304,6 @@ "subtitle": "What happened when, beside your values.", "standing": "Ongoing", "startUnknown": "start unknown", - "openDay": "Open {date}", "zoom": { "all": "All", "year": "12 months", diff --git a/messages/es.json b/messages/es.json index 0b60539b6..f28a25543 100644 --- a/messages/es.json +++ b/messages/es.json @@ -167,7 +167,7 @@ "anamnesisShiftSchedule": "Horario de trabajo", "anamnesisColFact": "Dato del perfil", "anamnesisColValue": "Valor registrado", - "subtitle": "HealthLog — Informe personal de salud", + "subtitle": "HealthLog: informe personal de salud", "patient": "Paciente", "dateOfBirth": "Fecha de nacimiento", "gender": "Sexo", @@ -177,18 +177,18 @@ "height": "Altura", "period": "Período del informe", "createdOn": "Creado el", - "vitalsTitle": "Signos vitales — Resumen", + "vitalsTitle": "Signos vitales: resumen", "colParameter": "Parámetro", "colCurrent": "Actual", "colAvgPeriod": "Med. periodo", "colMin": "Mín", "colMax": "Máx", "colN": "n", - "bpClassificationTitle": "Tensión arterial — Clasificación ESH (2023)", + "bpClassificationTitle": "Tensión arterial: clasificación ESH (2023)", "avgBp": "Tensión arterial media", "classification": "Clasificación", "bmiTitle": "Índice de masa corporal (IMC)", - "bmiRow": "IMC:{bmi} kg/m² — Classification: {class} (WHO)", + "bmiRow": "IMC:{bmi} kg/m², Classification: {class} (WHO)", "complianceTitle": "Cumplimiento de medicación", "glp1Title": "Terapia GLP-1", "glp1WeightSummary": "Peso en el periodo del informe: {start} kg → {end} kg ({delta} kg)", @@ -236,8 +236,8 @@ "typeGlucoseRandom": "Glucosa (aleatoria)", "typeGlucoseBedtime": "Glucosa (antes de dormir)", "typeGlucoseUnspecified": "Glucosa (sin indicar)", - "glucoseClassificationTitle": "Glucemia — Rangos de referencia (ADA 2024 / DDG)", - "glucoseRow": "{label}: med. {avg} {unit} (objetivo {rangeMin}–{rangeMax}) — {class}", + "glucoseClassificationTitle": "Glucemia: rangos de referencia (ADA 2024 / DDG)", + "glucoseRow": "{label}: med. {avg} {unit} (objetivo {rangeMin}–{rangeMax}), {class}", "glucoseInTarget": "en objetivo", "glucoseBelowTarget": "por debajo del objetivo", "glucoseAboveTarget": "por encima del objetivo", @@ -289,7 +289,7 @@ "gmi": "Indicador de gestión de la glucosa (GMI)", "eA1c": "A1C estimada", "cv": "Variabilidad (CV%)", - "spotCaveat": "Son estimaciones a partir de mediciones puntuales, no un perfil de monitor continuo — léelas como una tendencia, no como un veredicto clínico." + "spotCaveat": "Son estimaciones a partir de mediciones puntuales, no un perfil de monitor continuo. Léelas como una tendencia, no como un veredicto clínico." }, "illnessTitle": "Afecciones y enfermedades", "illnessOngoing": "En curso", @@ -378,12 +378,12 @@ "backToDashboard": "Volver al panel" }, "offlineBanner": { - "message": "Sin conexión — los cambios no se pueden guardar hasta que vuelvas a estar en línea.", - "saveFailed": "No se pudo guardar — estás sin conexión. Inténtalo de nuevo cuando vuelvas a estar en línea.", + "message": "Sin conexión: los cambios no se pueden guardar hasta que vuelvas a estar en línea.", + "saveFailed": "No se pudo guardar porque estás sin conexión. Inténtalo de nuevo cuando vuelvas a estar en línea.", "showingCached": "Mostrando tus últimos datos sincronizados." }, "demoBanner": { - "message": "Modo demo — los cambios no se guardan." + "message": "Modo demo: los cambios no se guardan." }, "nav": { "dashboard": "Panel", @@ -775,7 +775,7 @@ "formReset": "Restablecer formulario", "saveError": "Error al guardar", "duplicateTimestamp": "Ya existe una medición de este tipo en la marca de tiempo seleccionada.", - "serverOwnedSource": "Los valores de una fuente conectada no se pueden editar — la fecha y la nota siguen siendo editables.", + "serverOwnedSource": "Los valores de una fuente conectada no se pueden editar, pero la fecha y la nota siguen siendo editables.", "deleteError": "Error al eliminar", "deletedToast": "Medición eliminada", "restoredToast": "Medición restaurada", @@ -883,11 +883,11 @@ "connectCta": "Conectar una fuente", "viewCta": "Ver", "ecg": { - "source": "Tiras de ECG de una derivación desde un reloj compatible — hoy, Withings ScanWatch — sincronizadas automáticamente." + "source": "Tiras de ECG de una derivación desde un reloj compatible (hoy, Withings ScanWatch), sincronizadas automáticamente." }, "watchdog": { "title": "Supervisión automática", - "description": "HealthLog también vigila en segundo plano — notificaciones de ritmo irregular y alteraciones respiratorias de un reloj conectado, alertas de desviación de tu valor de referencia, y cambios destacables entre tus dos últimos paneles de laboratorio — y solo muestra una tarjeta cuando algo destaca. Si al menos una de esas fuentes está conectada, que no aparezca ninguna tarjeta es una buena señal, no una función ausente; si todavía no hay ninguna conectada, sencillamente no se está vigilando nada." + "description": "HealthLog también vigila en segundo plano (notificaciones de ritmo irregular y alteraciones respiratorias de un reloj conectado, alertas de desviación de tu valor de referencia, y cambios destacables entre tus dos últimos paneles de laboratorio) y solo muestra una tarjeta cuando algo destaca. Si al menos una de esas fuentes está conectada, que no aparezca ninguna tarjeta es una buena señal, no una función ausente; si todavía no hay ninguna conectada, sencillamente no se está vigilando nada." } }, "mood": { @@ -1247,8 +1247,8 @@ "dialogDescription": "Estos medicamentos están pendientes ahora. Confirma para registrarlos todos como tomados.", "confirm": "Tomar todos ({count})", "successToast": "{count} tomas registradas", - "partialToast": "{taken} registradas, {failed} fallidas – inténtalo de nuevo", - "failedToast": "No se registró ninguna toma – inténtalo de nuevo" + "partialToast": "{taken} registradas, {failed} fallidas. Inténtalo de nuevo", + "failedToast": "No se registró ninguna toma. Inténtalo de nuevo" }, "logIntake": { "dialogTitle": "Registrar una toma", @@ -1431,10 +1431,10 @@ "error": { "empty": "Escribe una descripción primero.", "tooLong": "Mantén la descripción por debajo de 2000 caracteres.", - "rateLimit": "Demasiadas solicitudes — espera un momento e inténtalo de nuevo.", - "noProvider": "Sin proveedor de IA configurado — configúralo en Ajustes.", - "budget": "Se alcanzó el presupuesto diario de IA — inténtalo de nuevo mañana.", - "network": "No se pudo contactar con el proveedor de IA — inténtalo de nuevo.", + "rateLimit": "Demasiadas solicitudes. Espera un momento e inténtalo de nuevo.", + "noProvider": "Sin proveedor de IA configurado. Configúralo en Ajustes.", + "budget": "Se alcanzó el presupuesto diario de IA. Inténtalo de nuevo mañana.", + "network": "No se pudo contactar con el proveedor de IA. Inténtalo de nuevo.", "consent": "Leer tu descripción con IA necesita primero tu consentimiento.", "unavailable": "Leer descripciones con IA no está disponible aquí ahora mismo." } @@ -1450,7 +1450,7 @@ "everyNMonths": "Cada N meses un día concreto", "yearly": "Una vez al año", "rolling": "Cada N días desde la última toma (flexible)", - "rollingExplainer": "Cuenta desde tu última toma registrada — se pausa si te saltas una dosis.", + "rollingExplainer": "Cuenta desde tu última toma registrada y se pausa si te saltas una dosis.", "oneShot": "Dosis única" }, "weekdays": { @@ -1508,7 +1508,7 @@ "night": "Noche" }, "max": { - "reached": "Máximo alcanzado — quita una hora antes de añadir otra." + "reached": "Máximo alcanzado: quita una hora antes de añadir otra." } }, "courseWindow": { @@ -1558,7 +1558,7 @@ }, "step3": { "title": "¿Cuál es la dosis?", - "subline": "Una pastilla, una inhalación, una gota — según la forma.", + "subline": "Una pastilla, una inhalación, una gota, según la forma.", "amountLabel": "Cantidad", "amountPlaceholder": "p. ej. 5", "unitLabel": "Unidad", @@ -1584,7 +1584,7 @@ }, "dosesPerUnitLabel": "Dosis por unidad", "dosesPerUnitPlaceholder": "p. ej. 4", - "dosesPerUnitHint": "Dosis por pluma / vial — déjalo vacío para no controlar el inventario.", + "dosesPerUnitHint": "Dosis por pluma / vial. Déjalo vacío para no controlar el inventario.", "short": "Dosis", "unitsPerDoseLabel": "Unidades por dosis", "unitsPerDoseHint": "p. ej., 2 comprimidos de 2 mg para una dosis de 4 mg, o ½ comprimido para una dosis partida" @@ -1596,7 +1596,7 @@ }, "step5": { "title": "¿Con qué frecuencia lo tomas?", - "subline": "Elige la frecuencia — los detalles vienen en el siguiente paso.", + "subline": "Elige la frecuencia. Los detalles vienen en el siguiente paso.", "short": "Frecuencia" }, "step6": { @@ -1618,7 +1618,7 @@ }, "step7": { "title": "¿Cuándo lo tomas?", - "subline": "Una o varias horas del día — los recordatorios siguen esta lista.", + "subline": "Una o varias horas del día. Los recordatorios siguen esta lista.", "presetsLabel": "Preajustes por hora del día", "presets": { "morning": "Mañana", @@ -1634,11 +1634,11 @@ "short": "Horas" }, "step8": { - "title": "Listo — ¿quieres que HealthLog te lo recuerde?", + "title": "Listo. ¿Quieres que HealthLog te lo recuerde?", "subline": "Revisa todo abajo antes de guardar.", "remindersLabel": "Recordatorios activados", - "remindersDescription": "Push, Telegram o ntfy — según tus ajustes.", - "noChannelHint": "Los recordatorios necesitan un canal de notificaciones — ahora mismo no hay ninguno activo.", + "remindersDescription": "Push, Telegram o ntfy, según tus ajustes.", + "noChannelHint": "Los recordatorios necesitan un canal de notificaciones, pero ahora mismo no hay ninguno activo.", "noChannelHintLink": "Configurar notificaciones", "short": "Listo" } @@ -1722,7 +1722,7 @@ } }, "errors": { - "submitFailed": "No se pudo guardar el medicamento — inténtalo de nuevo." + "submitFailed": "No se pudo guardar el medicamento. Inténtalo de nuevo." } }, "doseStrength": { @@ -1830,7 +1830,7 @@ "cadence": { "oneShotOn": "Dosis única el {date}.", "oneShotPending": "Dosis única pendiente.", - "asNeeded": "Según necesidad — sin plan fijo." + "asNeeded": "Según necesidad, sin plan fijo." }, "intake": { "title": "Historial de tomas", @@ -1953,7 +1953,7 @@ }, "codes": { "label": "Códigos clínicos (ATC / RxNorm)", - "note": "Opcional. Se usan en la exportación FHIR del historial de salud. Los códigos se toman tal cual se introducen — nunca se adivinan.", + "note": "Opcional. Se usan en la exportación FHIR del historial de salud. Los códigos se toman tal cual se introducen; nunca se adivinan.", "atcLabel": "ATC", "rxNormLabel": "RxNorm", "saved": "Códigos clínicos guardados", @@ -1973,7 +1973,7 @@ "title": "Finalizar medicamento", "helper": "Detiene los recordatorios y marca el medicamento como finalizado. El historial sigue siendo visible.", "button": "Finalizar", - "dialogTitle": "Finalizar {name} — detiene los recordatorios, el historial sigue visible", + "dialogTitle": "Finalizar {name}: detiene los recordatorios, el historial sigue visible", "dialogBody": "No habrá más recordatorios. Las entradas antiguas permanecen en la línea de tiempo.", "toast": "Medicamento finalizado", "failed": "No se pudo finalizar el medicamento." @@ -2011,7 +2011,7 @@ "copyFailed": "No se pudo copiar.", "tokenCopied": "Token copiado", "copyToken": "Copiar token", - "mintedHint": "Copia este token ahora — solo se muestra una vez." + "mintedHint": "Copia este token ahora. Solo se muestra una vez." }, "advanced": { "dataPortability": { @@ -2051,9 +2051,9 @@ "statusTitle": "Estado", "nextDoseLabel": "Próxima dosis", "nextDoseNone": "No hay dosis pendiente.", - "nextDoseAsNeeded": "Según necesidad — sin dosis programada.", + "nextDoseAsNeeded": "Según necesidad, sin dosis programada.", "nextDoseNotTracked": "Sin registro de tomas, se guarda como registro.", - "pausedHint": "En pausa — sin recordatorios.", + "pausedHint": "En pausa, sin recordatorios.", "reminderLabel": "Recordatorio", "reminderOn": "Activado", "reminderOff": "Desactivado", @@ -2246,8 +2246,8 @@ "tableStockDoses": "{count} dosis", "tableStockRunway": "≈ {days} días restantes", "cardLowStockRunway": "Reserva: ≈ {days} días", - "takeActionFor": "Tomar – {name}", - "skipActionFor": "Omitir – {name}", + "takeActionFor": "Tomar: {name}", + "skipActionFor": "Omitir: {name}", "reorderDescription": "Define el orden de tus medicamentos: se aplica a la vista de tarjetas y a la de tabla.", "reorderSaved": "Orden guardado", "reorderSaveFailed": "No se pudo guardar el orden", @@ -2267,7 +2267,7 @@ "levelShift": "Se detectó un cambio de nivel en torno a {date}.", "plateau": { "title": "Meseta de peso con la dosis actual", - "evidence": "Variación de peso de {delta} {unit} en los últimos {window} días ({readings} mediciones) — {days} días con {dose}." + "evidence": "Variación de peso de {delta} {unit} en los últimos {window} días ({readings} mediciones), {days} días con {dose}." }, "retarget": { "label": "¿No es la medición correcta?", @@ -2392,7 +2392,7 @@ }, "charts": { "loadingLabel": "Cargando la gráfica…", - "loadingSlowHint": "Calculando los análisis — puede tardar un momento.", + "loadingSlowHint": "Calculando los análisis. Puede tardar un momento.", "weight": "Peso", "bloodPressure": "Tensión arterial", "pulse": "Pulso", @@ -2542,8 +2542,8 @@ }, "tooltipPrior": "Periodo anterior", "unavailable": { - "lastMonth": "Comparación no disponible — sin datos del mes anterior", - "lastYear": "Comparación no disponible — sin datos del año anterior" + "lastMonth": "Comparación no disponible: sin datos del mes anterior", + "lastYear": "Comparación no disponible: sin datos del año anterior" }, "notAvailableForCompliance": "Comparación no disponible para el cumplimiento" }, @@ -2666,7 +2666,7 @@ "narrativeWeek": "Esta semana", "narrativeMonth": "Este mes", "narrativeUpdating": "Actualizando…", - "heroFallbackSubtitle": "Una mirada diaria a tus tendencias — directamente de los datos que registras.", + "heroFallbackSubtitle": "Una mirada diaria a tus tendencias, directamente de los datos que registras.", "heroGreetingMorning": "Buenos días", "heroGreetingAfternoon": "Buenas tardes", "heroGreetingEvening": "Buenas noches", @@ -2841,14 +2841,14 @@ } }, "coach": { - "refusalOutOfScope": "Solo puedo ayudarte con los datos de salud de tu registro — mediciones, medicamentos, estado de ánimo, tendencias. Preguntas fuera de ese ámbito no las respondo.", - "refusalInjection": "Tu mensaje contiene instrucciones que pretenden sobrescribir mis indicaciones. Soy el coach de HealthLog y solo resumo tus propios datos de salud — reformula tu pregunta dentro de ese marco.", + "refusalOutOfScope": "Solo puedo ayudarte con los datos de salud de tu registro: mediciones, medicamentos, estado de ánimo, tendencias. Preguntas fuera de ese ámbito no las respondo.", + "refusalInjection": "Tu mensaje contiene instrucciones que pretenden sobrescribir mis indicaciones. Soy el coach de HealthLog y solo resumo tus propios datos de salud. Reformula tu pregunta dentro de ese marco.", "errorBudget": "Has alcanzado el límite diario del coach. El cupo se reinicia a medianoche (UTC).", "errorProvider": "El coach no ha podido contactar con un proveedor de análisis ahora mismo. Inténtalo en un momento.", "errorDemo": "En la demo, el Coach no responde.", "errorNoProvider": "El coach lee tus datos de salud registrados y responde preguntas sobre ellos (no es consejo médico). HealthLog necesita un proveedor de IA para ello: conecta tu propia clave o un modelo local.", "errorNoProviderAction": "Conectar un proveedor de IA", - "errorNetwork": "Sin conexión a Internet — inténtalo de nuevo cuando vuelvas a estar en línea.", + "errorNetwork": "Sin conexión a Internet. Inténtalo de nuevo cuando vuelvas a estar en línea.", "prefsSaveError": "No se pudieron guardar tus preferencias del Coach. Inténtalo de nuevo.", "errorCredentialExpired": "Tu conexión con el proveedor de IA ha caducado. Vuelve a conectarla en Ajustes para que el Coach siga funcionando.", "tagline": "Coach personal de salud, apoyado en tus datos.", @@ -2867,7 +2867,7 @@ "thinking": "Pensando…", "unverifiedFiguresNotice": "Algunas cifras no se pudieron contrastar con tus datos y se omitieron.", "composerPlaceholder": "Pregúntame algo …", - "nudgeBubbleLabel": "Nuevo mensaje del coach — abrir el chat", + "nudgeBubbleLabel": "Nuevo mensaje del coach: abrir el chat", "fabLabel": "Abrir el coach", "readAloud": "Leer en voz alta", "readAloudStop": "Detener lectura", @@ -2891,7 +2891,7 @@ "guided": { "offerTitle": "El Coach tiene {count} preguntas para ti", "offerTitleOne": "El Coach tiene una pregunta para ti", - "offerBody": "Respuestas breves afinan tu información personal — una pregunta a la vez, aquí en el chat.", + "offerBody": "Respuestas breves afinan tu información personal: una pregunta a la vez, aquí en el chat.", "offerStart": "Responder ahora", "offerLater": "Más tarde", "offerDismiss": "No volver a preguntar", @@ -2901,7 +2901,7 @@ "later": "Más tarde", "dismissRemaining": "No volver a preguntar", "answerPlaceholder": "Tu respuesta…", - "summaryTitle": "¡Listo — gracias por tus respuestas!", + "summaryTitle": "¡Listo, gracias por tus respuestas!", "summaryAnswered": "{answered} de {total} respondidas", "summaryAdopted": "{adopted} añadidas a tu información personal", "summaryAdoptedNone": "no se añadió nada nuevo a tu información personal", @@ -3090,7 +3090,7 @@ "steadyLatestWithin": "Tus valores suelen estar en {low} {unit}; tu última medición, del {date}, fue {value} y coincide.", "steadyLatestAbove": "Tus valores suelen estar en {low} {unit}; tu última medición, del {date}, fue {value}, por encima.", "steadyLatestBelow": "Tus valores suelen estar en {low} {unit}; tu última medición, del {date}, fue {value}, por debajo.", - "insufficient": "Todavía estoy aprendiendo tu rango habitual — sigue registrando unos días más.", + "insufficient": "Todavía estoy aprendiendo tu rango habitual. Sigue registrando unos días más.", "driver": "{note}" }, "scope": { @@ -3104,31 +3104,31 @@ "groupEarlier": "Anteriores" }, "seed": { - "bloodPressure": "Repasa conmigo la tendencia de mi presión arterial de los últimos 30 días — ¿hay algo que deba vigilar?", + "bloodPressure": "Repasa conmigo la tendencia de mi presión arterial de los últimos 30 días. ¿Hay algo que deba vigilar?", "weight": "¿Cómo ha evolucionado mi peso últimamente y la dirección es algo sobre lo que actuar?", "bmi": "¿Qué me dice mi tendencia de IMC y cómo debería interpretarla?", - "pulse": "Repasa conmigo mis lecturas de pulso — ¿hay algo fuera de lo normal?", + "pulse": "Repasa conmigo mis lecturas de pulso. ¿Hay algo fuera de lo normal?", "restingHr": "¿Cómo ha evolucionado mi frecuencia cardíaca en reposo y qué dice sobre mi forma física?", "hrv": "¿Qué me dice mi variabilidad de la frecuencia cardíaca sobre la recuperación y el estrés últimamente?", - "sleep": "Repasa conmigo mi sueño reciente — duración, regularidad y cualquier cosa que valga la pena cambiar.", + "sleep": "Repasa conmigo mi sueño reciente: duración, regularidad y cualquier cosa que valga la pena cambiar.", "mood": "¿Qué patrones ves en mi estado de ánimo durante las últimas semanas?", "medications": "¿Cómo va mi adherencia a la medicación y coincide con cómo me he sentido?", "steps": "¿Qué tan activo he estado últimamente según mis pasos y cómo se compara con un nivel de referencia saludable?", "activeEnergy": "¿Qué dice mi tendencia de energía activa sobre mi nivel de actividad últimamente?", "cardioFitness": "¿Qué significa la tendencia de mi capacidad cardiorrespiratoria (VO₂ máx.) y cómo la llevo en la dirección correcta?", - "bloodGlucose": "Repasa conmigo mis últimas lecturas de glucosa — ¿están en un rango saludable?", + "bloodGlucose": "Repasa conmigo mis últimas lecturas de glucosa. ¿Están en un rango saludable?", "oxygenSaturation": "¿Qué me dice mi tendencia de oxígeno en sangre (SpO₂)?", "respiratoryRate": "¿Qué dice mi tendencia de frecuencia respiratoria sobre mi salud?", - "workouts": "Repasa conmigo mis entrenamientos recientes — carga, frecuencia y cómo me recupero entre ellos.", + "workouts": "Repasa conmigo mis entrenamientos recientes: carga, frecuencia y cómo me recupero entre ellos.", "recoveryPage": "¿Por qué mi recuperación está donde está ahora mismo y qué la está provocando?", - "briefing": "Repasa conmigo el resumen de hoy — ¿en qué debería centrarme y hay algo en lo que valga la pena actuar?", + "briefing": "Repasa conmigo el resumen de hoy. ¿En qué debería centrarme y hay algo en lo que valga la pena actuar?", "healthScore": "¿Por qué mi puntuación de salud es {score} de 100 y qué la mejoraría más?", - "periodWeek": "Repasa conmigo cómo fue mi última semana en mis métricas de salud — ¿qué destaca?", - "periodMonth": "Repasa conmigo cómo fue mi último mes en mis métricas de salud — ¿qué destaca?", + "periodWeek": "Repasa conmigo cómo fue mi última semana en mis métricas de salud. ¿Qué destaca?", + "periodMonth": "Repasa conmigo cómo fue mi último mes en mis métricas de salud. ¿Qué destaca?", "correlationBpCompliance": "¿Cómo se relaciona mi adherencia a la medicación con mi presión arterial? Explícame qué significa esta correlación para mí.", "correlationMoodPulse": "¿Existe una relación real entre mi estado de ánimo y mi pulso? Ayúdame a interpretar esta correlación.", "correlationWeightWeekday": "¿Mi peso sigue un patrón semanal? ¿Qué me dice esta correlación por día de la semana?", - "recommendation": "Cuéntame más sobre esta recomendación: \"{text}\" — ¿por qué se aplica a mí y qué debería hacer al respecto?" + "recommendation": "Cuéntame más sobre esta recomendación: \"{text}\". ¿Por qué se aplica a mí y qué debería hacer al respecto?" }, "assessmentPrompt": "Explícame mi evaluación de {metric}: ¿qué significa y qué debería hacer al respecto?", "attach": { @@ -3321,7 +3321,7 @@ }, "hrv": { "title": "VFC", - "description": "Variabilidad de la frecuencia cardíaca a lo largo del tiempo — señal de recuperación del sistema nervioso, captada por la noche por Apple Watch y otros wearables compatibles.", + "description": "Variabilidad de la frecuencia cardíaca a lo largo del tiempo: señal de recuperación del sistema nervioso, captada por la noche por Apple Watch y otros wearables compatibles.", "chartTitle": "Variabilidad de la frecuencia cardíaca", "emptyState": { "title": "Aún no hay valores de VFC", @@ -3330,7 +3330,7 @@ }, "restingHr": { "title": "FC en reposo", - "description": "El nivel basal diario del corazón — distinto del pulso puntual de la página de pulso. Apple Salud aporta un valor al día.", + "description": "El nivel basal diario del corazón, distinto del pulso puntual de la página de pulso. Apple Salud aporta un valor al día.", "chartTitle": "Frecuencia cardíaca en reposo", "emptyState": { "title": "Aún no hay FC en reposo", @@ -3340,7 +3340,7 @@ }, "oxygenSaturation": { "title": "Saturación de oxígeno", - "description": "Oxígeno en sangre (SpO₂) — rango clínico normal 95–100 %, con zonas objetivo sombreadas en el gráfico.", + "description": "Oxígeno en sangre (SpO₂): rango clínico normal 95–100 %, con zonas objetivo sombreadas en el gráfico.", "chartTitle": "Saturación de oxígeno", "emptyState": { "title": "Aún no hay muestras de SpO₂", @@ -3353,13 +3353,13 @@ "chartTitle": "Temperatura corporal", "emptyState": { "title": "Aún no hay temperatura corporal", - "description": "Registra una lectura o deja que tu wearable sincronice una — la tendencia aparecerá aquí.", + "description": "Registra una lectura o deja que tu wearable sincronice una, y la tendencia aparecerá aquí.", "cta": "Registrar temperatura corporal" } }, "steps": { "title": "Pasos", - "description": "Recuento diario de pasos — una fila por día, desde Apple Salud o un dispositivo de actividad conectado.", + "description": "Recuento diario de pasos: una fila por día, desde Apple Salud o un dispositivo de actividad conectado.", "chartTitle": "Pasos por día", "emptyState": { "title": "Aún no hay datos de pasos", @@ -3368,7 +3368,7 @@ }, "activeEnergy": { "title": "Energía activa", - "description": "Total diario de energía activa en kilocalorías — una fila por día, desde Apple Salud o la actividad de Withings.", + "description": "Total diario de energía activa en kilocalorías: una fila por día, desde Apple Salud o la actividad de Withings.", "chartTitle": "Energía activa", "emptyState": { "title": "Aún no hay datos de energía activa", @@ -3435,7 +3435,7 @@ "breathingDisturbancesBody": "Un wearable puede estimar con qué frecuencia se interrumpió tu respiración mientras dormías. Un índice más bajo es mejor; un nivel marcado como elevado, sobre todo durante muchas noches, conviene comentarlo con un profesional. Es una aproximación de cribado, no un diagnóstico de apnea del sueño.", "stepsBody": "El recuento de pasos es el número total de pasos que das cada día: la medida más sencilla del movimiento cotidiano. Un hábito constante importa más que un único día destacado, y la meta redonda de 10.000 pasos es un eslogan publicitario, no una conclusión de la investigación.", "readinessBody": "La disposición es una lectura diaria de lo listo que está tu cuerpo para afrontar el día, combinando la frecuencia cardíaca en reposo, la variabilidad de la frecuencia cardíaca y el sueño. Es una aproximación del dispositivo respecto a tu propia base, no una medida clínica: una puntuación más alta indica recuperación, una más baja es un aviso suave para bajar el ritmo.", - "sleepScoreBody": "Tu puntuación de sueño resume toda una noche en un solo número — duración, eficiencia, regularidad y el equilibrio entre sueño ligero, profundo y REM. Fíjate en el patrón a lo largo de las semanas en lugar de perseguir una puntuación perfecta una sola noche.", + "sleepScoreBody": "Tu puntuación de sueño resume toda una noche en un solo número: duración, eficiencia, regularidad y el equilibrio entre sueño ligero, profundo y REM. Fíjate en el patrón a lo largo de las semanas en lugar de perseguir una puntuación perfecta una sola noche.", "recoveryBody": "La recuperación refleja lo bien que tu cuerpo se ha repuesto, a partir de señales nocturnas como la variabilidad de la frecuencia cardíaca y la frecuencia en reposo. Una puntuación alta es luz verde para exigirte; una más baja sugiere que tu organismo aún se está reconstruyendo.", "strainBody": "El esfuerzo capta cuánta carga cardiovascular y física le has impuesto a tu cuerpo, desde los entrenamientos hasta un día activo de pie. Cuando ya hay suficiente historial, se valora frente a tu propio esfuerzo habitual, no frente a un estándar ajeno.", "stressBody": "El estrés aquí es una estimación de la carga fisiológica sobre tu sistema nervioso, leída sobre todo a partir de patrones de variabilidad de la frecuencia cardíaca y no de cómo te sientes conscientemente. Una puntuación más baja apunta a un estado calmado y bien regulado; una más alta es una invitación a incorporar recuperación.", @@ -3458,7 +3458,7 @@ "mean": "Media" }, "showAllValues": "Mostrar todas las mediciones", - "valuesPageTitle": "{metric} — todas las mediciones", + "valuesPageTitle": "{metric}: todas las mediciones", "valuesPageDescription": "Cada medición detrás de esta métrica. Edita o elimina una entrada directamente.", "diversity": { "trigger": "Consejo de medición", @@ -3498,11 +3498,11 @@ "inBed": "En la cama", "nap": "Siesta", "napCount": "{count} siestas", - "unavailable": "Aún no hay datos de fases — las fases de sueño aparecerán aquí en cuanto una fuente conectada las proporcione." + "unavailable": "Aún no hay datos de fases. Las fases de sueño aparecerán aquí en cuanto una fuente conectada las proporcione." }, "empty": { "title": "Aún no hay datos de sueño", - "description": "Conecta una fuente como Apple Health o un wearable — o registra el sueño manualmente — y esta vista se llenará automáticamente.", + "description": "Conecta una fuente como Apple Health o un wearable (o registra el sueño manualmente) y esta vista se llenará automáticamente.", "action": "Gestionar dispositivos" }, "debt": { @@ -3511,21 +3511,21 @@ "caption": "Balance pendiente de las últimas {nights} noches", "clearValue": "Al día", "clearCaption": "Nada pendiente en las últimas {nights} noches", - "learning": "Aún estamos midiendo tu sueño — {counted} noches hasta ahora, faltan {remaining} para un balance fiable.", + "learning": "Aún estamos midiendo tu sueño: {counted} noches hasta ahora, faltan {remaining} para un balance fiable.", "computedInfo": "Esta es la estimación propia de HealthLog: un balance móvil de la necesidad menos el sueño de las últimas noches, que el sueño de recuperación va reduciendo. Puede diferir de la cifra de deuda de sueño nativa de un wearable, que usa su propio modelo de necesidad." }, "average": { "title": "Media por noche", "value": "{hours} h {minutes} min", "caption": "Sueño medio en las últimas {nights} noches", - "learning": "Aún estamos midiendo tu sueño — {counted} noches hasta ahora, faltan {remaining} para una media fiable." + "learning": "Aún estamos midiendo tu sueño: {counted} noches hasta ahora, faltan {remaining} para una media fiable." }, "chronotype": { "title": "Cronotipo", - "learning": "Aún estamos aprendiendo tu ritmo — {counted} de {total} noches libres. Un cronotipo necesita varias mañanas sin despertador para tener sentido.", + "learning": "Aún estamos aprendiendo tu ritmo: {counted} de {total} noches libres. Un cronotipo necesita varias mañanas sin despertador para tener sentido.", "advancedToggle": "Avanzado", "socialJetlagValue": "{hours} h {minutes} min de jet lag social", - "socialJetlagCaption": "La diferencia entre el horario de sueño laboral y el de los días libres — como un pequeño cambio de huso horario semanal.", + "socialJetlagCaption": "La diferencia entre el horario de sueño laboral y el de los días libres, como un pequeño cambio de huso horario semanal.", "msfScValue": "Punto medio corregido {clock}", "msfScCaption": "Ajustado por el sueño que recuperas el fin de semana (MSFsc).", "dayTypeNote": "Se asume que los días libres son los fines de semana hasta que se añada el registro del tipo de día.", @@ -3891,7 +3891,7 @@ "navSkinTemperature": "Temp. piel", "pulseWaveVelocity": { "title": "Velocidad de onda de pulso", - "description": "Tu velocidad de onda de pulso arterial en el tiempo, en m/s — valores más altos sugieren arterias más rígidas.", + "description": "Tu velocidad de onda de pulso arterial en el tiempo, en m/s. Valores más altos sugieren arterias más rígidas.", "chartTitle": "Velocidad de onda de pulso", "emptyState": { "title": "Aún no hay datos", @@ -4221,7 +4221,7 @@ }, "scoreRing": { "aria": "Puntuación {score} de 100, {band}", - "ariaProvisional": "Puntuación aún no disponible — datos insuficientes", + "ariaProvisional": "Puntuación aún no disponible: datos insuficientes", "provisionalCaption": "Datos aún insuficientes", "band": { "green": "bueno", @@ -4245,7 +4245,7 @@ "loadingLabel": "Cargando tus constantes", "loadError": "No se pudieron cargar tus constantes en este momento.", "infoLabel": "¿Cómo se calcula esto?", - "building": "Creando tu rango habitual — {count} de {target} días", + "building": "Creando tu rango habitual: {count} de {target} días", "typicalRange": "Habitual para ti: {low}–{high}", "fitnessYounger": "Forma cardiovascular de alguien ~{years} años más joven", "fitnessOlder": "Forma cardiovascular ~{years} años por encima de tu edad", @@ -4297,7 +4297,7 @@ "READINESS": { "title": "Disposición", "description": "Un indicador diario de bienestar según cómo se sitúan tus señales frente a tu propia base.", - "method": "Una mezcla de 0–100 de desviación de la frecuencia cardíaca en reposo, desviación de la VFC (SDNN), calidad del sueño, estabilidad de la frecuencia respiratoria y estabilidad del estado de ánimo — cada una medida frente a tu base personal. Los pesos se renormalizan según los componentes que tus datos sustentan. Un indicador de bienestar, no una puntuación de recuperación ni clínica.", + "method": "Una mezcla de 0–100 de desviación de la frecuencia cardíaca en reposo, desviación de la VFC (SDNN), calidad del sueño, estabilidad de la frecuencia respiratoria y estabilidad del estado de ánimo, cada una medida frente a tu base personal. Los pesos se renormalizan según los componentes que tus datos sustentan. Un indicador de bienestar, no una puntuación de recuperación ni clínica.", "component": { "rhr": "Frecuencia cardíaca en reposo", "hrv": "VFC (SDNN)", @@ -4405,7 +4405,7 @@ "sameTime": { "sectionTitle": "Hoy hasta ahora", "sectionSubtitle": "Tus totales acumulados frente a lo que es habitual en ti a esta hora", - "learning": "Aprendiendo tu día habitual — {count} de {target} días", + "learning": "Aprendiendo tu día habitual: {count} de {target} días", "framing": "Habitual a las {time}: {typical} {unit}", "comparisonLabel": "Tu día habitual" } @@ -4492,7 +4492,7 @@ "navBreathingDisturbances": "Respiración", "rhythmEvents": { "sectionTitle": "Notificaciones de salud del dispositivo", - "sectionIntro": "Notificaciones que tu reloj envió por su cuenta. HealthLog solo las muestra — no las detecta, confirma ni interpreta.", + "sectionIntro": "Notificaciones que tu reloj envió por su cuenta. HealthLog solo las muestra; no las detecta, confirma ni interpreta.", "loadError": "No se pudieron cargar las notificaciones de tu dispositivo.", "disclaimer": "Estas son alertas que tu dispositivo generó con su propia detección integrada. Se muestran aquí solo para tu información. No es una evaluación médica de HealthLog, y HealthLog no diagnostica ninguna afección. Si una notificación te preocupa, habla con tu médico.", "event": { @@ -4561,9 +4561,9 @@ "emptyTitle": "Aún no hay datos de recuperación", "empty": "Aún no hay datos de recuperación. Conecta una cuenta de WHOOP, Polar u Oura y estas puntuaciones se completarán cuando tu dispositivo sincronice.", "block": { - "ansChargeExplainer": "Cuán cargado está tu sistema nervioso autónomo para el día — una lectura de recarga obtenida de tus señales nocturnas de corazón y respiración.", + "ansChargeExplainer": "Cuán cargado está tu sistema nervioso autónomo para el día: una lectura de recarga obtenida de tus señales nocturnas de corazón y respiración.", "dayStrainExplainer": "La carga cardiovascular del día en la escala de esfuerzo de tu dispositivo. Léela en relación con tu recuperación, no como una meta en sí.", - "workoutStrainExplainer": "Cuán exigente fue un entrenamiento en la misma escala de esfuerzo — el coste cardiovascular de esa sesión.", + "workoutStrainExplainer": "Cuán exigente fue un entrenamiento en la misma escala de esfuerzo: el coste cardiovascular de esa sesión.", "cardioLoadExplainer": "Una aproximación de la carga de entrenamiento que sigue la carga cardiovascular acumulada. Compárala con tus propios días recientes.", "averageHeartRateExplainer": "Tu frecuencia cardíaca media a lo largo de todo el día o ciclo, según informa tu wearable.", "maxHeartRateExplainer": "Tu frecuencia cardíaca máxima a lo largo de todo el día o ciclo, según informa tu wearable.", @@ -4576,7 +4576,7 @@ }, "resilience": { "explainer": "Cómo equilibra tu cuerpo la carga diaria con la recuperación, leído a partir de tus señales nocturnas de los últimos días.", - "learning": "Aún estamos aprendiendo tu resiliencia — unos días más asentarán el nivel.", + "learning": "Aún estamos aprendiendo tu resiliencia. Unos días más asentarán el nivel.", "band": { "limited": "Limitada", "adequate": "Adecuada", @@ -4720,7 +4720,7 @@ "intradayPulse": { "title": "Pulso a lo largo del día", "caption": "Promediado en intervalos de 10 minutos.", - "hourlyNote": "Mostrando el promedio por hora de este día — los días recientes muestran el detalle completo de 10 minutos.", + "hourlyNote": "Mostrando el promedio por hora de este día. Los días recientes muestran el detalle completo de 10 minutos.", "empty": "Aún no hay suficientes lecturas para este día para mostrar su forma.", "coverageOne": "Basado en 1 lectura a lo largo de {hours}h.", "coverageMany": "Basado en {count} lecturas a lo largo de {hours}h.", @@ -4785,14 +4785,14 @@ "metricBodyFat": "Grasa corporal", "metricSleep": "Duración del sueño", "metricSteps": "Pasos/día", - "metricGlucoseFasting": "Glucemia — en ayunas", - "metricGlucosePostprandial": "Glucemia — posprandial", - "metricGlucoseRandom": "Glucemia — cualquiera", - "metricGlucoseBedtime": "Glucemia — antes de dormir", + "metricGlucoseFasting": "Glucemia (en ayunas)", + "metricGlucosePostprandial": "Glucemia (posprandial)", + "metricGlucoseRandom": "Glucemia (cualquiera)", + "metricGlucoseBedtime": "Glucemia (antes de dormir)", "metricBodyWater": "Agua corporal", "metricBoneMass": "Masa ósea", "metricOxygenSaturation": "Saturación de oxígeno (SpO₂)", - "unsetExplanation": "Sin valor propio — se aplica el valor por defecto calculado.", + "unsetExplanation": "Sin valor propio: se aplica el valor por defecto calculado.", "cardTitle": "Rangos por métrica" }, "onboarding": { @@ -4925,18 +4925,18 @@ "sampleTitle": "Resumen diario", "sampleTag": "Ejemplo", "sampleAriaLabel": "Resumen diario de ejemplo", - "sampleBody": "Peso 1,2 kg menos en dos semanas. Pulso en reposo estable en 58 lpm. Tensión dentro del rango 6 de 7 días — la única lectura alta llegó tras una cena tardía y salada.", - "sampleCaption": "Solo un ejemplo — no son tus datos. Así se lee un resumen cuando los insights están activos.", + "sampleBody": "Peso 1,2 kg menos en dos semanas. Pulso en reposo estable en 58 lpm. Tensión dentro del rango 6 de 7 días; la única lectura alta llegó tras una cena tardía y salada.", + "sampleCaption": "Solo un ejemplo, no son tus datos. Así se lee un resumen cuando los insights están activos.", "ladderTitle": "Tres formas de activarlo", - "ladderLocalTitle": "Modelo local — las solicitudes de IA no salen de tu red", - "ladderLocalBody": "Apunta HealthLog a Ollama o LM Studio en tu propia máquina. Gratis y totalmente privado — la opción tranquila por defecto.", + "ladderLocalTitle": "Modelo local: las solicitudes de IA no salen de tu red", + "ladderLocalBody": "Apunta HealthLog a Ollama o LM Studio en tu propia máquina. Gratis y totalmente privado: la opción tranquila por defecto.", "ladderByokTitle": "Usa tu propia clave", "ladderByokBody": "Usa tu propia clave de OpenAI o Anthropic. Funciona con tu cuenta y facturación, y el nivel de API mantiene tus datos fuera del entrenamiento por defecto.", "ladderOauthTitle": "Inicia sesión con una suscripción", - "ladderOauthBody": "Conecta una cuenta de ChatGPT — sin coste por token, pero los términos del nivel de consumo pueden usar el contenido para entrenamiento, así que es una elección deliberada, nunca la opción por defecto para tus datos de salud.", - "keylessLine": "HealthLog es plenamente útil sin IA. Tus paneles, gráficos, tendencias y exportaciones funcionan — la IA solo añade la lectura en lenguaje claro por encima.", + "ladderOauthBody": "Conecta una cuenta de ChatGPT. Sin coste por token, pero los términos del nivel de consumo pueden usar el contenido para entrenamiento, así que es una elección deliberada, nunca la opción por defecto para tus datos de salud.", + "keylessLine": "HealthLog es plenamente útil sin IA. Tus paneles, gráficos, tendencias y exportaciones funcionan; la IA solo añade la lectura en lenguaje claro por encima.", "setupCta": "Configúralo (un minuto aprox.)", - "sharedKeyNote": "Esta instancia ya ofrece un proveedor de IA compartido, así que los insights funcionan para ti ahora mismo — sin configuración.", + "sharedKeyNote": "Esta instancia ya ofrece un proveedor de IA compartido, así que los insights funcionan para ti ahora mismo, sin configuración.", "offer": { "title": "Esta instancia ya puede escribir tu resumen en lenguaje claro.", "body": "El operador ofrece un proveedor que funcionó por última vez en las últimas 24 horas. Con un toque activas el lenguaje claro; tus datos irán entonces a ese único proveedor y a nadie más.", @@ -5153,7 +5153,7 @@ "profileDescription": "Altura, fecha de nacimiento y sexo desbloquean objetivos personalizados.", "profileCta": "Abrir perfil", "measurementTitle": "Registrar la primera medición", - "measurementDescription": "Una medición activa la tarjeta — la tendencia se dibuja a partir de la 5.ª medición.", + "measurementDescription": "Una medición activa la tarjeta; la tendencia se dibuja a partir de la 5.ª medición.", "measurementCta": "Añadir medición", "medicationTitle": "Añadir medicamento", "medicationDescription": "Sigue el cumplimiento y recibe recordatorios justo cuando los necesites.", @@ -5162,7 +5162,7 @@ "dataSourceDescription": "Sincroniza peso, presión, sueño y más desde Withings, WHOOP, Oura, Polar, Nightscout, Fitbit o Apple Health.", "dataSourceCta": "Conectar", "notificationsTitle": "Configurar notificaciones", - "notificationsDescription": "Elige cómo te recuerda HealthLog — Telegram, ntfy o Web Push.", + "notificationsDescription": "Elige cómo te recuerda HealthLog: Telegram, ntfy o Web Push.", "notificationsCta": "Abrir notificaciones", "insightsTitle": "Activar insights (opcional)", "insightsDescription": "Añade un modelo local o tu propia clave de IA para desbloquear el resumen diario y Coach.", @@ -5388,7 +5388,7 @@ "resetSuccess": "Prioridad de fuentes restablecida a los valores predeterminados", "perMetricToggle": "Ajustes por métrica ({count})", "perMetricHelp": "Métricas que has personalizado respecto al orden predeterminado. Usa esta lista para devolver cualquier métrica concreta a su valor predeterminado sin tocar las demás.", - "perMetricEmpty": "No hay ajustes por métrica — todas las métricas usan el orden global de arriba.", + "perMetricEmpty": "No hay ajustes por métrica. Todas las métricas usan el orden global de arriba.", "resetMetric": "Restablecer", "deviceTypeToggle": "Prioridad por tipo de dispositivo ({count})", "deviceTypeHelp": "Dentro de una fuente, qué dispositivo prevalece. Cuando un Apple Watch y un iPhone registran ambos los pasos, el tipo de dispositivo mejor clasificado cuenta como la lectura canónica.", @@ -5497,7 +5497,7 @@ "fullBackup": { "title": "Copia completa", "description": "Todo tu historial en un archivo JSON.", - "scopeNote": "Los metadatos de los documentos y el resumen de IA, si existe, se incluyen en texto plano; los archivos originales de los documentos y los datos de rutas GPS/muestras de los entrenamientos no están incluidos — descárgalos por separado desde el archivo de documentos o la exportación de entrenamientos.", + "scopeNote": "Los metadatos de los documentos y el resumen de IA, si existe, se incluyen en texto plano; los archivos originales de los documentos y los datos de rutas GPS/muestras de los entrenamientos no están incluidos. Descárgalos por separado desde el archivo de documentos o la exportación de entrenamientos.", "encryptToggle": "Cifrar con una contraseña", "passphrasePlaceholder": "Contraseña (mín. 12 caracteres)", "passphraseHelp": "Deriva la clave del archivo con Argon2id y lo sella con AES-256-GCM. Guarda el archivo con la extensión .hlx.", @@ -6048,7 +6048,7 @@ "rawDataWarning": "Historial detallado activado: cada análisis envía además promedios diarios de los últimos 90 días, promedios semanales del año anterior y promedios mensuales hasta 5 años atrás.", "regenerateInsights": "Regenerar informes", "regenerateSuccess": "Informes regenerados correctamente", - "regenerateRateLimit": "Espera un momento — has alcanzado el límite por hora de análisis.", + "regenerateRateLimit": "Espera un momento: has alcanzado el límite por hora de análisis.", "lastGeneratedAt": "Generado por última vez", "ai": { "chatgptConnectedBadge": "ChatGPT conectado", @@ -6058,11 +6058,11 @@ "deviceCodeHeading": "Termina de conectar en chatgpt.com", "deviceCodeStep1": "Abre este enlace en cualquier dispositivo:", "deviceCodeStep2": "Introduce este código de un solo uso:", - "deviceCodeStep3": "Aprueba la conexión — esta página se actualiza automáticamente.", + "deviceCodeStep3": "Aprueba la conexión. Esta página se actualiza automáticamente.", "deviceCodeCopy": "Copiar", "deviceCodeWaiting": "Esperando aprobación…", "deviceCodeCancel": "Cancelar", - "oauthNotConfigured": "El OAuth de ChatGPT no está configurado en esta instancia — usa tu propia clave de API a continuación.", + "oauthNotConfigured": "El OAuth de ChatGPT no está configurado en esta instancia. Usa tu propia clave de API a continuación.", "modelLabel": "Modelo", "modelOptionDefault": "— Predeterminado —", "modelOptionCustom": "Personalizado…", @@ -6146,11 +6146,11 @@ "notConfigured": "El operador no ha configurado una clave de OpenAI compartida en esta instancia." }, "testProvider": "Probar el proveedor activo", - "testSuccess": "OK — {provider} ({model})", + "testSuccess": "OK: {provider} ({model})", "testFailedShort": "Prueba fallida: {message}", - "testUnexpectedResponse": "Falló la conexión con el proveedor de IA — respuesta inesperada del servidor.", - "testReasonCredentials": "El proveedor rechazó las credenciales — vuelve a autenticarte en los ajustes de IA.", - "testReasonRateLimited": "El proveedor limitó la solicitud — inténtalo de nuevo en breve.", + "testUnexpectedResponse": "Falló la conexión con el proveedor de IA: respuesta inesperada del servidor.", + "testReasonCredentials": "El proveedor rechazó las credenciales. Vuelve a autenticarte en los ajustes de IA.", + "testReasonRateLimited": "El proveedor limitó la solicitud. Inténtalo de nuevo en breve.", "testReasonServerError": "El proveedor de IA devolvió un error del servidor.", "testReasonBadRequest": "El proveedor rechazó la solicitud (HTTP {status}): el endpoint respondió, así que el problema está en el formato de la solicitud o en el nombre del modelo, no en la conexión.", "testReasonUnreachable": "No se pudo contactar con el proveedor de IA.", @@ -6194,7 +6194,7 @@ "markDone": "Hecho", "dismiss": "Descartar", "deleteAria": "Eliminar este recordatorio", - "note": "Los recordatorios se guardan cifrados. Elimina uno cuando quieras — desaparece de lo que el Coach puede ver.", + "note": "Los recordatorios se guardan cifrados. Elimina uno cuando quieras y desaparece de lo que el Coach puede ver.", "status": { "proposed": "Sugerido", "active": "Guardado", @@ -6324,8 +6324,8 @@ "withingsClientId": "ID de cliente", "withingsClientSecret": "Secreto de cliente", "withingsCredentialsSaved": "Credenciales guardadas", - "withingsCredentialsSavedPlaceholder": "Guardado — introduce uno nuevo para reemplazarlo", - "withingsCredentialsSavedPlaceholderSecret": "Guardado — introduce uno nuevo para reemplazarlo", + "withingsCredentialsSavedPlaceholder": "Guardado. Introduce uno nuevo para reemplazarlo", + "withingsCredentialsSavedPlaceholderSecret": "Guardado. Introduce uno nuevo para reemplazarlo", "withingsSaveCredentials": "Guardar", "configured": "Configurado", "withingsSync": "Sincronizar ahora", @@ -6340,7 +6340,7 @@ }, "withingsFullSyncResult": "{count} mediciones sincronizadas por completo", "withingsSyncFailed": "Falló la sincronización", - "withingsOauthConnected": "Withings conectado — la primera sincronización comienza en segundo plano.", + "withingsOauthConnected": "Withings conectado. La primera sincronización comienza en segundo plano.", "withingsOauthFailed": "Error al conectar con Withings", "withingsOauthError": { "csrf1": "La comprobación de seguridad falló porque faltaba la cookie del navegador. Inicia la conexión de nuevo en el mismo navegador.", @@ -6365,8 +6365,8 @@ "whoopClientId": "Client ID", "whoopClientSecret": "Client Secret", "whoopCredentialsSaved": "Credenciales guardadas", - "whoopCredentialsSavedPlaceholder": "Guardado — introduce nuevas para reemplazar", - "whoopCredentialsSavedPlaceholderSecret": "Guardado — introduce nuevas para reemplazar", + "whoopCredentialsSavedPlaceholder": "Guardado. Introduce nuevas para reemplazar", + "whoopCredentialsSavedPlaceholderSecret": "Guardado. Introduce nuevas para reemplazar", "whoopSaveCredentials": "Guardar", "whoopSync": "Sincronizar ahora", "whoopFullSync": "Sincronizar todos los datos", @@ -6395,7 +6395,7 @@ }, "fitbit": "Fitbit", "fitbitTag": "Fitbit y Pixel", - "fitbitDescription": "Conecta Fitbit para sincronizar tus datos de Fitbit y Pixel Watch — peso, frecuencia cardíaca y más.", + "fitbitDescription": "Conecta Fitbit para sincronizar tus datos de Fitbit y Pixel Watch: peso, frecuencia cardíaca y más.", "fitbitExperimentalBadge": "Experimental", "fitbitCredentials": "Credenciales de API", "fitbitClientId": "Client ID", @@ -6427,8 +6427,8 @@ "googleHealthClientId": "ID de cliente", "googleHealthClientSecret": "Secreto de cliente", "googleHealthCredentialsSaved": "Credenciales guardadas", - "googleHealthCredentialsSavedPlaceholder": "Guardado — introduce nuevas para reemplazar", - "googleHealthCredentialsSavedPlaceholderSecret": "Guardado — introduce nuevas para reemplazar", + "googleHealthCredentialsSavedPlaceholder": "Guardado. Introduce nuevas para reemplazar", + "googleHealthCredentialsSavedPlaceholderSecret": "Guardado. Introduce nuevas para reemplazar", "googleHealthSaveCredentials": "Guardar", "googleHealthSync": "Sincronizar ahora", "googleHealthSyncCheckStatus": "Actualizar estado", @@ -6499,10 +6499,10 @@ }, "integrationPill": { "connected": "Conectado", - "errorReconnect": "Error — reconectar", + "errorReconnect": "Error: reconectar", "warningServerError": "Sincronización con errores", "failureCount": "{count}/{threshold}", - "parkedReconnect": "Pausado — reconectar", + "parkedReconnect": "Pausado: reconectar", "notConnected": "No conectado", "justNow": "ahora mismo", "minutesAgo": "hace {count} min", @@ -6557,7 +6557,7 @@ "namePlaceholder": "Nombre, p. ej. Paperless-ngx" }, "tokenMintMovedDescription": "Los tokens se emiten donde se aplican: arriba para las mediciones, los entrenamientos y los documentos, o en el endpoint de API de un medicamento para ese medicamento concreto.", - "tokenCreated": "Token creado — ¡cópialo ahora! No se mostrará de nuevo.", + "tokenCreated": "Token creado. ¡Cópialo ahora! No se mostrará de nuevo.", "tokenCopy": "Copiar token", "tokenCopied": "Token copiado al portapapeles", "tokenCopyFailed": "No se pudo copiar el token", @@ -6596,7 +6596,7 @@ "deleteAccountCta": "Eliminar cuenta", "deleteAccountConfirmTitle": "¿Eliminar la cuenta de forma permanente?", "deleteAccountConfirmDescription": "Tu cuenta, todos los datos de salud, las claves de acceso, las sesiones y las entradas de auditoría se eliminarán de forma permanente. Se cerrará tu sesión inmediatamente después.", - "deleteAccountSuccess": "Cuenta eliminada — cerrando tu sesión.", + "deleteAccountSuccess": "Cuenta eliminada. Cerrando tu sesión.", "deleteAccountFailed": "No se pudo eliminar la cuenta", "deleteAccountFinal": "Eliminar permanentemente", "saved": "Guardado", @@ -6619,7 +6619,7 @@ "testing": "Probando…", "ok": "Conectado (latencia {latency} ms)", "errors": { - "credentials_rejected": "Credenciales rechazadas — comprueba tu token", + "credentials_rejected": "Credenciales rechazadas: comprueba tu token", "rate_limited": "Limitado por el servidor remoto", "timeout": "La solicitud agotó el tiempo de espera", "upstream_error": "El servidor remoto devolvió un error", @@ -6630,7 +6630,7 @@ "private_origin_not_approved": "Destino en una red privada. El operador debe añadir este origen a NOTIFICATION_PRIVATE_ORIGINS", "private_origin_not_grantable": "Esta dirección es de enlace local, de metadatos o no especificada; ninguna autorización del operador puede abrirla. Usa la dirección en la que escucha el relay", "url_invalid": "La URL no es válida", - "redirected": "El endpoint redirige — comprueba la URL", + "redirected": "El endpoint redirige: comprueba la URL", "endpoint_not_found": "No se encontró el endpoint en la URL", "credentials_unreadable": "Las credenciales no se pueden descifrar", "upstream_invalid_json": "El servidor remoto envió un JSON no válido", @@ -6641,7 +6641,7 @@ }, "notificationStatus": { "title": "Fiabilidad de los canales", - "description": "Estado de cada canal — «Desactivado automáticamente» significa detenido tras errores permanentes.", + "description": "Estado de cada canal; «Desactivado automáticamente» significa detenido tras errores permanentes.", "emptyDescription": "Configura un canal en Ajustes › Integraciones › Canales de entrega.", "stateActive": "Activo", "stateAutoDisabled": "Desactivado automáticamente", @@ -6699,7 +6699,7 @@ "createTitle": "Nuevo enlace para compartir", "createDescription": "El enlace es de solo lectura y limitado en el tiempo.", "label": "Etiqueta", - "labelPlaceholder": "p. ej. Dra. García — revisión anual", + "labelPlaceholder": "p. ej. Dra. García, revisión anual", "range": "Días de historial", "rangeHint": "Hasta cuándo se remonta la ventana compartida.", "expiry": "Caduca en (días)", @@ -6719,7 +6719,7 @@ "statusRevoked": "Revocado", "statusExpired": "Caducado", "inactiveTitle": "Revocados y caducados ({count})", - "shownOnce": "Se muestra una sola vez. Guarde ahora el código QR y la frase de acceso — no se pueden recuperar después.", + "shownOnce": "Se muestra una sola vez. Guarde ahora el código QR y la frase de acceso: no se pueden recuperar después.", "qrAlt": "Código QR con el enlace para compartir y la frase de acceso", "linkLabel": "Enlace", "passphraseLabel": "Frase de acceso", @@ -6748,7 +6748,7 @@ "statusNeedsReselect": "Elegir contenido de nuevo", "reselectReason": "Este enlace mostraba un alcance que nadie eligió, por eso se cerró. Crea uno nuevo y elige su contenido.", "reselectAction": "Crear un reemplazo", - "createDetail": "El token se muestra una sola vez al crearlo — guárdalo entonces; no se puede recuperar.", + "createDetail": "El token se muestra una sola vez al crearlo. Guárdalo entonces; no se puede recuperar.", "activeDescription": "Los enlaces que has compartido, cuándo caducan y cuántas veces se abrieron." }, "genderOther": "Otro", @@ -6781,7 +6781,7 @@ "polarClientId": "Client ID", "polarClientSecret": "Client Secret", "polarCredentialsSaved": "Credenciales guardadas", - "polarCredentialsSavedPlaceholder": "Guardado — introduce nuevas para reemplazar", + "polarCredentialsSavedPlaceholder": "Guardado. Introduce nuevas para reemplazar", "polarSaveCredentials": "Guardar", "polarUnavailable": "Polar no está configurado en este servidor. Añade arriba tus propias credenciales OAuth de Polar, o pide a tu administrador que configure la app compartida.", "polarConnect": "Conectar Polar", @@ -6810,7 +6810,7 @@ "ouraClientId": "Client ID", "ouraClientSecret": "Client Secret", "ouraCredentialsSaved": "Credenciales guardadas", - "ouraCredentialsSavedPlaceholder": "Guardado — introduce nuevas para reemplazar", + "ouraCredentialsSavedPlaceholder": "Guardado. Introduce nuevas para reemplazar", "ouraSaveCredentials": "Guardar", "ouraUnavailable": "Oura no está configurado en este servidor. Añade arriba tus propias credenciales OAuth de Oura, o pide a tu administrador que configure la app compartida.", "ouraConnect": "Conectar Oura", @@ -6851,7 +6851,7 @@ } }, "integrationRedirectGuide": { - "intro": "Esto se conecta mediante tu propia app de desarrollador de {provider} — unos 5 minutos de configuración:", + "intro": "Esto se conecta mediante tu propia app de desarrollador de {provider}, con unos 5 minutos de configuración:", "step1": "Crea una app en el portal de desarrolladores de {provider}.", "step2": "Configura su URL de redirección/callback en:", "step3": "Pega arriba el ID de cliente y el secreto de cliente que te da." @@ -7038,7 +7038,7 @@ "stravaClientId": "ID de cliente", "stravaClientSecret": "Secreto de cliente", "stravaCredentialsSaved": "Credenciales guardadas", - "stravaCredentialsSavedPlaceholder": "Guardadas — introduce nuevas para reemplazar", + "stravaCredentialsSavedPlaceholder": "Guardadas. Introduce nuevas para reemplazar", "stravaSaveCredentials": "Guardar", "stravaUnavailable": "Strava no está configurado en este servidor. Añade arriba tus propias credenciales de API de Strava o pide a tu administrador que configure la app compartida.", "stravaConnect": "Conectar Strava", @@ -7102,7 +7102,7 @@ }, "garminInfo": { "title": "Garmin", - "body": "Garmin no tiene conexión directa aquí. Conéctalo a través de Apple Health (iOS) o Google Health Connect (Android). Las métricas propias de Garmin — Body Battery, Training Load, estado de HRV, VO₂ máx.— no las comparte Garmin con ninguna de las dos plataformas.", + "body": "Garmin no tiene conexión directa aquí. Conéctalo a través de Apple Health (iOS) o Google Health Connect (Android). Las métricas propias de Garmin (Body Battery, Training Load, estado de HRV, VO₂ máx.) no las comparte Garmin con ninguna de las dos plataformas.", "docsLink": "Leer la guía" }, "glucoseReference": { @@ -7196,14 +7196,14 @@ "aiServerKey": { "title": "Clave de IA del servidor", "description": "Una clave del operador para las cuentas que no tienen una propia.", - "byokHint": "La clave propia del usuario (BYOK, inicio de sesión de ChatGPT o proveedor local) siempre tiene prioridad — la clave del servidor es el último paso de la cadena de proveedores.", + "byokHint": "La clave propia del usuario (BYOK, inicio de sesión de ChatGPT o proveedor local) siempre tiene prioridad; la clave del servidor es el último paso de la cadena de proveedores.", "consentHint": "Las solicitudes con la clave del servidor requieren el consentimiento de IA activo del usuario; sin un recibo de consentimiento no se envía nada.", "baseUrlHint": "La URL base determina la API: se reconoce una URL de Anthropic como https://api.anthropic.com/v1, cualquier otro host se llama a través de la API compatible con OpenAI.", "statusConfigured": "Configurada", "statusNotConfigured": "Sin configurar", "keyLabel": "Clave de API", "keyPlaceholder": "sk-...", - "keyPlaceholderSet": "Guardada ({preview}) — introduce una clave nueva para reemplazarla", + "keyPlaceholderSet": "Guardada ({preview}). Introduce una clave nueva para reemplazarla", "modelLabel": "Modelo", "baseUrlLabel": "URL base", "save": "Guardar", @@ -7294,7 +7294,7 @@ "integrationWebPush": "Web Push", "offlineGeoLabel": "Datos geográficos", "offlineGeoEnabled": "Sin conexión (GeoLite2)", - "offlineGeoFallback": "En línea ({host}) — monta las bases GeoLite2 y define GEOLITE2_DIR", + "offlineGeoFallback": "En línea ({host}): monta las bases GeoLite2 y define GEOLITE2_DIR", "offlineGeoOff": "Desactivado", "offlineGeoChosen": "En línea ({host})", "apiGlobal": "Permitir endpoints de API y tokens de API.", @@ -7702,7 +7702,7 @@ "restorePromptLabel": "Escribe RESTORE para continuar", "previewTitle": "Contenido de la copia", "previewLoading": "Leyendo el contenido…", - "previewUnavailable": "No se pudo leer el contenido — restaurar sigue siendo posible.", + "previewUnavailable": "No se pudo leer el contenido, pero restaurar sigue siendo posible.", "previewStillReading": "Esta copia se hizo con una versión anterior, así que su contenido se está leyendo completo, y con un historial grande eso lleva un rato. Vuelve a abrir este diálogo en unos minutos para verlo. Restaurar no depende de ello.", "previewEmpty": "El archivo no contiene registros.", "previewOther": "Otros registros", @@ -8276,7 +8276,7 @@ }, "selfContextComplete": { "title": "Autoinforme al día", - "description": "Los cuatro campos del autoinforme completados — el Coach conoce tu contexto." + "description": "Los cuatro campos del autoinforme completados: el Coach conoce tu contexto." }, "sleepLog7": { "title": "Registro de sueño durante 7 días", @@ -8298,7 +8298,7 @@ }, "hiddenCard": { "title": "Logro oculto", - "description": "Sigue registrando — quizá te topes con él.", + "description": "Sigue registrando y quizá te topes con él.", "ariaLabel": "Logro oculto bloqueado" }, "hiddenUnlockToast": { @@ -8307,7 +8307,7 @@ "dashboardCard": { "title": "Desbloqueos recientes", "viewAll": "Ver todo", - "empty": "Aún no hay logros — sigue registrando para desbloquear el primero." + "empty": "Aún no hay logros. Sigue registrando para desbloquear el primero." } }, "notifications": { @@ -8490,7 +8490,7 @@ } }, "edit": { - "title": "Editar rango objetivo — {metric}", + "title": "Editar rango objetivo: {metric}", "description": "Ajusta el rango objetivo usado en gráficas, insights y el informe médico. Valores en {unit}.", "derivedHint": "Esta tarjeta se calcula a partir de otras métricas. Edita en su lugar los objetivos subyacentes (p. ej. tensión arterial o peso).", "minLabel": "Mín", @@ -8522,11 +8522,11 @@ "aboveTarget": "{delta} {unit} por encima del rango", "belowTarget": "{delta} {unit} por debajo del rango", "diastolic": "Diastólica", - "glucoseFasting": "Glucemia — en ayunas", - "glucosePostprandial": "Glucemia — posprandial", - "glucoseRandom": "Glucemia — cualquiera", - "glucoseBedtime": "Glucemia — antes de dormir", - "glucoseUnspecified": "Glucemia — sin indicar", + "glucoseFasting": "Glucemia (en ayunas)", + "glucosePostprandial": "Glucemia (posprandial)", + "glucoseRandom": "Glucemia (cualquiera)", + "glucoseBedtime": "Glucemia (antes de dormir)", + "glucoseUnspecified": "Glucemia (sin indicar)", "status": { "underweight": "Peso insuficiente", "normal": "Normal", @@ -8612,7 +8612,7 @@ "askMedicationName": "Indica el medicamento, p. ej. tomado Ramipril.", "medicationNotFoundExact": "Medicamento no encontrado. Envía el nombre exactamente como aparece en HealthLog.", "helpHeader": "Comandos disponibles:", - "helpBody": "/help — mostrar esta ayuda\n/add — registrar una toma\n/start — iniciar el bot\n\nComandos de texto:\ntaken <nombre> — confirmar una toma\n\nBotones en los recordatorios:\n• Tomado — confirmar la toma\n• 🕐 1h / 🕐 3h — posponer el recordatorio\n• ⏭ Omitir — omitir la toma\n• ✓ Confirmar — confirmar una toma omitida", + "helpBody": "/help: mostrar esta ayuda\n/add: registrar una toma\n/start: iniciar el bot\n\nComandos de texto:\ntaken <nombre>: confirmar una toma\n\nBotones en los recordatorios:\n• Tomado: confirmar la toma\n• 🕐 1h / 🕐 3h: posponer el recordatorio\n• ⏭ Omitir: omitir la toma\n• ✓ Confirmar: confirmar una toma omitida", "measureValuePrompt": "Responde con el valor para registrarlo (opcional).", "buttonMeasureValue": "Valor…", "measureValueSaved": "Lectura guardada.", @@ -8637,9 +8637,9 @@ }, "lowStockReminders": { "title": "Quedan pocas existencias: {medName}", - "bodyToday": "{medName}: quedan {units} unidades — menos de un día de suministro.", - "bodyReorder": "{medName}: quedan {units} unidades. Las existencias se agotan hacia el {runsOutOn} — vuelve a pedir antes del {reorderBy}.", - "bodyLastDose": "{medName}: quedan {units} unidades — alrededor de tu última dosis. Las existencias se agotan hacia el {runsOutOn}.", + "bodyToday": "{medName}: quedan {units} unidades, menos de un día de suministro.", + "bodyReorder": "{medName}: quedan {units} unidades. Las existencias se agotan hacia el {runsOutOn}. Vuelve a pedir antes del {reorderBy}.", + "bodyLastDose": "{medName}: quedan {units} unidades, alrededor de tu última dosis. Las existencias se agotan hacia el {runsOutOn}.", "bodyExpired": "{medName}: no quedan existencias utilizables. {units} unidades están marcadas como caducadas.", "bodyAsNeeded": "{medName}: solo quedan {units} unidades. Vuelve a pedir antes de necesitar la próxima dosis." }, @@ -8670,7 +8670,7 @@ }, "clinicianView": { "title": "Registro de salud compartido", - "period": "Período del informe: {start} – {end}", + "period": "Período del informe: {start}–{end}", "expires": "Este enlace caduca el {date}.", "provenance": "Este es un resumen de solo lectura compartido por la persona a la que pertenece, exportado de sus datos de HealthLog autorregistrados. Los valores son autoinformados y pueden incluir lecturas sincronizadas desde dispositivos; trátelos como informados por el paciente, no como un examen clínico.", "labs": "Valores de laboratorio", @@ -8694,7 +8694,7 @@ "strain": "Puntuación de esfuerzo", "score": "Puntuación de bienestar" }, - "footer": "Compartido desde HealthLog — un registro de salud autoalojado.", + "footer": "Compartido desde HealthLog, un registro de salud autoalojado.", "unlock": { "title": "Introduzca la frase de acceso", "description": "Este registro de salud compartido está protegido. Introduzca la frase de acceso que recibió para verlo.", @@ -8909,8 +8909,8 @@ "ariaUnknown": "Aún no hay ciclo activo", "caption": "de tu ciclo", "firstPeriodCta": "Registrar mi primer periodo", - "periodOverdue": "Tu período llega más tarde de lo habitual — el conteo de días se pausa hasta que registres el próximo período.", - "periodOverdueDays": "Tu período llega {days} días más tarde de lo habitual — el conteo de días se pausa hasta que registres el próximo período.", + "periodOverdue": "Tu período llega más tarde de lo habitual. El conteo de días se pausa hasta que registres el próximo período.", + "periodOverdueDays": "Tu período llega {days} días más tarde de lo habitual. El conteo de días se pausa hasta que registres el próximo período.", "logPeriodCta": "Registrar período" }, "calendar": { @@ -8935,7 +8935,7 @@ "predictions": { "title": "Qué viene después", "nextPeriod": "Próximo periodo", - "nextPeriodWindow": "{low} – {high}", + "nextPeriodWindow": "{low}–{high}", "fertileWindow": "Ventana fértil", "ovulation": "Ovulación estimada", "confidenceHigh": "Alta", @@ -8944,7 +8944,7 @@ "stillLearning": "Aún aprendiendo", "stillLearningBody": "Registra al menos tres ciclos completos y tus predicciones mejorarán. Hasta entonces es una estimación aproximada.", "rawMode": "Predicción desactivada", - "rawModeBody": "Has desactivado las predicciones — solo se muestran tus datos registrados, sin pronóstico.", + "rawModeBody": "Has desactivado las predicciones: solo se muestran tus datos registrados, sin pronóstico.", "none": "Aún no hay predicción. Registra un periodo para empezar.", "ovulationConfirmed": "Ovulación (confirmada)" }, @@ -9134,14 +9134,14 @@ "postpone": { "menuItem": "Aplazar…", "title": "Aplazar vencimiento", - "description": "Solo mueve el vencimiento actual — el ritmo regular no cambia.", + "description": "Solo mueve el vencimiento actual; el ritmo regular no cambia.", "chip": "+{days} días", "dateLabel": "Nueva fecha", "confirm": "Aplazar" }, "skip": { "heading": "Omitir este vencimiento", - "explainer": "Se registra honestamente como omitido — no como hecho. El intervalo se reinicia desde hoy.", + "explainer": "Se registra honestamente como omitido, no como hecho. El intervalo se reinicia desde hoy.", "action": "Omitir", "confirmTitle": "¿Omitir este vencimiento?" }, @@ -9344,7 +9344,7 @@ "emptyDescription": "Añade un valor para seguir este biomarcador con el tiempo.", "title": "Biomarcador", "genericDescription": "Un biomarcador de laboratorio que sigues. Añade lecturas para ver su evolución frente al rango de referencia.", - "valuesTitle": "{marker} — todas las lecturas", + "valuesTitle": "{marker}: todas las lecturas", "valuesDescription": "Cada lectura de este biomarcador. Edita o elimina una entrada directamente.", "backToMarker": "Volver a {marker}", "latestResult": "Último resultado" @@ -9515,12 +9515,12 @@ "dateLabel": "Fecha", "refLowLabel": "Referencia inferior", "refHighLabel": "Referencia superior", - "newBiomarker": "Nuevo biomarcador — se creará", + "newBiomarker": "Nuevo biomarcador: se creará", "linksExisting": "Se vincula a {name} existente", "duplicateWarning": "Ya existe un valor coincidente", "lowConfidence": "Verifica este valor", "lowConfidenceBadge": "Confianza baja", - "valueUnreadable": "Valor ilegible — introdúcelo manualmente", + "valueUnreadable": "Valor ilegible: introdúcelo manualmente", "saveSelected": "Guardar {count} seleccionados", "discardAll": "Descartar todo", "savedToast": "{count} resultados de laboratorio guardados", @@ -10004,7 +10004,7 @@ "dismiss": "Ahora no", "applied": "Añadido", "dismissed": "Descartado", - "failed": "No se pudo añadir — inténtalo de nuevo", + "failed": "No se pudo añadir. Inténtalo de nuevo", "checkup": { "title": "¿Añadir un recordatorio de revisión?" }, @@ -11186,7 +11186,7 @@ "genericDescription": "Una medición que registras. Añade valores para seguirla con el tiempo.", "emptyTitle": "Aún sin valores", "emptyDescription": "Añade tu primer valor para empezar a representar esta métrica.", - "valuesTitle": "{metric} — todos los valores", + "valuesTitle": "{metric}: todos los valores", "valuesDescription": "Todos los valores registrados de esta métrica.", "backToMetric": "Volver a {metric}" } @@ -11926,7 +11926,7 @@ "notFound": "Ese acceso ya no existe.", "revokeFailed": "No se pudo terminar el acceso.", "renounceFailed": "No se pudo devolver el acceso.", - "profileNotFound": "Ese perfil ya no está — puede que se haya eliminado, o que tu acceso haya terminado.", + "profileNotFound": "Ese perfil ya no está. Puede que se haya eliminado, o que tu acceso haya terminado.", "deleteProfileFailed": "No se pudo eliminar el perfil.", "removeGuardianFailed": "No se pudo terminar ese acceso." }, @@ -12260,15 +12260,11 @@ "rugLegend": "Los puntos bajo el eje marcan días con entradas, y un anillo, un día destacado.", "sheetExpand": "Ampliar a toda la altura", "sheetShrink": "Reducir", - "usualLabel": "Tus 30 días anteriores", "valuesLegend": "Punto para este día, barra para los 30 días anteriores", "valuesAllOne": "Todos los valores", "valuesAllFew": "Los {count} valores", "valuesAllOther": "Los {count} valores", "valuesFewer": "Menos valores", - "countValuesOne": "1 valor", - "countValuesFew": "{count} valores", - "countValuesOther": "{count} valores", "countEntriesOne": "1 entrada", "countEntriesFew": "{count} entradas", "countEntriesOther": "{count} entradas", @@ -12308,7 +12304,6 @@ "subtitle": "Qué pasó y cuándo, junto a tus valores.", "standing": "Permanente", "startUnknown": "inicio desconocido", - "openDay": "Abrir {date}", "zoom": { "all": "Todo", "year": "12 meses", diff --git a/messages/fr.json b/messages/fr.json index f544efb27..5e73cfb4a 100644 --- a/messages/fr.json +++ b/messages/fr.json @@ -167,7 +167,7 @@ "anamnesisShiftSchedule": "Organisation du travail", "anamnesisColFact": "Élément du profil", "anamnesisColValue": "Valeur enregistrée", - "subtitle": "HealthLog — Rapport personnel de santé", + "subtitle": "HealthLog : rapport personnel de santé", "patient": "Patient", "dateOfBirth": "Date de naissance", "gender": "Sexe", @@ -177,18 +177,18 @@ "height": "Taille", "period": "Période du rapport", "createdOn": "Créé le", - "vitalsTitle": "Signes vitaux — Résumé", + "vitalsTitle": "Signes vitaux : résumé", "colParameter": "Paramètre", "colCurrent": "Actuel", "colAvgPeriod": "Moy. période", "colMin": "Min", "colMax": "Max", "colN": "n", - "bpClassificationTitle": "Tension artérielle — Classification ESH (2023)", + "bpClassificationTitle": "Tension artérielle : classification ESH (2023)", "avgBp": "Tension artérielle moyenne", "classification": "Classification", "bmiTitle": "Indice de masse corporelle (IMC)", - "bmiRow": "IMC:{bmi} kg/m² — Classification: {class} (WHO)", + "bmiRow": "IMC:{bmi} kg/m², classification: {class} (WHO)", "complianceTitle": "Observance des médicaments", "glp1Title": "Traitement GLP-1", "glp1WeightSummary": "Poids sur la période du rapport : {start} kg → {end} kg ({delta} kg)", @@ -236,8 +236,8 @@ "typeGlucoseRandom": "Glycémie (indifférente)", "typeGlucoseBedtime": "Glycémie (avant le coucher)", "typeGlucoseUnspecified": "Glycémie (non précisée)", - "glucoseClassificationTitle": "Glycémie — Plages de référence (ADA 2024 / DDG)", - "glucoseRow": "{label} : moy. {avg} {unit} (cible {rangeMin}–{rangeMax}) — {class}", + "glucoseClassificationTitle": "Glycémie : plages de référence (ADA 2024 / DDG)", + "glucoseRow": "{label} : moy. {avg} {unit} (cible {rangeMin}–{rangeMax}), {class}", "glucoseInTarget": "dans la cible", "glucoseBelowTarget": "sous la cible", "glucoseAboveTarget": "au-dessus de la cible", @@ -289,7 +289,7 @@ "gmi": "Indicateur de gestion du glucose (GMI)", "eA1c": "HbA1c estimée", "cv": "Variabilité (CV%)", - "spotCaveat": "Ce sont des estimations issues de mesures ponctuelles, et non un profil de capteur continu — à lire comme une tendance, pas comme un verdict clinique." + "spotCaveat": "Ce sont des estimations issues de mesures ponctuelles, et non un profil de capteur continu. À lire comme une tendance, pas comme un verdict clinique." }, "illnessTitle": "Affections et maladies", "illnessOngoing": "En cours", @@ -378,12 +378,12 @@ "backToDashboard": "Retour au tableau de bord" }, "offlineBanner": { - "message": "Pas de connexion — les modifications ne peuvent pas être enregistrées tant que tu n'es pas de nouveau en ligne.", - "saveFailed": "Enregistrement impossible — tu es hors ligne. Réessaie une fois de nouveau en ligne.", + "message": "Pas de connexion : les modifications ne peuvent pas être enregistrées tant que tu n'es pas de nouveau en ligne.", + "saveFailed": "Enregistrement impossible : tu es hors ligne. Réessaie une fois de nouveau en ligne.", "showingCached": "Affichage de tes dernières données synchronisées." }, "demoBanner": { - "message": "Mode démo — les modifications ne sont pas enregistrées." + "message": "Mode démo : les modifications ne sont pas enregistrées." }, "nav": { "dashboard": "Tableau de bord", @@ -458,7 +458,7 @@ "hasAccount": "Déjà un compte ?", "loginFailed": "Échec de la connexion", "registerFailed": "Échec de l’inscription", - "invitedBanner": "Vous avez été invité — créez votre compte même si les inscriptions sont fermées.", + "invitedBanner": "Vous avez été invité. Créez votre compte même si les inscriptions sont fermées.", "alreadySignedIn": { "title": "Tu es déjà connecté", "body": "Tu es connecté en tant que {username}. Une invitation crée un nouveau compte. Déconnecte-toi pour l'accepter.", @@ -775,7 +775,7 @@ "formReset": "Réinitialiser le formulaire", "saveError": "Erreur lors de l’enregistrement", "duplicateTimestamp": "Une mesure de ce type existe déjà à cet horodatage.", - "serverOwnedSource": "Les valeurs provenant d’une source connectée ne peuvent pas être modifiées — l’horodatage et la note restent modifiables.", + "serverOwnedSource": "Les valeurs provenant d’une source connectée ne peuvent pas être modifiées, mais l’horodatage et la note restent modifiables.", "deleteError": "Erreur lors de la suppression", "deletedToast": "Mesure supprimée", "restoredToast": "Mesure restaurée", @@ -875,7 +875,7 @@ }, "metricCatalog": { "title": "Ce que HealthLog peut suivre", - "description": "Tous les domaines de mesures pris en charge par HealthLog, que tu aies déjà des données ou non — et ce qui les fournirait.", + "description": "Tous les domaines de mesures pris en charge par HealthLog, que tu aies déjà des données ou non, et ce qui les fournirait.", "statusPresent": "Suivi", "statusAbsent": "Pas encore suivi", "statusModuleOff": "Désactivé", @@ -883,11 +883,11 @@ "connectCta": "Connecter une source", "viewCta": "Voir", "ecg": { - "source": "Tracés ECG à une dérivation depuis une montre compatible — Withings ScanWatch aujourd'hui — synchronisés automatiquement." + "source": "Tracés ECG à une dérivation depuis une montre compatible (Withings ScanWatch aujourd'hui), synchronisés automatiquement." }, "watchdog": { "title": "Surveillance automatique", - "description": "HealthLog surveille aussi discrètement en arrière-plan — notifications de rythme irrégulier et de perturbations respiratoires envoyées par une montre connectée, alertes d'écart par rapport à ta valeur de référence, ainsi que des changements notables entre tes deux derniers bilans de laboratoire — et n'affiche une carte que si quelque chose se démarque. Si au moins une de ces sources est connectée, l'absence de carte est bon signe, pas une fonctionnalité manquante ; si aucune ne l'est encore, c'est simplement qu'il n'y a rien à surveiller." + "description": "HealthLog surveille aussi discrètement en arrière-plan (notifications de rythme irrégulier et de perturbations respiratoires envoyées par une montre connectée, alertes d'écart par rapport à ta valeur de référence, ainsi que des changements notables entre tes deux derniers bilans de laboratoire) et n'affiche une carte que si quelque chose se démarque. Si au moins une de ces sources est connectée, l'absence de carte est bon signe, pas une fonctionnalité manquante ; si aucune ne l'est encore, c'est simplement qu'il n'y a rien à surveiller." } }, "mood": { @@ -1044,7 +1044,7 @@ "archive": "Archiver", "restore": "Restaurer", "archivedTitle": "Étiquettes archivées", - "archivedDescription": "Les étiquettes archivées restent dans tes saisies passées — elles disparaissent seulement du sélecteur.", + "archivedDescription": "Les étiquettes archivées restent dans tes saisies passées. Elles disparaissent seulement du sélecteur.", "archivedEmpty": "Rien d’archivé.", "purgeTitle": "Supprimer l’étiquette définitivement ?", "purgeBody": "L’étiquette sera retirée de {count} saisies passées. Cette action est irréversible.", @@ -1069,7 +1069,7 @@ }, "sectionMoreTags": "Plus de tags", "sectionNoteDetails": "Note et détails", - "quickTagsHelp": "Vos tags fréquents — en un geste", + "quickTagsHelp": "Vos tags fréquents, en un geste", "quickTagsExpand": "Plus", "loadError": "Impossible de charger vos entrées d'humeur.", "sectionLevelA": "État d'esprit", @@ -1247,8 +1247,8 @@ "dialogDescription": "Ces médicaments sont à prendre maintenant. Confirmez pour les enregistrer tous comme pris.", "confirm": "Tout prendre ({count})", "successToast": "{count} prises enregistrées", - "partialToast": "{taken} enregistrées, {failed} échouées – veuillez réessayer", - "failedToast": "Aucune prise enregistrée – veuillez réessayer" + "partialToast": "{taken} enregistrées, {failed} échouées. Veuillez réessayer", + "failedToast": "Aucune prise enregistrée. Veuillez réessayer" }, "logIntake": { "dialogTitle": "Enregistrer une prise", @@ -1346,10 +1346,10 @@ "skipped": "Sauté", "intakeToastTaken": "{name} enregistré comme pris", "intakeToastSkipped": "{name} sauté", - "intakeToastFailed": "Impossible d'enregistrer {name} — réessayez", + "intakeToastFailed": "Impossible d'enregistrer {name}. Réessayez", "intakeUndo": "Annuler", "intakeUndone": "Entrée annulée", - "intakeUndoFailed": "Annulation impossible — corrigez dans l'historique", + "intakeUndoFailed": "Annulation impossible. Corrigez dans l'historique", "glp1LastInjection": "{label}", "glp1NextInjectionDays": "{label} (dans {days} jours)", "glp1NextInjectionToday": "aujourd’hui", @@ -1431,10 +1431,10 @@ "error": { "empty": "Saisis d'abord une description.", "tooLong": "Garde la description sous 2000 caractères.", - "rateLimit": "Trop de requêtes — attends un instant et réessaie.", - "noProvider": "Aucun fournisseur d'IA configuré — configure-le dans les Paramètres.", - "budget": "Budget IA quotidien atteint — réessaie demain.", - "network": "Impossible de joindre le fournisseur d'IA — réessaie.", + "rateLimit": "Trop de requêtes. Attends un instant et réessaie.", + "noProvider": "Aucun fournisseur d'IA configuré. Configure-le dans les Paramètres.", + "budget": "Budget IA quotidien atteint. Réessaie demain.", + "network": "Impossible de joindre le fournisseur d'IA. Réessaie.", "consent": "La lecture de votre description par IA nécessite d'abord votre consentement.", "unavailable": "La lecture de descriptions par IA n'est pas disponible ici pour le moment." } @@ -1450,7 +1450,7 @@ "everyNMonths": "Tous les N mois un jour précis", "yearly": "Une fois par an", "rolling": "Tous les N jours depuis la dernière prise (flexible)", - "rollingExplainer": "Compte à partir de votre dernière prise enregistrée — se met en pause si vous sautez une dose.", + "rollingExplainer": "Compte à partir de votre dernière prise enregistrée ; se met en pause si vous sautez une dose.", "oneShot": "Dose unique" }, "weekdays": { @@ -1508,7 +1508,7 @@ "night": "Nuit" }, "max": { - "reached": "Maximum atteint — retirez une heure avant d’en ajouter une autre." + "reached": "Maximum atteint : retirez une heure avant d’en ajouter une autre." } }, "courseWindow": { @@ -1558,7 +1558,7 @@ }, "step3": { "title": "Quelle est la dose ?", - "subline": "Un comprimé, une bouffée, une goutte — selon la forme.", + "subline": "Un comprimé, une bouffée, une goutte, selon la forme.", "amountLabel": "Quantité", "amountPlaceholder": "par exemple 5", "unitLabel": "Unité", @@ -1584,7 +1584,7 @@ }, "dosesPerUnitLabel": "Doses par unité", "dosesPerUnitPlaceholder": "p. ex. 4", - "dosesPerUnitHint": "Doses par stylo / flacon — laisser vide pour ne pas suivre le stock.", + "dosesPerUnitHint": "Doses par stylo / flacon. Laisser vide pour ne pas suivre le stock.", "short": "Dose", "unitsPerDoseLabel": "Unités par dose", "unitsPerDoseHint": "p. ex. 2 comprimés de 2 mg pour une dose de 4 mg, ou ½ comprimé pour une dose fractionnée" @@ -1596,7 +1596,7 @@ }, "step5": { "title": "À quelle fréquence le prenez-vous ?", - "subline": "Choisissez la cadence — les détails suivent à l’étape suivante.", + "subline": "Choisissez la cadence. Les détails suivent à l’étape suivante.", "short": "Fréquence" }, "step6": { @@ -1618,7 +1618,7 @@ }, "step7": { "title": "Quand le prenez-vous ?", - "subline": "Une ou plusieurs heures de la journée — les rappels suivent cette liste.", + "subline": "Une ou plusieurs heures de la journée. Les rappels suivent cette liste.", "presetsLabel": "Préréglages par moment de la journée", "presets": { "morning": "Matin", @@ -1626,7 +1626,7 @@ "evening": "Soir", "night": "Nuit" }, - "overrideHint": "Facultatif — définissez une dose ou un nombre d'unités différent pour cet horaire uniquement. Laissez vide pour utiliser la valeur par défaut du médicament.", + "overrideHint": "Facultatif : définissez une dose ou un nombre d'unités différent pour cet horaire uniquement. Laissez vide pour utiliser la valeur par défaut du médicament.", "doseOverrideLabel": "Dose pour cet horaire (facultatif)", "doseOverridePlaceholder": "ex. un demi-comprimé", "unitsOverrideLabel": "Unités consommées à cet horaire", @@ -1634,11 +1634,11 @@ "short": "Heures" }, "step8": { - "title": "Terminé — HealthLog doit-il vous le rappeler ?", + "title": "Terminé ! HealthLog doit-il vous le rappeler ?", "subline": "Vérifiez tout ci-dessous avant d’enregistrer.", "remindersLabel": "Rappels activés", - "remindersDescription": "Push, Telegram ou ntfy — selon vos réglages.", - "noChannelHint": "Les rappels nécessitent un canal de notification — aucun n'est actif pour le moment.", + "remindersDescription": "Push, Telegram ou ntfy, selon vos réglages.", + "noChannelHint": "Les rappels nécessitent un canal de notification, et aucun n'est actif pour le moment.", "noChannelHintLink": "Configurer les notifications", "short": "Fini" } @@ -1687,7 +1687,7 @@ }, "asNeeded": { "label": "Au besoin", - "description": "Pas de plan fixe — enregistrez une prise quand vous en avez besoin (p. ex. antidouleur)." + "description": "Pas de plan fixe : enregistrez une prise quand vous en avez besoin (p. ex. antidouleur)." } }, "summary": { @@ -1722,7 +1722,7 @@ } }, "errors": { - "submitFailed": "Impossible d’enregistrer le médicament — veuillez réessayer." + "submitFailed": "Impossible d’enregistrer le médicament. Veuillez réessayer." } }, "doseStrength": { @@ -1742,7 +1742,7 @@ }, "injectionSiteBodyOutlineAriaLabel": "Silhouette du corps", "injectionSitePickerAriaLabel": "Sélecteur de site d'injection", - "injectionSiteRecommendedAriaLabel": "{site} — prochain site recommandé", + "injectionSiteRecommendedAriaLabel": "{site}, prochain site recommandé", "injectionSiteLegendAriaLabel": "Légende des repères", "injectionSiteLegendRecommended": "Prochain site recommandé", "injectionSiteLegendLastUsed": "Dernier site utilisé", @@ -1830,7 +1830,7 @@ "cadence": { "oneShotOn": "Dose unique le {date}.", "oneShotPending": "Dose unique en attente.", - "asNeeded": "Au besoin — pas de plan fixe." + "asNeeded": "Au besoin, pas de plan fixe." }, "intake": { "title": "Historique des prises", @@ -1857,7 +1857,7 @@ "dialogTitle": "Modifier la prise", "takenAtLabel": "Prise à", "scheduledForHint": "Prévue : {dateTime}", - "farFromScheduledWarning": "Très éloignée de l’heure prévue — vérifiez la date.", + "farFromScheduledWarning": "Très éloignée de l’heure prévue. Vérifiez la date.", "skippedLabel": "Sautée", "save": "Enregistrer", "cancel": "Annuler", @@ -1904,7 +1904,7 @@ "description": "Enregistrez une dose, même rétroactive ou hors planning.", "takenAtLabel": "Prise à", "skippedLabel": "Sautée", - "nudgeHint": "Proche du créneau {slot} — à l'enregistrement, nous demandons s'il faut l'y rattacher.", + "nudgeHint": "Proche du créneau {slot} : à l'enregistrement, nous demandons s'il faut l'y rattacher.", "cancel": "Annuler", "submit": "Enregistrer" }, @@ -1953,7 +1953,7 @@ }, "codes": { "label": "Codes cliniques (ATC / RxNorm)", - "note": "Facultatif. Utilisés lors de l'export FHIR du dossier de santé. Les codes sont repris tels qu'ils sont saisis — jamais devinés.", + "note": "Facultatif. Utilisés lors de l'export FHIR du dossier de santé. Les codes sont repris tels qu'ils sont saisis, jamais devinés.", "atcLabel": "ATC", "rxNormLabel": "RxNorm", "saved": "Codes cliniques enregistrés", @@ -1973,7 +1973,7 @@ "title": "Terminer le médicament", "helper": "Arrête les rappels et marque le médicament comme terminé. L’historique reste visible.", "button": "Terminer", - "dialogTitle": "Terminer {name} — arrête les rappels, l’historique reste visible", + "dialogTitle": "Terminer {name} : arrête les rappels, l’historique reste visible", "dialogBody": "Plus de rappels. Les anciennes entrées restent dans la chronologie.", "toast": "Médicament terminé", "failed": "Impossible de terminer le médicament." @@ -2011,7 +2011,7 @@ "copyFailed": "Impossible de copier.", "tokenCopied": "Jeton copié", "copyToken": "Copier le jeton", - "mintedHint": "Copiez ce jeton maintenant — il n’est affiché qu’une seule fois." + "mintedHint": "Copiez ce jeton maintenant : il n’est affiché qu’une seule fois." }, "advanced": { "dataPortability": { @@ -2051,9 +2051,9 @@ "statusTitle": "Statut", "nextDoseLabel": "Prochaine dose", "nextDoseNone": "Aucune dose à venir.", - "nextDoseAsNeeded": "Au besoin — aucune dose planifiée.", + "nextDoseAsNeeded": "Au besoin, aucune dose planifiée.", "nextDoseNotTracked": "Prises non suivies, conservé pour mémoire.", - "pausedHint": "En pause — aucun rappel.", + "pausedHint": "En pause, aucun rappel.", "reminderLabel": "Rappel", "reminderOn": "Activé", "reminderOff": "Désactivé", @@ -2124,7 +2124,7 @@ "packagingDefaultPack": "Taille de boîte par défaut : {units} unités", "packagingNoDefaultPack": "Aucune taille de boîte par défaut", "packagingEdit": "Modifier", - "packagingDescription": "Définis combien d’unités consomme une dose et la taille habituelle d’une nouvelle boîte — p. ex. après un changement de fabricant avec une autre taille de plaquette.", + "packagingDescription": "Définis combien d’unités consomme une dose et la taille habituelle d’une nouvelle boîte, p. ex. après un changement de fabricant avec une autre taille de plaquette.", "packagingUnitsPerDoseLabel": "Unités par dose", "packagingUnitsPerDoseHelper": "P. ex. deux comprimés de 2 mg pour une dose de 4 mg, ou 1,5 pour un et demi (plus de 0, jusqu’à 100). Les prises déjà enregistrées restent inchangées.", "packagingDefaultPackLabel": "Taille de boîte par défaut (unités)", @@ -2175,11 +2175,11 @@ "hideEras": "Masquer les périodes antérieures", "addEra": "Ajouter une période antérieure", "addEraTitle": "Ajouter une période antérieure", - "addEraDescription": "Notez à quelles heures ce médicament était pris auparavant — par exemple avant de l'ajuster ici.", + "addEraDescription": "Notez à quelles heures ce médicament était pris auparavant, par exemple avant de l'ajuster ici.", "editAria": "Modifier la période", "editEraTitle": "Modifier la période", "editEraDescription": "Ajustez les heures de prise et la plage de dates de cette période.", - "archivedEditHint": "Cette période a été enregistrée automatiquement — votre modification corrige l'historique enregistré ; l'original est conservé en interne comme trace.", + "archivedEditHint": "Cette période a été enregistrée automatiquement. Votre modification corrige l'historique enregistré ; l'original est conservé en interne comme trace.", "updatedToast": "Période mise à jour", "updateError": "Impossible de mettre à jour la période. Elle ne doit pas chevaucher d'autres périodes et doit se terminer avant le plan actuel.", "timesLabel": "Heures de prise", @@ -2218,10 +2218,10 @@ } }, "logInjectionSiteTitle": "Enregistrer le site d'injection", - "logInjectionSiteDescription": "Où avez-vous injecté {name} ? Facultatif — vous pouvez l'ignorer.", + "logInjectionSiteDescription": "Où avez-vous injecté {name} ? Facultatif, vous pouvez l'ignorer.", "logInjectionSiteSkip": "Ignorer", "logInjectionSiteConfirm": "Enregistrer le site", - "logInjectionSiteNoneAvailable": "Aucun site d'injection disponible — tous les sites sont exclus dans vos réglages.", + "logInjectionSiteNoneAvailable": "Aucun site d'injection disponible : tous les sites sont exclus dans vos réglages.", "logInjectionSiteSaveFailed": "Impossible d’enregistrer le site d’injection. Veuillez réessayer.", "perSlotUnits": "{units} par dose", "trackInjectionSitesToggle": "Suivre les sites d'injection", @@ -2246,9 +2246,9 @@ "tableStockDoses": "{count} doses", "tableStockRunway": "≈ {days} jours restants", "cardLowStockRunway": "Réserve : ≈ {days} jours", - "takeActionFor": "Prendre – {name}", - "skipActionFor": "Passer – {name}", - "reorderDescription": "Définis l'ordre de tes médicaments – il s'applique à la vue cartes et à la vue tableau.", + "takeActionFor": "Prendre : {name}", + "skipActionFor": "Passer : {name}", + "reorderDescription": "Définis l'ordre de tes médicaments pour la vue cartes et la vue tableau.", "reorderSaved": "Ordre enregistré", "reorderSaveFailed": "L'ordre n'a pas pu être enregistré", "customize": "Personnaliser les médicaments", @@ -2267,7 +2267,7 @@ "levelShift": "Un changement de niveau a été détecté autour du {date}.", "plateau": { "title": "Plateau de poids à la dose actuelle", - "evidence": "Variation de poids de {delta} {unit} sur les {window} derniers jours ({readings} mesures) — {days} jours sous {dose}." + "evidence": "Variation de poids de {delta} {unit} sur les {window} derniers jours ({readings} mesures), {days} jours sous {dose}." }, "retarget": { "label": "Ce n'est pas la bonne mesure ?", @@ -2277,16 +2277,16 @@ "error": "Impossible d'enregistrer cette modification. Réessaie." }, "beforeAfter": { - "summary": "Ø {before} avant → Ø {after} depuis — un écart de {delta}.", + "summary": "Ø {before} avant → Ø {after} depuis, soit un écart de {delta}.", "counts": "D'après {beforeCount} mesures avant et {afterCount} depuis.", - "needBefore": "Pas encore assez de mesures avant le début — il faut environ {weeks} semaines avant et après pour comparer.", - "needAfter": "Pas encore assez de mesures depuis le début — il faut environ {weeks} semaines avant et après pour comparer.", + "needBefore": "Pas encore assez de mesures avant le début. Il faut environ {weeks} semaines avant et après pour comparer.", + "needAfter": "Pas encore assez de mesures depuis le début. Il faut environ {weeks} semaines avant et après pour comparer.", "needStart": "Renseignez une date de début pour comparer les mesures avant et après le début.", - "needData": "Pas encore assez de mesures — il faut environ {weeks} semaines avant et après le début pour comparer." + "needData": "Pas encore assez de mesures. Il faut environ {weeks} semaines avant et après le début pour comparer." }, "insights": { "title": "Effet des médicaments", - "subtitle": "Ce qui coïncide avec les mesures visées par vos médicaments — association seulement, jamais un verdict.", + "subtitle": "Ce qui coïncide avec les mesures visées par vos médicaments : association seulement, jamais un verdict.", "link": "Ouvrir la vue Effet", "empty": "Pas encore assez de données pour relier vos médicaments à leurs mesures cibles." }, @@ -2392,7 +2392,7 @@ }, "charts": { "loadingLabel": "Chargement du graphique…", - "loadingSlowHint": "Calcul des analyses — cela peut prendre un instant.", + "loadingSlowHint": "Calcul des analyses, cela peut prendre un instant.", "weight": "Poids", "bloodPressure": "Tension artérielle", "pulse": "Pouls", @@ -2542,8 +2542,8 @@ }, "tooltipPrior": "Période précédente", "unavailable": { - "lastMonth": "Comparaison indisponible — pas de données du mois précédent", - "lastYear": "Comparaison indisponible — pas de données de l’année précédente" + "lastMonth": "Comparaison indisponible : pas de données du mois précédent", + "lastYear": "Comparaison indisponible : pas de données de l’année précédente" }, "notAvailableForCompliance": "Comparaison indisponible pour l’observance" }, @@ -2666,7 +2666,7 @@ "narrativeWeek": "Cette semaine", "narrativeMonth": "Ce mois-ci", "narrativeUpdating": "Mise à jour…", - "heroFallbackSubtitle": "Un coup d’œil quotidien sur tes tendances — directement issu des chiffres que tu saisis.", + "heroFallbackSubtitle": "Un coup d’œil quotidien sur tes tendances, directement issu des chiffres que tu saisis.", "heroGreetingMorning": "Bonjour", "heroGreetingAfternoon": "Bonjour", "heroGreetingEvening": "Bonsoir", @@ -2777,7 +2777,7 @@ "emptyDescription": "Génère le briefing du jour pour obtenir un récap de tes tendances.", "emptyAction": "Générer le briefing", "loadingLabel": "Préparation du briefing", - "refreshFailedHint": "Impossible d'actualiser le briefing — affichage du précédent.", + "refreshFailedHint": "Impossible d'actualiser le briefing. Affichage du précédent.", "retryAction": "Réessayer", "failedTitle": "Impossible de générer le briefing", "failedDescription": "Le fournisseur d'IA a dépassé le délai ou renvoyé une erreur. Réessayez ou augmentez le délai de réponse dans les paramètres d'IA pour un modèle local lent.", @@ -2841,14 +2841,14 @@ } }, "coach": { - "refusalOutOfScope": "Je ne peux aider que pour les données de santé de ton journal — mesures, médicaments, humeur, tendances. Les questions hors de ce périmètre ne sont pas traitées.", - "refusalInjection": "Ton message contient des instructions qui cherchent à remplacer mes consignes. Je suis le coach HealthLog et je ne résume que tes propres données de santé — reformule ta question dans ce cadre.", + "refusalOutOfScope": "Je ne peux aider que pour les données de santé de ton journal : mesures, médicaments, humeur, tendances. Les questions hors de ce périmètre ne sont pas traitées.", + "refusalInjection": "Ton message contient des instructions qui cherchent à remplacer mes consignes. Je suis le coach HealthLog et je ne résume que tes propres données de santé. Reformule ta question dans ce cadre.", "errorBudget": "Tu as atteint la limite quotidienne du coach. Le quota se réinitialise à minuit (UTC).", "errorProvider": "Le coach n’a pas pu joindre un fournisseur d’analyse maintenant. Réessaie dans un instant.", "errorDemo": "Dans la démo, le Coach ne répond pas.", "errorNoProvider": "Le coach lit tes données de santé enregistrées et répond aux questions à leur sujet (pas un avis médical). HealthLog a besoin d'un fournisseur d'IA pour cela : connecte ta propre clé ou un modèle local.", "errorNoProviderAction": "Connecter un fournisseur d'IA", - "errorNetwork": "Pas de connexion Internet — réessaie une fois reconnecté.", + "errorNetwork": "Pas de connexion Internet. Réessaie une fois reconnecté.", "prefsSaveError": "Impossible d’enregistrer vos préférences du Coach. Réessayez.", "errorCredentialExpired": "Ta connexion au fournisseur d'IA a expiré. Reconnecte-la dans les Réglages pour que le Coach continue de fonctionner.", "tagline": "Coach personnel de santé, ancré sur tes données.", @@ -2867,7 +2867,7 @@ "thinking": "Réflexion en cours…", "unverifiedFiguresNotice": "Certains chiffres n'ont pas pu être vérifiés avec tes données et ont été omis.", "composerPlaceholder": "Pose ta question …", - "nudgeBubbleLabel": "Nouveau message du coach — ouvrir le chat", + "nudgeBubbleLabel": "Nouveau message du coach : ouvrir le chat", "fabLabel": "Ouvrir le coach", "readAloud": "Lire à voix haute", "readAloudStop": "Arrêter la lecture", @@ -2891,7 +2891,7 @@ "guided": { "offerTitle": "Le Coach a {count} questions pour vous", "offerTitleOne": "Le Coach a une question pour vous", - "offerBody": "De courtes réponses affinent vos informations personnelles — une question à la fois, ici dans le chat.", + "offerBody": "De courtes réponses affinent vos informations personnelles : une question à la fois, ici dans le chat.", "offerStart": "Répondre maintenant", "offerLater": "Plus tard", "offerDismiss": "Ne plus demander", @@ -2901,7 +2901,7 @@ "later": "Plus tard", "dismissRemaining": "Ne plus demander", "answerPlaceholder": "Votre réponse…", - "summaryTitle": "C’est fait — merci pour vos réponses !", + "summaryTitle": "C’est fait, merci pour vos réponses !", "summaryAnswered": "{answered} sur {total} répondues", "summaryAdopted": "{adopted} ajoutées à vos informations personnelles", "summaryAdoptedNone": "rien de nouveau ajouté à vos informations personnelles", @@ -2983,7 +2983,7 @@ "settingsVerbosityBrief": "Bref", "settingsVerbosityDefault": "Standard", "settingsVerbosityDetailed": "Détaillé", - "settingsVerbosityConciseHint": "Le ton concis garde déjà les réponses courtes — la longueur reste fixée sur « Bref » tant qu'il est actif.", + "settingsVerbosityConciseHint": "Le ton concis garde déjà les réponses courtes : la longueur reste fixée sur « Bref » tant qu'il est actif.", "settingsSourcesSummary": "Le coach voit {count} domaines de données sur {total} et remonte sur {window}.", "settingsSourcesSummaryAll": "Le coach voit {count} domaines de données sur {total} et tout l’historique.", "settingsSourcesPointerLink": "Ouvrir les paramètres du coach", @@ -3090,7 +3090,7 @@ "steadyLatestWithin": "Tes valeurs sont habituellement à {low} {unit} ; ta dernière mesure, du {date}, était de {value}, comme d'habitude.", "steadyLatestAbove": "Tes valeurs sont habituellement à {low} {unit} ; ta dernière mesure, du {date}, était de {value}, au-dessus.", "steadyLatestBelow": "Tes valeurs sont habituellement à {low} {unit} ; ta dernière mesure, du {date}, était de {value}, en dessous.", - "insufficient": "J'apprends encore ta plage habituelle — continue à enregistrer quelques jours de plus.", + "insufficient": "J'apprends encore ta plage habituelle. Continue à enregistrer quelques jours de plus.", "driver": "{note}" }, "scope": { @@ -3104,31 +3104,31 @@ "groupEarlier": "Plus tôt" }, "seed": { - "bloodPressure": "Passe en revue avec moi la tendance de ma tension artérielle sur les 30 derniers jours — y a-t-il quelque chose à surveiller ?", + "bloodPressure": "Passe en revue avec moi la tendance de ma tension artérielle sur les 30 derniers jours. Y a-t-il quelque chose à surveiller ?", "weight": "Comment mon poids a-t-il évolué ces derniers temps, et la tendance mérite-t-elle d'agir ?", "bmi": "Que m'indique la tendance de mon IMC, et comment dois-je l'interpréter ?", - "pulse": "Passe en revue avec moi mes mesures de pouls — y a-t-il quelque chose d'inhabituel ?", + "pulse": "Passe en revue avec moi mes mesures de pouls. Y a-t-il quelque chose d'inhabituel ?", "restingHr": "Comment ma fréquence cardiaque au repos a-t-elle évolué, et que dit-elle de ma condition physique ?", "hrv": "Que m'indique ma variabilité de la fréquence cardiaque sur ma récupération et mon stress ces derniers temps ?", - "sleep": "Passe en revue avec moi mon sommeil récent — durée, régularité et tout ce qui mériterait d'être changé.", + "sleep": "Passe en revue avec moi mon sommeil récent : durée, régularité et tout ce qui mériterait d'être changé.", "mood": "Quels schémas observes-tu dans mon humeur ces dernières semaines ?", "medications": "Où en est mon observance médicamenteuse, et correspond-elle à la façon dont je me sens ?", "steps": "À quel point ai-je été actif ces derniers temps d'après mes pas, et comment cela se compare-t-il à un niveau de référence sain ?", "activeEnergy": "Que dit ma tendance de dépense énergétique active sur mon niveau d'activité ces derniers temps ?", "cardioFitness": "Que signifie la tendance de ma condition cardio (VO₂ max), et comment la faire évoluer dans le bon sens ?", - "bloodGlucose": "Passe en revue avec moi mes dernières mesures de glycémie — sont-elles dans une fourchette saine ?", + "bloodGlucose": "Passe en revue avec moi mes dernières mesures de glycémie. Sont-elles dans une fourchette saine ?", "oxygenSaturation": "Que m'indique ma tendance de saturation en oxygène (SpO₂) ?", "respiratoryRate": "Que dit ma tendance de fréquence respiratoire sur ma santé ?", - "workouts": "Passe en revue avec moi mes séances d'entraînement récentes — charge, fréquence et comment je récupère entre elles.", + "workouts": "Passe en revue avec moi mes séances d'entraînement récentes : charge, fréquence et comment je récupère entre elles.", "recoveryPage": "Pourquoi ma récupération en est-elle là en ce moment, et qu'est-ce qui l'explique ?", - "briefing": "Passe en revue avec moi le briefing d'aujourd'hui — sur quoi devrais-je me concentrer, et y a-t-il quelque chose à entreprendre ?", + "briefing": "Passe en revue avec moi le briefing d'aujourd'hui. Sur quoi devrais-je me concentrer, et y a-t-il quelque chose à entreprendre ?", "healthScore": "Pourquoi mon score de santé est-il de {score} sur 100, et qu'est-ce qui le ferait le plus progresser ?", - "periodWeek": "Passe en revue avec moi comment s'est déroulée ma dernière semaine sur mes indicateurs de santé — qu'est-ce qui ressort ?", - "periodMonth": "Passe en revue avec moi comment s'est déroulé mon dernier mois sur mes indicateurs de santé — qu'est-ce qui ressort ?", + "periodWeek": "Passe en revue avec moi comment s'est déroulée ma dernière semaine sur mes indicateurs de santé. Qu'est-ce qui ressort ?", + "periodMonth": "Passe en revue avec moi comment s'est déroulé mon dernier mois sur mes indicateurs de santé. Qu'est-ce qui ressort ?", "correlationBpCompliance": "Quel est le lien entre mon observance médicamenteuse et ma tension artérielle ? Explique-moi ce que cette corrélation signifie pour moi.", "correlationMoodPulse": "Y a-t-il un lien réel entre mon humeur et mon pouls ? Aide-moi à interpréter cette corrélation.", "correlationWeightWeekday": "Mon poids suit-il un schéma hebdomadaire ? Que m'indique cette corrélation selon le jour de la semaine ?", - "recommendation": "Parle-moi davantage de cette recommandation : \"{text}\" — pourquoi s'applique-t-elle à moi, et que devrais-je faire ?" + "recommendation": "Parle-moi davantage de cette recommandation : \"{text}\". Pourquoi s'applique-t-elle à moi, et que devrais-je faire ?" }, "assessmentPrompt": "Explique-moi mon évaluation de {metric} : qu'est-ce que cela signifie et que dois-je faire ?", "attach": { @@ -3321,7 +3321,7 @@ }, "hrv": { "title": "VFC", - "description": "Variabilité de la fréquence cardiaque dans le temps — signal de récupération du système nerveux, capté la nuit par l'Apple Watch et d'autres wearables compatibles.", + "description": "Variabilité de la fréquence cardiaque dans le temps : signal de récupération du système nerveux, capté la nuit par l'Apple Watch et d'autres wearables compatibles.", "chartTitle": "Variabilité de la fréquence cardiaque", "emptyState": { "title": "Aucune mesure de VFC", @@ -3330,17 +3330,17 @@ }, "restingHr": { "title": "FC au repos", - "description": "La fréquence cardiaque de base sur la journée — distincte des pointages ponctuels de la page Pulse. Apple Santé fournit une valeur par jour.", + "description": "La fréquence cardiaque de base sur la journée, distincte des pointages ponctuels de la page Pulse. Apple Santé fournit une valeur par jour.", "chartTitle": "Fréquence cardiaque au repos", "emptyState": { "title": "Aucune FC au repos", "description": "La FC au repos arrive dès que l'Apple Watch ou un appareil Withings compatible a porté une journée calme." }, - "coachPrefill": "Je n'ai pas encore enregistré de fréquence cardiaque au repos — pourquoi la valeur quotidienne au repos diffère-t-elle d'un pouls ponctuel, et comment l'améliorer ?" + "coachPrefill": "Je n'ai pas encore enregistré de fréquence cardiaque au repos. Pourquoi la valeur quotidienne au repos diffère-t-elle d'un pouls ponctuel, et comment l'améliorer ?" }, "oxygenSaturation": { "title": "Saturation en oxygène", - "description": "Oxygène sanguin (SpO₂) — plage clinique normale 95–100 %, avec zones cibles ombrées sur le graphique.", + "description": "Oxygène sanguin (SpO₂) : plage clinique normale 95–100 %, avec zones cibles ombrées sur le graphique.", "chartTitle": "Saturation en oxygène", "emptyState": { "title": "Aucune mesure SpO₂", @@ -3353,13 +3353,13 @@ "chartTitle": "Température corporelle", "emptyState": { "title": "Aucune température corporelle", - "description": "Enregistre une mesure ou laisse ton wearable en synchroniser une — la tendance apparaîtra ici.", + "description": "Enregistre une mesure ou laisse ton wearable en synchroniser une, et la tendance apparaîtra ici.", "cta": "Enregistrer la température" } }, "steps": { "title": "Pas", - "description": "Nombre de pas quotidien — une ligne par jour, depuis Apple Santé ou un appareil d'activité connecté.", + "description": "Nombre de pas quotidien : une ligne par jour, depuis Apple Santé ou un appareil d'activité connecté.", "chartTitle": "Pas par jour", "emptyState": { "title": "Aucune donnée de pas", @@ -3368,7 +3368,7 @@ }, "activeEnergy": { "title": "Énergie active", - "description": "Total quotidien d'énergie active en kilocalories — une ligne par jour, depuis Apple Santé ou Withings activité.", + "description": "Total quotidien d'énergie active en kilocalories : une ligne par jour, depuis Apple Santé ou Withings activité.", "chartTitle": "Énergie active", "emptyState": { "title": "Aucune donnée d'énergie active", @@ -3392,7 +3392,7 @@ "weightBody": "Le poids corporel est l'un des signaux les plus simples de l'équilibre énergétique à long terme et de la santé globale. La tendance sur plusieurs semaines compte bien plus qu'une mesure isolée, qui varie avec l'hydratation, l'alimentation et l'heure de la journée.", "bmiBody": "L'IMC correspond à votre poids divisé par votre taille au carré, un seul chiffre qui vous situe dans une large catégorie de poids. C'est un dépistage de population, pas un diagnostic, et il ne distingue pas le muscle de la graisse.", "sleepBody": "La durée du sommeil est le temps réellement dormi au cours de la nuit, réparti entre sommeil léger, profond et paradoxal. La plupart des adultes ont besoin d'environ sept à neuf heures ; une quantité et une qualité régulières soutiennent la récupération, l'humeur et le métabolisme.", - "moodBody": "Le suivi de l'humeur consigne ce que vous ressentez au fil du temps sur une échelle simple. Le noter régulièrement révèle des tendances — comment le sommeil, l'activité ou les médicaments s'alignent sur votre ressenti — qu'une seule journée ne montre jamais.", + "moodBody": "Le suivi de l'humeur consigne ce que vous ressentez au fil du temps sur une échelle simple. Le noter régulièrement révèle des tendances (comment le sommeil, l'activité ou les médicaments s'alignent sur votre ressenti) qu'une seule journée ne montre jamais.", "medicationsBody": "L'observance mesure la fiabilité avec laquelle vous prenez votre traitement comme prescrit, ici sous forme de la part des doses attendues que vous avez enregistrées. Une prise régulière est souvent ce qui permet à un traitement d'agir comme prévu.", "restingHrBody": "La fréquence cardiaque au repos est votre rythme cardiaque lorsque vous êtes totalement au repos, généralement mesuré la nuit. Une fréquence plus basse indique souvent une meilleure forme cardiovasculaire, et une tendance à la hausse peut être un signe précoce de stress ou de maladie.", "hrvBody": "La VFC est la petite variation du temps entre des battements consécutifs. Une variabilité plus élevée reflète généralement un système nerveux bien récupéré et adaptable, tandis qu'une baisse durable peut signaler de la fatigue, du stress ou une récupération insuffisante.", @@ -3404,7 +3404,7 @@ "bodyWaterBody": "L'eau corporelle totale est la part de votre poids constituée de liquide, à l'intérieur et autour des cellules. Elle varie avec l'hydratation, l'alimentation et l'activité, si bien que la tendance sur plusieurs semaines en dit plus qu'une seule mesure.", "boneMassBody": "La masse osseuse est le poids estimé des minéraux de votre squelette. Les estimations sur balance sont approximatives, mais une tendance stable ou en hausse soutient la solidité osseuse à long terme.", "fatFreeMassBody": "La masse non grasse est tout ce qui, dans votre corps, n'est pas de la graisse : muscle, os, organes et eau. La maintenir ou la développer tout en perdant du poids signale en général une composition corporelle plus saine.", - "fatMassBody": "La masse grasse est le poids total de la graisse de votre corps. Une part de graisse est indispensable aux hormones et au stockage d'énergie, mais un excès — surtout au niveau de l'abdomen — augmente le risque pour la santé à long terme (WHO 2024).", + "fatMassBody": "La masse grasse est le poids total de la graisse de votre corps. Une part de graisse est indispensable aux hormones et au stockage d'énergie, mais un excès, surtout au niveau de l'abdomen, augmente le risque pour la santé à long terme (WHO 2024).", "bodyFatBody": "Le taux de masse grasse est la part de votre poids constituée de graisse. Les plages saines dépendent du sexe et de l'âge, et les balances l'estiment par bio-impédance : la tendance sur plusieurs semaines en dit plus qu'une mesure isolée.", "muscleMassBody": "La masse musculaire est le poids estimé des muscles de votre corps. Plus de muscle soutient la force, le métabolisme et la mobilité, et demande généralement un effort actif pour être préservé avec l'âge.", "visceralFatBody": "La graisse viscérale est la graisse stockée au plus profond de l'abdomen, autour des organes. Contrairement à la graisse sous la peau, un niveau élevé est étroitement lié aux maladies cardiaques et au diabète de type 2 : plus elle est basse, mieux c'est.", @@ -3425,7 +3425,7 @@ "daylightBody": "Le temps à la lumière du jour correspond à la durée passée en lumière extérieure chaque jour. Une lumière naturelle régulière soutient un rythme veille-sommeil et une humeur sains (CDC 2024), et le temps passé dehors est lié à la santé oculaire.", "bloodGlucoseBody": "La glycémie est la quantité de sucre dans votre sang, principale source d'énergie de l'organisme. Elle augmente après les repas et se stabilise entre eux ; des valeurs durablement élevées peuvent signaler un diabète ou un prédiabète.", "skinTemperatureBody": "La température cutanée correspond ici à la petite variation nocturne de la température de votre poignet par rapport à votre propre référence, et non à une mesure absolue de fièvre. Les variations peuvent suivre le sommeil, l'environnement, une maladie ou la phase du cycle menstruel.", - "cardioFitnessBody": "Le VO₂ max correspond à la quantité d'oxygène que votre corps peut utiliser à l'effort maximal — le meilleur indice de laboratoire de la forme aérobie, que les wearables estiment de façon indirecte. Une tendance plus élevée ou en hausse est un fort signe de santé cardiovasculaire.", + "cardioFitnessBody": "Le VO₂ max correspond à la quantité d'oxygène que votre corps peut utiliser à l'effort maximal. C'est le meilleur indice de laboratoire de la forme aérobie, que les wearables estiment de façon indirecte. Une tendance plus élevée ou en hausse est un fort signe de santé cardiovasculaire.", "cardioRecoveryBody": "La récupération cardiaque correspond au nombre de battements par minute dont votre fréquence cardiaque diminue dans la première minute après l'arrêt d'un effort intense. Une baisse plus forte signifie que votre cœur se calme plus vite, signe d'une bonne condition physique.", "wristTemperatureBody": "La température du poignet est mesurée pendant votre sommeil et indiquée comme l'écart par rapport à votre valeur de référence, et non comme une valeur absolue. Une valeur stable est normale, tandis qu'une hausse durable peut signaler une maladie, un entraînement intense ou un changement de cycle.", "fallsBody": "Ceci compte les chutes lourdes détectées par votre wearable. L'objectif est zéro ; un nombre en hausse est un signal de risque de mobilité à évoquer avec un professionnel, surtout pour les personnes âgées (CDC STEADI 2024).", @@ -3433,13 +3433,13 @@ "stairAscentSpeedBody": "C'est la vitesse à laquelle vous montez une volée de marches. C'est un marqueur sensible de la force des jambes et de la mobilité : un rythme stable ou en hausse est bon signe, un rythme en baisse mérite attention.", "stairDescentSpeedBody": "C'est la vitesse à laquelle vous descendez une volée de marches. Avec la vitesse de montée, elle reflète le contrôle des jambes et l'équilibre : un rythme stable est bon signe, un rythme en baisse mérite attention.", "breathingDisturbancesBody": "Un wearable peut estimer à quelle fréquence votre respiration a été interrompue pendant le sommeil. Un indice plus bas est préférable ; un niveau signalé comme élevé, surtout sur plusieurs nuits, mérite d'être évoqué avec un professionnel. C'est une approximation de dépistage, pas un diagnostic d'apnée du sommeil.", - "stepsBody": "Le nombre de pas correspond au total de pas que vous faites chaque jour — la mesure la plus simple de l'activité quotidienne. Une habitude régulière compte plus qu'une seule grosse journée, et l'objectif rond de 10 000 pas est un slogan publicitaire, pas un résultat de recherche.", + "stepsBody": "Le nombre de pas correspond au total de pas que vous faites chaque jour : la mesure la plus simple de l'activité quotidienne. Une habitude régulière compte plus qu'une seule grosse journée, et l'objectif rond de 10 000 pas est un slogan publicitaire, pas un résultat de recherche.", "readinessBody": "La disponibilité est une lecture quotidienne de la disposition de votre corps à affronter la journée, mêlant fréquence cardiaque au repos, variabilité de la fréquence cardiaque et sommeil. C'est une approximation de l'appareil rapportée à votre propre référence, pas une mesure clinique : un score élevé signifie récupéré, un score plus bas invite à lever le pied.", - "sleepScoreBody": "Votre score de sommeil résume toute une nuit en un seul chiffre — durée, efficacité, régularité des horaires et équilibre entre sommeil léger, profond et paradoxal. Observez la tendance sur plusieurs semaines plutôt que de courir après un score parfait sur une seule nuit.", + "sleepScoreBody": "Votre score de sommeil résume toute une nuit en un seul chiffre : durée, efficacité, régularité des horaires et équilibre entre sommeil léger, profond et paradoxal. Observez la tendance sur plusieurs semaines plutôt que de courir après un score parfait sur une seule nuit.", "recoveryBody": "La récupération reflète la qualité du rétablissement de votre corps, à partir de signaux nocturnes comme la variabilité de la fréquence cardiaque et la fréquence au repos. Un score élevé est un feu vert pour pousser ; un score plus bas suggère que votre organisme se reconstruit encore.", "strainBody": "La charge mesure l'effort cardiovasculaire et physique que vous avez imposé à votre corps, des entraînements à une journée active debout. Dès qu'il y a assez d'historique, elle est évaluée par rapport à votre propre effort habituel, pas à un standard extérieur.", "stressBody": "Le stress est ici une estimation de la charge physiologique sur votre système nerveux, lue surtout à partir des schémas de variabilité de la fréquence cardiaque et non de ce que vous ressentez consciemment. Un score plus bas indique un état calme et bien régulé ; un score plus élevé invite à prévoir de la récupération.", - "recoveryPageBody": "La récupération rassemble les signaux nocturnes enregistrés par votre wearable — recharge, effort, charge ainsi que vos totaux de fréquence cardiaque et d'énergie du jour — pour montrer à quel point votre corps a récupéré. Observez la tendance sur plusieurs jours plutôt qu'un seul chiffre ; une valeur plus faible invite à lever le pied, ce n'est pas une alarme.", + "recoveryPageBody": "La récupération rassemble les signaux nocturnes enregistrés par votre wearable (recharge, effort, charge ainsi que vos totaux de fréquence cardiaque et d'énergie du jour) pour montrer à quel point votre corps a récupéré. Observez la tendance sur plusieurs jours plutôt qu'un seul chiffre ; une valeur plus faible invite à lever le pied, ce n'est pas une alarme.", "pulsePressureBody": "La pression pulsée est l'écart entre votre valeur systolique et diastolique (systolique moins diastolique). À titre indicatif général, environ 40 mmHg est typique au repos ; un écart large au-dessus d'environ 60 mmHg à l'âge moyen peut refléter des artères rigidifiées, tandis qu'un écart étroit en dessous d'environ 25 mmHg peut accompagner un faible volume d'éjection (StatPearls/NIH 2023). C'est un sujet de discussion, pas un diagnostic.", "meanArterialPressureBody": "La pression artérielle moyenne est la pression moyenne que voient vos organes sur un battement, soit grosso modo la diastolique plus un tiers de l'écart avec la systolique. À titre indicatif général, une valeur au repos se situe autour de 70–100 mmHg (StatPearls/NIH 2023). Le seuil de ~60 mmHg souvent cité est un concept de soins aigus, pas une alarme pour l'autosurveillance.", "cycleEducationBody": "Votre cycle traverse quatre phases pilotées par les hormones, et sa durée et sa régularité sont une fenêtre accessible sur la santé globale. À titre indicatif général, les cycles chez l'adulte durent typiquement 21–35 jours (les références cliniques citent 24–38), avec des règles d'environ cinq jours (ACOG 2015). La phase lutéale est l'ancrage stable, donc l'ovulation s'estime au mieux en comptant à rebours depuis vos prochaines règles prévues, jamais à un « jour 14 » fixe. Une fenêtre fertile prédite est une estimation qui demande plusieurs cycles enregistrés et reste approximative, et la température basale confirme l'ovulation après coup plutôt qu'elle ne la prédit. Ce n'est pas une méthode de contraception.", @@ -3458,7 +3458,7 @@ "mean": "Moyenne" }, "showAllValues": "Afficher toutes les mesures", - "valuesPageTitle": "{metric} — toutes les mesures", + "valuesPageTitle": "{metric} : toutes les mesures", "valuesPageDescription": "Chaque mesure derrière cette métrique. Modifiez ou supprimez une entrée directement.", "diversity": { "trigger": "Conseil de mesure", @@ -3498,11 +3498,11 @@ "inBed": "Au lit", "nap": "Sieste", "napCount": "{count} siestes", - "unavailable": "Pas encore de données de phases — les phases de sommeil apparaîtront ici dès qu’une source connectée les fournira." + "unavailable": "Pas encore de données de phases. Les phases de sommeil apparaîtront ici dès qu’une source connectée les fournira." }, "empty": { "title": "Pas encore de données de sommeil", - "description": "Connecte une source comme Apple Health ou un objet connecté — ou enregistre ton sommeil manuellement — et cette vue se remplira automatiquement.", + "description": "Connecte une source comme Apple Health ou un objet connecté (ou enregistre ton sommeil manuellement) et cette vue se remplira automatiquement.", "action": "Gérer les appareils" }, "debt": { @@ -3511,21 +3511,21 @@ "caption": "Solde restant sur les {nights} dernières nuits", "clearValue": "À jour", "clearCaption": "Rien en attente sur les {nights} dernières nuits", - "learning": "Votre sommeil est encore en cours d'analyse — {counted} nuits jusqu'ici, encore {remaining} pour un bilan fiable.", + "learning": "Votre sommeil est encore en cours d'analyse : {counted} nuits jusqu'ici, encore {remaining} pour un bilan fiable.", "computedInfo": "Il s'agit de l'estimation propre à HealthLog : un solde glissant entre le besoin et le sommeil des dernières nuits, que le sommeil de récupération réduit. Elle peut différer de la dette de sommeil native d'un wearable, qui utilise son propre modèle de besoin." }, "average": { "title": "Moyenne par nuit", "value": "{hours} h {minutes} min", "caption": "Sommeil moyen sur les {nights} dernières nuits", - "learning": "Votre sommeil est encore en cours d'analyse — {counted} nuits jusqu'ici, encore {remaining} pour une moyenne fiable." + "learning": "Votre sommeil est encore en cours d'analyse : {counted} nuits jusqu'ici, encore {remaining} pour une moyenne fiable." }, "chronotype": { "title": "Chronotype", - "learning": "Votre rythme est encore en cours d'analyse — {counted} sur {total} nuits libres. Un chronotype a besoin de quelques matins sans réveil pour avoir du sens.", + "learning": "Votre rythme est encore en cours d'analyse : {counted} sur {total} nuits libres. Un chronotype a besoin de quelques matins sans réveil pour avoir du sens.", "advancedToggle": "Avancé", "socialJetlagValue": "{hours} h {minutes} min de jet lag social", - "socialJetlagCaption": "L'écart entre vos horaires de sommeil les jours travaillés et les jours libres — comme un petit décalage horaire hebdomadaire.", + "socialJetlagCaption": "L'écart entre vos horaires de sommeil les jours travaillés et les jours libres, comme un petit décalage horaire hebdomadaire.", "msfScValue": "Milieu de sommeil corrigé {clock}", "msfScCaption": "Ajusté pour le sommeil rattrapé le week-end (MSFsc).", "dayTypeNote": "Les jours libres sont supposés être les week-ends jusqu'à l'ajout du suivi du type de jour.", @@ -3736,7 +3736,7 @@ "labsLink": "Résultats de laboratoire ? Saisis une HbA1c ou une glycémie à jeun issue d'une prise de sang dans Laboratoire.", "learningTitle": "Votre glucose se découvre encore", "learningBody": "Pour l’instant, cela fait {count} sur {days}. Avec un peu plus d’historique, le tableau se précise : continuez à enregistrer ou laissez un appareil connecté compléter.", - "learningBodyEmpty": "Dès que quelques mesures arrivent — saisies par vous ou synchronisées depuis un appareil — votre temps dans la cible, votre moyenne et votre variabilité prennent forme ici.", + "learningBodyEmpty": "Dès que quelques mesures arrivent (saisies par vous ou synchronisées depuis un appareil), votre temps dans la cible, votre moyenne et votre variabilité prennent forme ici.", "readingsCount": "{count} mesures", "readingsCountOne": "1 mesure", "daysCount": "{days} jours", @@ -3774,7 +3774,7 @@ "intro": "Des indicateurs de niveau recherche pour regarder de plus près. Chacun condense vos mesures en un seul chiffre pondéré par le risque.", "jIndex": { "label": "Indice J", - "help": "Un score unique mêlant votre moyenne et sa dispersion — plus il est bas, plus le contrôle est serré." + "help": "Un score unique mêlant votre moyenne et sa dispersion : plus il est bas, plus le contrôle est serré." }, "lbgi": { "label": "Risque d’hypoglycémie (LBGI)", @@ -3891,7 +3891,7 @@ "navSkinTemperature": "Temp. peau", "pulseWaveVelocity": { "title": "Vitesse de l’onde de pouls", - "description": "Votre vitesse d’onde de pouls artérielle au fil du temps, en m/s — des valeurs plus élevées suggèrent des artères plus rigides.", + "description": "Votre vitesse d’onde de pouls artérielle au fil du temps, en m/s. Des valeurs plus élevées suggèrent des artères plus rigides.", "chartTitle": "Vitesse de l’onde de pouls", "emptyState": { "title": "Aucune donnée", @@ -4084,7 +4084,7 @@ "inTargetCaption": "des derniers jours dans votre plage de bonne humeur", "narrative": { "title": "Ce qui ressort", - "weekdayDip": "Votre humeur baisse surtout le {weekday} — {delta} sous votre semaine.", + "weekdayDip": "Votre humeur baisse surtout le {weekday}, {delta} sous votre semaine.", "weekdayPeak": "Le {weekday} est toujours votre meilleur jour, avec une moyenne de {value}.", "trendUp": "Votre humeur progresse sur les {days} derniers jours (+{delta} par rapport à la période précédente).", "trendDown": "Votre humeur recule sur les {days} derniers jours (-{delta} par rapport à la période précédente).", @@ -4093,7 +4093,7 @@ "tagLift": "Les jours marqués « {tag} » dépassent votre humeur générale de {delta} en moyenne.", "tagDrop": "Les jours marqués « {tag} » sont {delta} sous votre moyenne.", "inTarget": "Vous avez été dans votre plage de bonne humeur {pct} % des 30 derniers jours.", - "streak": "Vous avez noté votre humeur {days} jours d'affilée — continuez.", + "streak": "Vous avez noté votre humeur {days} jours d'affilée. Continuez.", "timeOfDay": "Vous vous sentez mieux le {bucket}, en moyenne {value}." }, "timeOfDay": { @@ -4203,8 +4203,8 @@ "deviationAbove": "Ta propre évaluation se situe {amount} points au-dessus de cette plage.", "deviationBelow": "Ta propre évaluation se situe {amount} points en dessous de cette plage.", "weightedTitle": "Ce qui a le plus pesé dans la comparaison de cette journée", - "weightedUp": "{label} — comptait vers une valeur attendue plus élevée", - "weightedDown": "{label} — comptait vers une valeur attendue plus basse", + "weightedUp": "{label} : comptait vers une valeur attendue plus élevée", + "weightedDown": "{label} : comptait vers une valeur attendue plus basse", "caveat": "C'est une comparaison avec tes propres journées passées, pas une affirmation sur la manière dont une journée s'est déroulée.", "learning": "Phase d'apprentissage : {entries} journées sur {threshold} enregistrées. La comparaison apparaît une fois qu'il y en a assez.", "noPattern": "Dans les {entries} journées enregistrées jusqu'ici, rien n'est assez régulier pour comparer une journée. Quand tu notes aussi le contexte d'une journée, tu en rends davantage comparable.", @@ -4221,7 +4221,7 @@ }, "scoreRing": { "aria": "Score {score} sur 100, {band}", - "ariaProvisional": "Score pas encore disponible — données insuffisantes", + "ariaProvisional": "Score pas encore disponible : données insuffisantes", "provisionalCaption": "Données encore insuffisantes", "band": { "green": "bon", @@ -4245,7 +4245,7 @@ "loadingLabel": "Chargement de vos constantes", "loadError": "Impossible de charger vos constantes pour le moment.", "infoLabel": "Comment ce résultat est-il calculé ?", - "building": "Construction de votre plage habituelle — {count} sur {target} jours", + "building": "Construction de votre plage habituelle : {count} sur {target} jours", "typicalRange": "Habituel pour vous : {low}–{high}", "fitnessYounger": "Forme cardio d'une personne ~{years} ans plus jeune", "fitnessOlder": "Forme cardio ~{years} ans au-dessus de votre âge", @@ -4297,7 +4297,7 @@ "READINESS": { "title": "Disponibilité", "description": "Un indicateur quotidien de bien-être selon la position de vos signaux par rapport à votre propre référence.", - "method": "Un mélange de 0–100 entre l’écart de la fréquence cardiaque au repos, l’écart de la VFC (SDNN), la qualité du sommeil, la stabilité de la fréquence respiratoire et la stabilité de l’humeur — chacun mesuré par rapport à votre référence personnelle. Les poids sont renormalisés sur les composantes que vos données étayent. Un indicateur de bien-être, pas un score de récupération ni clinique.", + "method": "Un mélange de 0–100 entre l’écart de la fréquence cardiaque au repos, l’écart de la VFC (SDNN), la qualité du sommeil, la stabilité de la fréquence respiratoire et la stabilité de l’humeur, chacun mesuré par rapport à votre référence personnelle. Les poids sont renormalisés sur les composantes que vos données étayent. Un indicateur de bien-être, pas un score de récupération ni clinique.", "component": { "rhr": "Fréquence cardiaque au repos", "hrv": "VFC (SDNN)", @@ -4337,31 +4337,31 @@ }, "STRAIN_SCORE": { "method": "Un indice d’effort nocturne de 0 à 100 à partir de votre charge d’activité pondérée par la fréquence cardiaque (un modèle d’impulsion d’entraînement de type TRIMP). Plus élevé signifie une journée plus exigeante.", - "anchorPersonal": "Calé sur votre propre charge récente des jours d’entraînement — évalué par rapport à votre effort habituel, de sorte qu’une journée vraiment difficile pour vous ressort élevée.", + "anchorPersonal": "Calé sur votre propre charge récente des jours d’entraînement : évalué par rapport à votre effort habituel, de sorte qu’une journée vraiment difficile pour vous ressort élevée.", "anchorPopulation": "Évalué par rapport à une référence générale pendant que vous constituez votre historique d’entraînement ; dès que vous en avez assez, le calcul passe à votre propre effort habituel.", "description": "Un indice de charge d’activité nocturne à partir de votre effort pondéré par la fréquence cardiaque, relatif à votre effort habituel.", "deviceCaption": "Effort du jour de votre appareil : {value} sur {max}", "deviceSource": "Tant que HealthLog n’a pas calculé sa propre valeur pendant la nuit, la carte affiche l’effort du jour de votre appareil, ramené sur 0–100." }, "WRIST_TEMPERATURE_BASELINE": { - "method": "Votre température nocturne typique au poignet est la médiane de vos relevés nocturnes sur la période, ± une dispersion robuste (écart absolu médian, mis à l’échelle). Elle suit VOS relevés — la nuit dernière est affichée comme un écart par rapport à votre propre référence, pas à une norme de population.", - "caveat": "Une simple bande d’écart personnel — descriptive, ni un signe de maladie, de fièvre ou de phase du cycle. À vous de l’interpréter." + "method": "Votre température nocturne typique au poignet est la médiane de vos relevés nocturnes sur la période, ± une dispersion robuste (écart absolu médian, mis à l’échelle). Elle suit VOS relevés : la nuit dernière est affichée comme un écart par rapport à votre propre référence, pas à une norme de population.", + "caveat": "Une simple bande d’écart personnel, descriptive, ni un signe de maladie, de fièvre ou de phase du cycle. À vous de l’interpréter." }, "STAIR_ASCENT_SPEED_BASELINE": { - "method": "Votre allure typique en montant les escaliers est la médiane de vos valeurs quotidiennes sur la période, ± une dispersion robuste (écart absolu médian, mis à l’échelle). La bande est construite à partir de vos données — il n’existe pas de seuil de population pour l’allure dans les escaliers, car elle dépend de la géométrie des marches et de la longueur des jambes.", - "caveat": "Une bande personnelle de tendance de mobilité — descriptive, ni une évaluation de fragilité ni de risque de chute." + "method": "Votre allure typique en montant les escaliers est la médiane de vos valeurs quotidiennes sur la période, ± une dispersion robuste (écart absolu médian, mis à l’échelle). La bande est construite à partir de vos données : il n’existe pas de seuil de population pour l’allure dans les escaliers, car elle dépend de la géométrie des marches et de la longueur des jambes.", + "caveat": "Une bande personnelle de tendance de mobilité, descriptive, ni une évaluation de fragilité ni de risque de chute." }, "STAIR_DESCENT_SPEED_BASELINE": { - "method": "Votre allure typique en descendant les escaliers est la médiane de vos valeurs quotidiennes sur la période, ± une dispersion robuste (écart absolu médian, mis à l’échelle). La bande est construite à partir de vos données — il n’existe pas de seuil de population pour l’allure dans les escaliers, car elle dépend de la géométrie des marches et de la longueur des jambes.", - "caveat": "Une bande personnelle de tendance de mobilité — descriptive, ni une évaluation de fragilité ni de risque de chute." + "method": "Votre allure typique en descendant les escaliers est la médiane de vos valeurs quotidiennes sur la période, ± une dispersion robuste (écart absolu médian, mis à l’échelle). La bande est construite à partir de vos données : il n’existe pas de seuil de population pour l’allure dans les escaliers, car elle dépend de la géométrie des marches et de la longueur des jambes.", + "caveat": "Une bande personnelle de tendance de mobilité, descriptive, ni une évaluation de fragilité ni de risque de chute." }, "SIX_MINUTE_WALK_BAND": { - "method": "La distance de marche de six minutes ESTIMÉE par votre appareil, située par rapport à la référence d’Enright et Sherrill pour votre âge, votre taille, votre poids et votre sexe, en pourcentage de la valeur prédite. La distance est l’estimation de l’appareil — jamais recalculée ici. Sans votre âge, taille, poids et sexe, le pourcentage est masqué et seules la distance et la tendance sont affichées.", - "caveat": "Une estimation reformulée par rapport à une référence publiée — un indicateur de capacité fonctionnelle, ni un test de marche de six minutes clinique ni un diagnostic. La référence a été établie pour les âges de 40 à 80 ans ; en dehors de cette plage, la valeur prédite est une extrapolation." + "method": "La distance de marche de six minutes ESTIMÉE par votre appareil, située par rapport à la référence d’Enright et Sherrill pour votre âge, votre taille, votre poids et votre sexe, en pourcentage de la valeur prédite. La distance est l’estimation de l’appareil, jamais recalculée ici. Sans votre âge, taille, poids et sexe, le pourcentage est masqué et seules la distance et la tendance sont affichées.", + "caveat": "Une estimation reformulée par rapport à une référence publiée : un indicateur de capacité fonctionnelle, ni un test de marche de six minutes clinique ni un diagnostic. La référence a été établie pour les âges de 40 à 80 ans ; en dehors de cette plage, la valeur prédite est une extrapolation." }, "TRAJECTORY": { "method": "Une droite des moindres carrés ajustée à vos valeurs journalières récentes et projetée sur un court horizon, avec l’intervalle de prédiction classique qui s’élargit à mesure qu’il s’éloigne. Calculée uniquement lorsque la tendance récente est suffisamment marquée et que votre historique est assez long et récent ; sinon aucune ligne n’est tracée.", - "caveat": "Une projection de votre propre tendance récente — ni une prédiction, ni un objectif, ni un pronostic clinique. Elle ne tient que si le schéma récent se poursuit ; la bande ombrée montre la vitesse à laquelle cette certitude s’estompe." + "caveat": "Une projection de votre propre tendance récente, ni une prédiction, ni un objectif, ni un pronostic clinique. Elle ne tient que si le schéma récent se poursuit ; la bande ombrée montre la vitesse à laquelle cette certitude s’estompe." }, "SAME_TIME_BASELINE": { "method": "Votre total cumulé du jour comparé à la médiane de cette même heure locale sur vos quatre dernières semaines, avec une bande robuste médiane ± MAD autour. Seuls les jours suffisamment détaillés comptent, et aucune comparaison n'apparaît avant d'en avoir au moins quatorze.", @@ -4388,31 +4388,31 @@ "allClear": "Aujourd’hui, toutes vos constantes sont dans leur plage personnelle.", "allClearMeta": "{count} de vos constantes vérifiées par rapport à votre propre plage habituelle.", "watch": "Aujourd’hui, une constante est hors de sa plage habituelle.", - "watchVital": "Hors plage : {vital}. Souvent ponctuel — à surveiller ces prochains jours.", + "watchVital": "Hors plage : {vital}. Souvent ponctuel, à surveiller ces prochains jours.", "firedHeadline": "Aujourd’hui, {count} de vos constantes sont hors de leur plage personnelle.", - "factors": "Facteurs possibles — jamais une cause : un entraînement intense, un mauvais sommeil, l’alcool, l’altitude, le stress ou une maladie. C’est un repère issu de vos propres références, pas un diagnostic.", - "building": "Construction de vos références personnelles — enregistrez quelques jours de plus et cela apparaîtra.", + "factors": "Facteurs possibles, jamais une cause : un entraînement intense, un mauvais sommeil, l’alcool, l’altitude, le stress ou une maladie. C’est un repère issu de vos propres références, pas un diagnostic.", + "building": "Construction de vos références personnelles. Enregistrez quelques jours de plus et cela apparaîtra.", "illnessExplained": "Ces écarts reflètent probablement l’affection que vous avez consignée." }, "trajectory": { "cardTitle": "Projection à court terme", - "headline": "Si ce schéma se poursuit — les {days} prochains jours", + "headline": "Si ce schéma se poursuit : les {days} prochains jours", "range": "Projeté autour de {low}–{high} {unit} dans {days} jours.", "caveat": "Une projection de votre propre tendance récente, pas une prédiction. La bande ombrée s’élargit pour montrer la vitesse à laquelle l’incertitude augmente.", - "insufficient": "Pas encore de tendance assez nette pour projeter — continuez à enregistrer et une projection apparaîtra dès que le schéma récent sera suffisamment marqué.", + "insufficient": "Pas encore de tendance assez nette pour projeter. Continuez à enregistrer et une projection apparaîtra dès que le schéma récent sera suffisamment marqué.", "daysNeeded": "Encore environ {count} jours d’enregistrement nécessaires avant qu’une projection puisse apparaître." }, "sameTime": { "sectionTitle": "Aujourd'hui jusqu'ici", "sectionSubtitle": "Vos totaux cumulés face à ce qui est habituel chez vous à cette heure", - "learning": "Apprentissage de votre journée habituelle — {count} jours sur {target}", + "learning": "Apprentissage de votre journée habituelle : {count} jours sur {target}", "framing": "Habituel à {time} : {typical} {unit}", "comparisonLabel": "Votre journée habituelle" } }, "cardioFitness": { "title": "Condition physique", - "description": "Votre VO₂ max au fil du temps — la principale mesure de la forme aérobie.", + "description": "Votre VO₂ max au fil du temps, la principale mesure de la forme aérobie.", "chartTitle": "VO₂ max (mL/(kg·min))", "emptyState": { "title": "Pas encore de données de condition physique", @@ -4492,7 +4492,7 @@ "navBreathingDisturbances": "Respiration", "rhythmEvents": { "sectionTitle": "Notifications de santé de l’appareil", - "sectionIntro": "Notifications que votre montre a envoyées d’elle-même. HealthLog se contente de les afficher — il ne les détecte, ne les confirme ni ne les interprète.", + "sectionIntro": "Notifications que votre montre a envoyées d’elle-même. HealthLog se contente de les afficher : il ne les détecte, ne les confirme ni ne les interprète.", "loadError": "Impossible de charger les notifications de votre appareil.", "disclaimer": "Ce sont des alertes que votre appareil a produites avec sa propre détection intégrée. Elles sont affichées ici uniquement à titre informatif. Il ne s’agit pas d’une évaluation médicale de HealthLog, et HealthLog ne pose aucun diagnostic. Si une notification vous inquiète, parlez-en à votre médecin.", "event": { @@ -4537,9 +4537,9 @@ "detail": "Les pages de détail masquées disparaissent aussi de la navigation supérieure." }, "customize": "Personnaliser les Analyses", - "regenerateRateLimited": "Limite d'actualisation atteinte — réessayez plus tard.", - "regenerateUnavailable": "Aucune nouvelle analyse reçue — réessayez plus tard.", - "regenerateError": "Actualisation en cours — réessayez dans un instant.", + "regenerateRateLimited": "Limite d'actualisation atteinte. Réessayez plus tard.", + "regenerateUnavailable": "Aucune nouvelle analyse reçue. Réessayez plus tard.", + "regenerateError": "Actualisation en cours. Réessayez dans un instant.", "regenerateSettling": "L’évaluation est encore en cours de préparation", "regenerateSettleFailed": "L’actualisation n’a pas pu aboutir. Réessayez plus tard.", "deviceScore": { @@ -4561,9 +4561,9 @@ "emptyTitle": "Pas encore de données de récupération", "empty": "Pas encore de données de récupération. Connectez un compte WHOOP, Polar ou Oura et ces scores se rempliront dès que votre appareil se synchronise.", "block": { - "ansChargeExplainer": "À quel point votre système nerveux autonome est rechargé pour la journée — une mesure de recharge issue de vos signaux nocturnes de cœur et de respiration.", + "ansChargeExplainer": "À quel point votre système nerveux autonome est rechargé pour la journée : une mesure de recharge issue de vos signaux nocturnes de cœur et de respiration.", "dayStrainExplainer": "La charge cardiovasculaire de la journée sur l'échelle d'effort de votre appareil. Lisez-la au regard de votre récupération, pas comme un objectif en soi.", - "workoutStrainExplainer": "À quel point une séance a été exigeante sur la même échelle d'effort — le coût cardiovasculaire de cette séance.", + "workoutStrainExplainer": "À quel point une séance a été exigeante sur la même échelle d'effort : le coût cardiovasculaire de cette séance.", "cardioLoadExplainer": "Une estimation de la charge d'entraînement qui suit la charge cardiovasculaire accumulée. Comparez-la à vos propres journées récentes.", "averageHeartRateExplainer": "Votre fréquence cardiaque moyenne sur toute la journée ou le cycle, telle que rapportée par votre wearable.", "maxHeartRateExplainer": "Votre fréquence cardiaque maximale sur toute la journée ou le cycle, telle que rapportée par votre wearable.", @@ -4576,7 +4576,7 @@ }, "resilience": { "explainer": "Comment votre corps équilibre la charge quotidienne et la récupération, d'après vos signaux nocturnes des derniers jours.", - "learning": "Votre résilience est encore en cours d'apprentissage — quelques jours de plus stabiliseront le niveau.", + "learning": "Votre résilience est encore en cours d'apprentissage. Quelques jours de plus stabiliseront le niveau.", "band": { "limited": "Limitée", "adequate": "Adéquate", @@ -4621,7 +4621,7 @@ "nights": "{count} nuits suivies", "indexLine": "indice moyen récent {value}", "eventsFlagged": "{count} événements signalés par votre appareil", - "disclaimer": "Il s'agit d'un signal de dépistage, pas d'un diagnostic — parlez-en à un professionnel de santé." + "disclaimer": "Il s'agit d'un signal de dépistage, pas d'un diagnostic. Parlez-en à un professionnel de santé." }, "labsChanges": { "sectionTitle": "Depuis votre dernier bilan", @@ -4644,7 +4644,7 @@ "description": "Enregistrez une mesure avec un dynamomètre à main (notez le meilleur de plusieurs serrages) et la tendance apparaîtra ici.", "cta": "Enregistrer la force de préhension" }, - "coachPrefill": "Je n'ai pas encore enregistré de force de préhension — que dit-elle sur ma santé musculaire, et comment la mesurer et l'améliorer ?" + "coachPrefill": "Je n'ai pas encore enregistré de force de préhension. Que dit-elle sur ma santé musculaire, et comment la mesurer et l'améliorer ?" }, "pain": { "title": "Douleur (0–10)", @@ -4655,7 +4655,7 @@ "description": "Enregistrez votre douleur actuelle sur l'échelle 0–10 et la tendance apparaîtra ici.", "cta": "Enregistrer un score de douleur" }, - "coachPrefill": "Je n'ai pas encore enregistré de score de douleur — comment suivre la douleur sur l'échelle 0–10, et qu'est-ce qu'un changement significatif ?" + "coachPrefill": "Je n'ai pas encore enregistré de score de douleur. Comment suivre la douleur sur l'échelle 0–10, et qu'est-ce qu'un changement significatif ?" }, "waist": { "title": "Tour de taille", @@ -4666,7 +4666,7 @@ "description": "Mesurez votre tour de taille à mi-chemin entre la dernière côte et l'os de la hanche, en fin d'expiration normale, et enregistrez-le ici.", "cta": "Enregistrer le tour de taille" }, - "coachPrefill": "Je n'ai pas encore enregistré de tour de taille — comment le mesurer correctement, et que signifie ce chiffre pour ma santé ?" + "coachPrefill": "Je n'ai pas encore enregistré de tour de taille. Comment le mesurer correctement, et que signifie ce chiffre pour ma santé ?" }, "waistToHeight": { "title": "Rapport taille-hauteur", @@ -4677,7 +4677,7 @@ "description": "Enregistrez un rapport taille-hauteur et la tendance apparaîtra ici. Règle simple : gardez votre tour de taille sous la moitié de votre taille.", "cta": "Enregistrer le rapport taille-hauteur" }, - "coachPrefill": "Je n'ai pas encore enregistré de rapport taille-hauteur — pourquoi est-ce un chiffre utile, et comment le maintenir sous 0,5 ?" + "coachPrefill": "Je n'ai pas encore enregistré de rapport taille-hauteur. Pourquoi est-ce un chiffre utile, et comment le maintenir sous 0,5 ?" }, "ecg": { "sectionTitle": "Enregistrements ECG", @@ -4720,7 +4720,7 @@ "intradayPulse": { "title": "Pouls au fil de la journée", "caption": "Moyenné par tranches de 10 minutes.", - "hourlyNote": "Moyenne horaire affichée pour cette journée — les jours récents affichent le détail complet par tranches de 10 minutes.", + "hourlyNote": "Moyenne horaire affichée pour cette journée. Les jours récents affichent le détail complet par tranches de 10 minutes.", "empty": "Pas encore assez de mesures pour cette journée pour en afficher le rythme.", "coverageOne": "Basé sur 1 mesure sur {hours}h.", "coverageMany": "Basé sur {count} mesures sur {hours}h.", @@ -4729,10 +4729,10 @@ "previousDay": "Jour précédent", "nextDay": "Jour suivant", "tension": { - "morning": "Une période élevée au repos ce matin — peut-être un peu de tension.", - "afternoon": "Une période élevée au repos cet après-midi — peut-être un peu de tension.", - "evening": "Une période élevée au repos ce soir — peut-être un peu de tension.", - "night": "Une période élevée au repos cette nuit — peut-être un peu de tension." + "morning": "Une période élevée au repos ce matin, peut-être un peu de tension.", + "afternoon": "Une période élevée au repos cet après-midi, peut-être un peu de tension.", + "evening": "Une période élevée au repos ce soir, peut-être un peu de tension.", + "night": "Une période élevée au repos cette nuit, peut-être un peu de tension." } }, "navEcg": "ECG", @@ -4785,14 +4785,14 @@ "metricBodyFat": "Masse grasse", "metricSleep": "Durée du sommeil", "metricSteps": "Pas/jour", - "metricGlucoseFasting": "Glycémie — à jeun", - "metricGlucosePostprandial": "Glycémie — postprandiale", - "metricGlucoseRandom": "Glycémie — indifférente", - "metricGlucoseBedtime": "Glycémie — avant le coucher", + "metricGlucoseFasting": "Glycémie (à jeun)", + "metricGlucosePostprandial": "Glycémie (postprandiale)", + "metricGlucoseRandom": "Glycémie (indifférente)", + "metricGlucoseBedtime": "Glycémie (avant le coucher)", "metricBodyWater": "Eau corporelle", "metricBoneMass": "Masse osseuse", "metricOxygenSaturation": "Saturation en oxygène (SpO₂)", - "unsetExplanation": "Pas de valeur personnelle — la valeur par défaut calculée s’applique.", + "unsetExplanation": "Pas de valeur personnelle : la valeur par défaut calculée s’applique.", "cardTitle": "Plages par métrique" }, "onboarding": { @@ -4806,11 +4806,11 @@ "steps": { "dashboardOverview": { "title": "Votre tableau de bord", - "body": "Le tableau de bord rassemble tous les modules d’un coup d’œil. Appuyez longuement sur une tuile pour la réorganiser ou la masquer (Réglages → Disposition du tableau de bord). Une tuile ne vaut que par les données derrière elle — les modules suivants les remplissent." + "body": "Le tableau de bord rassemble tous les modules d’un coup d’œil. Appuyez longuement sur une tuile pour la réorganiser ou la masquer (Réglages → Disposition du tableau de bord). Une tuile ne vaut que par les données derrière elle, et les modules suivants les remplissent." }, "quickAdd": { "title": "Saisi en quelques secondes", - "body": "Avec « + Ajouter », saisissez n’importe quelle mesure en quelques secondes — poids, tension, pouls, glycémie. Atout caché : antidater les valeurs oubliées. Tout ce que vous saisissez ici alimente les tendances, le score santé et les analyses IA." + "body": "Avec « + Ajouter », saisissez n’importe quelle mesure en quelques secondes : poids, tension, pouls, glycémie. Atout caché : antidater les valeurs oubliées. Tout ce que vous saisissez ici alimente les tendances, le score santé et les analyses IA." }, "measurements": { "title": "Mesures et plages cibles", @@ -4822,7 +4822,7 @@ }, "labs": { "title": "Valeurs de laboratoire", - "body": "Laboratoire recense les biomarqueurs avec plages de référence — hémogramme, cholestérol, HbA1c. Atout : import et export FHIR. Les valeurs hors plage réapparaissent comme preuves dans les analyses et le rapport médical." + "body": "Laboratoire recense les biomarqueurs avec plages de référence : hémogramme, cholestérol, HbA1c. Atout : import et export FHIR. Les valeurs hors plage réapparaissent comme preuves dans les analyses et le rapport médical." }, "illness": { "title": "Journal des maladies", @@ -4838,15 +4838,15 @@ }, "mood": { "title": "Humeur", - "body": "Humeur saisit votre ressenti et des tags en deux secondes. Atout : vos propres tags. Les tendances d’humeur se corrèlent au sommeil, aux médicaments et au cycle — le Coach repère les schémas." + "body": "Humeur saisit votre ressenti et des tags en deux secondes. Atout : vos propres tags. Les tendances d’humeur se corrèlent au sommeil, aux médicaments et au cycle, et le Coach repère les schémas." }, "insights": { "title": "Analyses", - "body": "Analyses, c’est le cœur : une analyse dynamique et fondée sur des preuves plutôt que des conseils génériques — chaque affirmation pointe vos données réelles. Caché : la disposition est personnalisable. Analyses réunit tout ce que les modules ci-dessus fournissent." + "body": "Analyses, c’est le cœur : une analyse dynamique et fondée sur des preuves plutôt que des conseils génériques, où chaque affirmation pointe vos données réelles. Caché : la disposition est personnalisable. Analyses réunit tout ce que les modules ci-dessus fournissent." }, "coach": { "title": "Coach", - "body": "Le Coach répond à vos questions sur vos données en dialogue, en utilisant antécédents, médicaments et résultats comme contexte. Vous choisissez le fournisseur IA (votre clé ou local). Il ne recalcule rien — il lit les mêmes chiffres que le tableau de bord." + "body": "Le Coach répond à vos questions sur vos données en dialogue, en utilisant antécédents, médicaments et résultats comme contexte. Vous choisissez le fournisseur IA (votre clé ou local). Il ne recalcule rien : il lit les mêmes chiffres que le tableau de bord." }, "integrations": { "title": "Intégrations", @@ -4854,15 +4854,15 @@ }, "export": { "title": "Rapport médical", - "body": "Le rapport médical regroupe mesures, médicaments, valeurs de laboratoire et examens en PDF ou FHIR pour le rendez-vous. Tous les modules convergent ici — un rapport complet ne vient que de données bien tenues." + "body": "Le rapport médical regroupe mesures, médicaments, valeurs de laboratoire et examens en PDF ou FHIR pour le rendez-vous. Tous les modules convergent ici : un rapport complet ne vient que de données bien tenues." }, "achievements": { "title": "Réussites", - "body": "Les réussites récompensent la régularité — séries et jalons. Une petite boucle de motivation qui aide à tenir bon." + "body": "Les réussites récompensent la régularité : séries et jalons. Une petite boucle de motivation qui aide à tenir bon." }, "wrapUp": { "title": "C’est la fin de la visite", - "body": "Cette visite guidée ne s'affiche qu'une fois — elle ne se rouvrira pas d'elle-même. Tout ce qu'elle a montré reste en place, et vous pouvez activer ou désactiver des fonctionnalités à tout moment dans Réglages → Modules." + "body": "Cette visite guidée ne s'affiche qu'une fois et ne se rouvrira pas d'elle-même. Tout ce qu'elle a montré reste en place, et vous pouvez activer ou désactiver des fonctionnalités à tout moment dans Réglages → Modules." } } }, @@ -4893,7 +4893,7 @@ "title": "Tout est prêt", "body": "Bienvenue à bord. Votre tableau de bord vous attend.", "returnCta": "Ouvrir le tableau de bord", - "learning": "Certaines analyses — glycémie, rythme de sommeil, tendances de tension, cycle — s'affinent au cours de la première semaine ou deux à mesure que vos données s'accumulent. Des tuiles vides signifient simplement que nous apprenons encore votre référence.", + "learning": "Certaines analyses (glycémie, rythme de sommeil, tendances de tension, cycle) s'affinent au cours de la première semaine ou deux à mesure que vos données s'accumulent. Des tuiles vides signifient simplement que nous apprenons encore votre référence.", "connectCta": "Connecter un appareil", "logCta": "Enregistrez votre première mesure", "importCta": "Importer un historique existant", @@ -4916,7 +4916,7 @@ "conditionsHint": "Aide HealthLog à replacer vos mesures dans leur contexte plutôt que de signaler l'attendu.", "allergiesLabel": "Allergies ou intolérances", "allergiesPlaceholder": "p. ex. pénicilline, lactose", - "privacyNote": "Stocké chiffré et utilisé uniquement pour un meilleur contexte. Nous ne demandons pas vos médicaments ici — ajoutez-les quand vous voulez depuis la page Médicaments." + "privacyNote": "Stocké chiffré et utilisé uniquement pour un meilleur contexte. Nous ne demandons pas vos médicaments ici : ajoutez-les quand vous voulez depuis la page Médicaments." }, "ai": { "panelTitle": "Voyez à quoi ressemblent les insights", @@ -4925,18 +4925,18 @@ "sampleTitle": "Briefing quotidien", "sampleTag": "Exemple", "sampleAriaLabel": "Exemple de briefing quotidien", - "sampleBody": "Poids en baisse de 1,2 kg en deux semaines. Pouls au repos stable à 58 bpm. Tension dans la plage 6 jours sur 7 — la seule valeur élevée a suivi un dîner tardif et salé.", - "sampleCaption": "Exemple uniquement — pas vos données. Voilà à quoi ressemble un briefing une fois les insights activés.", + "sampleBody": "Poids en baisse de 1,2 kg en deux semaines. Pouls au repos stable à 58 bpm. Tension dans la plage 6 jours sur 7 ; la seule valeur élevée a suivi un dîner tardif et salé.", + "sampleCaption": "Exemple uniquement, pas vos données. Voilà à quoi ressemble un briefing une fois les insights activés.", "ladderTitle": "Trois façons de l'activer", - "ladderLocalTitle": "Modèle local — les requêtes d’IA restent sur votre réseau", - "ladderLocalBody": "Pointez HealthLog vers Ollama ou LM Studio sur votre propre machine. Gratuit et totalement privé — le choix calme par défaut.", + "ladderLocalTitle": "Modèle local : les requêtes d’IA restent sur votre réseau", + "ladderLocalBody": "Pointez HealthLog vers Ollama ou LM Studio sur votre propre machine. Gratuit et totalement privé, le choix calme par défaut.", "ladderByokTitle": "Apportez votre clé", "ladderByokBody": "Utilisez votre propre clé OpenAI ou Anthropic. Elle fonctionne avec votre compte et votre facturation, et le niveau API exclut vos données de l'entraînement par défaut.", "ladderOauthTitle": "Connectez-vous avec un abonnement", - "ladderOauthBody": "Reliez un compte ChatGPT — sans coût par jeton, mais les conditions du niveau grand public peuvent utiliser le contenu pour l'entraînement : c'est donc un choix délibéré, jamais l'option par défaut pour vos données de santé.", - "keylessLine": "HealthLog est pleinement utile sans IA. Vos tuiles, graphiques, tendances et exports fonctionnent tous — l'IA n'ajoute que la lecture en langage clair par-dessus.", + "ladderOauthBody": "Reliez un compte ChatGPT, sans coût par jeton, mais les conditions du niveau grand public peuvent utiliser le contenu pour l'entraînement : c'est donc un choix délibéré, jamais l'option par défaut pour vos données de santé.", + "keylessLine": "HealthLog est pleinement utile sans IA. Vos tuiles, graphiques, tendances et exports fonctionnent tous ; l'IA n'ajoute que la lecture en langage clair par-dessus.", "setupCta": "Configurez-le (environ une minute)", - "sharedKeyNote": "Cette instance fournit déjà un fournisseur d'IA partagé : les insights fonctionnent pour vous dès maintenant — aucune configuration nécessaire.", + "sharedKeyNote": "Cette instance fournit déjà un fournisseur d'IA partagé : les insights fonctionnent pour vous dès maintenant, aucune configuration nécessaire.", "offer": { "title": "Cette instance peut rédiger votre résumé en langage clair.", "body": "L’exploitant met à disposition un fournisseur qui a fonctionné au cours des dernières 24 heures. Une seule touche active le langage clair ; vos données partent alors vers ce seul fournisseur et vers personne d’autre.", @@ -5153,7 +5153,7 @@ "profileDescription": "Taille, date de naissance et sexe débloquent des objectifs personnalisés.", "profileCta": "Ouvrir le profil", "measurementTitle": "Saisir la première mesure", - "measurementDescription": "Une mesure suffit à activer la tuile — la tendance se dessine à partir de la 5ᵉ mesure.", + "measurementDescription": "Une mesure suffit à activer la tuile ; la tendance se dessine à partir de la 5ᵉ mesure.", "measurementCta": "Ajouter une mesure", "medicationTitle": "Ajouter un médicament", "medicationDescription": "Suis l’observance et reçois des rappels au moment où tu en as besoin.", @@ -5162,7 +5162,7 @@ "dataSourceDescription": "Synchronisez poids, tension, sommeil et plus depuis Withings, WHOOP, Oura, Polar, Nightscout, Fitbit ou Apple Health.", "dataSourceCta": "Connecter", "notificationsTitle": "Configurer les notifications", - "notificationsDescription": "Choisis comment HealthLog te prévient — Telegram, ntfy ou Web Push.", + "notificationsDescription": "Choisis comment HealthLog te prévient : Telegram, ntfy ou Web Push.", "notificationsCta": "Ouvrir les notifications", "insightsTitle": "Activer les insights (facultatif)", "insightsDescription": "Ajoutez un modèle local ou votre propre clé IA pour débloquer le briefing quotidien et Coach.", @@ -5388,7 +5388,7 @@ "resetSuccess": "Priorité des sources rétablie aux valeurs par défaut", "perMetricToggle": "Réglages par métrique ({count})", "perMetricHelp": "Métriques que vous avez personnalisées par rapport à l’ordre par défaut. Utilisez cette liste pour rétablir une métrique donnée à sa valeur par défaut sans toucher aux autres.", - "perMetricEmpty": "Aucun réglage par métrique — chaque métrique utilise l’ordre global ci-dessus.", + "perMetricEmpty": "Aucun réglage par métrique : chaque métrique utilise l’ordre global ci-dessus.", "resetMetric": "Réinitialiser", "deviceTypeToggle": "Priorité par type d’appareil ({count})", "deviceTypeHelp": "Au sein d’une source, quel appareil l’emporte. Lorsqu’une Apple Watch et un iPhone enregistrent tous deux les pas, le type d’appareil le mieux classé compte comme la lecture canonique.", @@ -5497,7 +5497,7 @@ "fullBackup": { "title": "Sauvegarde complète", "description": "L'ensemble de votre dossier dans un fichier JSON.", - "scopeNote": "Les métadonnées des documents et le résumé IA, s'il existe, sont inclus en texte clair ; les fichiers originaux des documents ainsi que les tracés GPS/données d'échantillons des entraînements ne le sont pas — téléchargez-les séparément depuis le coffre de documents ou l'export des entraînements.", + "scopeNote": "Les métadonnées des documents et le résumé IA, s'il existe, sont inclus en texte clair ; les fichiers originaux des documents ainsi que les tracés GPS/données d'échantillons des entraînements ne le sont pas. Téléchargez-les séparément depuis le coffre de documents ou l'export des entraînements.", "encryptToggle": "Chiffrer avec une phrase secrète", "passphrasePlaceholder": "Phrase secrète (12 caractères min.)", "passphraseHelp": "Dérive la clé de l'archive avec Argon2id et la scelle avec AES-256-GCM. Enregistrez le fichier avec l'extension .hlx.", @@ -6048,7 +6048,7 @@ "rawDataWarning": "Historique détaillé activé : chaque analyse envoie aussi les moyennes journalières des 90 derniers jours, les moyennes hebdomadaires de l’année précédente et les moyennes mensuelles jusqu’à 5 ans en arrière.", "regenerateInsights": "Régénérer les rapports", "regenerateSuccess": "Rapports régénérés", - "regenerateRateLimit": "Veuillez patienter — vous avez atteint la limite horaire d’analyses.", + "regenerateRateLimit": "Veuillez patienter : vous avez atteint la limite horaire d’analyses.", "lastGeneratedAt": "Dernière génération", "ai": { "chatgptConnectedBadge": "ChatGPT connecté", @@ -6058,11 +6058,11 @@ "deviceCodeHeading": "Terminez la connexion sur chatgpt.com", "deviceCodeStep1": "Ouvrez ce lien sur n’importe quel appareil :", "deviceCodeStep2": "Saisissez ce code à usage unique :", - "deviceCodeStep3": "Approuvez la connexion — cette page se met à jour automatiquement.", + "deviceCodeStep3": "Approuvez la connexion. Cette page se met à jour automatiquement.", "deviceCodeCopy": "Copier", "deviceCodeWaiting": "En attente d’approbation…", "deviceCodeCancel": "Annuler", - "oauthNotConfigured": "L’OAuth ChatGPT n’est pas configuré sur cette instance — utilisez plutôt votre propre clé API ci-dessous.", + "oauthNotConfigured": "L’OAuth ChatGPT n’est pas configuré sur cette instance. Utilisez plutôt votre propre clé API ci-dessous.", "modelLabel": "Modèle", "modelOptionDefault": "— Par défaut —", "modelOptionCustom": "Personnalisé…", @@ -6070,7 +6070,7 @@ "anthropicKeyLabel": "Clé API Anthropic", "baseUrlLabel": "Base URL", "localKeyLabel": "Clé API (facultative)", - "localDescription": "Tout point de terminaison compatible OpenAI fonctionne ici — un modèle local (Ollama, LM Studio) comme une passerelle telle que LiteLLM, OpenRouter ou vLLM. L'URL de base se termine par /v1 ; la clé API est facultative.", + "localDescription": "Tout point de terminaison compatible OpenAI fonctionne ici : un modèle local (Ollama, LM Studio) comme une passerelle telle que LiteLLM, OpenRouter ou vLLM. L'URL de base se termine par /v1 ; la clé API est facultative.", "savedPreview": "(enregistrée {preview})", "savedShort": "(enregistrée)", "saveCta": "Enregistrer", @@ -6110,7 +6110,7 @@ "admin-openai": "OpenAI fourni par l’administrateur" }, "compat": { - "description": "Un fournisseur à part entière pour tout point de terminaison qui parle l'API /v1/chat/completions d'OpenAI : LiteLLM, OpenRouter, vLLM ou une autre passerelle. L'URL de base se termine par /v1, la clé API est facultative et le modèle est celui que votre passerelle achemine. Votre clé OpenAI n'atteint jamais ce point de terminaison — ce fournisseur a la sienne.", + "description": "Un fournisseur à part entière pour tout point de terminaison qui parle l'API /v1/chat/completions d'OpenAI : LiteLLM, OpenRouter, vLLM ou une autre passerelle. L'URL de base se termine par /v1, la clé API est facultative et le modèle est celui que votre passerelle achemine. Votre clé OpenAI n'atteint jamais ce point de terminaison : ce fournisseur a la sienne.", "keyLabel": "Clé API (facultative)", "modelHint": "Le nom de modèle attendu par votre passerelle. Laissé vide, le modèle enregistré pour vos autres fournisseurs est utilisé ; si aucun n'est défini, ce fournisseur est ignoré." }, @@ -6146,18 +6146,18 @@ "notConfigured": "L’opérateur n’a pas configuré de clé OpenAI partagée sur cette instance." }, "testProvider": "Tester le fournisseur actif", - "testSuccess": "OK — {provider} ({model})", + "testSuccess": "OK : {provider} ({model})", "testFailedShort": "Échec du test : {message}", - "testUnexpectedResponse": "Échec de la connexion au fournisseur d’IA — réponse inattendue du serveur.", - "testReasonCredentials": "Le fournisseur a rejeté les identifiants — réauthentifiez-vous dans les réglages IA.", - "testReasonRateLimited": "Le fournisseur a limité la requête — réessayez sous peu.", + "testUnexpectedResponse": "Échec de la connexion au fournisseur d’IA : réponse inattendue du serveur.", + "testReasonCredentials": "Le fournisseur a rejeté les identifiants. Réauthentifiez-vous dans les réglages IA.", + "testReasonRateLimited": "Le fournisseur a limité la requête. Réessayez sous peu.", "testReasonServerError": "Le fournisseur d’IA a renvoyé une erreur serveur.", - "testReasonBadRequest": "Le fournisseur a rejeté la requête (HTTP {status}) — le point de terminaison a répondu ; le problème vient donc du format de la requête ou du nom du modèle, pas de la connexion.", + "testReasonBadRequest": "Le fournisseur a rejeté la requête (HTTP {status}). Le point de terminaison a répondu ; le problème vient donc du format de la requête ou du nom du modèle, pas de la connexion.", "testReasonUnreachable": "Impossible de joindre le fournisseur d’IA.", "coachMemory": { "title": "Ce dont le Coach se souvient", "description": "Les informations durables que vous avez confiées au Coach.", - "empty": "Le Coach n'a encore enregistré aucune information. Au fil de vos échanges, il retient les détails durables que vous partagez — vos objectifs, vos affections, vos préférences — et vous pouvez les effacer ici à tout moment.", + "empty": "Le Coach n'a encore enregistré aucune information. Au fil de vos échanges, il retient les détails durables que vous partagez (vos objectifs, vos affections, vos préférences) et vous pouvez les effacer ici à tout moment.", "learnedPrefix": "appris {when}", "categoryPreference": "Préférences", "categoryCondition": "Affections", @@ -6173,7 +6173,7 @@ "forgetAllConfirmBody": "Cela supprime toutes les informations enregistrées. Le Coach repartira de zéro lors de votre prochaine conversation. Cette action est irréversible.", "forgetAllConfirmAction": "Tout oublier", "cancel": "Annuler", - "summaryNote": "Le Coach peut aussi conserver un bref résumé évolutif de chaque conversation. Il n'existe pas de commande individuelle pour cela — supprimer une conversation supprime son résumé.", + "summaryNote": "Le Coach peut aussi conserver un bref résumé évolutif de chaque conversation. Il n'existe pas de commande individuelle pour cela : supprimer une conversation supprime son résumé.", "loadError": "Impossible de charger ce dont le Coach se souvient.", "forgotToast": "Information oubliée.", "forgotError": "Impossible d'oublier cette information. Veuillez réessayer.", @@ -6194,7 +6194,7 @@ "markDone": "Terminé", "dismiss": "Ignorer", "deleteAria": "Supprimer ce rappel", - "note": "Les rappels sont stockés chiffrés. Supprime-en un à tout moment — il disparaît de ce que le Coach peut voir.", + "note": "Les rappels sont stockés chiffrés. Supprime-en un à tout moment : il disparaît de ce que le Coach peut voir.", "status": { "proposed": "Suggéré", "active": "Enregistré", @@ -6241,14 +6241,14 @@ "title": "Lire les documents automatiquement avec l'IA", "subLabel": "Les documents sont lus et indexés par votre fournisseur d'IA configuré, sans validation document par document.", "honesty": "Lorsque cette option est activée, chaque document que vous téléversez est envoyé à votre fournisseur d'IA configuré pour être lu, décrit et indexé pour la recherche, sans confirmation par document. L'activation agit aussi rétroactivement : les documents que vous avez déjà téléversés et qui n'ont pas encore de résumé sont envoyés eux aussi, jusqu'à 200 à chaque activation. Cela se produit sur le serveur et le contenu du document quitte cette machine vers ce fournisseur. Si votre fournisseur configuré est une connexion par abonnement (un compte d'IA connecté plutôt qu'une clé API), ses propres paramètres de données s'appliquent : les fournisseurs par abonnement peuvent utiliser le contenu pour améliorer leurs modèles, et aucun accord de traitement des données ne le couvre. Les documents lus par un modèle local auto-hébergé ne quittent jamais votre serveur. Désactivé par défaut ; activez-le uniquement si vous acceptez ce compromis pour vos documents.", - "confirm": "Compris — activer", + "confirm": "Compris, activer", "cancel": "Annuler" }, "centralCodex": { "title": "Utiliser l'accès IA partagé du serveur", "subLabel": "Les requêtes IA passent par la connexion partagée du serveur, vos propres fournisseurs servant de repli.", "honesty": "L'accès partagé est un unique compte IA connecté que l'opérateur a relié pour tout le monde sur ce serveur, et non votre propre clé. Les requêtes que vous y faites servent par défaut à entraîner les modèles du fournisseur et aucun accord de traitement des données ne les couvre, les limites horaires et hebdomadaires du compte sont partagées avec tous les autres qui ont accepté, et vos propres fournisseurs sont essayés en premier. Ne l'activez que si vous acceptez ce compromis.", - "confirm": "Compris — utiliser la connexion", + "confirm": "Compris, utiliser la connexion", "cancel": "Annuler" }, "consent": { @@ -6324,8 +6324,8 @@ "withingsClientId": "ID client", "withingsClientSecret": "Secret client", "withingsCredentialsSaved": "Identifiants enregistrés", - "withingsCredentialsSavedPlaceholder": "Enregistré — saisissez-en un nouveau pour remplacer", - "withingsCredentialsSavedPlaceholderSecret": "Enregistré — saisissez-en un nouveau pour remplacer", + "withingsCredentialsSavedPlaceholder": "Enregistré. Saisissez-en un nouveau pour remplacer", + "withingsCredentialsSavedPlaceholderSecret": "Enregistré. Saisissez-en un nouveau pour remplacer", "withingsSaveCredentials": "Enregistrer", "configured": "Configuré", "withingsSync": "Synchroniser maintenant", @@ -6340,7 +6340,7 @@ }, "withingsFullSyncResult": "{count} mesures entièrement synchronisées", "withingsSyncFailed": "Échec de la synchronisation", - "withingsOauthConnected": "Withings connecté — la première synchronisation démarre en arrière-plan.", + "withingsOauthConnected": "Withings connecté. La première synchronisation démarre en arrière-plan.", "withingsOauthFailed": "Échec de la connexion Withings", "withingsOauthError": { "csrf1": "Le contrôle de sécurité a échoué car le cookie du navigateur manquait. Relancez la connexion dans le même navigateur.", @@ -6365,8 +6365,8 @@ "whoopClientId": "Client ID", "whoopClientSecret": "Client Secret", "whoopCredentialsSaved": "Identifiants enregistrés", - "whoopCredentialsSavedPlaceholder": "Enregistré — saisir de nouveaux pour remplacer", - "whoopCredentialsSavedPlaceholderSecret": "Enregistré — saisir de nouveaux pour remplacer", + "whoopCredentialsSavedPlaceholder": "Enregistré. Saisir de nouveaux pour remplacer", + "whoopCredentialsSavedPlaceholderSecret": "Enregistré. Saisir de nouveaux pour remplacer", "whoopSaveCredentials": "Enregistrer", "whoopSync": "Synchroniser", "whoopFullSync": "Synchroniser toutes les données", @@ -6381,7 +6381,7 @@ "whoopConnect": "Se connecter avec WHOOP", "whoopNoCredentials": "Veuillez saisir vos identifiants API ci-dessus pour connecter WHOOP.", "whoopBackfillInProgress": "Importation de votre historique WHOOP en arrière-plan…", - "whoopOauthConnected": "WHOOP connecté — la première synchronisation démarre en arrière-plan.", + "whoopOauthConnected": "WHOOP connecté. La première synchronisation démarre en arrière-plan.", "whoopOauthFailed": "Échec de la connexion à WHOOP", "whoopOauthError": { "csrf1": "La vérification de sécurité a échoué car le cookie du navigateur était absent. Veuillez relancer la connexion dans le même navigateur.", @@ -6395,14 +6395,14 @@ }, "fitbit": "Fitbit", "fitbitTag": "Fitbit et Pixel", - "fitbitDescription": "Connecte Fitbit pour synchroniser tes données Fitbit et Pixel Watch — poids, fréquence cardiaque et plus.", + "fitbitDescription": "Connecte Fitbit pour synchroniser tes données Fitbit et Pixel Watch : poids, fréquence cardiaque et plus.", "fitbitExperimentalBadge": "Expérimental", "fitbitCredentials": "Identifiants d'API", "fitbitClientId": "Client ID", "fitbitClientSecret": "Client Secret", "fitbitCredentialsSaved": "Identifiants enregistrés", - "fitbitCredentialsSavedPlaceholder": "Enregistré — saisissez-en de nouveaux pour remplacer", - "fitbitCredentialsSavedPlaceholderSecret": "Enregistré — saisissez-en de nouveaux pour remplacer", + "fitbitCredentialsSavedPlaceholder": "Enregistré. Saisissez-en de nouveaux pour remplacer", + "fitbitCredentialsSavedPlaceholderSecret": "Enregistré. Saisissez-en de nouveaux pour remplacer", "fitbitSaveCredentials": "Enregistrer", "fitbitSync": "Synchroniser maintenant", "fitbitFullSync": "Tout synchroniser", @@ -6417,18 +6417,18 @@ "fitbitConnect": "Se connecter à Fitbit", "fitbitNoCredentials": "Veuillez saisir vos identifiants d'API ci-dessus pour connecter Fitbit.", "fitbitBackfillInProgress": "Importation de votre historique Fitbit en arrière-plan…", - "fitbitOauthConnected": "Fitbit connecté — la première synchronisation démarre en arrière-plan.", + "fitbitOauthConnected": "Fitbit connecté. La première synchronisation démarre en arrière-plan.", "fitbitOauthFailed": "Échec de la connexion à Fitbit", "googleHealth": "Google Health", "googleHealthTag": "Fitbit et Pixel", "googleHealthBetaBadge": "Bêta", - "googleHealthDescription": "Connecte Fitbit, Pixel Watch et Fitbit Air via ton compte Google — poids, fréquence cardiaque, sommeil et activité. Cela remplace la connexion Fitbit classique, que Google arrête en septembre 2026.", + "googleHealthDescription": "Connecte Fitbit, Pixel Watch et Fitbit Air via ton compte Google : poids, fréquence cardiaque, sommeil et activité. Cela remplace la connexion Fitbit classique, que Google arrête en septembre 2026.", "googleHealthCredentials": "Identifiants d'API", "googleHealthClientId": "ID client", "googleHealthClientSecret": "Secret client", "googleHealthCredentialsSaved": "Identifiants enregistrés", - "googleHealthCredentialsSavedPlaceholder": "Enregistré — saisir de nouveaux pour remplacer", - "googleHealthCredentialsSavedPlaceholderSecret": "Enregistré — saisir de nouveaux pour remplacer", + "googleHealthCredentialsSavedPlaceholder": "Enregistré. Saisir de nouveaux pour remplacer", + "googleHealthCredentialsSavedPlaceholderSecret": "Enregistré. Saisir de nouveaux pour remplacer", "googleHealthSaveCredentials": "Enregistrer", "googleHealthSync": "Synchroniser maintenant", "googleHealthSyncCheckStatus": "Actualiser le statut", @@ -6462,9 +6462,9 @@ "googleHealthConnect": "Se connecter avec Google", "googleHealthNoCredentials": "Saisis tes identifiants d'API ci-dessus pour connecter Google Health.", "googleHealthBackfillInProgress": "Importation de ton historique Google Health en arrière-plan…", - "googleHealthReauthBanner": "Google a expiré la connexion — cela arrive régulièrement tant que ton application OAuth reste en mode Test. Reconnecte-toi pour reprendre la synchronisation.", + "googleHealthReauthBanner": "Google a expiré la connexion. Cela arrive régulièrement tant que ton application OAuth reste en mode Test. Reconnecte-toi pour reprendre la synchronisation.", "googleHealthReconnect": "Se reconnecter", - "googleHealthOauthConnected": "Google Health connecté — la première synchronisation démarre en arrière-plan.", + "googleHealthOauthConnected": "Google Health connecté. La première synchronisation démarre en arrière-plan.", "googleHealthOauthFailed": "Échec de la connexion à Google Health", "googleHealthOauthError": { "csrf1": "La vérification de sécurité a échoué car le cookie du navigateur était manquant. Relance la connexion dans le même navigateur.", @@ -6499,10 +6499,10 @@ }, "integrationPill": { "connected": "Connecté", - "errorReconnect": "Erreur — reconnecter", + "errorReconnect": "Erreur : reconnecter", "warningServerError": "Échec de synchronisation", "failureCount": "{count}/{threshold}", - "parkedReconnect": "En pause — reconnecter", + "parkedReconnect": "En pause : reconnecter", "notConnected": "Non connecté", "justNow": "à l’instant", "minutesAgo": "il y a {count} min", @@ -6557,7 +6557,7 @@ "namePlaceholder": "Nom, p. ex. Paperless-ngx" }, "tokenMintMovedDescription": "Les jetons sont émis là où ils s'appliquent : ci-dessus pour les mesures, les entraînements et les documents, ou dans le point de terminaison API d'un médicament pour ce seul médicament.", - "tokenCreated": "Jeton créé — copiez-le maintenant ! Il ne sera plus affiché.", + "tokenCreated": "Jeton créé, copiez-le maintenant ! Il ne sera plus affiché.", "tokenCopy": "Copier le jeton", "tokenCopied": "Jeton copié dans le presse-papiers", "tokenCopyFailed": "Impossible de copier le jeton", @@ -6596,7 +6596,7 @@ "deleteAccountCta": "Supprimer le compte", "deleteAccountConfirmTitle": "Supprimer définitivement le compte ?", "deleteAccountConfirmDescription": "Votre compte, toutes vos données de santé, vos clés d’accès, vos sessions et vos entrées d’audit seront définitivement supprimés. Vous serez déconnecté immédiatement après.", - "deleteAccountSuccess": "Compte supprimé — déconnexion en cours.", + "deleteAccountSuccess": "Compte supprimé, déconnexion en cours.", "deleteAccountFailed": "Le compte n’a pas pu être supprimé", "deleteAccountFinal": "Supprimer définitivement", "saved": "Enregistré", @@ -6619,7 +6619,7 @@ "testing": "Test en cours…", "ok": "Connecté (latence {latency} ms)", "errors": { - "credentials_rejected": "Identifiants rejetés — vérifiez votre jeton", + "credentials_rejected": "Identifiants rejetés : vérifiez votre jeton", "rate_limited": "Limité par le service en amont", "timeout": "Délai de la requête dépassé", "upstream_error": "Le service en amont a renvoyé une erreur", @@ -6630,7 +6630,7 @@ "private_origin_not_approved": "Cible sur un réseau privé. L’opérateur doit ajouter cette origine à NOTIFICATION_PRIVATE_ORIGINS", "private_origin_not_grantable": "Cette adresse est une adresse de lien local, de métadonnées ou non spécifiée ; aucune autorisation de l’opérateur ne peut l’ouvrir. Utilisez l’adresse sur laquelle le relais écoute", "url_invalid": "L’URL n’est pas valide", - "redirected": "Le point de terminaison redirige — vérifiez l’URL", + "redirected": "Le point de terminaison redirige : vérifiez l’URL", "endpoint_not_found": "Point de terminaison introuvable à l’URL", "credentials_unreadable": "Les identifiants ne peuvent pas être déchiffrés", "upstream_invalid_json": "Le service en amont a envoyé un JSON non valide", @@ -6641,7 +6641,7 @@ }, "notificationStatus": { "title": "Fiabilité des canaux", - "description": "État de chaque canal — « Désactivé automatiquement » signifie arrêté après des erreurs permanentes.", + "description": "État de chaque canal ; « Désactivé automatiquement » signifie arrêté après des erreurs permanentes.", "emptyDescription": "Ajoutez un canal dans Paramètres › Intégrations › Canaux de diffusion.", "stateActive": "Actif", "stateAutoDisabled": "Désactivé automatiquement", @@ -6667,7 +6667,7 @@ }, "healthRecord": { "title": "Exporter le dossier de santé", - "description": "Un dossier complet pour votre médecin — en PDF, en FHIR ou les deux.", + "description": "Un dossier complet pour votre médecin, en PDF, en FHIR ou les deux.", "format": "Format", "format_pdf": "PDF", "format_fhir": "Structuré (FHIR)", @@ -6699,7 +6699,7 @@ "createTitle": "Nouveau lien de partage", "createDescription": "Le lien est en lecture seule et limité dans le temps.", "label": "Libellé", - "labelPlaceholder": "ex. Dr Martin — bilan annuel", + "labelPlaceholder": "ex. Dr Martin, bilan annuel", "range": "Jours d'historique", "rangeHint": "Jusqu'où remonte la fenêtre partagée.", "expiry": "Expire dans (jours)", @@ -6719,7 +6719,7 @@ "statusRevoked": "Révoqué", "statusExpired": "Expiré", "inactiveTitle": "Révoqués et expirés ({count})", - "shownOnce": "Affiché une seule fois. Enregistrez le code QR et la phrase secrète maintenant — ils ne pourront pas être récupérés ensuite.", + "shownOnce": "Affiché une seule fois. Enregistrez le code QR et la phrase secrète maintenant : ils ne pourront pas être récupérés ensuite.", "qrAlt": "Code QR contenant le lien de partage et la phrase secrète", "linkLabel": "Lien", "passphraseLabel": "Phrase secrète", @@ -6730,12 +6730,12 @@ "attachTitle": "Joindre des documents", "attachButton": "Choisir des documents", "attachCount": "{count} sur {max} sélectionnés", - "attachFrozen": "La sélection de documents est figée à la création du lien — impossible d'ajouter ou de retirer des documents ensuite.", + "attachFrozen": "La sélection de documents est figée à la création du lien : impossible d'ajouter ou de retirer des documents ensuite.", "attachRemove": "Retirer {title}", "exifNote": "Les métadonnées de l'appareil photo (EXIF/GPS) sont supprimées des images JPEG, PNG et WebP lors du partage. Les fichiers PDF, TIFF, HEIC et Office sont transmis tels quels.", "documentCount": "Documents joints : {count}", "qrScanTitle": "Scannez pour ouvrir sur un autre appareil", - "qrScanHint": "Pointez l'appareil photo d'un téléphone vers le code pour ouvrir le dossier partagé — la phrase secrète est déjà incluse.", + "qrScanHint": "Pointez l'appareil photo d'un téléphone vers le code pour ouvrir le dossier partagé. La phrase secrète est déjà incluse.", "pickerTitle": "Joindre des documents", "pickerDescription": "Recherchez dans votre coffre et sélectionnez les documents à partager. Jusqu'à {max}.", "pickerSearch": "Rechercher des documents", @@ -6748,7 +6748,7 @@ "statusNeedsReselect": "Choisir à nouveau le contenu", "reselectReason": "Ce lien diffusait un périmètre que personne n'avait choisi ; il a donc été fermé. Créez-en un nouveau et choisissez son contenu.", "reselectAction": "Créer un remplacement", - "createDetail": "Le jeton n'est affiché qu'une fois à la création — conservez-le alors ; il ne peut pas être récupéré.", + "createDetail": "Le jeton n'est affiché qu'une fois à la création. Conservez-le alors ; il ne peut pas être récupéré.", "activeDescription": "Les liens que vous avez partagés, leur expiration et le nombre d'ouvertures." }, "genderOther": "Autre", @@ -6757,10 +6757,10 @@ "nightscoutDescription": "Connecte ton propre site Nightscout pour synchroniser les mesures de glucose en continu dans le panneau glucose.", "nightscoutViewData": "Voir votre glycémie", "nightscoutUrl": "URL Nightscout", - "nightscoutUrlSavedPlaceholder": "Enregistré — saisissez une nouvelle URL pour la remplacer", + "nightscoutUrlSavedPlaceholder": "Enregistré. Saisissez une nouvelle URL pour la remplacer", "nightscoutToken": "Jeton d'API", "nightscoutTokenOptional": "Facultatif pour un site public", - "nightscoutTokenSavedPlaceholder": "Enregistré — saisissez un nouveau jeton pour le remplacer", + "nightscoutTokenSavedPlaceholder": "Enregistré. Saisissez un nouveau jeton pour le remplacer", "nightscoutTokenHelp": "Collez un jeton d'accès depuis les outils d'administration de Nightscout. Laissez vide si votre site est lisible publiquement.", "nightscoutPrivateOperatorTitle": "L’accès à un Nightscout privé nécessite l’autorisation de l’administrateur du serveur.", "nightscoutPrivateOperatorDescription": "Demandez à l’administrateur du serveur d’autoriser précisément cette origine Nightscout.", @@ -6781,7 +6781,7 @@ "polarClientId": "Client ID", "polarClientSecret": "Client Secret", "polarCredentialsSaved": "Identifiants enregistrés", - "polarCredentialsSavedPlaceholder": "Enregistré — saisir de nouveaux pour remplacer", + "polarCredentialsSavedPlaceholder": "Enregistré. Saisir de nouveaux pour remplacer", "polarSaveCredentials": "Enregistrer", "polarUnavailable": "Polar n'est pas configuré sur ce serveur. Ajoutez vos propres identifiants OAuth Polar ci-dessus, ou demandez à votre administrateur de configurer l'application partagée.", "polarConnect": "Connecter Polar", @@ -6791,7 +6791,7 @@ "polarDisconnect": "Déconnecter", "polarDisconnectTitle": "Déconnecter Polar ?", "polarDisconnectDescription": "Les synchronisations futures s'arrêtent. Les mesures déjà importées restent dans votre historique.", - "polarOauthConnected": "Polar connecté — la première synchronisation démarre en arrière-plan.", + "polarOauthConnected": "Polar connecté. La première synchronisation démarre en arrière-plan.", "polarOauthFailed": "Échec de la connexion à Polar", "polarOauthError": { "csrf1": "La vérification de sécurité a échoué car le cookie du navigateur était absent. Veuillez relancer la connexion dans le même navigateur.", @@ -6810,7 +6810,7 @@ "ouraClientId": "Client ID", "ouraClientSecret": "Client Secret", "ouraCredentialsSaved": "Identifiants enregistrés", - "ouraCredentialsSavedPlaceholder": "Enregistré — saisir de nouveaux pour remplacer", + "ouraCredentialsSavedPlaceholder": "Enregistré. Saisir de nouveaux pour remplacer", "ouraSaveCredentials": "Enregistrer", "ouraUnavailable": "Oura n'est pas configuré sur ce serveur. Ajoutez vos propres identifiants OAuth Oura ci-dessus, ou demandez à votre administrateur de configurer l'application partagée.", "ouraConnect": "Connecter Oura", @@ -6820,7 +6820,7 @@ "ouraDisconnect": "Déconnecter", "ouraDisconnectTitle": "Déconnecter Oura ?", "ouraDisconnectDescription": "Les synchronisations futures s'arrêtent. Les mesures déjà importées restent dans votre historique.", - "ouraOauthConnected": "Oura connecté — la première synchronisation démarre en arrière-plan.", + "ouraOauthConnected": "Oura connecté. La première synchronisation démarre en arrière-plan.", "ouraOauthFailed": "Échec de la connexion à Oura", "ouraOauthError": { "csrf1": "La vérification de sécurité a échoué car le cookie du navigateur était absent. Veuillez relancer la connexion dans le même navigateur.", @@ -6851,7 +6851,7 @@ } }, "integrationRedirectGuide": { - "intro": "Cette connexion passe par votre propre application développeur {provider} — environ 5 minutes de configuration :", + "intro": "Cette connexion passe par votre propre application développeur {provider}, environ 5 minutes de configuration :", "step1": "Créez une application dans le portail développeur {provider}.", "step2": "Réglez son URL de redirection/callback sur :", "step3": "Collez ci-dessus l'ID client et le secret client fournis." @@ -6911,7 +6911,7 @@ }, "recovery": { "saveNow": "Enregistrez ces codes de récupération maintenant", - "saveNowHint": "Chaque code ne fonctionne qu'une fois. Ils ne sont affichés que cette fois — conservez-les en lieu sûr. Si vous perdez votre authentificateur, un code de récupération est le seul moyen de revenir.", + "saveNowHint": "Chaque code ne fonctionne qu'une fois. Ils ne sont affichés que cette fois : conservez-les en lieu sûr. Si vous perdez votre authentificateur, un code de récupération est le seul moyen de revenir.", "download": "Télécharger", "remainingOne": "{count} code de récupération restant.", "remainingOther": "{count} codes de récupération restants.", @@ -7014,7 +7014,7 @@ "endpointLabel": "URL du connecteur", "connectDescription": "Collez cette URL dans la configuration du connecteur personnalisé de votre assistant, puis autorisez avec le jeton ci-dessous ou connectez-vous lorsque vous y êtes invité.", "tokensTitle": "Jetons du connecteur", - "tokensDescription": "Générez un jeton pour connecter un assistant — lecture seule, sauf si vous autorisez l'écriture ci-dessous.", + "tokensDescription": "Générez un jeton pour connecter un assistant, en lecture seule sauf si vous autorisez l'écriture ci-dessous.", "scopeNote": "Les nouveaux jetons ne peuvent que lire vos propres données. L'accès en écriture (health:write) s'accorde par jeton avec le commutateur ci-dessous. Un jeton ne peut jamais atteindre les fonctions d'administration.", "writeScopeToggleLabel": "Autoriser l'enregistrement (health:write)", "writeScopeNote": "Ajoute la portée health:write pour que l'assistant puisse enregistrer de nouvelles mesures et entrées d'humeur dans votre compte. Chaque écriture est d'abord confirmée. Le jeton ne peut toujours pas supprimer ni modifier des entrées existantes, changer les médicaments, ni atteindre les fonctions REST ou d'administration. Laissez désactivé pour un accès en lecture seule.", @@ -7038,7 +7038,7 @@ "stravaClientId": "ID client", "stravaClientSecret": "Secret client", "stravaCredentialsSaved": "Identifiants enregistrés", - "stravaCredentialsSavedPlaceholder": "Enregistrés — saisis-en de nouveaux pour remplacer", + "stravaCredentialsSavedPlaceholder": "Enregistrés. Saisis-en de nouveaux pour remplacer", "stravaSaveCredentials": "Enregistrer", "stravaUnavailable": "Strava n'est pas configuré sur ce serveur. Ajoute tes propres identifiants API Strava ci-dessus ou demande à ton administrateur de configurer l'application partagée.", "stravaConnect": "Connecter Strava", @@ -7048,7 +7048,7 @@ "stravaDisconnect": "Déconnecter", "stravaDisconnectTitle": "Déconnecter Strava ?", "stravaDisconnectDescription": "Les synchronisations futures s'arrêtent. Les activités déjà importées restent dans ton historique.", - "stravaOauthConnected": "Strava connecté — la première synchronisation démarre en arrière-plan.", + "stravaOauthConnected": "Strava connecté. La première synchronisation démarre en arrière-plan.", "stravaOauthFailed": "La connexion à Strava a échoué", "stravaOauthError": { "csrf1": "Le contrôle de sécurité a échoué car le cookie du navigateur était manquant. Relance la connexion dans le même navigateur.", @@ -7102,7 +7102,7 @@ }, "garminInfo": { "title": "Garmin", - "body": "Garmin n'a pas de connexion directe ici. Connecte-le via Apple Health (iOS) ou Google Health Connect (Android). Les scores propriétaires de Garmin — Body Battery, Training Load, statut VFC, VO₂ max — ne sont partagés par Garmin avec aucune des deux plateformes.", + "body": "Garmin n'a pas de connexion directe ici. Connecte-le via Apple Health (iOS) ou Google Health Connect (Android). Les scores propriétaires de Garmin (Body Battery, Training Load, statut VFC, VO₂ max) ne sont partagés par Garmin avec aucune des deux plateformes.", "docsLink": "Lire le guide" }, "glucoseReference": { @@ -7183,27 +7183,27 @@ "loadingStatus": "Chargement de l'état...", "systemStatusLoadError": "Échec du chargement de l'état du système.", "systemStatusRetry": "Réessayer", - "adminSettingsLoadError": "Échec du chargement des paramètres d'administration. Les commutateurs ci-dessous peuvent ne pas refléter l'état actuel — actualisez la page.", + "adminSettingsLoadError": "Échec du chargement des paramètres d'administration. Les commutateurs ci-dessous peuvent ne pas refléter l'état actuel : actualisez la page.", "hostMetrics": { "title": "Charge de l'hôte", "load1": "Charge (1 min)", "memUsedPercent": "Mémoire", "diskBusyPercent": "Disk I/O", "last2hours": "2 dernières heures", - "empty": "Échantillonnage démarré — les données apparaissent dans 1 à 2 minutes.", + "empty": "Échantillonnage démarré. Les données apparaissent dans 1 à 2 minutes.", "loadError": "Échec du chargement des métriques de l'hôte. Essayez d'actualiser la page." }, "aiServerKey": { "title": "Clé IA du serveur", "description": "Une clé de l'opérateur pour les comptes qui n'en ont pas configuré une.", - "byokHint": "La clé personnelle de l'utilisateur (BYOK, connexion ChatGPT ou fournisseur local) a toujours la priorité — la clé du serveur est la dernière étape de la chaîne de fournisseurs.", + "byokHint": "La clé personnelle de l'utilisateur (BYOK, connexion ChatGPT ou fournisseur local) a toujours la priorité ; la clé du serveur est la dernière étape de la chaîne de fournisseurs.", "consentHint": "Les requêtes via la clé du serveur nécessitent le consentement IA actif de l'utilisateur ; sans justificatif de consentement, rien n'est envoyé.", "baseUrlHint": "L'URL de base détermine l'API : une URL Anthropic telle que https://api.anthropic.com/v1 est reconnue, tout autre hôte est appelé via l'API compatible OpenAI.", "statusConfigured": "Configurée", "statusNotConfigured": "Non configurée", "keyLabel": "Clé API", "keyPlaceholder": "sk-...", - "keyPlaceholderSet": "Enregistrée ({preview}) — saisissez une nouvelle clé pour la remplacer", + "keyPlaceholderSet": "Enregistrée ({preview}). Saisissez une nouvelle clé pour la remplacer", "modelLabel": "Modèle", "baseUrlLabel": "URL de base", "save": "Enregistrer", @@ -7246,7 +7246,7 @@ "title": "Qualité des analyses", "loading": "Chargement du résumé des retours...", "loadError": "Échec du chargement du résumé de qualité des analyses. Essayez d'actualiser la page.", - "empty": "Aucun retour pour l'instant. L'agrégateur s'exécute chaque jour à 04:00 — dès que les utilisateurs évaluent les recommandations, les taux d'utilité apparaissent ici.", + "empty": "Aucun retour pour l'instant. L'agrégateur s'exécute chaque jour à 04:00 ; dès que les utilisateurs évaluent les recommandations, les taux d'utilité apparaissent ici.", "windowLabel": "{days} derniers jours", "generatedAtLabel": "Généré", "colSeverity": "Gravité", @@ -7261,7 +7261,7 @@ "title": "Retours sur le Coach", "loading": "Chargement du résumé des retours sur le Coach...", "loadError": "Échec du chargement du résumé des retours sur le Coach. Essayez d'actualiser la page.", - "empty": "Aucun retour sur le Coach pour l'instant. L'agrégateur s'exécute chaque jour à 04:00 — dès que les utilisateurs évaluent les réponses du Coach, les taux d'utilité apparaissent ici.", + "empty": "Aucun retour sur le Coach pour l'instant. L'agrégateur s'exécute chaque jour à 04:00 ; dès que les utilisateurs évaluent les réponses du Coach, les taux d'utilité apparaissent ici.", "windowLabel": "{days} derniers jours", "generatedAtLabel": "Généré", "colPromptVersion": "Version du prompt", @@ -7294,7 +7294,7 @@ "integrationWebPush": "Web Push", "offlineGeoLabel": "Données géographiques", "offlineGeoEnabled": "Hors ligne (GeoLite2)", - "offlineGeoFallback": "En ligne ({host}) — montez les bases GeoLite2 et définissez GEOLITE2_DIR", + "offlineGeoFallback": "En ligne ({host}) : montez les bases GeoLite2 et définissez GEOLITE2_DIR", "offlineGeoOff": "Désactivé", "offlineGeoChosen": "En ligne ({host})", "apiGlobal": "Autoriser les points de terminaison d'API et les jetons d'API.", @@ -7331,7 +7331,7 @@ "webPushVapidGenerating": "Génération…", "webPushVapidGenerated": "Clés VAPID générées. Enregistrez le sujet pour terminer.", "webPushVapidGenerateFailed": "Impossible de générer les clés VAPID.", - "webPushVapidGenerateConfirm": "Les clés VAPID sont déjà configurées. Générer une nouvelle paire invalide tous les abonnements push du navigateur — chaque appareil doit se réabonner. Continuer ?", + "webPushVapidGenerateConfirm": "Les clés VAPID sont déjà configurées. Générer une nouvelle paire invalide tous les abonnements push du navigateur : chaque appareil doit se réabonner. Continuer ?", "webPushVapidGenerateConfirmTitle": "Régénérer les clés VAPID ?", "webPushVapidRegenerate": "Régénérer", "configured": "Configuré", @@ -7387,7 +7387,7 @@ "createdToast": "Invitation créée", "createError": "Impossible de créer l'invitation.", "tokenTitle": "Lien d'invitation", - "tokenOnceHint": "Copiable uniquement maintenant — copiez le lien ou faites scanner le code QR.", + "tokenOnceHint": "Copiable uniquement maintenant : copiez le lien ou faites scanner le code QR.", "hashExplainer": "Seul un hachage du lien est stocké : il ne pourra plus être affiché. En cas de perte, révoquez l'invitation et créez-en une nouvelle.", "copyLink": "Copier le lien", "copiedToast": "Lien copié", @@ -7449,7 +7449,7 @@ "tokenName": "Nom", "tokenPermissions": "Autorisations", "tokenPermissionAll": "Tout", - "tokenPermissionAllTooltip": "Autorisation joker — ce jeton peut appeler toutes les routes de l'API.", + "tokenPermissionAllTooltip": "Autorisation joker : ce jeton peut appeler toutes les routes de l'API.", "tokenStatus": "Statut", "tokenLastUsed": "Dernière utilisation", "tokenCreated": "Créé", @@ -7627,7 +7627,7 @@ "app-logs": { "title": "Journaux de l'app", "subtitle": "Affichez les wide-events structurés les plus récents émis par ce processus.", - "processNote": "Seuls les journaux du processus de l'app sont affichés — ceux du processus worker vont vers Loki lorsque cette intégration est configurée.", + "processNote": "Seuls les journaux du processus de l'app sont affichés ; ceux du processus worker vont vers Loki lorsque cette intégration est configurée.", "filterTraceId": "ID de trace", "filterAction": "L'action contient…", "filterLevel": "Niveau", @@ -7662,7 +7662,7 @@ "loading": "Chargement des sauvegardes...", "loadError": "Échec du chargement des sauvegardes.", "emptyTitle": "Aucune sauvegarde pour l'instant", - "emptyDescription": "Les sauvegardes s'exécutent automatiquement chaque dimanche à 03:00 — ou lancez-en une maintenant pour créer le premier instantané.", + "emptyDescription": "Les sauvegardes s'exécutent automatiquement chaque dimanche à 03:00, ou lancez-en une maintenant pour créer le premier instantané.", "colUser": "Utilisateur", "colType": "Type", "typeWeeklyAuto": "Hebdomadaire (auto)", @@ -7698,11 +7698,11 @@ "restoreTitle": "Restaurer à partir d'une sauvegarde", "restoreDescription": "Cette action remplacera TOUTES les données actuelles de {username} par l'instantané du {when}. Les mesures, médicaments, événements de prise, entrées d'humeur, canaux de notification, abonnements push et suppressions Telegram en file d'attente existants seront supprimés.", "restoreInstanceSettingsLabel": "Restaurer aussi les paramètres de l'instance", - "restoreInstanceSettingsHint": "Inscription, exigence MFA, langue par défaut, disponibilité des modules, configuration des notifications et de l'IA — repris de l'instantané et appliqués à tout le monde sur cette installation. Laissez décoché pour ne restaurer que ce compte.", + "restoreInstanceSettingsHint": "Inscription, exigence MFA, langue par défaut, disponibilité des modules, configuration des notifications et de l'IA : repris de l'instantané et appliqués à tout le monde sur cette installation. Laissez décoché pour ne restaurer que ce compte.", "restorePromptLabel": "Tapez RESTORE pour continuer", "previewTitle": "Contenu de la sauvegarde", "previewLoading": "Lecture du contenu…", - "previewUnavailable": "Le contenu n'a pas pu être lu — la restauration reste possible.", + "previewUnavailable": "Le contenu n'a pas pu être lu, mais la restauration reste possible.", "previewStillReading": "Cette sauvegarde a été créée par une version antérieure, son contenu est donc lu en entier, ce qui prend un moment pour un gros dossier. Rouvrez cette fenêtre dans quelques minutes pour le voir. La restauration n'en dépend pas.", "previewEmpty": "Le fichier ne contient aucun enregistrement.", "previewOther": "Autres enregistrements", @@ -7745,7 +7745,7 @@ "restoreSkippedMedicationTarget": "Analyte cible d'un médicament", "restoreSkippedScheduleRevisionLink": "Succession des périodes de schéma", "restoreSkippedAccountSetting": "Réglage du compte", - "restoreMissingTitle": "Restauration refusée — le fichier est incomplet", + "restoreMissingTitle": "Restauration refusée : le fichier est incomplet", "restoreMissingDescription": "Le manifeste du fichier indique qu'il contient la section ci-dessous, et il ne la contient pas. Rien n'a été modifié : une restauration remplace toute une classe d'enregistrements, une section absente l'aurait donc vidée.", "restoreMissingRemedy": "Utilise une sauvegarde de reprise après sinistre, ou réexporte le compte et téléverse le nouveau fichier. Une section que le manifeste déclare omise est autre chose et se restaure normalement.", "restoreMissingDocuments": "Documents", @@ -7935,7 +7935,7 @@ "centralCodex": { "title": "Connexion IA partagée", "description": "Reliez un compte ChatGPT connecté que chaque utilisateur de ce serveur peut activer pour les fonctions IA.", - "honesty": "Il s'agit d'un unique compte IA partagé et connecté, pas d'une clé d'API. Chaque personne qui l'active envoie ses requêtes par ce biais : les limites horaires et hebdomadaires du compte sont donc partagées entre elles, et ces mêmes limites alimentent déjà le Coach. Les fournisseurs par abonnement peuvent utiliser le contenu pour améliorer leurs modèles et aucun accord de traitement des données ne le couvre — ce n'est donc jamais l'option par défaut et cela reste après les fournisseurs sans entraînement pour la lecture de documents. Ne reliez qu'un compte que vous êtes prêt à partager ainsi.", + "honesty": "Il s'agit d'un unique compte IA partagé et connecté, pas d'une clé d'API. Chaque personne qui l'active envoie ses requêtes par ce biais : les limites horaires et hebdomadaires du compte sont donc partagées entre elles, et ces mêmes limites alimentent déjà le Coach. Les fournisseurs par abonnement peuvent utiliser le contenu pour améliorer leurs modèles et aucun accord de traitement des données ne le couvre. Ce n'est donc jamais l'option par défaut et cela reste après les fournisseurs sans entraînement pour la lecture de documents. Ne reliez qu'un compte que vous êtes prêt à partager ainsi.", "statusConnected": "Connecté", "statusDisconnected": "Non connecté", "statusExpired": "Expiré", @@ -7947,7 +7947,7 @@ "connectedSince": "Connecté depuis le {when}", "connected": "Connexion IA partagée reliée", "disconnected": "Connexion IA partagée supprimée", - "error": "Une erreur s'est produite — veuillez réessayer" + "error": "Une erreur s'est produite. Veuillez réessayer" }, "failingJobs": { "title": "Tâches en arrière-plan", @@ -8276,7 +8276,7 @@ }, "selfContextComplete": { "title": "Auto-déclaration à jour", - "description": "Les quatre champs de l’auto-déclaration sont remplis — le Coach connaît votre contexte." + "description": "Les quatre champs de l’auto-déclaration sont remplis : le Coach connaît votre contexte." }, "sleepLog7": { "title": "Journal de sommeil pendant 7 jours", @@ -8298,7 +8298,7 @@ }, "hiddenCard": { "title": "Réussite cachée", - "description": "Continuez à suivre — vous pourriez bien tomber dessus.", + "description": "Continuez à suivre, vous pourriez bien tomber dessus.", "ariaLabel": "Réussite cachée verrouillée" }, "hiddenUnlockToast": { @@ -8307,7 +8307,7 @@ "dashboardCard": { "title": "Débloqués récemment", "viewAll": "Tout voir", - "empty": "Pas encore de réussites — continuez à suivre pour débloquer la première." + "empty": "Pas encore de réussites. Continuez à suivre pour débloquer la première." } }, "notifications": { @@ -8490,7 +8490,7 @@ } }, "edit": { - "title": "Modifier la plage cible — {metric}", + "title": "Modifier la plage cible : {metric}", "description": "Ajuste la plage cible utilisée dans les graphiques, les insights et le rapport médical. Valeurs en {unit}.", "derivedHint": "Cette carte est dérivée d’autres métriques. Modifie plutôt les objectifs sous-jacents (p. ex. tension ou poids).", "minLabel": "Min", @@ -8522,11 +8522,11 @@ "aboveTarget": "{delta} {unit} au-dessus de la plage", "belowTarget": "{delta} {unit} en dessous de la plage", "diastolic": "Diastolique", - "glucoseFasting": "Glycémie — à jeun", - "glucosePostprandial": "Glycémie — postprandiale", - "glucoseRandom": "Glycémie — indifférente", - "glucoseBedtime": "Glycémie — avant le coucher", - "glucoseUnspecified": "Glycémie — non précisée", + "glucoseFasting": "Glycémie (à jeun)", + "glucosePostprandial": "Glycémie (postprandiale)", + "glucoseRandom": "Glycémie (indifférente)", + "glucoseBedtime": "Glycémie (avant le coucher)", + "glucoseUnspecified": "Glycémie (non précisée)", "status": { "underweight": "Insuffisance pondérale", "normal": "Normal", @@ -8612,7 +8612,7 @@ "askMedicationName": "Indique le médicament, p. ex. pris Ramipril.", "medicationNotFoundExact": "Médicament introuvable. Envoie le nom exactement tel qu’il apparaît dans HealthLog.", "helpHeader": "Commandes disponibles :", - "helpBody": "/help — afficher cette aide\n/add — enregistrer une prise\n/start — démarrer le bot\n\nCommandes texte :\ntaken <nom> — confirmer une prise\n\nBoutons dans les rappels :\n• Pris — confirmer la prise\n• 🕐 1h / 🕐 3h — reporter le rappel\n• ⏭ Ignorer — ignorer la prise\n• ✓ Confirmer — confirmer une prise manquée", + "helpBody": "/help : afficher cette aide\n/add : enregistrer une prise\n/start : démarrer le bot\n\nCommandes texte :\ntaken <nom> : confirmer une prise\n\nBoutons dans les rappels :\n• Pris : confirmer la prise\n• 🕐 1h / 🕐 3h : reporter le rappel\n• ⏭ Ignorer : ignorer la prise\n• ✓ Confirmer : confirmer une prise manquée", "measureValuePrompt": "Répondez avec la valeur pour l’enregistrer (facultatif).", "buttonMeasureValue": "Valeur…", "measureValueSaved": "Mesure enregistrée.", @@ -8637,9 +8637,9 @@ }, "lowStockReminders": { "title": "Stock faible : {medName}", - "bodyToday": "{medName} : {units} unités restantes — moins d’un jour de réserve.", - "bodyReorder": "{medName} : {units} unités restantes. Le stock sera épuisé vers le {runsOutOn} — recommandez avant le {reorderBy}.", - "bodyLastDose": "{medName} : {units} unités restantes — environ votre dernière dose. Le stock sera épuisé vers le {runsOutOn}.", + "bodyToday": "{medName} : {units} unités restantes, moins d’un jour de réserve.", + "bodyReorder": "{medName} : {units} unités restantes. Le stock sera épuisé vers le {runsOutOn}, recommandez avant le {reorderBy}.", + "bodyLastDose": "{medName} : {units} unités restantes, environ votre dernière dose. Le stock sera épuisé vers le {runsOutOn}.", "bodyExpired": "{medName} : plus de stock utilisable. {units} unités sont marquées périmées.", "bodyAsNeeded": "{medName} : plus que {units} unités. Recommandez avant d’avoir besoin de la prochaine dose." }, @@ -8666,11 +8666,11 @@ "questionConditions": "Avez-vous des maladies chroniques que le Coach devrait connaître ?", "questionFocus": "Y a-t-il quelque chose de précis auquel le Coach devrait veiller ?", "questionAllergies": "Avez-vous des allergies ou des intolérances ?", - "questionAboutMe": "Envie de parler un peu de vous au Coach — habitudes, objectifs, contexte ?" + "questionAboutMe": "Envie de parler un peu de vous au Coach (habitudes, objectifs, contexte) ?" }, "clinicianView": { "title": "Dossier de santé partagé", - "period": "Période couverte : {start} – {end}", + "period": "Période couverte : {start}–{end}", "expires": "Ce lien expire le {date}.", "provenance": "Il s'agit d'un résumé en lecture seule partagé par la personne concernée, exporté de ses données HealthLog auto-enregistrées. Les valeurs sont auto-déclarées et peuvent inclure des mesures synchronisées depuis des appareils ; à considérer comme rapportées par le patient, non comme un examen clinique.", "labs": "Valeurs de laboratoire", @@ -8694,7 +8694,7 @@ "strain": "Score de charge", "score": "Score de bien-être" }, - "footer": "Partagé depuis HealthLog — un suivi de santé auto-hébergé.", + "footer": "Partagé depuis HealthLog, un suivi de santé auto-hébergé.", "unlock": { "title": "Saisir la phrase secrète", "description": "Ce dossier de santé partagé est protégé. Saisissez la phrase secrète qui vous a été communiquée pour le consulter.", @@ -8909,8 +8909,8 @@ "ariaUnknown": "Pas encore de cycle actif", "caption": "de ton cycle", "firstPeriodCta": "Enregistrer mes premières règles", - "periodOverdue": "Tes règles arrivent plus tard que d’habitude — le compteur de jours est en pause jusqu’à ce que les prochaines règles soient enregistrées.", - "periodOverdueDays": "Tes règles arrivent {days} jours plus tard que d’habitude — le compteur de jours est en pause jusqu’à ce que les prochaines règles soient enregistrées.", + "periodOverdue": "Tes règles arrivent plus tard que d’habitude. Le compteur de jours est en pause jusqu’à ce que les prochaines règles soient enregistrées.", + "periodOverdueDays": "Tes règles arrivent {days} jours plus tard que d’habitude. Le compteur de jours est en pause jusqu’à ce que les prochaines règles soient enregistrées.", "logPeriodCta": "Enregistrer les règles" }, "calendar": { @@ -8922,7 +8922,7 @@ "prevMonth": "Mois précédent", "nextMonth": "Mois suivant", "loading": "Chargement de ton calendrier…", - "learning": "Nous apprenons ton cycle — enregistre au moins trois cycles complets et la fenêtre fertile, l'ovulation et les phases se compléteront. D'ici là, le calendrier n'affiche que ce que tu as enregistré.", + "learning": "Nous apprenons ton cycle : enregistre au moins trois cycles complets et la fenêtre fertile, l'ovulation et les phases se compléteront. D'ici là, le calendrier n'affiche que ce que tu as enregistré.", "legendSymptom": "Symptômes", "legendOvulationConfirmed": "Ovulation confirmée", "flowSpotting": "spotting", @@ -8935,7 +8935,7 @@ "predictions": { "title": "Ce qui arrive ensuite", "nextPeriod": "Prochaines règles", - "nextPeriodWindow": "{low} – {high}", + "nextPeriodWindow": "{low}–{high}", "fertileWindow": "Fenêtre fertile", "ovulation": "Ovulation estimée", "confidenceHigh": "Élevée", @@ -8944,7 +8944,7 @@ "stillLearning": "Encore en apprentissage", "stillLearningBody": "Enregistre au moins trois cycles complets et tes prévisions s'affineront. D'ici là, ceci reste une estimation approximative.", "rawMode": "Prévision désactivée", - "rawModeBody": "Tu as désactivé les prévisions — seules tes données enregistrées sont affichées, sans prévision.", + "rawModeBody": "Tu as désactivé les prévisions : seules tes données enregistrées sont affichées, sans prévision.", "none": "Pas encore de prévision. Enregistre des règles pour commencer.", "ovulationConfirmed": "Ovulation (confirmée)" }, @@ -8977,7 +8977,7 @@ "symptoms": "Symptômes", "temperature": "Température basale", "temperatureDisturbed": "Marquer la mesure comme perturbée", - "temperatureDisturbedHint": "Fièvre, maladie, alcool ou mesure tardive — exclue de l'évaluation de la température.", + "temperatureDisturbedHint": "Fièvre, maladie, alcool ou mesure tardive : exclue de l'évaluation de la température.", "ovulationTest": "Test d'ovulation", "mucus": "Glaire cervicale", "cervix": "Col de l'utérus", @@ -9073,15 +9073,15 @@ "fieldInfo": { "bbt": "Ta température au repos, prise dès le matin avant de te lever. Elle augmente légèrement (environ 0,2–0,3 °C) après l'ovulation.", "bbtLabel": "Qu'est-ce que la température basale ?", - "mucus": "Les pertes vaginales évoluent au fil du cycle — de sèches ou collantes à crémeuses, puis aqueuses et comme du blanc d'œuf autour des jours les plus fertiles.", + "mucus": "Les pertes vaginales évoluent au fil du cycle, de sèches ou collantes à crémeuses, puis aqueuses et comme du blanc d'œuf autour des jours les plus fertiles.", "mucusLabel": "Qu'est-ce que la glaire cervicale ?", - "ovulationTest": "Un test urinaire à domicile qui détecte le pic de LH — la montée hormonale environ 24–36 h avant l'ovulation. Un test positif signale la période la plus fertile.", + "ovulationTest": "Un test urinaire à domicile qui détecte le pic de LH, la montée hormonale environ 24–36 h avant l'ovulation. Un test positif signale la période la plus fertile.", "ovulationTestLabel": "Qu'est-ce qu'un test d'ovulation ?", "spotting": "Léger saignement en dehors des règles.", "spottingLabel": "Qu'est-ce que le spotting entre les règles ?", "pregnancyTest": "Résultat d'un test de grossesse (hCG) à domicile.", "pregnancyTestLabel": "Qu'est-ce qu'un test de grossesse ?", - "progesteroneTest": "Un test confirmant que l'ovulation a eu lieu — la progestérone augmente ensuite.", + "progesteroneTest": "Un test confirmant que l'ovulation a eu lieu : la progestérone augmente ensuite.", "progesteroneTestLabel": "Qu'est-ce qu'un test de progestérone ?", "intercourse": "Si un rapport sexuel a eu lieu ce jour-là.", "intercourseLabel": "Que suit le rapport ?", @@ -9134,14 +9134,14 @@ "postpone": { "menuItem": "Reporter…", "title": "Reporter l'échéance", - "description": "Ne déplace que l'échéance actuelle — le rythme régulier reste inchangé.", + "description": "Ne déplace que l'échéance actuelle ; le rythme régulier reste inchangé.", "chip": "+{days} jours", "dateLabel": "Nouvelle date", "confirm": "Reporter" }, "skip": { "heading": "Passer cette échéance", - "explainer": "Enregistré honnêtement comme passé — pas comme fait. L'intervalle redémarre à partir d'aujourd'hui.", + "explainer": "Enregistré honnêtement comme passé, pas comme fait. L'intervalle redémarre à partir d'aujourd'hui.", "action": "Passer", "confirmTitle": "Passer cette échéance ?" }, @@ -9282,7 +9282,7 @@ "localOcr": { "heading": "Lire les scans sur cet appareil", "description": "Lit la photo sur votre appareil et n'envoie que le texte extrait à votre fournisseur.", - "detail": "Utile quand votre fournisseur d'IA ne lit pas les images. Moins précis — vérifiez chaque valeur avant d'enregistrer." + "detail": "Utile quand votre fournisseur d'IA ne lit pas les images. Moins précis : vérifiez chaque valeur avant d'enregistrer." }, "sort": { "heading": "Tri", @@ -9344,7 +9344,7 @@ "emptyDescription": "Ajoutez une valeur pour suivre ce biomarqueur dans le temps.", "title": "Biomarqueur", "genericDescription": "Un biomarqueur biologique que vous suivez. Ajoutez des mesures pour observer son évolution par rapport à la plage de référence.", - "valuesTitle": "{marker} — toutes les valeurs", + "valuesTitle": "{marker} : toutes les valeurs", "valuesDescription": "Chaque mesure de ce biomarqueur. Modifiez ou supprimez une entrée directement.", "backToMarker": "Retour à {marker}", "latestResult": "Dernier résultat" @@ -9364,7 +9364,7 @@ }, "biomarker": { "manageTitle": "Biomarqueurs", - "managerDescription": "Définissez un marqueur une fois — son unité et sa plage sont réutilisées pour chaque mesure.", + "managerDescription": "Définissez un marqueur une fois : son unité et sa plage sont réutilisées pour chaque mesure.", "define": "Définir", "defineFirst": "Définir votre premier biomarqueur", "defineTitle": "Définir un biomarqueur", @@ -9383,7 +9383,7 @@ "form": { "seedLabel": "Partir d'un marqueur courant", "seedPlaceholder": "Choisir un marqueur (facultatif)", - "seedHint": "En choisir un remplit les champs — ajustez la plage à votre laboratoire.", + "seedHint": "En choisir un remplit les champs. Ajustez la plage à votre laboratoire.", "name": "Nom", "namePlaceholder": "ex. Cholestérol LDL", "unit": "Unité", @@ -9397,7 +9397,7 @@ "upperPlaceholder": "Borne supérieure", "context": "Contexte", "contextPlaceholder": "Note facultative sur ce marqueur", - "rangeHint": "Les deux bornes sont facultatives — laissez-en une vide pour une plage ouverte (ex. LDL < 116).", + "rangeHint": "Les deux bornes sont facultatives. Laissez-en une vide pour une plage ouverte (ex. LDL < 116).", "requiredError": "Le nom et l'unité sont requis.", "rangeOrderError": "La borne inférieure ne doit pas dépasser la borne supérieure.", "save": "Enregistrer le biomarqueur", @@ -9462,17 +9462,17 @@ "tsh": "La TSH (hormone thyréostimulante) est libérée par l'hypophyse pour signaler à la thyroïde de produire ses hormones, et elle s'ajuste à la hausse ou à la baisse pour les maintenir en équilibre. Grâce à cette boucle de rétroaction, la TSH est le dépistage de première intention le plus sensible de la fonction thyroïdienne : elle bouge généralement avant que les hormones thyroïdiennes elles-mêmes ne dévient. Une valeur élevée ou abaissée oriente vers une thyroïde hypo ou hyperactive et conduit habituellement à doser directement les hormones thyroïdiennes. La grossesse et l'âge décalent la plage attendue.", "ft3": "La T3 libre (triiodothyronine) est la forme non liée et biologiquement active de l'hormone thyroïdienne la plus puissante, la fraction disponible pour agir sur les tissus. La majeure partie de la T3 circulante est liée à des protéines de transport et inactive ; la part libre reflète donc la disponibilité réelle de l'hormone. Elle est mesurée pour caractériser la fonction thyroïdienne, surtout avec la TSH et la T4 libre lorsque les résultats sont incertains. Les taux dépendent fortement de la technique de dosage et se lisent dans leur contexte clinique.", "ft4": "La T4 libre (thyroxine) est la forme non liée de la principale hormone que la thyroïde libère dans le sang ; elle sert de réservoir que les tissus convertissent en T3 plus active selon les besoins. La fraction libre reflète ce qui est réellement disponible pour le corps, indépendamment du taux de protéines de transport. On la mesure généralement avec la TSH pour distinguer un problème de la thyroïde d'un trouble de la signalisation hypophysaire. La grossesse et certains médicaments peuvent la décaler.", - "ferritin": "La ferritine est la principale protéine de stockage du fer de l'organisme, et son taux sanguin reflète globalement les réserves totales en fer. Une valeur basse oriente vers des réserves épuisées, tandis qu'une valeur élevée peut traduire une surcharge en fer — ou simplement une inflammation, car la ferritine monte aussi comme protéine de la phase aiguë. Pour cette raison, elle s'interprète souvent avec d'autres marqueurs du fer et des signes d'inflammation. C'est l'une des mesures centrales pour évaluer le statut en fer.", - "transferrin-saturation": "Le coefficient de saturation de la transferrine est le pourcentage de transferrine — la protéine qui transporte le fer dans le sang — actuellement chargé en fer. Il relie la quantité de fer en circulation à la capacité de transport de l'organisme, offrant un instantané de la disponibilité du fer qui complète la vue des réserves donnée par la ferritine. Une saturation basse suggère un fer en quantité insuffisante, tandis qu'une valeur élevée peut indiquer une surcharge. Elle se lit avec la ferritine et le bilan martial complet.", + "ferritin": "La ferritine est la principale protéine de stockage du fer de l'organisme, et son taux sanguin reflète globalement les réserves totales en fer. Une valeur basse oriente vers des réserves épuisées, tandis qu'une valeur élevée peut traduire une surcharge en fer, ou simplement une inflammation, car la ferritine monte aussi comme protéine de la phase aiguë. Pour cette raison, elle s'interprète souvent avec d'autres marqueurs du fer et des signes d'inflammation. C'est l'une des mesures centrales pour évaluer le statut en fer.", + "transferrin-saturation": "Le coefficient de saturation de la transferrine est le pourcentage de transferrine (la protéine qui transporte le fer dans le sang) actuellement chargé en fer. Il relie la quantité de fer en circulation à la capacité de transport de l'organisme, offrant un instantané de la disponibilité du fer qui complète la vue des réserves donnée par la ferritine. Une saturation basse suggère un fer en quantité insuffisante, tandis qu'une valeur élevée peut indiquer une surcharge. Elle se lit avec la ferritine et le bilan martial complet.", "vitamin-d": "La vitamine D se mesure sous forme de 25-hydroxyvitamine D, la forme de stockage circulante et le marqueur standard du statut global en vitamine D. Le corps la fabrique dans la peau exposée à la lumière du soleil et en absorbe une partie par l'alimentation ; elle soutient l'équilibre du calcium, la santé osseuse et la fonction immunitaire. Les taux varient selon la saison, la latitude, le teint de peau et la supplémentation. Elle est suivie pour estimer dans le temps si les réserves sont suffisantes.", - "vitamin-b12": "La vitamine B12 (cobalamine) est une vitamine essentielle, obtenue surtout à partir d'aliments d'origine animale et stockée en grande partie dans le foie. Elle est nécessaire à la formation des globules rouges, à la synthèse de l'ADN et à la santé du système nerveux. Une carence prolongée — par faible apport ou absorption altérée — peut entraîner une anémie et des symptômes neurologiques. Elle est mesurée pour évaluer le statut nutritionnel, en particulier lorsque l'apport ou l'absorption peuvent être limités.", + "vitamin-b12": "La vitamine B12 (cobalamine) est une vitamine essentielle, obtenue surtout à partir d'aliments d'origine animale et stockée en grande partie dans le foie. Elle est nécessaire à la formation des globules rouges, à la synthèse de l'ADN et à la santé du système nerveux. Une carence prolongée, par faible apport ou absorption altérée, peut entraîner une anémie et des symptômes neurologiques. Elle est mesurée pour évaluer le statut nutritionnel, en particulier lorsque l'apport ou l'absorption peuvent être limités.", "folate": "Le folate (vitamine B9) est une vitamine du groupe B présente dans les légumes à feuilles vertes, les légumineuses et les aliments enrichis, centrale pour la formation des globules rouges et la synthèse de l'ADN. Il travaille en étroite collaboration avec la vitamine B12, et une carence de l'un ou de l'autre peut produire un type d'anémie similaire. Un apport suffisant en folate est particulièrement important autour du début de la grossesse pour un développement sain du fœtus. Il est mesuré pour évaluer le statut nutritionnel et la cause de certaines anémies.", "hs-crp": "La CRP ultrasensible mesure la protéine C-réactive, un marqueur que le foie libère en réponse à l'inflammation, avec une technique affinée pour détecter les faibles concentrations pertinentes pour le risque cardiovasculaire. Contrairement à la CRP standard utilisée pour les infections aiguës, la version ultrasensible capte l'inflammation discrète et chronique liée à la maladie vasculaire. Comme toute infection ou blessure récente peut l'élever, elle s'interprète à distance d'une affection aiguë et se confirme souvent par un prélèvement répété. Elle se lit comme un facteur parmi d'autres du risque cardiovasculaire global.", "creatinine": "La créatinine est un déchet du métabolisme musculaire normal que les reins filtrent du sang à un rythme assez constant. Comme la production est relativement stable, son taux sanguin sert de jauge pratique de la capacité des reins à éliminer les déchets. Les valeurs dépendent aussi de la masse musculaire, de l'hydratation et de l'alimentation ; on les interprète donc généralement avec le débit de filtration estimé. C'est un marqueur central de la fonction rénale.", "egfr": "Le DFG estimé (débit de filtration glomérulaire) estime la quantité de sang que les reins filtrent chaque minute, calculée à partir de la créatinine, de l'âge et du sexe. Il traduit une valeur brute de créatinine en une mesure plus directement interprétable de la fonction rénale. Un DFG qui baisse au fil du temps est le principal moyen de classer et de suivre les atteintes rénales chroniques. En tant qu'estimation, il se lit comme une tendance plutôt que comme un chiffre exact unique.", "alt": "L'ALAT (alanine aminotransférase) est une enzyme concentrée dans les cellules du foie, libérée dans le sang lorsque ces cellules sont stressées ou endommagées. Comme elle est relativement spécifique du foie, c'est l'un des principaux marqueurs pour détecter une atteinte ou une inflammation hépatique. Les valeurs peuvent monter avec la stéatose hépatique, une hépatite virale, l'alcool ou certains médicaments. On la lit généralement avec l'ASAT et les autres marqueurs du bilan hépatique.", "ast": "L'ASAT (aspartate aminotransférase) est une enzyme présente dans le foie, mais aussi dans le muscle, le cœur et les globules rouges, libérée lorsque l'un de ces tissus est lésé. Comme elle est moins spécifique du foie que l'ALAT, les deux s'interprètent ensemble, et leur rapport peut orienter sur l'origine et la nature du problème. Un exercice intense ou une lésion musculaire peuvent l'élever indépendamment du foie. C'est l'une des enzymes standard du bilan hépatique.", - "ggt": "La GGT (gamma-glutamyl transférase) est une enzyme du foie et des voies biliaires qui monte en particulier lorsque l'écoulement de la bile est entravé ou en cas d'exposition à l'alcool. Elle sert souvent à clarifier pourquoi un autre marqueur hépatique est élevé — par exemple, pour distinguer une origine hépatique ou biliaire. Elle est sensible mais peu spécifique ; on la lit donc dans le contexte du reste du bilan hépatique. C'est l'un des marqueurs utilisés pour évaluer la santé du foie et des voies biliaires.", + "ggt": "La GGT (gamma-glutamyl transférase) est une enzyme du foie et des voies biliaires qui monte en particulier lorsque l'écoulement de la bile est entravé ou en cas d'exposition à l'alcool. Elle sert souvent à clarifier pourquoi un autre marqueur hépatique est élevé, par exemple pour distinguer une origine hépatique ou biliaire. Elle est sensible mais peu spécifique ; on la lit donc dans le contexte du reste du bilan hépatique. C'est l'un des marqueurs utilisés pour évaluer la santé du foie et des voies biliaires.", "sodium": "Le sodium est le principal électrolyte du liquide situé à l'extérieur des cellules et le moteur essentiel de l'équilibre hydrique et du volume sanguin. Le corps le régule étroitement par la soif, les hormones et les reins, de sorte que son taux sanguin reflète davantage l'équilibre entre l'eau et le sel que le seul apport alimentaire. Des valeurs anormales signalent généralement un trouble de l'équilibre de l'eau plutôt que du sodium lui-même. C'est un élément central du bilan métabolique de base et des électrolytes.", "potassium": "Le potassium est le principal électrolyte à l'intérieur des cellules et il est essentiel à la transmission nerveuse et au rythme régulier du muscle cardiaque. Son taux sanguin est maintenu dans une plage étroite par les reins et les signaux hormonaux, car des valeurs hautes comme basses peuvent perturber l'activité électrique du cœur. Les taux peuvent être influencés par la fonction rénale, l'hydratation et plusieurs médicaments courants. C'est une mesure centrale du bilan des électrolytes.", "hemoglobin": "L'hémoglobine est la protéine contenant du fer des globules rouges, qui fixe l'oxygène dans les poumons et le transporte vers les tissus. Sa concentration est la principale mesure de la capacité du sang à transporter l'oxygène et le marqueur central pour détecter l'anémie. Des valeurs basses peuvent refléter une perte de sang, un manque de fer ou de vitamines, ou une production réduite, tandis que des valeurs élevées peuvent suivre une déshydratation ou des conditions pauvres en oxygène. C'est une pierre angulaire de la numération formule sanguine.", @@ -9481,8 +9481,8 @@ "platelets": "Les plaquettes sont de petits fragments cellulaires du sang qui s'agrègent et forment le bouchon initial arrêtant le saignement d'un vaisseau lésé. Leur nombre reflète l'équilibre entre la production dans la moelle osseuse et la consommation ou la destruction. Un nombre bas peut accroître la tendance au saignement, tandis qu'un nombre élevé peut suivre une inflammation ou d'autres stimuli. Elles font partie de la numération formule sanguine et constituent une jauge de base de la capacité de coagulation.", "apob": "L'apolipoprotéine B est la protéine structurale portée par chacune des particules de lipoprotéines athérogènes ; la doser revient donc à compter directement ces particules plutôt que le cholestérol qu'elles transportent. Comme il y a une molécule d'ApoB sur chaque particule de LDL, de VLDL et apparentée, elle peut capter un risque cardiovasculaire qu'une valeur de cholestérol LDL manque, en particulier lorsque le nombre de particules et leur teneur en cholestérol divergent. C'est pourquoi elle est de plus en plus utilisée pour affiner l'évaluation du risque fondée sur les lipides. Elle s'interprète avec le bilan lipidique habituel.", "lp-a": "La lipoprotéine(a) est une particule semblable au LDL avec une protéine supplémentaire attachée, dont le taux est en grande partie déterminé par la génétique et reste assez stable toute la vie. Une Lp(a) élevée est un facteur de risque indépendant et héréditaire de maladie cardiovasculaire et de rétrécissement de la valve aortique. Comme elle varie peu, on la mesure généralement une seule fois pour établir le risque à vie d'une personne, plutôt que de la suivre de façon répétée. Elle s'exprime en unités molaires et se lit dans le cadre du risque cardiovasculaire global.", - "fasting-insulin": "L'insuline à jeun est le taux d'insuline — l'hormone qui fait passer le glucose du sang vers les cellules — mesuré après un jeûne nocturne. Associée à la glycémie à jeun, elle aide à estimer la résistance à l'insuline, l'état dans lequel le corps a besoin de plus d'insuline pour maintenir le glucose dans sa plage. Une insuline à jeun élevée avec une glycémie normale peut être un signe précoce que cette compensation est en cours. Elle se lit dans le cadre d'un bilan de santé métabolique et non isolément.", - "omega-3-index": "L'indice oméga-3 est la part d'EPA et de DHA — les deux acides gras oméga-3 marins à longue chaîne — parmi les acides gras des membranes des globules rouges. Comme les globules rouges se renouvellent lentement, il reflète l'apport en oméga-3 sur le long terme plutôt qu'un repas récent. Un indice plus élevé a été associé, dans des études d'observation, à un risque cardiovasculaire moindre. Il est suivi comme un marqueur stable du statut en oméga-3, qui répond à l'alimentation sur plusieurs mois." + "fasting-insulin": "L'insuline à jeun est le taux d'insuline (l'hormone qui fait passer le glucose du sang vers les cellules) mesuré après un jeûne nocturne. Associée à la glycémie à jeun, elle aide à estimer la résistance à l'insuline, l'état dans lequel le corps a besoin de plus d'insuline pour maintenir le glucose dans sa plage. Une insuline à jeun élevée avec une glycémie normale peut être un signe précoce que cette compensation est en cours. Elle se lit dans le cadre d'un bilan de santé métabolique et non isolément.", + "omega-3-index": "L'indice oméga-3 est la part d'EPA et de DHA (les deux acides gras oméga-3 marins à longue chaîne) parmi les acides gras des membranes des globules rouges. Comme les globules rouges se renouvellent lentement, il reflète l'apport en oméga-3 sur le long terme plutôt qu'un repas récent. Un indice plus élevé a été associé, dans des études d'observation, à un risque cardiovasculaire moindre. Il est suivi comme un marqueur stable du statut en oméga-3, qui répond à l'alimentation sur plusieurs mois." }, "apob": "Apolipoprotéine B (ApoB)", "lp-a": "Lipoprotéine(a)", @@ -9500,7 +9500,7 @@ "acceptImageOnly": "JPEG, PNG ou WebP", "extracting": "Lecture de votre compte rendu…", "readingOnDevice": "Lecture sur votre appareil…", - "localModeHint": "Lu sur votre appareil, puis envoyé sous forme de texte. Moins précis — vérifiez chaque valeur.", + "localModeHint": "Lu sur votre appareil, puis envoyé sous forme de texte. Moins précis : vérifiez chaque valeur.", "rangeFromScan": "Valeurs de référence issues du scan", "rangeVerify": "Vérifiez les valeurs de référence", "reviewTitle": "Vérifier avant d'enregistrer", @@ -9515,12 +9515,12 @@ "dateLabel": "Date", "refLowLabel": "Référence basse", "refHighLabel": "Référence haute", - "newBiomarker": "Nouveau biomarqueur — sera créé", + "newBiomarker": "Nouveau biomarqueur, sera créé", "linksExisting": "Lié au {name} existant", "duplicateWarning": "Une valeur correspondante existe déjà", "lowConfidence": "Veuillez vérifier cette valeur", "lowConfidenceBadge": "Confiance faible", - "valueUnreadable": "Valeur illisible — saisissez-la manuellement", + "valueUnreadable": "Valeur illisible : saisissez-la manuellement", "saveSelected": "Enregistrer {count} sélectionnées", "discardAll": "Tout abandonner", "savedToast": "{count} résultats de laboratoire enregistrés", @@ -9903,7 +9903,7 @@ }, "correlation": { "title": "Comment cela s'est déroulé", - "learning": "Encore en apprentissage — enregistre quelques jours de plus pour voir des tendances ici.", + "learning": "Encore en apprentissage. Enregistre quelques jours de plus pour voir des tendances ici.", "preOnsetTitle": "Comment cela s'est annoncé", "preOnsetBody": "Signaux qui se sont écartés de ta base avant le début que tu as noté.", "nadirTitle": "Ce qui a changé", @@ -9930,7 +9930,7 @@ "countOne": "Tu as enregistré 1 épisode sur cette période.", "countOther": "Tu as enregistré {count} épisodes sur cette période.", "typicalGap": "Écart de récupération typique : {days} jours entre le mieux-être et la stabilisation de tes valeurs.", - "typicalGapWithDriver": "Écart de récupération typique : {days} jours – tu te sens généralement mieux avant que {vital} ne se stabilise.", + "typicalGapWithDriver": "Écart de récupération typique : {days} jours. Tu te sens généralement mieux avant que {vital} ne se stabilise.", "typicalGapLearning": "Encore quelques épisodes résolus et un écart de récupération typique apparaîtra ici.", "none": "Aucun épisode enregistré sur cette période.", "analyze": "Analyser l'écart de récupération" @@ -10004,7 +10004,7 @@ "dismiss": "Pas maintenant", "applied": "Ajouté", "dismissed": "Ignoré", - "failed": "Impossible d'ajouter — réessaie", + "failed": "Impossible d'ajouter. Réessaie", "checkup": { "title": "Ajouter un rappel d'examen ?" }, @@ -10032,9 +10032,9 @@ "reviewPrefix": "Point d'étape : {when}", "accept": "Adopter le plan", "decline": "Refuser", - "accepted": "Plan adopté — le Coach le gardera en tête.", + "accepted": "Plan adopté : le Coach le gardera en tête.", "declined": "Proposition refusée.", - "failed": "Échec de l'action — veuillez réessayer.", + "failed": "Échec de l'action. Veuillez réessayer.", "markMet": "Objectif atteint", "abandon": "Terminer le plan", "remove": "Supprimer", @@ -10056,7 +10056,7 @@ }, "refusal": { "outOfScope": "Je peux uniquement t'aider avec les données de santé de ton journal : mesures, médicaments, humeur, tendances. Je ne réponds pas aux questions en dehors de ce cadre.", - "promptInjection": "J'ai repéré des instructions qui cherchent à contourner mes consignes. Je suis le Coach HealthLog et je résume uniquement tes propres données de santé — reformule ta question dans ce cadre, s'il te plaît.", + "promptInjection": "J'ai repéré des instructions qui cherchent à contourner mes consignes. Je suis le Coach HealthLog et je résume uniquement tes propres données de santé. Reformule ta question dans ce cadre, s'il te plaît.", "conversationPoisoned": "Un message précédent de cette conversation contient des instructions qui cherchent à contourner mes consignes. Démarre une nouvelle conversation, s'il te plaît." }, "noRecordedData": "Aucune mesure n'est enregistrée pour ce que tu demandes, je ne peux donc te donner aucun chiffre. Dès que tu en auras saisi, repose-moi la question et je partirai de tes propres valeurs.", @@ -10307,7 +10307,7 @@ "2": "Très gênant", "3": "Extrêmement gênant" }, - "functionalOptionalHint": "Facultatif — tu peux envoyer sans répondre à cette question.", + "functionalOptionalHint": "Facultatif : tu peux envoyer sans répondre à cette question.", "result": { "title": "Ton résultat", "totalLabel": "Score total", @@ -10360,7 +10360,7 @@ "3": "Difficultés à s'endormir ou à rester endormi(e), ou dormir trop", "4": "Se sentir fatigué(e) ou avoir peu d'énergie", "5": "Avoir peu d'appétit ou manger trop", - "6": "Avoir une mauvaise opinion de soi-même — ou avoir le sentiment d'être nul(le) ou d'avoir déçu sa famille ou soi-même", + "6": "Avoir une mauvaise opinion de soi-même, ou avoir le sentiment d'être nul(le) ou d'avoir déçu sa famille ou soi-même", "7": "Avoir du mal à se concentrer, par exemple pour lire le journal ou regarder la télévision", "8": "Bouger ou parler si lentement que les autres ont pu le remarquer. Ou au contraire, être si agité(e) que vous avez bougé beaucoup plus que d'habitude", "9": "Penser qu'il vaudrait mieux mourir ou envisager de vous faire du mal d'une manière ou d'une autre" @@ -11186,7 +11186,7 @@ "genericDescription": "Une mesure que vous suivez. Ajoutez des valeurs pour la suivre dans le temps.", "emptyTitle": "Aucune valeur pour l'instant", "emptyDescription": "Ajoutez votre première valeur pour commencer à représenter cette mesure.", - "valuesTitle": "{metric} — toutes les valeurs", + "valuesTitle": "{metric} : toutes les valeurs", "valuesDescription": "Toutes les valeurs enregistrées pour cette mesure.", "backToMetric": "Retour à {metric}" } @@ -11233,7 +11233,7 @@ "lastAttemptReason": { "unitMismatch": "Les valeurs reçues ne correspondaient pas aux unités attendues par l'appli pour ces nutriments, elles n'ont donc pas pu être enregistrées.", "valueOutOfRange": "Les quantités reçues étaient supérieures à ce que l'appli peut raisonnablement enregistrer, elles n'ont donc pas pu être sauvegardées.", - "dayInvalid": "Les entrées portaient une date que le serveur n'a pas pu accepter. Cela peut arriver quand l'horloge ou le fuseau horaire du côté qui envoie les données est incorrect — cela vaut la peine de vérifier.", + "dayInvalid": "Les entrées portaient une date que le serveur n'a pas pu accepter. Cela peut arriver quand l'horloge ou le fuseau horaire du côté qui envoie les données est incorrect ; cela vaut la peine de vérifier.", "upsertFailed": "Ces entrées sont arrivées jusqu'au serveur, mais un problème de notre côté a empêché leur enregistrement. Tu n'as rien à faire.", "unknown": "Ces entrées sont arrivées mais n'ont pas pu être enregistrées." } @@ -11252,7 +11252,7 @@ "emptyTitle": "Aucune donnée de micronutriments synchronisée pour l'instant", "loadError": "Tes données de nutriments n'ont pas pu être chargées" }, - "sparseNote": "Une valeur basse ici signifie généralement un suivi partiel, pas une carence — les totaux journaliers Apple Health reflètent ce que vos applis ont enregistré, pas l'apport alimentaire total." + "sparseNote": "Une valeur basse ici signifie généralement un suivi partiel, pas une carence : les totaux journaliers Apple Health reflètent ce que vos applis ont enregistré, pas l'apport alimentaire total." }, "daily": { "line": { @@ -11279,7 +11279,7 @@ }, "syncIssue": { "title": "La synchronisation demande votre attention", - "body": "{integration} ne se synchronise pas — reconnecte-le pour garder tes données à jour." + "body": "{integration} ne se synchronise pas. Reconnecte-le pour garder tes données à jour." }, "coachCheckin": { "title": "Il est temps de revoir un plan", @@ -11291,10 +11291,10 @@ "tensionWindow": { "title": "Peut-être un peu de tension", "body": { - "morning": "Votre fréquence cardiaque est restée au-dessus de votre valeur de repos un bon moment ce matin alors que vous étiez au calme — peut-être un peu de tension.", - "afternoon": "Votre fréquence cardiaque est restée au-dessus de votre valeur de repos un bon moment cet après-midi alors que vous étiez au calme — peut-être un peu de tension.", - "evening": "Votre fréquence cardiaque est restée au-dessus de votre valeur de repos un bon moment ce soir alors que vous étiez au calme — peut-être un peu de tension.", - "night": "Votre fréquence cardiaque est restée au-dessus de votre valeur de repos un bon moment cette nuit alors que vous étiez au calme — peut-être un peu de tension." + "morning": "Votre fréquence cardiaque est restée au-dessus de votre valeur de repos un bon moment ce matin alors que vous étiez au calme, peut-être un peu de tension.", + "afternoon": "Votre fréquence cardiaque est restée au-dessus de votre valeur de repos un bon moment cet après-midi alors que vous étiez au calme, peut-être un peu de tension.", + "evening": "Votre fréquence cardiaque est restée au-dessus de votre valeur de repos un bon moment ce soir alors que vous étiez au calme, peut-être un peu de tension.", + "night": "Votre fréquence cardiaque est restée au-dessus de votre valeur de repos un bon moment cette nuit alors que vous étiez au calme, peut-être un peu de tension." } }, "ecgNewRecording": { @@ -11319,9 +11319,9 @@ }, "upcomingVisit": { "title": "Rendez-vous à venir", - "bodyToday": "{what} — aujourd'hui", - "bodyTomorrow": "{what} — demain", - "bodyDayAfterTomorrow": "{what} — après-demain" + "bodyToday": "{what}, aujourd'hui", + "bodyTomorrow": "{what}, demain", + "bodyDayAfterTomorrow": "{what}, après-demain" } }, "action": { @@ -11340,7 +11340,7 @@ "scoreLabel": "Score de santé", "deltaVsBaseline": "{delta} par rapport à ta référence", "deltaFlat": "Conforme à ta référence", - "sleepPending": "Le sommeil de la nuit dernière n'est pas encore arrivé — la lecture du jour est provisoire.", + "sleepPending": "Le sommeil de la nuit dernière n'est pas encore arrivé : la lecture du jour est provisoire.", "worthALook": "À regarder", "allClear": "Rien ne requiert ton attention aujourd'hui.", "ringLink": "Ouvrir les détails de {metric}", @@ -11594,7 +11594,7 @@ "errorScope": "Ces rubriques ne peuvent pas être partagées ainsi. Choisissez au moins une rubrique, ou partagez le dossier complet.", "errorManageBrowserOnly": "Un accès de gestion ne peut être proposé que depuis un navigateur.", "errorStepUp": "Confirmez votre deuxième facteur, puis réessayez.", - "errorOffline": "Cela n'a pas atteint le serveur. Votre invitation est toujours là — vérifiez votre connexion et réessayez." + "errorOffline": "Cela n'a pas atteint le serveur. Votre invitation est toujours là : vérifiez votre connexion et réessayez." }, "given": { "title": "Qui peut ouvrir mon dossier", @@ -11914,7 +11914,7 @@ }, "actionError": { "retry": "Réessayer", - "offline": "Cela n'a pas atteint le serveur. Rien n'a changé — vérifiez votre connexion et réessayez.", + "offline": "Cela n'a pas atteint le serveur. Rien n'a changé : vérifiez votre connexion et réessayez.", "rateLimited": "Trop de tentatives d'affilée. Attendez une minute et réessayez.", "acceptExpired": "Cette invitation a expiré. Demandez-en une nouvelle.", "acceptWithdrawn": "Cette invitation a été retirée.", @@ -11926,7 +11926,7 @@ "notFound": "Cet accès n'existe plus.", "revokeFailed": "L'accès n'a pas pu être terminé.", "renounceFailed": "L'accès n'a pas pu être rendu.", - "profileNotFound": "Ce profil n'existe plus — il a peut-être été supprimé, ou votre accès a pris fin.", + "profileNotFound": "Ce profil n'existe plus. Il a peut-être été supprimé, ou votre accès a pris fin.", "deleteProfileFailed": "Le profil n'a pas pu être supprimé.", "removeGuardianFailed": "Cet accès n'a pas pu prendre fin." }, @@ -12260,15 +12260,11 @@ "rugLegend": "Les points sous l’axe marquent les jours avec entrées, un anneau un jour remarquable.", "sheetExpand": "Agrandir en pleine hauteur", "sheetShrink": "Réduire", - "usualLabel": "Vos 30 jours précédents", "valuesLegend": "Point pour ce jour, barre pour les 30 jours précédents", "valuesAllOne": "Toutes les valeurs", "valuesAllFew": "Les {count} valeurs", "valuesAllOther": "Les {count} valeurs", "valuesFewer": "Moins de valeurs", - "countValuesOne": "1 valeur", - "countValuesFew": "{count} valeurs", - "countValuesOther": "{count} valeurs", "countEntriesOne": "1 entrée", "countEntriesFew": "{count} entrées", "countEntriesOther": "{count} entrées", @@ -12308,7 +12304,6 @@ "subtitle": "Ce qui s’est passé et quand, à côté de vos valeurs.", "standing": "Permanent", "startUnknown": "début inconnu", - "openDay": "Ouvrir le {date}", "zoom": { "all": "Tout", "year": "12 mois", diff --git a/messages/it.json b/messages/it.json index 145cded2e..fece67e6c 100644 --- a/messages/it.json +++ b/messages/it.json @@ -167,7 +167,7 @@ "anamnesisShiftSchedule": "Orario di lavoro", "anamnesisColFact": "Voce del profilo", "anamnesisColValue": "Valore registrato", - "subtitle": "HealthLog — Rapporto personale di salute", + "subtitle": "HealthLog: rapporto personale di salute", "patient": "Paziente", "dateOfBirth": "Data di nascita", "gender": "Sesso", @@ -177,18 +177,18 @@ "height": "Altezza", "period": "Periodo del rapporto", "createdOn": "Creato il", - "vitalsTitle": "Parametri vitali — Riepilogo", + "vitalsTitle": "Parametri vitali: riepilogo", "colParameter": "Parametro", "colCurrent": "Attuale", "colAvgPeriod": "Media periodo", "colMin": "Min", "colMax": "Max", "colN": "n", - "bpClassificationTitle": "Pressione arteriosa — Classificazione ESH (2023)", + "bpClassificationTitle": "Pressione arteriosa: classificazione ESH (2023)", "avgBp": "Pressione arteriosa media", "classification": "Classificazione", "bmiTitle": "Indice di massa corporea (BMI)", - "bmiRow": "IMC:{bmi} kg/m² — Classification: {class} (WHO)", + "bmiRow": "IMC:{bmi} kg/m², Classification: {class} (WHO)", "complianceTitle": "Aderenza ai farmaci", "glp1Title": "Terapia GLP-1", "glp1WeightSummary": "Peso nel periodo del referto: {start} kg → {end} kg ({delta} kg)", @@ -236,8 +236,8 @@ "typeGlucoseRandom": "Glicemia (qualsiasi)", "typeGlucoseBedtime": "Glicemia (prima di coricarsi)", "typeGlucoseUnspecified": "Glicemia (non indicata)", - "glucoseClassificationTitle": "Glicemia — Intervalli di riferimento (ADA 2024 / DDG)", - "glucoseRow": "{label}: media {avg} {unit} (obiettivo {rangeMin}–{rangeMax}) — {class}", + "glucoseClassificationTitle": "Glicemia: intervalli di riferimento (ADA 2024 / DDG)", + "glucoseRow": "{label}: media {avg} {unit} (obiettivo {rangeMin}–{rangeMax}), {class}", "glucoseInTarget": "in obiettivo", "glucoseBelowTarget": "sotto obiettivo", "glucoseAboveTarget": "sopra obiettivo", @@ -289,7 +289,7 @@ "gmi": "Indicatore di gestione del glucosio (GMI)", "eA1c": "A1C stimata", "cv": "Variabilità (CV%)", - "spotCaveat": "Sono stime da misurazioni occasionali, non un profilo da monitor continuo — vanno lette come una tendenza, non come un verdetto clinico." + "spotCaveat": "Sono stime da misurazioni occasionali, non un profilo da monitor continuo: vanno lette come una tendenza, non come un verdetto clinico." }, "illnessTitle": "Condizioni e malattie", "illnessOngoing": "In corso", @@ -378,12 +378,12 @@ "backToDashboard": "Torna alla dashboard" }, "offlineBanner": { - "message": "Nessuna connessione — le modifiche non possono essere salvate finché non torni online.", - "saveFailed": "Impossibile salvare — sei offline. Riprova quando torni online.", + "message": "Nessuna connessione: le modifiche non possono essere salvate finché non torni online.", + "saveFailed": "Impossibile salvare: sei offline. Riprova quando torni online.", "showingCached": "Vengono mostrati i tuoi ultimi dati sincronizzati." }, "demoBanner": { - "message": "Modalità demo — le modifiche non vengono salvate." + "message": "Modalità demo: le modifiche non vengono salvate." }, "nav": { "dashboard": "Dashboard", @@ -458,7 +458,7 @@ "hasAccount": "Hai già un account?", "loginFailed": "Accesso non riuscito", "registerFailed": "Registrazione non riuscita", - "invitedBanner": "Sei stato invitato — crea il tuo account anche se la registrazione è chiusa.", + "invitedBanner": "Sei stato invitato: crea il tuo account anche se la registrazione è chiusa.", "alreadySignedIn": { "title": "Hai già effettuato l'accesso", "body": "Hai effettuato l'accesso come {username}. Un invito crea un nuovo account. Esci per accettarlo.", @@ -775,7 +775,7 @@ "formReset": "Reimposta modulo", "saveError": "Errore durante il salvataggio", "duplicateTimestamp": "Esiste già una misurazione di questo tipo a questa marca temporale.", - "serverOwnedSource": "I valori provenienti da una fonte collegata non possono essere modificati — data e nota restano modificabili.", + "serverOwnedSource": "I valori provenienti da una fonte collegata non possono essere modificati, ma data e nota restano modificabili.", "deleteError": "Errore durante l’eliminazione", "deletedToast": "Misurazione eliminata", "restoredToast": "Misurazione ripristinata", @@ -875,7 +875,7 @@ }, "metricCatalog": { "title": "Cosa può monitorare HealthLog", - "description": "Tutti gli ambiti di metriche supportati da HealthLog, che tu abbia già dei dati oppure no — e cosa li fornirebbe.", + "description": "Tutti gli ambiti di metriche supportati da HealthLog, che tu abbia già dei dati oppure no, e cosa li fornirebbe.", "statusPresent": "Monitorato", "statusAbsent": "Non ancora monitorato", "statusModuleOff": "Disattivato", @@ -883,11 +883,11 @@ "connectCta": "Collega una fonte", "viewCta": "Visualizza", "ecg": { - "source": "Tracciati ECG a una derivazione da un orologio compatibile — oggi Withings ScanWatch — sincronizzati automaticamente." + "source": "Tracciati ECG a una derivazione da un orologio compatibile (oggi Withings ScanWatch), sincronizzati automaticamente." }, "watchdog": { "title": "Monitoraggio automatico", - "description": "HealthLog osserva anche silenziosamente in background — notifiche di ritmo irregolare e disturbi respiratori da un orologio connesso, avvisi di scostamento dalla tua base di riferimento, e variazioni degne di nota tra i tuoi due ultimi pannelli di laboratorio — mostrando una scheda solo quando qualcosa emerge. Se almeno una di queste fonti è collegata, nessuna scheda visibile è un buon segno, non una funzione mancante; se non ne è ancora collegata nessuna, semplicemente non c'è ancora nulla sotto controllo." + "description": "HealthLog osserva anche silenziosamente in background (notifiche di ritmo irregolare e disturbi respiratori da un orologio connesso, avvisi di scostamento dalla tua base di riferimento, e variazioni degne di nota tra i tuoi due ultimi pannelli di laboratorio), mostrando una scheda solo quando qualcosa emerge. Se almeno una di queste fonti è collegata, nessuna scheda visibile è un buon segno, non una funzione mancante; se non ne è ancora collegata nessuna, semplicemente non c'è ancora nulla sotto controllo." } }, "mood": { @@ -1044,7 +1044,7 @@ "archive": "Archivia", "restore": "Ripristina", "archivedTitle": "Tag archiviati", - "archivedDescription": "I tag archiviati restano nelle tue voci passate — scompaiono solo dal selettore.", + "archivedDescription": "I tag archiviati restano nelle tue voci passate: scompaiono solo dal selettore.", "archivedEmpty": "Niente in archivio.", "purgeTitle": "Eliminare il tag definitivamente?", "purgeBody": "Il tag verrà rimosso da {count} voci passate. L’operazione non può essere annullata.", @@ -1247,8 +1247,8 @@ "dialogDescription": "Questi farmaci sono da assumere adesso. Conferma per registrarli tutti come assunti.", "confirm": "Assumi tutti ({count})", "successToast": "{count} assunzioni registrate", - "partialToast": "{taken} registrate, {failed} non riuscite – riprova", - "failedToast": "Nessuna assunzione registrata – riprova" + "partialToast": "{taken} registrate, {failed} non riuscite. Riprova", + "failedToast": "Nessuna assunzione registrata. Riprova" }, "logIntake": { "dialogTitle": "Registra un'assunzione", @@ -1431,10 +1431,10 @@ "error": { "empty": "Scrivi prima una descrizione.", "tooLong": "Mantieni la descrizione entro 2000 caratteri.", - "rateLimit": "Troppe richieste — attendi un momento e riprova.", - "noProvider": "Nessun provider IA configurato — configurane uno in Impostazioni.", - "budget": "Budget IA giornaliero raggiunto — riprova domani.", - "network": "Impossibile contattare il provider IA — riprova.", + "rateLimit": "Troppe richieste. Attendi un momento e riprova.", + "noProvider": "Nessun provider IA configurato: configurane uno in Impostazioni.", + "budget": "Budget IA giornaliero raggiunto. Riprova domani.", + "network": "Impossibile contattare il provider IA. Riprova.", "consent": "La lettura della tua descrizione con IA richiede prima il tuo consenso.", "unavailable": "La lettura delle descrizioni con IA non è disponibile qui al momento." } @@ -1450,7 +1450,7 @@ "everyNMonths": "Ogni N mesi in un giorno specifico", "yearly": "Una volta all’anno", "rolling": "Ogni N giorni dall’ultima assunzione (flessibile)", - "rollingExplainer": "Conta dall’ultima assunzione registrata — si mette in pausa se salti una dose.", + "rollingExplainer": "Conta dall’ultima assunzione registrata e si mette in pausa se salti una dose.", "oneShot": "Dose singola" }, "weekdays": { @@ -1508,7 +1508,7 @@ "night": "Notte" }, "max": { - "reached": "Massimo raggiunto — rimuovi un orario prima di aggiungerne un altro." + "reached": "Massimo raggiunto: rimuovi un orario prima di aggiungerne un altro." } }, "courseWindow": { @@ -1558,7 +1558,7 @@ }, "step3": { "title": "Qual è la dose?", - "subline": "Una compressa, uno spruzzo, una goccia — a seconda della forma.", + "subline": "Una compressa, uno spruzzo, una goccia, a seconda della forma.", "amountLabel": "Quantità", "amountPlaceholder": "ad es. 5", "unitLabel": "Unità", @@ -1584,7 +1584,7 @@ }, "dosesPerUnitLabel": "Dosi per unità", "dosesPerUnitPlaceholder": "es. 4", - "dosesPerUnitHint": "Dosi per penna / fiala — lascia vuoto per non tracciare le scorte.", + "dosesPerUnitHint": "Dosi per penna / fiala. Lascia vuoto per non tracciare le scorte.", "short": "Dose", "unitsPerDoseLabel": "Unità per dose", "unitsPerDoseHint": "ad es. 2 compresse da 2 mg per una dose da 4 mg, oppure ½ compressa per una dose divisa" @@ -1596,7 +1596,7 @@ }, "step5": { "title": "Con quale frequenza lo assumi?", - "subline": "Scegli la cadenza — i dettagli arrivano al passo successivo.", + "subline": "Scegli la cadenza: i dettagli arrivano al passo successivo.", "short": "Frequenza" }, "step6": { @@ -1618,7 +1618,7 @@ }, "step7": { "title": "Quando lo assumi?", - "subline": "Uno o più orari del giorno — i promemoria seguono questo elenco.", + "subline": "Uno o più orari del giorno: i promemoria seguono questo elenco.", "presetsLabel": "Preimpostazioni per orario del giorno", "presets": { "morning": "Mattina", @@ -1634,11 +1634,11 @@ "short": "Orari" }, "step8": { - "title": "Fatto — vuoi che HealthLog te lo ricordi?", + "title": "Fatto. Vuoi che HealthLog te lo ricordi?", "subline": "Controlla tutto qui sotto prima di salvare.", "remindersLabel": "Promemoria attivi", - "remindersDescription": "Push, Telegram o ntfy — in base alle tue impostazioni.", - "noChannelHint": "I promemoria richiedono un canale di notifica — al momento nessuno è attivo.", + "remindersDescription": "Push, Telegram o ntfy, in base alle tue impostazioni.", + "noChannelHint": "I promemoria richiedono un canale di notifica, ma al momento nessuno è attivo.", "noChannelHintLink": "Configura le notifiche", "short": "Fatto" } @@ -1722,7 +1722,7 @@ } }, "errors": { - "submitFailed": "Impossibile salvare il farmaco — riprova." + "submitFailed": "Impossibile salvare il farmaco. Riprova." } }, "doseStrength": { @@ -1742,7 +1742,7 @@ }, "injectionSiteBodyOutlineAriaLabel": "Sagoma del corpo", "injectionSitePickerAriaLabel": "Selettore del sito di iniezione", - "injectionSiteRecommendedAriaLabel": "{site} — prossimo sito consigliato", + "injectionSiteRecommendedAriaLabel": "{site}, prossimo sito consigliato", "injectionSiteLegendAriaLabel": "Legenda dei segnaposto", "injectionSiteLegendRecommended": "Prossimo sito consigliato", "injectionSiteLegendLastUsed": "Ultimo sito utilizzato", @@ -1830,7 +1830,7 @@ "cadence": { "oneShotOn": "Dose singola il {date}.", "oneShotPending": "Dose singola in sospeso.", - "asNeeded": "Al bisogno — nessun piano fisso." + "asNeeded": "Al bisogno, nessun piano fisso." }, "intake": { "title": "Storico delle assunzioni", @@ -1857,7 +1857,7 @@ "dialogTitle": "Modifica assunzione", "takenAtLabel": "Assunta alle", "scheduledForHint": "Programmata: {dateTime}", - "farFromScheduledWarning": "Molto distante dall’orario programmato — controlla la data.", + "farFromScheduledWarning": "Molto distante dall’orario programmato: controlla la data.", "skippedLabel": "Saltata", "save": "Salva", "cancel": "Annulla", @@ -1953,7 +1953,7 @@ }, "codes": { "label": "Codici clinici (ATC / RxNorm)", - "note": "Facoltativo. Usati nell'esportazione FHIR della cartella sanitaria. I codici vengono presi esattamente come inseriti — mai indovinati.", + "note": "Facoltativo. Usati nell'esportazione FHIR della cartella sanitaria. I codici vengono presi esattamente come inseriti, mai indovinati.", "atcLabel": "ATC", "rxNormLabel": "RxNorm", "saved": "Codici clinici salvati", @@ -1973,7 +1973,7 @@ "title": "Termina il farmaco", "helper": "Interrompe i promemoria e segna il farmaco come terminato. Lo storico resta visibile.", "button": "Termina", - "dialogTitle": "Termina {name} — interrompe i promemoria, lo storico resta visibile", + "dialogTitle": "Termina {name}: interrompe i promemoria, lo storico resta visibile", "dialogBody": "Nessun altro promemoria. Le voci precedenti restano nella cronologia.", "toast": "Farmaco terminato", "failed": "Impossibile terminare il farmaco." @@ -2011,7 +2011,7 @@ "copyFailed": "Impossibile copiare.", "tokenCopied": "Token copiato", "copyToken": "Copia token", - "mintedHint": "Copia questo token ora — viene mostrato una sola volta." + "mintedHint": "Copia questo token ora: viene mostrato una sola volta." }, "advanced": { "dataPortability": { @@ -2051,9 +2051,9 @@ "statusTitle": "Stato", "nextDoseLabel": "Prossima dose", "nextDoseNone": "Nessuna dose in programma.", - "nextDoseAsNeeded": "Al bisogno — nessuna dose programmata.", + "nextDoseAsNeeded": "Al bisogno, nessuna dose programmata.", "nextDoseNotTracked": "Assunzioni non registrate, solo annotato.", - "pausedHint": "In pausa — nessun promemoria.", + "pausedHint": "In pausa, nessun promemoria.", "reminderLabel": "Promemoria", "reminderOn": "Attivo", "reminderOff": "Disattivo", @@ -2218,7 +2218,7 @@ } }, "logInjectionSiteTitle": "Registra il sito di iniezione", - "logInjectionSiteDescription": "Dove hai iniettato {name}? Facoltativo — puoi saltarlo.", + "logInjectionSiteDescription": "Dove hai iniettato {name}? Facoltativo, puoi saltarlo.", "logInjectionSiteSkip": "Salta", "logInjectionSiteConfirm": "Salva il sito", "logInjectionSiteNoneAvailable": "Nessun sito di iniezione disponibile: tutti i siti sono esclusi nelle tue impostazioni.", @@ -2246,8 +2246,8 @@ "tableStockDoses": "{count} dosi", "tableStockRunway": "≈ {days} giorni rimanenti", "cardLowStockRunway": "Scorta: ≈ {days} giorni", - "takeActionFor": "Assumi – {name}", - "skipActionFor": "Salta – {name}", + "takeActionFor": "Assumi: {name}", + "skipActionFor": "Salta: {name}", "reorderDescription": "Imposta l'ordine dei tuoi farmaci: vale per la vista a schede e per la tabella.", "reorderSaved": "Ordine salvato", "reorderSaveFailed": "Impossibile salvare l’ordine", @@ -2267,7 +2267,7 @@ "levelShift": "È stato rilevato un cambio di livello intorno al {date}.", "plateau": { "title": "Plateau del peso alla dose attuale", - "evidence": "Variazione di peso di {delta} {unit} negli ultimi {window} giorni ({readings} misurazioni) — {days} giorni con {dose}." + "evidence": "Variazione di peso di {delta} {unit} negli ultimi {window} giorni ({readings} misurazioni), {days} giorni con {dose}." }, "retarget": { "label": "Non è la misurazione giusta?", @@ -2277,7 +2277,7 @@ "error": "Impossibile salvare questa modifica. Riprova." }, "beforeAfter": { - "summary": "Ø {before} prima → Ø {after} da allora — una variazione di {delta}.", + "summary": "Ø {before} prima → Ø {after} da allora, una variazione di {delta}.", "counts": "In base a {beforeCount} misurazioni prima e {afterCount} da allora.", "needBefore": "Ancora troppe poche misurazioni prima dell'inizio: servono circa {weeks} settimane prima e dopo per confrontare.", "needAfter": "Ancora troppe poche misurazioni dall'inizio: servono circa {weeks} settimane prima e dopo per confrontare.", @@ -2392,7 +2392,7 @@ }, "charts": { "loadingLabel": "Caricamento del grafico…", - "loadingSlowHint": "Calcolo delle analisi — può richiedere un momento.", + "loadingSlowHint": "Calcolo delle analisi. Può richiedere un momento.", "weight": "Peso", "bloodPressure": "Pressione arteriosa", "pulse": "Pulsazioni", @@ -2542,8 +2542,8 @@ }, "tooltipPrior": "Periodo precedente", "unavailable": { - "lastMonth": "Confronto non disponibile — nessun dato del mese precedente", - "lastYear": "Confronto non disponibile — nessun dato dell’anno precedente" + "lastMonth": "Confronto non disponibile: nessun dato del mese precedente", + "lastYear": "Confronto non disponibile: nessun dato dell’anno precedente" }, "notAvailableForCompliance": "Confronto non disponibile per l’aderenza" }, @@ -2666,7 +2666,7 @@ "narrativeWeek": "Questa settimana", "narrativeMonth": "Questo mese", "narrativeUpdating": "Aggiornamento…", - "heroFallbackSubtitle": "Uno sguardo quotidiano ai tuoi trend — direttamente dai numeri che registri.", + "heroFallbackSubtitle": "Uno sguardo quotidiano ai tuoi trend, direttamente dai numeri che registri.", "heroGreetingMorning": "Buongiorno", "heroGreetingAfternoon": "Buon pomeriggio", "heroGreetingEvening": "Buonasera", @@ -2841,14 +2841,14 @@ } }, "coach": { - "refusalOutOfScope": "Posso aiutarti solo con i dati di salute del tuo log — misurazioni, farmaci, umore, trend. Domande fuori da questo ambito non le rispondo.", - "refusalInjection": "Nel tuo messaggio ci sono istruzioni che cercano di sovrascrivere le mie indicazioni. Sono il coach di HealthLog e riassumo solo i tuoi dati di salute — riformula la domanda in questo perimetro.", + "refusalOutOfScope": "Posso aiutarti solo con i dati di salute del tuo log: misurazioni, farmaci, umore, trend. Domande fuori da questo ambito non le rispondo.", + "refusalInjection": "Nel tuo messaggio ci sono istruzioni che cercano di sovrascrivere le mie indicazioni. Sono il coach di HealthLog e riassumo solo i tuoi dati di salute: riformula la domanda in questo perimetro.", "errorBudget": "Hai raggiunto il limite giornaliero del coach. Il budget si reimposta a mezzanotte (UTC).", "errorProvider": "Il coach non è riuscito a contattare un provider di analisi ora. Riprova fra poco.", "errorDemo": "Nella demo il Coach non risponde.", "errorNoProvider": "Il coach legge i tuoi dati di salute registrati e risponde a domande su di essi (non è consulenza medica). HealthLog ha bisogno di un provider IA per questo: collega la tua chiave o un modello locale.", "errorNoProviderAction": "Collega un provider IA", - "errorNetwork": "Nessuna connessione Internet — riprova quando sei di nuovo online.", + "errorNetwork": "Nessuna connessione Internet. Riprova quando sei di nuovo online.", "prefsSaveError": "Impossibile salvare le preferenze del Coach. Riprova.", "errorCredentialExpired": "La connessione al provider di IA è scaduta. Riconnettila nelle Impostazioni per mantenere attivo il Coach.", "tagline": "Coach personale di salute, basato sui tuoi dati.", @@ -2867,7 +2867,7 @@ "thinking": "Sto pensando…", "unverifiedFiguresNotice": "Alcuni numeri non è stato possibile verificarli con i tuoi dati e sono stati omessi.", "composerPlaceholder": "Chiedimi pure …", - "nudgeBubbleLabel": "Nuovo messaggio dal coach — apri la chat", + "nudgeBubbleLabel": "Nuovo messaggio dal coach: apri la chat", "fabLabel": "Apri il coach", "readAloud": "Leggi ad alta voce", "readAloudStop": "Interrompi lettura", @@ -2891,7 +2891,7 @@ "guided": { "offerTitle": "Il Coach ha {count} domande per te", "offerTitleOne": "Il Coach ha una domanda per te", - "offerBody": "Risposte brevi affinano le tue informazioni personali — una domanda alla volta, qui in chat.", + "offerBody": "Risposte brevi affinano le tue informazioni personali, una domanda alla volta, qui in chat.", "offerStart": "Rispondi ora", "offerLater": "Più tardi", "offerDismiss": "Non chiedere più", @@ -2901,7 +2901,7 @@ "later": "Più tardi", "dismissRemaining": "Non chiedere più", "answerPlaceholder": "La tua risposta…", - "summaryTitle": "Fatto — grazie per le tue risposte!", + "summaryTitle": "Fatto, grazie per le tue risposte!", "summaryAnswered": "{answered} di {total} risposte", "summaryAdopted": "{adopted} aggiunte alle tue informazioni personali", "summaryAdoptedNone": "nulla di nuovo aggiunto alle tue informazioni personali", @@ -3090,7 +3090,7 @@ "steadyLatestWithin": "I tuoi valori sono di solito {low} {unit}; la tua ultima misurazione, del {date}, era {value}, in linea.", "steadyLatestAbove": "I tuoi valori sono di solito {low} {unit}; la tua ultima misurazione, del {date}, era {value}, al di sopra.", "steadyLatestBelow": "I tuoi valori sono di solito {low} {unit}; la tua ultima misurazione, del {date}, era {value}, al di sotto.", - "insufficient": "Sto ancora imparando il tuo intervallo abituale — continua a registrare per qualche giorno in più.", + "insufficient": "Sto ancora imparando il tuo intervallo abituale. Continua a registrare per qualche giorno in più.", "driver": "{note}" }, "scope": { @@ -3104,31 +3104,31 @@ "groupEarlier": "Precedenti" }, "seed": { - "bloodPressure": "Esamina con me l'andamento della mia pressione arteriosa negli ultimi 30 giorni — c'è qualcosa che dovrei tenere d'occhio?", + "bloodPressure": "Esamina con me l'andamento della mia pressione arteriosa negli ultimi 30 giorni: c'è qualcosa che dovrei tenere d'occhio?", "weight": "Come si è evoluto il mio peso ultimamente e la direzione è qualcosa su cui intervenire?", "bmi": "Cosa mi dice l'andamento del mio BMI e come dovrei interpretarlo?", - "pulse": "Esamina con me le mie letture del battito — c'è qualcosa fuori dal comune?", + "pulse": "Esamina con me le mie letture del battito: c'è qualcosa fuori dal comune?", "restingHr": "Come si è evoluta la mia frequenza cardiaca a riposo e cosa dice sulla mia forma fisica?", "hrv": "Cosa mi dice la mia variabilità della frequenza cardiaca su recupero e stress ultimamente?", - "sleep": "Esamina con me il mio sonno recente — durata, regolarità e qualsiasi cosa valga la pena cambiare.", + "sleep": "Esamina con me il mio sonno recente: durata, regolarità e qualsiasi cosa valga la pena cambiare.", "mood": "Quali schemi noti nel mio umore nelle ultime settimane?", "medications": "Com'è la mia aderenza alla terapia e corrisponde a come mi sono sentito?", "steps": "Quanto sono stato attivo ultimamente in base ai miei passi e come si confronta con un valore di riferimento sano?", "activeEnergy": "Cosa dice il mio andamento dell'energia attiva sul mio livello di attività ultimamente?", "cardioFitness": "Cosa significa l'andamento della mia forma cardiorespiratoria (VO₂ max) e come la indirizzo nella direzione giusta?", - "bloodGlucose": "Esamina con me le mie ultime letture di glicemia — sono in un intervallo sano?", + "bloodGlucose": "Esamina con me le mie ultime letture di glicemia: sono in un intervallo sano?", "oxygenSaturation": "Cosa mi dice l'andamento della mia saturazione di ossigeno (SpO₂)?", "respiratoryRate": "Cosa dice il mio andamento della frequenza respiratoria sulla mia salute?", - "workouts": "Esamina con me i miei allenamenti recenti — carico, frequenza e come recupero tra uno e l'altro.", + "workouts": "Esamina con me i miei allenamenti recenti: carico, frequenza e come recupero tra uno e l'altro.", "recoveryPage": "Perché il mio recupero è dov'è in questo momento e cosa lo determina?", - "briefing": "Esamina con me il riepilogo di oggi — su cosa dovrei concentrarmi e c'è qualcosa su cui vale la pena agire?", + "briefing": "Esamina con me il riepilogo di oggi: su cosa dovrei concentrarmi e c'è qualcosa su cui vale la pena agire?", "healthScore": "Perché il mio punteggio di salute è {score} su 100 e cosa lo migliorerebbe di più?", - "periodWeek": "Esamina con me com'è andata la mia ultima settimana sui miei parametri di salute — cosa spicca?", - "periodMonth": "Esamina con me com'è andato il mio ultimo mese sui miei parametri di salute — cosa spicca?", + "periodWeek": "Esamina con me com'è andata la mia ultima settimana sui miei parametri di salute: cosa spicca?", + "periodMonth": "Esamina con me com'è andato il mio ultimo mese sui miei parametri di salute: cosa spicca?", "correlationBpCompliance": "Che relazione c'è tra la mia aderenza alla terapia e la mia pressione arteriosa? Spiegami cosa significa per me questa correlazione.", "correlationMoodPulse": "C'è un legame reale tra il mio umore e il mio battito? Aiutami a interpretare questa correlazione.", "correlationWeightWeekday": "Il mio peso segue uno schema settimanale? Cosa mi dice questa correlazione per giorno della settimana?", - "recommendation": "Dimmi di più su questa raccomandazione: \"{text}\" — perché si applica a me e cosa dovrei fare?" + "recommendation": "Dimmi di più su questa raccomandazione: \"{text}\". Perché si applica a me e cosa dovrei fare?" }, "assessmentPrompt": "Spiegami la mia valutazione di {metric}: cosa significa e cosa dovrei fare?", "attach": { @@ -3321,7 +3321,7 @@ }, "hrv": { "title": "HRV", - "description": "Variabilità della frequenza cardiaca nel tempo — segnale di recupero del sistema nervoso, captato di notte da Apple Watch e altri wearable compatibili.", + "description": "Variabilità della frequenza cardiaca nel tempo: segnale di recupero del sistema nervoso, captato di notte da Apple Watch e altri wearable compatibili.", "chartTitle": "Variabilità della frequenza cardiaca", "emptyState": { "title": "Ancora nessun valore HRV", @@ -3330,7 +3330,7 @@ }, "restingHr": { "title": "FC a riposo", - "description": "Il livello cardiaco di base sulla giornata — distinto dalle frequenze puntuali della pagina Polso. Apple Salute fornisce un valore al giorno.", + "description": "Il livello cardiaco di base sulla giornata, distinto dalle frequenze puntuali della pagina Polso. Apple Salute fornisce un valore al giorno.", "chartTitle": "Frequenza cardiaca a riposo", "emptyState": { "title": "Ancora nessuna FC a riposo", @@ -3340,7 +3340,7 @@ }, "oxygenSaturation": { "title": "Saturazione di ossigeno", - "description": "Ossigeno nel sangue (SpO₂) — intervallo clinico normale 95–100 %, con zone obiettivo ombreggiate sul grafico.", + "description": "Ossigeno nel sangue (SpO₂): intervallo clinico normale 95–100 %, con zone obiettivo ombreggiate sul grafico.", "chartTitle": "Saturazione di ossigeno", "emptyState": { "title": "Ancora nessun campione SpO₂", @@ -3353,13 +3353,13 @@ "chartTitle": "Temperatura corporea", "emptyState": { "title": "Ancora nessuna temperatura corporea", - "description": "Registra una misura o lascia che il tuo wearable ne sincronizzi una — l'andamento apparirà qui.", + "description": "Registra una misura o lascia che il tuo wearable ne sincronizzi una: l'andamento apparirà qui.", "cta": "Registra temperatura corporea" } }, "steps": { "title": "Passi", - "description": "Conteggio giornaliero dei passi — una riga al giorno, da Apple Salute o da un dispositivo di attività collegato.", + "description": "Conteggio giornaliero dei passi: una riga al giorno, da Apple Salute o da un dispositivo di attività collegato.", "chartTitle": "Passi al giorno", "emptyState": { "title": "Ancora nessun dato sui passi", @@ -3368,7 +3368,7 @@ }, "activeEnergy": { "title": "Energia attiva", - "description": "Totale giornaliero di energia attiva in kilocalorie — una riga al giorno, da Apple Salute o dall'attività Withings.", + "description": "Totale giornaliero di energia attiva in kilocalorie: una riga al giorno, da Apple Salute o dall'attività Withings.", "chartTitle": "Energia attiva", "emptyState": { "title": "Ancora nessun dato di energia attiva", @@ -3392,7 +3392,7 @@ "weightBody": "Il peso corporeo è uno dei segnali più semplici dell'equilibrio energetico a lungo termine e della salute generale. L'andamento nelle settimane conta molto più di una singola misurazione, che varia con l'idratazione, il cibo e l'ora del giorno.", "bmiBody": "L'IMC è il peso diviso per l'altezza al quadrato, un singolo numero che ti colloca in un'ampia categoria di peso. È uno screening di popolazione, non una diagnosi, e non distingue il muscolo dal grasso.", "sleepBody": "La durata del sonno è quanto hai effettivamente dormito nella notte, suddivisa in fasi leggera, profonda e REM. La maggior parte degli adulti necessita di circa sette-nove ore; quantità e qualità costanti favoriscono recupero, umore e metabolismo.", - "moodBody": "Il monitoraggio dell'umore registra come ti senti nel tempo su una scala semplice. Annotarlo con regolarità rivela schemi — come sonno, attività o farmaci si allineano a come ti senti — che un singolo giorno non mostra mai.", + "moodBody": "Il monitoraggio dell'umore registra come ti senti nel tempo su una scala semplice. Annotarlo con regolarità rivela schemi (come sonno, attività o farmaci si allineano a come ti senti) che un singolo giorno non mostra mai.", "medicationsBody": "L'aderenza misura quanto regolarmente assumi i farmaci come prescritto, qui come quota delle dosi previste che hai registrato. Un'assunzione costante è spesso ciò che fa funzionare una terapia come previsto.", "restingHrBody": "La frequenza cardiaca a riposo è il battito quando sei completamente a riposo, di solito misurato durante la notte. Una frequenza più bassa indica in genere una migliore forma cardiovascolare, mentre un andamento in aumento può essere un segnale precoce di stress o malattia.", "hrvBody": "L'HRV è la piccola variazione del tempo tra battiti consecutivi. Una variabilità più alta riflette di solito un sistema nervoso ben recuperato e adattabile, mentre un calo prolungato può segnalare affaticamento, stress o recupero insufficiente.", @@ -3404,7 +3404,7 @@ "bodyWaterBody": "L'acqua corporea totale è la quota del tuo peso costituita da liquido, dentro e intorno alle cellule. Varia con l'idratazione, l'alimentazione e l'attività, quindi l'andamento nelle settimane dice più di una singola misura.", "boneMassBody": "La massa ossea è il peso stimato dei minerali del tuo scheletro. Le stime da bilancia sono approssimative, ma un andamento stabile o in aumento sostiene la robustezza ossea a lungo termine.", "fatFreeMassBody": "La massa magra è tutto ciò che nel corpo non è grasso: muscoli, ossa, organi e acqua. Mantenerla o aumentarla mentre si perde peso indica di solito una composizione corporea più sana.", - "fatMassBody": "La massa grassa è il peso totale del grasso nel corpo. Un po' di grasso è essenziale per gli ormoni e le riserve di energia, ma un eccesso — soprattutto sull'addome — aumenta il rischio per la salute a lungo termine (WHO 2024).", + "fatMassBody": "La massa grassa è il peso totale del grasso nel corpo. Un po' di grasso è essenziale per gli ormoni e le riserve di energia, ma un eccesso, soprattutto sull'addome, aumenta il rischio per la salute a lungo termine (WHO 2024).", "bodyFatBody": "La percentuale di grasso corporeo è la parte del tuo peso costituita da grasso. Gli intervalli sani dipendono da sesso ed età, e le bilance la stimano con la bioimpedenza, quindi l'andamento su più settimane dice più di una singola misura.", "muscleMassBody": "La massa muscolare è il peso stimato dei muscoli del corpo. Più muscolo sostiene forza, metabolismo e mobilità, e di solito richiede impegno attivo per essere mantenuto con l'età.", "visceralFatBody": "Il grasso viscerale è il grasso depositato in profondità nell'addome, intorno agli organi. A differenza del grasso sottocutaneo, un livello elevato è strettamente legato a malattie cardiache e diabete di tipo 2, quindi più basso è in genere meglio.", @@ -3435,11 +3435,11 @@ "breathingDisturbancesBody": "Un wearable può stimare quanto spesso la respirazione si è interrotta durante il sonno. Un indice più basso è migliore; un livello segnalato come elevato, soprattutto su molte notti, andrebbe segnalato a un medico. È un'approssimazione di screening, non una diagnosi di apnea del sonno.", "stepsBody": "Il conteggio dei passi è il numero totale di passi che fai ogni giorno: la misura più semplice del movimento quotidiano. Un'abitudine costante conta più di un singolo giorno intenso, e l'obiettivo tondo di 10.000 passi è uno slogan pubblicitario, non un dato della ricerca.", "readinessBody": "La prontezza è una lettura giornaliera di quanto il tuo corpo sia pronto ad affrontare la giornata, combinando frequenza cardiaca a riposo, variabilità della frequenza cardiaca e sonno. È un'approssimazione del dispositivo rispetto alla tua baseline, non una misura clinica: un punteggio più alto indica recupero, uno più basso è un invito gentile a rallentare.", - "sleepScoreBody": "Il tuo punteggio del sonno riassume un'intera notte in un solo numero — durata, efficienza, regolarità degli orari ed equilibrio tra sonno leggero, profondo e REM. Osserva l'andamento nell'arco delle settimane invece di rincorrere un punteggio perfetto in una singola notte.", + "sleepScoreBody": "Il tuo punteggio del sonno riassume un'intera notte in un solo numero: durata, efficienza, regolarità degli orari ed equilibrio tra sonno leggero, profondo e REM. Osserva l'andamento nell'arco delle settimane invece di rincorrere un punteggio perfetto in una singola notte.", "recoveryBody": "Il recupero riflette quanto bene il tuo corpo si è ripreso, basandosi su segnali notturni come la variabilità della frequenza cardiaca e la frequenza a riposo. Un punteggio alto è il via libera per spingere; uno più basso suggerisce che il tuo organismo si sta ancora ricostruendo.", "strainBody": "Lo sforzo misura quanto carico cardiovascolare e fisico hai imposto al tuo corpo, dagli allenamenti a una giornata attiva in piedi. Quando c'è abbastanza storico, viene valutato rispetto al tuo sforzo abituale, non rispetto a uno standard esterno.", "stressBody": "Lo stress qui è una stima del carico fisiologico sul tuo sistema nervoso, letto soprattutto dagli schemi di variabilità della frequenza cardiaca e non da come ti senti consapevolmente. Un punteggio più basso indica uno stato calmo e ben regolato; uno più alto è un invito a inserire del recupero.", - "recoveryPageBody": "Il recupero riunisce i segnali notturni registrati dal tuo wearable — ricarica, sforzo, carico e i totali di frequenza cardiaca ed energia della giornata — per mostrare quanto bene il tuo corpo si è ripreso. Guarda l'andamento su più giorni piuttosto che un singolo numero; un valore più basso è un invito a rallentare, non un allarme.", + "recoveryPageBody": "Il recupero riunisce i segnali notturni registrati dal tuo wearable (ricarica, sforzo, carico e i totali di frequenza cardiaca ed energia della giornata) per mostrare quanto bene il tuo corpo si è ripreso. Guarda l'andamento su più giorni piuttosto che un singolo numero; un valore più basso è un invito a rallentare, non un allarme.", "pulsePressureBody": "La pressione differenziale è la differenza tra il valore sistolico e quello diastolico (sistolica meno diastolica). Come orientamento generale, circa 40 mmHg è tipico a riposo; un divario ampio sopra i 60 mmHg circa nella mezza età può riflettere arterie più rigide, mentre un divario stretto sotto i 25 mmHg circa può accompagnare una bassa gittata sistolica (StatPearls/NIH 2023). È uno spunto di discussione, non una diagnosi.", "meanArterialPressureBody": "La pressione arteriosa media è la pressione media che i tuoi organi vedono in un battito, all'incirca la diastolica più un terzo del divario con la sistolica. Come orientamento generale, un valore a riposo si aggira sui 70–100 mmHg (StatPearls/NIH 2023). La soglia di ~60 mmHg spesso citata è un concetto di terapia intensiva, non un allarme per l'automisurazione.", "cycleEducationBody": "Il tuo ciclo attraversa quattro fasi guidate dagli ormoni, e la sua durata e regolarità sono una finestra accessibile sulla salute generale. Come orientamento generale, nei adulti i cicli durano tipicamente 21–35 giorni (i riferimenti clinici citano 24–38), con un sanguinamento di circa cinque giorni (ACOG 2015). La fase luteale è l'ancora stabile, quindi l'ovulazione si stima meglio contando a ritroso dalla prossima mestruazione attesa, mai con un «giorno 14» fisso. Una finestra fertile prevista è una stima che richiede più cicli registrati e resta approssimativa, e la temperatura basale conferma l'ovulazione a posteriori anziché prevederla. Non è un metodo contraccettivo.", @@ -3458,7 +3458,7 @@ "mean": "Media" }, "showAllValues": "Mostra tutte le misurazioni", - "valuesPageTitle": "{metric} — tutte le misurazioni", + "valuesPageTitle": "{metric}: tutte le misurazioni", "valuesPageDescription": "Ogni misurazione dietro questa metrica. Modifica o rimuovi una voce direttamente.", "diversity": { "trigger": "Suggerimento di misurazione", @@ -3498,11 +3498,11 @@ "inBed": "A letto", "nap": "Pisolino", "napCount": "{count} pisolini", - "unavailable": "Ancora nessun dato sulle fasi — le fasi del sonno appariranno qui non appena una fonte collegata le fornirà." + "unavailable": "Ancora nessun dato sulle fasi. Le fasi del sonno appariranno qui non appena una fonte collegata le fornirà." }, "empty": { "title": "Ancora nessun dato sul sonno", - "description": "Collega una fonte come Apple Health o un wearable — oppure registra il sonno manualmente — e questa vista si riempirà in automatico.", + "description": "Collega una fonte come Apple Health o un wearable, oppure registra il sonno manualmente, e questa vista si riempirà in automatico.", "action": "Gestisci dispositivi" }, "debt": { @@ -3511,21 +3511,21 @@ "caption": "Bilancio in sospeso nelle ultime {nights} notti", "clearValue": "In pari", "clearCaption": "Niente in sospeso nelle ultime {nights} notti", - "learning": "Stiamo ancora misurando il tuo sonno — {counted} notti finora, ne mancano {remaining} per un bilancio affidabile.", + "learning": "Stiamo ancora misurando il tuo sonno: {counted} notti finora, ne mancano {remaining} per un bilancio affidabile.", "computedInfo": "Questa è la stima propria di HealthLog: un bilancio mobile tra fabbisogno e sonno delle ultime notti, che il sonno di recupero riduce. Può differire dal dato di debito di sonno nativo di un dispositivo indossabile, che usa un proprio modello di fabbisogno." }, "average": { "title": "Media per notte", "value": "{hours} h {minutes} min", "caption": "Sonno medio nelle ultime {nights} notti", - "learning": "Stiamo ancora misurando il tuo sonno — {counted} notti finora, ne mancano {remaining} per una media affidabile." + "learning": "Stiamo ancora misurando il tuo sonno: {counted} notti finora, ne mancano {remaining} per una media affidabile." }, "chronotype": { "title": "Cronotipo", - "learning": "Stiamo ancora imparando il tuo ritmo — {counted} di {total} notti libere. Un cronotipo richiede alcune mattine senza sveglia per avere significato.", + "learning": "Stiamo ancora imparando il tuo ritmo: {counted} di {total} notti libere. Un cronotipo richiede alcune mattine senza sveglia per avere significato.", "advancedToggle": "Avanzate", "socialJetlagValue": "{hours} h {minutes} min di jet lag sociale", - "socialJetlagCaption": "La differenza tra gli orari del sonno nei giorni lavorativi e in quelli liberi — come un piccolo cambio di fuso orario settimanale.", + "socialJetlagCaption": "La differenza tra gli orari del sonno nei giorni lavorativi e in quelli liberi, come un piccolo cambio di fuso orario settimanale.", "msfScValue": "Metà del sonno corretta {clock}", "msfScCaption": "Corretta per il sonno recuperato nel fine settimana (MSFsc).", "dayTypeNote": "Si presume che i giorni liberi siano i fine settimana finché non verrà aggiunto il tracciamento del tipo di giorno.", @@ -3736,7 +3736,7 @@ "labsLink": "Risultati di laboratorio? Registra una HbA1c o la glicemia a digiuno da un prelievo in Laboratorio.", "learningTitle": "Stiamo ancora imparando la tua glicemia", "learningBody": "Per ora sono {count} su {days}. Con un po’ più di storico il quadro si chiarisce: continua a registrare o lascia che lo completi un dispositivo connesso.", - "learningBodyEmpty": "Appena arrivano alcune misurazioni — registrate da te o sincronizzate da un dispositivo — il tempo nel range, la media e la variabilità prendono forma qui.", + "learningBodyEmpty": "Appena arrivano alcune misurazioni (registrate da te o sincronizzate da un dispositivo), il tempo nel range, la media e la variabilità prendono forma qui.", "readingsCount": "{count} misurazioni", "readingsCountOne": "1 misurazione", "daysCount": "{days} giorni", @@ -3891,7 +3891,7 @@ "navSkinTemperature": "Temp. pelle", "pulseWaveVelocity": { "title": "Velocità dell’onda di polso", - "description": "La tua velocità dell’onda di polso arteriosa nel tempo, in m/s — valori più alti indicano arterie più rigide.", + "description": "La tua velocità dell’onda di polso arteriosa nel tempo, in m/s. Valori più alti indicano arterie più rigide.", "chartTitle": "Velocità dell’onda di polso", "emptyState": { "title": "Nessun dato", @@ -4093,7 +4093,7 @@ "tagLift": "I giorni con l'etichetta «{tag}» superano in media il tuo umore generale di {delta}.", "tagDrop": "I giorni con l'etichetta «{tag}» restano {delta} sotto la tua media.", "inTarget": "Sei stato nel tuo intervallo di buon umore il {pct} % degli ultimi 30 giorni.", - "streak": "Hai registrato il tuo umore per {days} giorni di fila — continua così.", + "streak": "Hai registrato il tuo umore per {days} giorni di fila. Continua così.", "timeOfDay": "Ti senti meglio di {bucket}, con una media di {value}." }, "timeOfDay": { @@ -4203,8 +4203,8 @@ "deviationAbove": "La tua valutazione è {amount} punti sopra questo intervallo.", "deviationBelow": "La tua valutazione è {amount} punti sotto questo intervallo.", "weightedTitle": "Che cosa ha pesato di più nel confronto di questa giornata", - "weightedUp": "{label} — contava verso un valore atteso più alto", - "weightedDown": "{label} — contava verso un valore atteso più basso", + "weightedUp": "{label}: contava verso un valore atteso più alto", + "weightedDown": "{label}: contava verso un valore atteso più basso", "caveat": "È un confronto con le tue giornate passate, non un'affermazione su come una giornata sia andata a finire così.", "learning": "Fase di apprendimento: {entries} giornate su {threshold} registrate. Il confronto compare quando ce ne sono abbastanza.", "noPattern": "Nelle {entries} giornate registrate finora non c'è nulla di abbastanza costante per confrontare una giornata. Quando registri anche il contesto della giornata, ne rendi confrontabile una parte maggiore.", @@ -4221,7 +4221,7 @@ }, "scoreRing": { "aria": "Punteggio {score} su 100, {band}", - "ariaProvisional": "Punteggio non ancora disponibile — dati insufficienti", + "ariaProvisional": "Punteggio non ancora disponibile: dati insufficienti", "provisionalCaption": "Dati ancora insufficienti", "band": { "green": "buono", @@ -4245,7 +4245,7 @@ "loadingLabel": "Caricamento dei tuoi parametri vitali", "loadError": "Al momento non è stato possibile caricare i tuoi parametri vitali.", "infoLabel": "Come viene calcolato questo dato?", - "building": "Creazione del tuo intervallo abituale — {count} di {target} giorni", + "building": "Creazione del tuo intervallo abituale: {count} di {target} giorni", "typicalRange": "Abituale per te: {low}–{high}", "fitnessYounger": "Forma cardio di chi ha ~{years} anni in meno", "fitnessOlder": "Forma cardio ~{years} anni oltre la tua età", @@ -4297,7 +4297,7 @@ "READINESS": { "title": "Prontezza", "description": "Un indicatore quotidiano di benessere in base a come i tuoi segnali si collocano rispetto alla tua baseline.", - "method": "Una combinazione 0–100 di deviazione della frequenza cardiaca a riposo, deviazione della HRV (SDNN), qualità del sonno, stabilità della frequenza respiratoria e stabilità dell’umore — ciascuna misurata rispetto alla tua baseline personale. I pesi vengono rinormalizzati sui componenti supportati dai tuoi dati. Un indicatore di benessere, non un punteggio di recupero né clinico.", + "method": "Una combinazione 0–100 di deviazione della frequenza cardiaca a riposo, deviazione della HRV (SDNN), qualità del sonno, stabilità della frequenza respiratoria e stabilità dell’umore, ciascuna misurata rispetto alla tua baseline personale. I pesi vengono rinormalizzati sui componenti supportati dai tuoi dati. Un indicatore di benessere, non un punteggio di recupero né clinico.", "component": { "rhr": "Frequenza cardiaca a riposo", "hrv": "HRV (SDNN)", @@ -4337,31 +4337,31 @@ }, "STRAIN_SCORE": { "method": "Un indicatore notturno di sforzo da 0 a 100 dal tuo carico di attività pesato sulla frequenza cardiaca (un modello di impulso d’allenamento tipo TRIMP). Più alto significa una giornata più impegnativa.", - "anchorPersonal": "Ancorato al tuo carico recente nei giorni di allenamento — valutato rispetto al tuo sforzo abituale, così che una giornata davvero dura per te risulti alta.", + "anchorPersonal": "Ancorato al tuo carico recente nei giorni di allenamento: valutato rispetto al tuo sforzo abituale, così che una giornata davvero dura per te risulti alta.", "anchorPopulation": "Valutato rispetto a un riferimento generale mentre costruisci lo storico di allenamento; quando ne hai abbastanza passa al tuo sforzo abituale.", "description": "Un indicatore notturno di carico di attività dal tuo sforzo pesato sulla frequenza cardiaca, relativo al tuo sforzo abituale.", "deviceCaption": "Sforzo giornaliero del tuo dispositivo: {value} su {max}", "deviceSource": "Finché HealthLog non ha calcolato un proprio valore durante la notte, la scheda mostra lo sforzo giornaliero del tuo dispositivo, riportato su 0–100." }, "WRIST_TEMPERATURE_BASELINE": { - "method": "La tua tipica temperatura notturna al polso è la mediana delle tue letture notturne nel periodo, ± una dispersione robusta (deviazione assoluta mediana, scalata). Segue le TUE letture — la notte scorsa è mostrata come scostamento dalla tua baseline, non da una norma di popolazione.", - "caveat": "Solo una banda di scostamento personale — descrittiva, non un segnale di malattia, febbre o fase del ciclo. Sei tu a interpretarla." + "method": "La tua tipica temperatura notturna al polso è la mediana delle tue letture notturne nel periodo, ± una dispersione robusta (deviazione assoluta mediana, scalata). Segue le TUE letture: la notte scorsa è mostrata come scostamento dalla tua baseline, non da una norma di popolazione.", + "caveat": "Solo una banda di scostamento personale, descrittiva, non un segnale di malattia, febbre o fase del ciclo. Sei tu a interpretarla." }, "STAIR_ASCENT_SPEED_BASELINE": { - "method": "Il tuo passo tipico in salita sulle scale è la mediana dei tuoi valori giornalieri nel periodo, ± una dispersione robusta (deviazione assoluta mediana, scalata). La banda è costruita sui tuoi dati — non esiste una soglia di popolazione per la velocità sulle scale, perché il passo dipende dalla geometria dei gradini e dalla lunghezza delle gambe.", - "caveat": "Una banda personale di tendenza della mobilità — descrittiva, non una valutazione di fragilità o di rischio di caduta." + "method": "Il tuo passo tipico in salita sulle scale è la mediana dei tuoi valori giornalieri nel periodo, ± una dispersione robusta (deviazione assoluta mediana, scalata). La banda è costruita sui tuoi dati: non esiste una soglia di popolazione per la velocità sulle scale, perché il passo dipende dalla geometria dei gradini e dalla lunghezza delle gambe.", + "caveat": "Una banda personale di tendenza della mobilità, descrittiva, non una valutazione di fragilità o di rischio di caduta." }, "STAIR_DESCENT_SPEED_BASELINE": { - "method": "Il tuo passo tipico in discesa sulle scale è la mediana dei tuoi valori giornalieri nel periodo, ± una dispersione robusta (deviazione assoluta mediana, scalata). La banda è costruita sui tuoi dati — non esiste una soglia di popolazione per la velocità sulle scale, perché il passo dipende dalla geometria dei gradini e dalla lunghezza delle gambe.", - "caveat": "Una banda personale di tendenza della mobilità — descrittiva, non una valutazione di fragilità o di rischio di caduta." + "method": "Il tuo passo tipico in discesa sulle scale è la mediana dei tuoi valori giornalieri nel periodo, ± una dispersione robusta (deviazione assoluta mediana, scalata). La banda è costruita sui tuoi dati: non esiste una soglia di popolazione per la velocità sulle scale, perché il passo dipende dalla geometria dei gradini e dalla lunghezza delle gambe.", + "caveat": "Una banda personale di tendenza della mobilità, descrittiva, non una valutazione di fragilità o di rischio di caduta." }, "SIX_MINUTE_WALK_BAND": { - "method": "La distanza di cammino di sei minuti STIMATA dal tuo dispositivo, collocata rispetto al riferimento di Enright e Sherrill per la tua età, altezza, peso e sesso, come percentuale del previsto. La distanza è la stima del dispositivo — mai ricalcolata qui. Senza età, altezza, peso e sesso la percentuale è nascosta e vengono mostrate solo distanza e tendenza.", - "caveat": "Una stima riformulata rispetto a un riferimento pubblicato — un segnale di capacità funzionale, non un test del cammino di sei minuti clinico né una diagnosi. Il riferimento è stato stabilito per le età 40–80; al di fuori di questo intervallo il valore previsto è un’estrapolazione." + "method": "La distanza di cammino di sei minuti STIMATA dal tuo dispositivo, collocata rispetto al riferimento di Enright e Sherrill per la tua età, altezza, peso e sesso, come percentuale del previsto. La distanza è la stima del dispositivo, mai ricalcolata qui. Senza età, altezza, peso e sesso la percentuale è nascosta e vengono mostrate solo distanza e tendenza.", + "caveat": "Una stima riformulata rispetto a un riferimento pubblicato: un segnale di capacità funzionale, non un test del cammino di sei minuti clinico né una diagnosi. Il riferimento è stato stabilito per le età 40–80; al di fuori di questo intervallo il valore previsto è un’estrapolazione." }, "TRAJECTORY": { "method": "Una retta ai minimi quadrati adattata ai tuoi valori giornalieri recenti e proiettata in avanti su un breve orizzonte, con l’intervallo di previsione classico che si allarga man mano che si estende. Calcolata solo quando la tendenza recente è abbastanza marcata e la tua cronologia è abbastanza lunga e aggiornata; altrimenti non viene tracciata alcuna linea.", - "caveat": "Una proiezione della tua tendenza recente — non una previsione, un obiettivo o una prognosi clinica. Vale solo se lo schema recente continua; la banda ombreggiata mostra quanto rapidamente quella certezza svanisce." + "caveat": "Una proiezione della tua tendenza recente, non una previsione, un obiettivo o una prognosi clinica. Vale solo se lo schema recente continua; la banda ombreggiata mostra quanto rapidamente quella certezza svanisce." }, "SAME_TIME_BASELINE": { "method": "Il tuo totale progressivo di oggi confrontato con la mediana della stessa ora locale nelle ultime quattro settimane, con una banda robusta mediana ± MAD attorno. Contano solo i giorni con abbastanza dettaglio registrato, e nessun confronto viene mostrato finché non ce ne sono almeno quattordici.", @@ -4388,24 +4388,24 @@ "allClear": "Oggi tutti i tuoi parametri vitali sono nel loro intervallo personale.", "allClearMeta": "Controllati {count} dei tuoi parametri rispetto al tuo intervallo abituale.", "watch": "Oggi un parametro è fuori dal suo intervallo abituale.", - "watchVital": "Fuori intervallo: {vital}. Spesso è un episodio isolato — tienilo d’occhio nei prossimi giorni.", + "watchVital": "Fuori intervallo: {vital}. Spesso è un episodio isolato: tienilo d’occhio nei prossimi giorni.", "firedHeadline": "Oggi {count} dei tuoi parametri vitali sono fuori dal loro intervallo personale.", - "factors": "Possibili fattori — mai una causa: un allenamento intenso, poco sonno, alcol, altitudine, stress o una malattia. È un avviso basato sui tuoi parametri, non una diagnosi.", - "building": "Stiamo costruendo i tuoi riferimenti personali — registra ancora qualche giorno e comparirà.", + "factors": "Possibili fattori, mai una causa: un allenamento intenso, poco sonno, alcol, altitudine, stress o una malattia. È un avviso basato sui tuoi parametri, non una diagnosi.", + "building": "Stiamo costruendo i tuoi riferimenti personali. Registra ancora qualche giorno e comparirà.", "illnessExplained": "Questi scostamenti riflettono probabilmente la condizione che hai registrato." }, "trajectory": { "cardTitle": "Proiezione a breve termine", - "headline": "Se questo schema continua — i prossimi {days} giorni", + "headline": "Se questo schema continua: i prossimi {days} giorni", "range": "Proiettato intorno a {low}–{high} {unit} tra {days} giorni.", "caveat": "Una proiezione della tua tendenza recente, non una previsione. La banda ombreggiata si allarga per mostrare quanto rapidamente cresce l’incertezza.", - "insufficient": "Non c’è ancora una tendenza abbastanza chiara da proiettare — continua a registrare e comparirà una proiezione quando lo schema recente sarà abbastanza marcato.", + "insufficient": "Non c’è ancora una tendenza abbastanza chiara da proiettare. Continua a registrare e comparirà una proiezione quando lo schema recente sarà abbastanza marcato.", "daysNeeded": "Servono ancora circa {count} giorni di registrazione prima che possa comparire una proiezione." }, "sameTime": { "sectionTitle": "Oggi finora", "sectionSubtitle": "I tuoi totali progressivi rispetto a ciò che per te è abituale a quest'ora", - "learning": "Sto imparando la tua giornata tipo — {count} di {target} giorni", + "learning": "Sto imparando la tua giornata tipo: {count} di {target} giorni", "framing": "Abituale entro le {time}: {typical} {unit}", "comparisonLabel": "La tua giornata tipo" } @@ -4492,7 +4492,7 @@ "navBreathingDisturbances": "Respirazione", "rhythmEvents": { "sectionTitle": "Notifiche sulla salute del dispositivo", - "sectionIntro": "Notifiche che il tuo orologio ha inviato autonomamente. HealthLog si limita a mostrarle — non le rileva, conferma né interpreta.", + "sectionIntro": "Notifiche che il tuo orologio ha inviato autonomamente. HealthLog si limita a mostrarle: non le rileva, conferma né interpreta.", "loadError": "Impossibile caricare le notifiche del dispositivo.", "disclaimer": "Questi sono avvisi generati dal tuo dispositivo con il proprio rilevamento integrato. Sono mostrati qui solo a scopo informativo. Non è una valutazione medica da parte di HealthLog, e HealthLog non diagnostica alcuna condizione. Se una notifica ti preoccupa, parla con il tuo medico.", "event": { @@ -4537,9 +4537,9 @@ "detail": "Le pagine di dettaglio nascoste vengono rimosse anche dalla navigazione in alto." }, "customize": "Personalizza gli Approfondimenti", - "regenerateRateLimited": "Limite di aggiornamento raggiunto — riprova più tardi.", - "regenerateUnavailable": "Nessuna nuova analisi ricevuta — riprova più tardi.", - "regenerateError": "Aggiornamento ancora in corso — riprova tra un momento.", + "regenerateRateLimited": "Limite di aggiornamento raggiunto. Riprova più tardi.", + "regenerateUnavailable": "Nessuna nuova analisi ricevuta. Riprova più tardi.", + "regenerateError": "Aggiornamento ancora in corso. Riprova tra un momento.", "regenerateSettling": "La valutazione è ancora in preparazione", "regenerateSettleFailed": "Non è stato possibile completare l’aggiornamento. Riprova più tardi.", "deviceScore": { @@ -4561,9 +4561,9 @@ "emptyTitle": "Ancora nessun dato di recupero", "empty": "Ancora nessun dato di recupero. Collega un account WHOOP, Polar o Oura e questi punteggi si popoleranno appena il dispositivo si sincronizza.", "block": { - "ansChargeExplainer": "Quanto è carico il tuo sistema nervoso autonomo per la giornata — una lettura di ricarica ricavata dai segnali notturni di cuore e respiro.", + "ansChargeExplainer": "Quanto è carico il tuo sistema nervoso autonomo per la giornata: una lettura di ricarica ricavata dai segnali notturni di cuore e respiro.", "dayStrainExplainer": "Il carico cardiovascolare della giornata sulla scala di sforzo del tuo dispositivo. Leggilo in rapporto al tuo recupero, non come obiettivo a sé.", - "workoutStrainExplainer": "Quanto è stato impegnativo un singolo allenamento sulla stessa scala di sforzo — il costo cardiovascolare di quella sessione.", + "workoutStrainExplainer": "Quanto è stato impegnativo un singolo allenamento sulla stessa scala di sforzo: il costo cardiovascolare di quella sessione.", "cardioLoadExplainer": "Una stima del carico di allenamento che traccia il carico cardiovascolare accumulato. Confrontala con i tuoi giorni recenti.", "averageHeartRateExplainer": "La tua frequenza cardiaca media nell'arco dell'intera giornata o ciclo, come riportata dal tuo wearable.", "maxHeartRateExplainer": "La tua frequenza cardiaca massima nell'arco dell'intera giornata o ciclo, come riportata dal tuo wearable.", @@ -4576,7 +4576,7 @@ }, "resilience": { "explainer": "Quanto bene il tuo corpo bilancia il carico quotidiano con il recupero, letto dai tuoi segnali notturni degli ultimi giorni.", - "learning": "Stiamo ancora imparando la tua resilienza — qualche giorno in più stabilizzerà il livello.", + "learning": "Stiamo ancora imparando la tua resilienza. Qualche giorno in più stabilizzerà il livello.", "band": { "limited": "Limitata", "adequate": "Adeguata", @@ -4644,7 +4644,7 @@ "description": "Registra una misura con un dinamometro manuale (annota la migliore di alcune strette) e l'andamento apparirà qui.", "cta": "Registra la forza di presa" }, - "coachPrefill": "Non ho ancora registrato la forza di presa — cosa dice sulla salute dei miei muscoli e come la misuro e la miglioro?" + "coachPrefill": "Non ho ancora registrato la forza di presa. Cosa dice sulla salute dei miei muscoli e come la misuro e la miglioro?" }, "pain": { "title": "Dolore (0–10)", @@ -4655,7 +4655,7 @@ "description": "Registra come senti il dolore in questo momento sulla scala 0–10 e l'andamento apparirà qui.", "cta": "Registra un punteggio del dolore" }, - "coachPrefill": "Non ho ancora registrato punteggi del dolore — come dovrei monitorare il dolore sulla scala 0–10 e cosa conta come variazione significativa?" + "coachPrefill": "Non ho ancora registrato punteggi del dolore. Come dovrei monitorare il dolore sulla scala 0–10 e cosa conta come variazione significativa?" }, "waist": { "title": "Circonferenza vita", @@ -4666,7 +4666,7 @@ "description": "Misura la vita nel punto medio tra l'ultima costola e l'osso dell'anca, a fine espirazione normale, e registrala qui.", "cta": "Registra la circonferenza vita" }, - "coachPrefill": "Non ho ancora registrato misure della vita — come misuro la vita correttamente e cosa significa il numero per la mia salute?" + "coachPrefill": "Non ho ancora registrato misure della vita. Come misuro la vita correttamente e cosa significa il numero per la mia salute?" }, "waistToHeight": { "title": "Rapporto vita-altezza", @@ -4677,7 +4677,7 @@ "description": "Registra un rapporto vita-altezza e l'andamento apparirà qui. Regola pratica: tieni la vita sotto la metà della tua altezza.", "cta": "Registra il rapporto vita-altezza" }, - "coachPrefill": "Non ho ancora registrato un rapporto vita-altezza — perché è un numero utile e come lo tengo sotto 0,5?" + "coachPrefill": "Non ho ancora registrato un rapporto vita-altezza. Perché è un numero utile e come lo tengo sotto 0,5?" }, "ecg": { "sectionTitle": "Registrazioni ECG", @@ -4720,7 +4720,7 @@ "intradayPulse": { "title": "Battito nel corso della giornata", "caption": "Media su intervalli di 10 minuti.", - "hourlyNote": "Media oraria per questo giorno — i giorni recenti mostrano il dettaglio completo a 10 minuti.", + "hourlyNote": "Media oraria per questo giorno. I giorni recenti mostrano il dettaglio completo a 10 minuti.", "empty": "Non ci sono ancora abbastanza misurazioni per questo giorno per mostrarne l'andamento.", "coverageOne": "Basato su 1 misurazione in {hours}h.", "coverageMany": "Basato su {count} misurazioni in {hours}h.", @@ -4729,10 +4729,10 @@ "previousDay": "Giorno precedente", "nextDay": "Giorno successivo", "tension": { - "morning": "Un tratto elevato a riposo stamattina — forse un po' di tensione.", - "afternoon": "Un tratto elevato a riposo questo pomeriggio — forse un po' di tensione.", - "evening": "Un tratto elevato a riposo stasera — forse un po' di tensione.", - "night": "Un tratto elevato a riposo durante la notte — forse un po' di tensione." + "morning": "Un tratto elevato a riposo stamattina, forse un po' di tensione.", + "afternoon": "Un tratto elevato a riposo questo pomeriggio, forse un po' di tensione.", + "evening": "Un tratto elevato a riposo stasera, forse un po' di tensione.", + "night": "Un tratto elevato a riposo durante la notte, forse un po' di tensione." } }, "navEcg": "ECG", @@ -4785,14 +4785,14 @@ "metricBodyFat": "Massa grassa", "metricSleep": "Durata del sonno", "metricSteps": "Passi/giorno", - "metricGlucoseFasting": "Glicemia — a digiuno", - "metricGlucosePostprandial": "Glicemia — postprandiale", - "metricGlucoseRandom": "Glicemia — qualsiasi", - "metricGlucoseBedtime": "Glicemia — prima di coricarsi", + "metricGlucoseFasting": "Glicemia (a digiuno)", + "metricGlucosePostprandial": "Glicemia (postprandiale)", + "metricGlucoseRandom": "Glicemia (qualsiasi)", + "metricGlucoseBedtime": "Glicemia (prima di coricarsi)", "metricBodyWater": "Acqua corporea", "metricBoneMass": "Massa ossea", "metricOxygenSaturation": "Saturazione di ossigeno (SpO₂)", - "unsetExplanation": "Nessun valore personale — è attivo il predefinito calcolato.", + "unsetExplanation": "Nessun valore personale: è attivo il predefinito calcolato.", "cardTitle": "Intervalli per metrica" }, "onboarding": { @@ -4810,7 +4810,7 @@ }, "quickAdd": { "title": "Registrato in pochi secondi", - "body": "Con « + Aggiungi » registri qualsiasi misurazione in pochi secondi — peso, pressione, polso, glicemia. Forza nascosta: retrodatare i valori dimenticati. Tutto ciò che inserisci qui alimenta tendenze, punteggio salute e analisi IA." + "body": "Con « + Aggiungi » registri qualsiasi misurazione in pochi secondi: peso, pressione, polso, glicemia. Forza nascosta: retrodatare i valori dimenticati. Tutto ciò che inserisci qui alimenta tendenze, punteggio salute e analisi IA." }, "measurements": { "title": "Misurazioni e intervalli obiettivo", @@ -4822,7 +4822,7 @@ }, "labs": { "title": "Valori di laboratorio", - "body": "Laboratorio raccoglie i biomarcatori con intervalli di riferimento — emocromo, colesterolo, HbA1c. Forza: importazione ed esportazione FHIR. I valori fuori intervallo riemergono come prove nelle analisi e nel referto medico." + "body": "Laboratorio raccoglie i biomarcatori con intervalli di riferimento: emocromo, colesterolo, HbA1c. Forza: importazione ed esportazione FHIR. I valori fuori intervallo riemergono come prove nelle analisi e nel referto medico." }, "illness": { "title": "Diario delle malattie", @@ -4838,11 +4838,11 @@ }, "mood": { "title": "Umore", - "body": "Umore cattura come ti senti e dei tag in due secondi. Forza: i tuoi tag personalizzati. Gli andamenti dell’umore si correlano con sonno, farmaci e ciclo — il Coach coglie gli schemi." + "body": "Umore cattura come ti senti e dei tag in due secondi. Forza: i tuoi tag personalizzati. Gli andamenti dell’umore si correlano con sonno, farmaci e ciclo, e il Coach coglie gli schemi." }, "insights": { "title": "Analisi", - "body": "Analisi è il cuore: analisi dinamica e basata su prove invece di consigli generici — ogni affermazione punta ai tuoi dati reali. Nascosto: il layout è personalizzabile. Analisi raccoglie tutto ciò che forniscono i moduli sopra." + "body": "Analisi è il cuore: analisi dinamica e basata su prove invece di consigli generici, dove ogni affermazione punta ai tuoi dati reali. Nascosto: il layout è personalizzabile. Analisi raccoglie tutto ciò che forniscono i moduli sopra." }, "coach": { "title": "Coach", @@ -4858,7 +4858,7 @@ }, "achievements": { "title": "Traguardi", - "body": "I traguardi premiano la costanza — serie e tappe. Un piccolo ciclo di motivazione che rende più facile non mollare." + "body": "I traguardi premiano la costanza: serie e tappe. Un piccolo ciclo di motivazione che rende più facile non mollare." }, "wrapUp": { "title": "Questa è la visita guidata", @@ -4893,7 +4893,7 @@ "title": "Tutto pronto", "body": "Benvenuto a bordo. La tua dashboard è pronta.", "returnCta": "Apri la dashboard", - "learning": "Alcune analisi — glicemia, ritmo del sonno, tendenze della pressione, ciclo — si affinano nella prima settimana o due man mano che i tuoi dati si accumulano. Le caselle vuote ora indicano solo che stiamo ancora imparando il tuo riferimento.", + "learning": "Alcune analisi (glicemia, ritmo del sonno, tendenze della pressione, ciclo) si affinano nella prima settimana o due man mano che i tuoi dati si accumulano. Le caselle vuote ora indicano solo che stiamo ancora imparando il tuo riferimento.", "connectCta": "Collega un dispositivo", "logCta": "Registra la tua prima misurazione", "importCta": "Importa la cronologia esistente", @@ -4925,18 +4925,18 @@ "sampleTitle": "Briefing quotidiano", "sampleTag": "Esempio", "sampleAriaLabel": "Briefing quotidiano di esempio", - "sampleBody": "Peso in calo di 1,2 kg in due settimane. Battito a riposo stabile a 58 bpm. Pressione nel range in 6 giorni su 7 — l'unico valore alto è arrivato dopo una cena tardiva e salata.", - "sampleCaption": "Solo un esempio — non i tuoi dati. Ecco come si legge un briefing quando gli insight sono attivi.", + "sampleBody": "Peso in calo di 1,2 kg in due settimane. Battito a riposo stabile a 58 bpm. Pressione nel range in 6 giorni su 7: l'unico valore alto è arrivato dopo una cena tardiva e salata.", + "sampleCaption": "Solo un esempio, non i tuoi dati. Ecco come si legge un briefing quando gli insight sono attivi.", "ladderTitle": "Tre modi per attivarlo", - "ladderLocalTitle": "Modello locale — le richieste all’IA restano nella tua rete", - "ladderLocalBody": "Punta HealthLog su Ollama o LM Studio sulla tua macchina. Gratis e del tutto privato — la scelta tranquilla di default.", + "ladderLocalTitle": "Modello locale: le richieste all’IA restano nella tua rete", + "ladderLocalBody": "Punta HealthLog su Ollama o LM Studio sulla tua macchina. Gratis e del tutto privato: la scelta tranquilla di default.", "ladderByokTitle": "Usa la tua chiave", "ladderByokBody": "Usa la tua chiave OpenAI o Anthropic. Gira sul tuo account e sulla tua fatturazione, e il piano API tiene i tuoi dati fuori dall'addestramento in modo predefinito.", "ladderOauthTitle": "Accedi con un abbonamento", - "ladderOauthBody": "Collega un account ChatGPT — nessun costo per token, ma i termini del piano consumer possono usare i contenuti per l'addestramento, quindi è una scelta deliberata, mai l'impostazione predefinita per i tuoi dati sanitari.", - "keylessLine": "HealthLog è pienamente utile anche senza IA. Le tue schede, i grafici, i trend e le esportazioni funzionano tutti — l'IA aggiunge solo la lettura in linguaggio chiaro.", + "ladderOauthBody": "Collega un account ChatGPT. Nessun costo per token, ma i termini del piano consumer possono usare i contenuti per l'addestramento, quindi è una scelta deliberata, mai l'impostazione predefinita per i tuoi dati sanitari.", + "keylessLine": "HealthLog è pienamente utile anche senza IA. Le tue schede, i grafici, i trend e le esportazioni funzionano tutti; l'IA aggiunge solo la lettura in linguaggio chiaro.", "setupCta": "Configuralo (circa un minuto)", - "sharedKeyNote": "Questa istanza fornisce già un provider IA condiviso, quindi gli insight funzionano per te fin da subito — nessuna configurazione necessaria.", + "sharedKeyNote": "Questa istanza fornisce già un provider IA condiviso, quindi gli insight funzionano per te fin da subito, senza alcuna configurazione.", "offer": { "title": "Questa istanza può già scrivere il tuo riepilogo in parole semplici.", "body": "Il gestore mette a disposizione un fornitore che ha funzionato nelle ultime 24 ore. Con un tocco attivi le parole semplici; i tuoi dati andranno allora a quell’unico fornitore e a nessun altro.", @@ -5153,7 +5153,7 @@ "profileDescription": "Altezza, data di nascita e sesso sbloccano obiettivi personalizzati.", "profileCta": "Apri profilo", "measurementTitle": "Registra la prima misurazione", - "measurementDescription": "Una misurazione attiva il tile — il trend si disegna dalla 5ª misurazione.", + "measurementDescription": "Una misurazione attiva il tile; il trend si disegna dalla 5ª misurazione.", "measurementCta": "Aggiungi misurazione", "medicationTitle": "Aggiungi un farmaco", "medicationDescription": "Monitora l’aderenza e ricevi promemoria proprio quando ti servono.", @@ -5162,7 +5162,7 @@ "dataSourceDescription": "Sincronizza peso, pressione, sonno e altro da Withings, WHOOP, Oura, Polar, Nightscout, Fitbit o Apple Health.", "dataSourceCta": "Collega", "notificationsTitle": "Configura le notifiche", - "notificationsDescription": "Scegli come HealthLog ti ricorda — Telegram, ntfy o Web Push.", + "notificationsDescription": "Scegli come HealthLog ti ricorda: Telegram, ntfy o Web Push.", "notificationsCta": "Apri notifiche", "insightsTitle": "Attiva gli insight (facoltativo)", "insightsDescription": "Aggiungi un modello locale o la tua chiave IA per sbloccare il briefing quotidiano e Coach.", @@ -5388,7 +5388,7 @@ "resetSuccess": "Priorità delle fonti ripristinata ai valori predefiniti", "perMetricToggle": "Personalizzazioni per metrica ({count})", "perMetricHelp": "Metriche che hai personalizzato rispetto all’ordine predefinito. Usa questo elenco per riportare una singola metrica al suo valore predefinito senza toccare le altre.", - "perMetricEmpty": "Nessuna personalizzazione per metrica — ogni metrica usa l’ordine globale qui sopra.", + "perMetricEmpty": "Nessuna personalizzazione per metrica: ogni metrica usa l’ordine globale qui sopra.", "resetMetric": "Reimposta", "deviceTypeToggle": "Priorità per tipo di dispositivo ({count})", "deviceTypeHelp": "All’interno di una fonte, quale dispositivo prevale. Quando un Apple Watch e un iPhone registrano entrambi i passi, il tipo di dispositivo più in alto conta come lettura canonica.", @@ -5497,7 +5497,7 @@ "fullBackup": { "title": "Backup completo", "description": "L'intera cartella in un unico file JSON.", - "scopeNote": "I metadati dei documenti e il riepilogo IA, se presente, sono inclusi in chiaro; i file originali dei documenti e i dati di percorso GPS/campionamento degli allenamenti non lo sono — scaricali separatamente dall'archivio documenti o dall'esportazione degli allenamenti.", + "scopeNote": "I metadati dei documenti e il riepilogo IA, se presente, sono inclusi in chiaro; i file originali dei documenti e i dati di percorso GPS/campionamento degli allenamenti non lo sono. Scaricali separatamente dall'archivio documenti o dall'esportazione degli allenamenti.", "encryptToggle": "Cifra con una passphrase", "passphrasePlaceholder": "Passphrase (min. 12 caratteri)", "passphraseHelp": "Deriva la chiave dell'archivio con Argon2id e lo sigilla con AES-256-GCM. Salva il file con estensione .hlx.", @@ -6048,7 +6048,7 @@ "rawDataWarning": "Cronologia dettagliata attiva: ogni analisi invia anche le medie giornaliere degli ultimi 90 giorni, le medie settimanali dell’anno precedente e le medie mensili fino a 5 anni fa.", "regenerateInsights": "Rigenera i report", "regenerateSuccess": "Report rigenerati correttamente", - "regenerateRateLimit": "Attendi — hai raggiunto il limite orario di analisi.", + "regenerateRateLimit": "Attendi: hai raggiunto il limite orario di analisi.", "lastGeneratedAt": "Ultima generazione", "ai": { "chatgptConnectedBadge": "ChatGPT connesso", @@ -6058,11 +6058,11 @@ "deviceCodeHeading": "Completa la connessione su chatgpt.com", "deviceCodeStep1": "Apri questo link su qualsiasi dispositivo:", "deviceCodeStep2": "Inserisci questo codice monouso:", - "deviceCodeStep3": "Approva la connessione — questa pagina si aggiorna automaticamente.", + "deviceCodeStep3": "Approva la connessione. Questa pagina si aggiorna automaticamente.", "deviceCodeCopy": "Copia", "deviceCodeWaiting": "In attesa di approvazione…", "deviceCodeCancel": "Annulla", - "oauthNotConfigured": "L’OAuth di ChatGPT non è configurato su questa istanza — usa invece la tua chiave API qui sotto.", + "oauthNotConfigured": "L’OAuth di ChatGPT non è configurato su questa istanza. Usa invece la tua chiave API qui sotto.", "modelLabel": "Modello", "modelOptionDefault": "— Predefinito —", "modelOptionCustom": "Personalizzato…", @@ -6146,18 +6146,18 @@ "notConfigured": "L’operatore non ha configurato una chiave OpenAI condivisa su questa istanza." }, "testProvider": "Prova il provider attivo", - "testSuccess": "OK — {provider} ({model})", + "testSuccess": "OK: {provider} ({model})", "testFailedShort": "Prova non riuscita: {message}", - "testUnexpectedResponse": "Connessione al provider IA non riuscita — risposta inattesa dal server.", - "testReasonCredentials": "Il provider ha rifiutato le credenziali — autenticati di nuovo nelle impostazioni IA.", - "testReasonRateLimited": "Il provider ha limitato la richiesta — riprova a breve.", + "testUnexpectedResponse": "Connessione al provider IA non riuscita: risposta inattesa dal server.", + "testReasonCredentials": "Il provider ha rifiutato le credenziali. Autenticati di nuovo nelle impostazioni IA.", + "testReasonRateLimited": "Il provider ha limitato la richiesta. Riprova a breve.", "testReasonServerError": "Il provider IA ha restituito un errore del server.", "testReasonBadRequest": "Il provider ha rifiutato la richiesta (HTTP {status}): l'endpoint ha risposto, quindi il problema riguarda il formato della richiesta o il nome del modello, non la connessione.", "testReasonUnreachable": "Impossibile raggiungere il provider IA.", "coachMemory": { "title": "Ciò che il Coach ricorda", "description": "Informazioni durature che hai comunicato al Coach.", - "empty": "Il Coach non ha ancora memorizzato alcuna informazione. Mentre chatti, ricorda i dettagli duraturi che condividi — i tuoi obiettivi, le condizioni, le preferenze — e puoi cancellarli qui in qualsiasi momento.", + "empty": "Il Coach non ha ancora memorizzato alcuna informazione. Mentre chatti, ricorda i dettagli duraturi che condividi (i tuoi obiettivi, le condizioni, le preferenze) e puoi cancellarli qui in qualsiasi momento.", "learnedPrefix": "appreso {when}", "categoryPreference": "Preferenze", "categoryCondition": "Condizioni", @@ -6173,7 +6173,7 @@ "forgetAllConfirmBody": "Questo rimuove tutte le informazioni memorizzate. Il Coach ripartirà da zero alla prossima chat. L'operazione non può essere annullata.", "forgetAllConfirmAction": "Dimentica tutto", "cancel": "Annulla", - "summaryNote": "Il Coach può anche conservare un breve riassunto progressivo di ogni conversazione. Non esiste un controllo per ogni voce — eliminando una conversazione si elimina anche il suo riassunto.", + "summaryNote": "Il Coach può anche conservare un breve riassunto progressivo di ogni conversazione. Non esiste un controllo per ogni voce: eliminando una conversazione si elimina anche il suo riassunto.", "loadError": "Impossibile caricare ciò che il Coach ricorda.", "forgotToast": "Informazione dimenticata.", "forgotError": "Impossibile dimenticare questa informazione. Riprova.", @@ -6194,7 +6194,7 @@ "markDone": "Fatto", "dismiss": "Ignora", "deleteAria": "Elimina questo promemoria", - "note": "I promemoria sono memorizzati cifrati. Eliminane uno in qualsiasi momento — viene rimosso da ciò che il Coach può vedere.", + "note": "I promemoria sono memorizzati cifrati. Eliminane uno in qualsiasi momento e viene rimosso da ciò che il Coach può vedere.", "status": { "proposed": "Suggerito", "active": "Salvato", @@ -6241,14 +6241,14 @@ "title": "Leggi i documenti automaticamente con l'IA", "subLabel": "I documenti vengono letti e indicizzati dal provider di IA configurato, senza confermare ogni documento.", "honesty": "Quando è attivo, ogni documento che carichi viene inviato al provider di IA configurato per essere letto, descritto e indicizzato per la ricerca, senza conferma per singolo documento. Attivarlo agisce anche retroattivamente: i documenti che hai già caricato e che non hanno ancora un riassunto vengono inviati anch'essi, fino a 200 per ogni attivazione. Questo avviene sul server e il contenuto del documento lascia questa macchina verso quel provider. Se il provider configurato è una connessione in abbonamento (un account IA con accesso effettuato anziché una chiave API), si applicano le sue impostazioni sui dati: i provider in abbonamento possono usare il contenuto per migliorare i propri modelli e nessun accordo sul trattamento dei dati lo copre. I documenti letti da un modello locale self-hosted non lasciano mai il tuo server. Disattivato per impostazione predefinita; attivalo solo se accetti questo compromesso per i tuoi documenti.", - "confirm": "Ho capito — attiva", + "confirm": "Ho capito, attiva", "cancel": "Annulla" }, "centralCodex": { "title": "Usa l'accesso IA condiviso del server", "subLabel": "Le richieste IA passano dalla connessione condivisa del server, con i tuoi provider come ripiego.", "honesty": "L'accesso condiviso è un unico account IA con accesso eseguito che l'operatore ha collegato per tutti su questo server, non la tua chiave. Le richieste che vi effettui vengono usate per impostazione predefinita per addestrare i modelli del provider e nessun accordo sul trattamento dei dati le copre, i limiti orari e settimanali dell'account sono condivisi con tutti gli altri che hanno aderito, e i tuoi provider vengono comunque provati per primi. Attivalo solo se accetti questo compromesso.", - "confirm": "Ho capito — usa la connessione", + "confirm": "Ho capito, usa la connessione", "cancel": "Annulla" }, "consent": { @@ -6324,8 +6324,8 @@ "withingsClientId": "ID client", "withingsClientSecret": "Secret client", "withingsCredentialsSaved": "Credenziali salvate", - "withingsCredentialsSavedPlaceholder": "Salvato — inseriscine uno nuovo per sostituirlo", - "withingsCredentialsSavedPlaceholderSecret": "Salvato — inseriscine uno nuovo per sostituirlo", + "withingsCredentialsSavedPlaceholder": "Salvato. Inseriscine uno nuovo per sostituirlo", + "withingsCredentialsSavedPlaceholderSecret": "Salvato. Inseriscine uno nuovo per sostituirlo", "withingsSaveCredentials": "Salva", "configured": "Configurato", "withingsSync": "Sincronizza ora", @@ -6340,7 +6340,7 @@ }, "withingsFullSyncResult": "{count} misurazioni sincronizzate completamente", "withingsSyncFailed": "Sincronizzazione non riuscita", - "withingsOauthConnected": "Withings collegato — la prima sincronizzazione parte in background.", + "withingsOauthConnected": "Withings collegato: la prima sincronizzazione parte in background.", "withingsOauthFailed": "Collegamento a Withings non riuscito", "withingsOauthError": { "csrf1": "Il controllo di sicurezza non è riuscito perché mancava il cookie del browser. Avvia di nuovo il collegamento nello stesso browser.", @@ -6365,8 +6365,8 @@ "whoopClientId": "Client ID", "whoopClientSecret": "Client Secret", "whoopCredentialsSaved": "Credenziali salvate", - "whoopCredentialsSavedPlaceholder": "Salvato — inserisci nuove per sostituire", - "whoopCredentialsSavedPlaceholderSecret": "Salvato — inserisci nuove per sostituire", + "whoopCredentialsSavedPlaceholder": "Salvato. Inserisci nuove per sostituire", + "whoopCredentialsSavedPlaceholderSecret": "Salvato. Inserisci nuove per sostituire", "whoopSaveCredentials": "Salva", "whoopSync": "Sincronizza ora", "whoopFullSync": "Sincronizza tutti i dati", @@ -6381,7 +6381,7 @@ "whoopConnect": "Connetti con WHOOP", "whoopNoCredentials": "Inserisci le tue credenziali API qui sopra per connettere WHOOP.", "whoopBackfillInProgress": "Importazione dello storico WHOOP in background…", - "whoopOauthConnected": "WHOOP collegato — la prima sincronizzazione parte in background.", + "whoopOauthConnected": "WHOOP collegato: la prima sincronizzazione parte in background.", "whoopOauthFailed": "Connessione a WHOOP non riuscita", "whoopOauthError": { "csrf1": "Il controllo di sicurezza è fallito perché il cookie del browser era assente. Riavvia la connessione nello stesso browser.", @@ -6395,14 +6395,14 @@ }, "fitbit": "Fitbit", "fitbitTag": "Fitbit e Pixel", - "fitbitDescription": "Collega Fitbit per sincronizzare i dati di Fitbit e Pixel Watch — peso, frequenza cardiaca e altro.", + "fitbitDescription": "Collega Fitbit per sincronizzare i dati di Fitbit e Pixel Watch: peso, frequenza cardiaca e altro.", "fitbitExperimentalBadge": "Sperimentale", "fitbitCredentials": "Credenziali API", "fitbitClientId": "Client ID", "fitbitClientSecret": "Client Secret", "fitbitCredentialsSaved": "Credenziali salvate", - "fitbitCredentialsSavedPlaceholder": "Salvato — inserisci nuove per sostituire", - "fitbitCredentialsSavedPlaceholderSecret": "Salvato — inserisci nuove per sostituire", + "fitbitCredentialsSavedPlaceholder": "Salvato. Inserisci nuove per sostituire", + "fitbitCredentialsSavedPlaceholderSecret": "Salvato. Inserisci nuove per sostituire", "fitbitSaveCredentials": "Salva", "fitbitSync": "Sincronizza ora", "fitbitFullSync": "Sincronizza tutti i dati", @@ -6417,18 +6417,18 @@ "fitbitConnect": "Connetti con Fitbit", "fitbitNoCredentials": "Inserisci le tue credenziali API qui sopra per connettere Fitbit.", "fitbitBackfillInProgress": "Importazione dello storico Fitbit in background…", - "fitbitOauthConnected": "Fitbit collegato — la prima sincronizzazione parte in background.", + "fitbitOauthConnected": "Fitbit collegato: la prima sincronizzazione parte in background.", "fitbitOauthFailed": "Connessione a Fitbit non riuscita", "googleHealth": "Google Health", "googleHealthTag": "Fitbit e Pixel", "googleHealthBetaBadge": "Beta", - "googleHealthDescription": "Collega Fitbit, Pixel Watch e Fitbit Air tramite il tuo account Google — peso, frequenza cardiaca, sonno e attività. Sostituisce la connessione Fitbit classica, che Google ritira a settembre 2026.", + "googleHealthDescription": "Collega Fitbit, Pixel Watch e Fitbit Air tramite il tuo account Google: peso, frequenza cardiaca, sonno e attività. Sostituisce la connessione Fitbit classica, che Google ritira a settembre 2026.", "googleHealthCredentials": "Credenziali API", "googleHealthClientId": "ID client", "googleHealthClientSecret": "Client secret", "googleHealthCredentialsSaved": "Credenziali salvate", - "googleHealthCredentialsSavedPlaceholder": "Salvate — inseriscine di nuove per sostituirle", - "googleHealthCredentialsSavedPlaceholderSecret": "Salvate — inseriscine di nuove per sostituirle", + "googleHealthCredentialsSavedPlaceholder": "Salvate. Inseriscine di nuove per sostituirle", + "googleHealthCredentialsSavedPlaceholderSecret": "Salvate. Inseriscine di nuove per sostituirle", "googleHealthSaveCredentials": "Salva", "googleHealthSync": "Sincronizza ora", "googleHealthSyncCheckStatus": "Aggiorna stato", @@ -6462,9 +6462,9 @@ "googleHealthConnect": "Connetti con Google", "googleHealthNoCredentials": "Inserisci le tue credenziali API qui sopra per connettere Google Health.", "googleHealthBackfillInProgress": "Importazione della cronologia di Google Health in background…", - "googleHealthReauthBanner": "Google ha fatto scadere la connessione — accade periodicamente finché la tua app OAuth resta in modalità Test. Riconnettiti per riprendere la sincronizzazione.", + "googleHealthReauthBanner": "Google ha fatto scadere la connessione. Accade periodicamente finché la tua app OAuth resta in modalità Test. Riconnettiti per riprendere la sincronizzazione.", "googleHealthReconnect": "Riconnetti", - "googleHealthOauthConnected": "Google Health connesso — la prima sincronizzazione parte in background.", + "googleHealthOauthConnected": "Google Health connesso: la prima sincronizzazione parte in background.", "googleHealthOauthFailed": "Connessione a Google Health non riuscita", "googleHealthOauthError": { "csrf1": "Il controllo di sicurezza non è riuscito perché mancava il cookie del browser. Riavvia la connessione nello stesso browser.", @@ -6499,10 +6499,10 @@ }, "integrationPill": { "connected": "Connesso", - "errorReconnect": "Errore — riconnetti", + "errorReconnect": "Errore, riconnetti", "warningServerError": "Sincronizzazione in errore", "failureCount": "{count}/{threshold}", - "parkedReconnect": "In pausa — riconnetti", + "parkedReconnect": "In pausa, riconnetti", "notConnected": "Non connesso", "justNow": "proprio ora", "minutesAgo": "{count} min fa", @@ -6557,7 +6557,7 @@ "namePlaceholder": "Nome, ad es. Paperless-ngx" }, "tokenMintMovedDescription": "I token vengono emessi dove si applicano: qui sopra per le misurazioni, gli allenamenti e i documenti, oppure nell'endpoint API di un farmaco per quel singolo farmaco.", - "tokenCreated": "Token creato — copialo ora! Non verrà mostrato di nuovo.", + "tokenCreated": "Token creato: copialo ora! Non verrà mostrato di nuovo.", "tokenCopy": "Copia token", "tokenCopied": "Token copiato negli appunti", "tokenCopyFailed": "Impossibile copiare il token", @@ -6596,7 +6596,7 @@ "deleteAccountCta": "Elimina account", "deleteAccountConfirmTitle": "Eliminare definitivamente l’account?", "deleteAccountConfirmDescription": "Il tuo account, tutti i dati sanitari, le passkey, le sessioni e le voci di audit verranno eliminati definitivamente. Verrai disconnesso subito dopo.", - "deleteAccountSuccess": "Account eliminato — disconnessione in corso.", + "deleteAccountSuccess": "Account eliminato, disconnessione in corso.", "deleteAccountFailed": "Impossibile eliminare l’account", "deleteAccountFinal": "Elimina definitivamente", "saved": "Salvato", @@ -6619,7 +6619,7 @@ "testing": "Test in corso…", "ok": "Connesso (latenza {latency} ms)", "errors": { - "credentials_rejected": "Credenziali rifiutate — controlla il token", + "credentials_rejected": "Credenziali rifiutate: controlla il token", "rate_limited": "Limitato dal servizio upstream", "timeout": "Richiesta scaduta", "upstream_error": "Il servizio upstream ha restituito un errore", @@ -6630,7 +6630,7 @@ "private_origin_not_approved": "Destinazione su una rete privata. L’operatore deve aggiungere questa origine a NOTIFICATION_PRIVATE_ORIGINS", "private_origin_not_grantable": "Questo indirizzo è link-local, dei metadati o non specificato; nessuna autorizzazione dell’operatore può aprirlo. Usa l’indirizzo su cui il relay è in ascolto", "url_invalid": "L’URL non è valido", - "redirected": "L’endpoint reindirizza — controlla l’URL", + "redirected": "L’endpoint reindirizza: controlla l’URL", "endpoint_not_found": "Endpoint non trovato all’URL", "credentials_unreadable": "Impossibile decifrare le credenziali", "upstream_invalid_json": "Il servizio upstream ha inviato un JSON non valido", @@ -6641,7 +6641,7 @@ }, "notificationStatus": { "title": "Affidabilità dei canali", - "description": "Stato di ogni canale — «Disattivato automaticamente» significa fermato dopo errori permanenti.", + "description": "Stato di ogni canale; «Disattivato automaticamente» significa fermato dopo errori permanenti.", "emptyDescription": "Aggiungi un canale in Impostazioni › Integrazioni › Canali di recapito.", "stateActive": "Attivo", "stateAutoDisabled": "Disattivato automaticamente", @@ -6667,7 +6667,7 @@ }, "healthRecord": { "title": "Esporta cartella clinica", - "description": "Una cartella completa per il medico — in PDF, in FHIR o entrambi.", + "description": "Una cartella completa per il medico, in PDF, in FHIR o entrambi.", "format": "Formato", "format_pdf": "PDF", "format_fhir": "Strutturato (FHIR)", @@ -6699,7 +6699,7 @@ "createTitle": "Nuovo link di condivisione", "createDescription": "Il link è di sola lettura e a tempo.", "label": "Etichetta", - "labelPlaceholder": "es. Dott. Rossi — controllo annuale", + "labelPlaceholder": "es. Dott. Rossi, controllo annuale", "range": "Giorni di cronologia", "rangeHint": "Fin dove si estende la finestra condivisa.", "expiry": "Scade tra (giorni)", @@ -6719,7 +6719,7 @@ "statusRevoked": "Revocato", "statusExpired": "Scaduto", "inactiveTitle": "Revocati e scaduti ({count})", - "shownOnce": "Mostrato una sola volta. Salva ora il codice QR e la passphrase — non potranno essere recuperati in seguito.", + "shownOnce": "Mostrato una sola volta. Salva ora il codice QR e la passphrase: non potranno essere recuperati in seguito.", "qrAlt": "Codice QR contenente il link di condivisione e la passphrase", "linkLabel": "Link", "passphraseLabel": "Passphrase", @@ -6748,7 +6748,7 @@ "statusNeedsReselect": "Scegli di nuovo il contenuto", "reselectReason": "Questo link mostrava un ambito che nessuno aveva scelto, perciò è stato chiuso. Creane uno nuovo e scegli cosa deve contenere.", "reselectAction": "Crea un sostituto", - "createDetail": "Il token viene mostrato una sola volta alla creazione — salvalo subito; non può essere recuperato.", + "createDetail": "Il token viene mostrato una sola volta alla creazione: salvalo subito, non può essere recuperato.", "activeDescription": "I link che hai condiviso, quando scadono e quante volte sono stati aperti." }, "genderOther": "Altro", @@ -6757,10 +6757,10 @@ "nightscoutDescription": "Collega il tuo sito Nightscout per sincronizzare le letture continue del glucosio nel pannello glucosio.", "nightscoutViewData": "Vedi la tua glicemia", "nightscoutUrl": "URL Nightscout", - "nightscoutUrlSavedPlaceholder": "Salvato — inserisci un nuovo URL per sostituirlo", + "nightscoutUrlSavedPlaceholder": "Salvato. Inserisci un nuovo URL per sostituirlo", "nightscoutToken": "Token API", "nightscoutTokenOptional": "Facoltativo per un sito pubblico", - "nightscoutTokenSavedPlaceholder": "Salvato — inserisci un nuovo token per sostituirlo", + "nightscoutTokenSavedPlaceholder": "Salvato. Inserisci un nuovo token per sostituirlo", "nightscoutTokenHelp": "Incolla un token di accesso dagli strumenti di amministrazione di Nightscout. Lascia vuoto se il tuo sito è leggibile pubblicamente.", "nightscoutPrivateOperatorTitle": "L’accesso a un Nightscout privato richiede l’approvazione dell’amministratore del server.", "nightscoutPrivateOperatorDescription": "Chiedi all’amministratore del server di approvare esattamente questa origine Nightscout.", @@ -6781,7 +6781,7 @@ "polarClientId": "Client ID", "polarClientSecret": "Client Secret", "polarCredentialsSaved": "Credenziali salvate", - "polarCredentialsSavedPlaceholder": "Salvato — inserisci nuove per sostituire", + "polarCredentialsSavedPlaceholder": "Salvato. Inserisci nuove per sostituire", "polarSaveCredentials": "Salva", "polarUnavailable": "Polar non è configurato su questo server. Aggiungi sopra le tue credenziali OAuth di Polar oppure chiedi al tuo amministratore di configurare l'app condivisa.", "polarConnect": "Collega Polar", @@ -6791,7 +6791,7 @@ "polarDisconnect": "Disconnetti", "polarDisconnectTitle": "Disconnettere Polar?", "polarDisconnectDescription": "Le sincronizzazioni future si interrompono. Le letture già importate restano nella tua cronologia.", - "polarOauthConnected": "Polar collegato — la prima sincronizzazione parte in background.", + "polarOauthConnected": "Polar collegato: la prima sincronizzazione parte in background.", "polarOauthFailed": "Connessione a Polar non riuscita", "polarOauthError": { "csrf1": "Il controllo di sicurezza è fallito perché il cookie del browser era assente. Riavvia la connessione nello stesso browser.", @@ -6810,7 +6810,7 @@ "ouraClientId": "Client ID", "ouraClientSecret": "Client Secret", "ouraCredentialsSaved": "Credenziali salvate", - "ouraCredentialsSavedPlaceholder": "Salvato — inserisci nuove per sostituire", + "ouraCredentialsSavedPlaceholder": "Salvato. Inserisci nuove per sostituire", "ouraSaveCredentials": "Salva", "ouraUnavailable": "Oura non è configurato su questo server. Aggiungi sopra le tue credenziali OAuth di Oura oppure chiedi al tuo amministratore di configurare l'app condivisa.", "ouraConnect": "Collega Oura", @@ -6820,7 +6820,7 @@ "ouraDisconnect": "Disconnetti", "ouraDisconnectTitle": "Disconnettere Oura?", "ouraDisconnectDescription": "Le sincronizzazioni future si interrompono. Le letture già importate restano nella tua cronologia.", - "ouraOauthConnected": "Oura collegato — la prima sincronizzazione parte in background.", + "ouraOauthConnected": "Oura collegato: la prima sincronizzazione parte in background.", "ouraOauthFailed": "Connessione a Oura non riuscita", "ouraOauthError": { "csrf1": "Il controllo di sicurezza è fallito perché il cookie del browser era assente. Riavvia la connessione nello stesso browser.", @@ -6851,7 +6851,7 @@ } }, "integrationRedirectGuide": { - "intro": "Questa connessione passa dalla tua app sviluppatore {provider} — circa 5 minuti di configurazione:", + "intro": "Questa connessione passa dalla tua app sviluppatore {provider} (circa 5 minuti di configurazione):", "step1": "Crea un'app nel portale sviluppatori {provider}.", "step2": "Imposta il suo URL di reindirizzamento/callback su:", "step3": "Incolla qui sopra l'ID client e il client secret ricevuti." @@ -7038,7 +7038,7 @@ "stravaClientId": "ID client", "stravaClientSecret": "Secret client", "stravaCredentialsSaved": "Credenziali salvate", - "stravaCredentialsSavedPlaceholder": "Salvate — inseriscine di nuove per sostituirle", + "stravaCredentialsSavedPlaceholder": "Salvate. Inseriscine di nuove per sostituirle", "stravaSaveCredentials": "Salva", "stravaUnavailable": "Strava non è configurato su questo server. Aggiungi sopra le tue credenziali API di Strava o chiedi al tuo amministratore di configurare l'app condivisa.", "stravaConnect": "Collega Strava", @@ -7048,7 +7048,7 @@ "stravaDisconnect": "Disconnetti", "stravaDisconnectTitle": "Disconnettere Strava?", "stravaDisconnectDescription": "Le sincronizzazioni future si interrompono. Le attività già importate restano nella cronologia.", - "stravaOauthConnected": "Strava collegato — la prima sincronizzazione parte in background.", + "stravaOauthConnected": "Strava collegato: la prima sincronizzazione parte in background.", "stravaOauthFailed": "Connessione a Strava non riuscita", "stravaOauthError": { "csrf1": "Il controllo di sicurezza non è riuscito perché mancava il cookie del browser. Riavvia la connessione nello stesso browser.", @@ -7102,7 +7102,7 @@ }, "garminInfo": { "title": "Garmin", - "body": "Garmin non ha una connessione diretta qui. Collegalo tramite Apple Health (iOS) o Google Health Connect (Android). I punteggi proprietari di Garmin — Body Battery, Training Load, stato HRV, VO₂ max — non vengono condivisi da Garmin con nessuna delle due piattaforme.", + "body": "Garmin non ha una connessione diretta qui. Collegalo tramite Apple Health (iOS) o Google Health Connect (Android). I punteggi proprietari di Garmin (Body Battery, Training Load, stato HRV, VO₂ max) non vengono condivisi da Garmin con nessuna delle due piattaforme.", "docsLink": "Leggi la guida" }, "glucoseReference": { @@ -7196,14 +7196,14 @@ "aiServerKey": { "title": "Chiave IA del server", "description": "Una chiave dell'operatore per gli account che non ne hanno una propria.", - "byokHint": "La chiave personale dell'utente (BYOK, accesso ChatGPT o provider locale) ha sempre la precedenza — la chiave del server è l'ultimo passo della catena dei provider.", + "byokHint": "La chiave personale dell'utente (BYOK, accesso ChatGPT o provider locale) ha sempre la precedenza: la chiave del server è l'ultimo passo della catena dei provider.", "consentHint": "Le richieste tramite la chiave del server richiedono il consenso IA attivo dell'utente; senza una ricevuta di consenso non viene inviato nulla.", "baseUrlHint": "L'URL di base determina l'API: un URL Anthropic come https://api.anthropic.com/v1 viene riconosciuto, qualsiasi altro host viene chiamato tramite l'API compatibile con OpenAI.", "statusConfigured": "Configurata", "statusNotConfigured": "Non configurata", "keyLabel": "Chiave API", "keyPlaceholder": "sk-...", - "keyPlaceholderSet": "Salvata ({preview}) — inserisci una nuova chiave per sostituirla", + "keyPlaceholderSet": "Salvata ({preview}). Inserisci una nuova chiave per sostituirla", "modelLabel": "Modello", "baseUrlLabel": "URL di base", "save": "Salva", @@ -7294,7 +7294,7 @@ "integrationWebPush": "Web Push", "offlineGeoLabel": "Dati geografici", "offlineGeoEnabled": "Offline (GeoLite2)", - "offlineGeoFallback": "Online ({host}) — monta i database GeoLite2 e imposta GEOLITE2_DIR", + "offlineGeoFallback": "Online ({host}): monta i database GeoLite2 e imposta GEOLITE2_DIR", "offlineGeoOff": "Disattivato", "offlineGeoChosen": "Online ({host})", "apiGlobal": "Consentire endpoint API e token API.", @@ -7702,7 +7702,7 @@ "restorePromptLabel": "Digita RESTORE per continuare", "previewTitle": "Contenuto del backup", "previewLoading": "Lettura del contenuto…", - "previewUnavailable": "Impossibile leggere il contenuto — il ripristino resta possibile.", + "previewUnavailable": "Impossibile leggere il contenuto, ma il ripristino resta possibile.", "previewStillReading": "Questo backup è stato creato da una versione precedente, quindi il suo contenuto viene letto per intero, e con un archivio grande ci vuole un po'. Riapri questa finestra tra qualche minuto per vederlo. Il ripristino non dipende da questo.", "previewEmpty": "Il file non contiene record.", "previewOther": "Altri record", @@ -7745,7 +7745,7 @@ "restoreSkippedMedicationTarget": "Analita obiettivo di un farmaco", "restoreSkippedScheduleRevisionLink": "Successione dei periodi di schema", "restoreSkippedAccountSetting": "Impostazione dell'account", - "restoreMissingTitle": "Ripristino rifiutato — il file è incompleto", + "restoreMissingTitle": "Ripristino rifiutato: il file è incompleto", "restoreMissingDescription": "Il manifesto del file dichiara di contenere la sezione qui sotto, e non la contiene. Non è stato modificato nulla: un ripristino sostituisce un'intera classe di record, quindi una sezione assente l'avrebbe svuotata.", "restoreMissingRemedy": "Usa uno snapshot di disaster recovery, oppure esporta di nuovo l'account e carica il file nuovo. Una sezione che il manifesto dichiara omessa è un'altra cosa e si ripristina normalmente.", "restoreMissingDocuments": "Documenti", @@ -7947,7 +7947,7 @@ "connectedSince": "Connesso dal {when}", "connected": "Connessione IA condivisa collegata", "disconnected": "Connessione IA condivisa rimossa", - "error": "Qualcosa è andato storto — riprova" + "error": "Qualcosa è andato storto. Riprova" }, "failingJobs": { "title": "Processi in background", @@ -8276,7 +8276,7 @@ }, "selfContextComplete": { "title": "Autodichiarazione aggiornata", - "description": "Tutti e quattro i campi dell’autodichiarazione compilati — il Coach conosce il tuo contesto." + "description": "Tutti e quattro i campi dell’autodichiarazione compilati: il Coach conosce il tuo contesto." }, "sleepLog7": { "title": "Diario del sonno per 7 giorni", @@ -8298,7 +8298,7 @@ }, "hiddenCard": { "title": "Obiettivo nascosto", - "description": "Continua a monitorare — potresti imbatterti in esso.", + "description": "Continua a monitorare: potresti imbatterti in esso.", "ariaLabel": "Obiettivo nascosto bloccato" }, "hiddenUnlockToast": { @@ -8307,7 +8307,7 @@ "dashboardCard": { "title": "Sbloccati di recente", "viewAll": "Vedi tutti", - "empty": "Ancora nessun obiettivo — continua a registrare per sbloccare il primo." + "empty": "Ancora nessun obiettivo. Continua a registrare per sbloccare il primo." } }, "notifications": { @@ -8490,7 +8490,7 @@ } }, "edit": { - "title": "Modifica range obiettivo — {metric}", + "title": "Modifica range obiettivo: {metric}", "description": "Regola il range obiettivo usato in grafici, insights e referto medico. Valori in {unit}.", "derivedHint": "Questa card è derivata da altre metriche. Modifica gli obiettivi sottostanti (es. pressione o peso).", "minLabel": "Min", @@ -8522,11 +8522,11 @@ "aboveTarget": "{delta} {unit} sopra il range", "belowTarget": "{delta} {unit} sotto il range", "diastolic": "Diastolica", - "glucoseFasting": "Glicemia — a digiuno", - "glucosePostprandial": "Glicemia — postprandiale", - "glucoseRandom": "Glicemia — qualsiasi", - "glucoseBedtime": "Glicemia — prima di coricarsi", - "glucoseUnspecified": "Glicemia — non indicata", + "glucoseFasting": "Glicemia (a digiuno)", + "glucosePostprandial": "Glicemia (postprandiale)", + "glucoseRandom": "Glicemia (qualsiasi)", + "glucoseBedtime": "Glicemia (prima di coricarsi)", + "glucoseUnspecified": "Glicemia (non indicata)", "status": { "underweight": "Sottopeso", "normal": "Normal", @@ -8612,7 +8612,7 @@ "askMedicationName": "Indica il farmaco, es. preso Ramipril.", "medicationNotFoundExact": "Farmaco non trovato. Invia il nome esattamente come appare in HealthLog.", "helpHeader": "Comandi disponibili:", - "helpBody": "/help — mostra questa guida\n/add — registra un'assunzione\n/start — avvia il bot\n\nComandi testuali:\ntaken <nome> — conferma un'assunzione\n\nPulsanti nei promemoria:\n• Assunto — conferma l'assunzione\n• 🕐 1h / 🕐 3h — posticipa il promemoria\n• ⏭ Salta — salta l'assunzione\n• ✓ Conferma — conferma un'assunzione saltata", + "helpBody": "/help: mostra questa guida\n/add: registra un'assunzione\n/start: avvia il bot\n\nComandi testuali:\ntaken <nome>: conferma un'assunzione\n\nPulsanti nei promemoria:\n• Assunto: conferma l'assunzione\n• 🕐 1h / 🕐 3h: posticipa il promemoria\n• ⏭ Salta: salta l'assunzione\n• ✓ Conferma: conferma un'assunzione saltata", "measureValuePrompt": "Rispondi con il valore per registrarlo (facoltativo).", "buttonMeasureValue": "Valore…", "measureValueSaved": "Misurazione salvata.", @@ -8637,9 +8637,9 @@ }, "lowStockReminders": { "title": "Scorte in esaurimento: {medName}", - "bodyToday": "{medName}: {units} unità rimaste — meno di un giorno di scorta.", - "bodyReorder": "{medName}: {units} unità rimaste. Le scorte finiscono intorno al {runsOutOn} — riordina entro il {reorderBy}.", - "bodyLastDose": "{medName}: {units} unità rimaste — circa la tua ultima dose. Le scorte finiscono intorno al {runsOutOn}.", + "bodyToday": "{medName}: {units} unità rimaste, meno di un giorno di scorta.", + "bodyReorder": "{medName}: {units} unità rimaste. Le scorte finiscono intorno al {runsOutOn}: riordina entro il {reorderBy}.", + "bodyLastDose": "{medName}: {units} unità rimaste, circa la tua ultima dose. Le scorte finiscono intorno al {runsOutOn}.", "bodyExpired": "{medName}: nessuna scorta utilizzabile. {units} unità sono contrassegnate come scadute.", "bodyAsNeeded": "{medName}: restano solo {units} unità. Riordina prima di aver bisogno della prossima dose." }, @@ -8666,11 +8666,11 @@ "questionConditions": "Hai malattie croniche che il Coach dovrebbe conoscere?", "questionFocus": "C'è qualcosa di specifico a cui il Coach dovrebbe fare attenzione?", "questionAllergies": "Hai allergie o intolleranze?", - "questionAboutMe": "Vuoi raccontare al Coach qualcosa di te — abitudini, obiettivi, contesto?" + "questionAboutMe": "Vuoi raccontare al Coach qualcosa di te? Abitudini, obiettivi, contesto?" }, "clinicianView": { "title": "Cartella sanitaria condivisa", - "period": "Periodo del report: {start} – {end}", + "period": "Periodo del report: {start}–{end}", "expires": "Questo link scade il {date}.", "provenance": "Questo è un riepilogo di sola lettura condiviso dalla persona a cui appartiene, esportato dai suoi dati HealthLog autoregistrati. I valori sono autodichiarati e possono includere letture sincronizzate da dispositivi; vanno considerati come riferiti dal paziente, non come un esame clinico.", "labs": "Valori di laboratorio", @@ -8694,7 +8694,7 @@ "strain": "Punteggio di sforzo", "score": "Punteggio di benessere" }, - "footer": "Condiviso da HealthLog — un tracker della salute self-hosted.", + "footer": "Condiviso da HealthLog, un tracker della salute self-hosted.", "unlock": { "title": "Inserisci la passphrase", "description": "Questo referto sanitario condiviso è protetto. Inserisci la passphrase che hai ricevuto per visualizzarlo.", @@ -8909,8 +8909,8 @@ "ariaUnknown": "Nessun ciclo attivo ancora", "caption": "del tuo ciclo", "firstPeriodCta": "Registra il mio primo ciclo", - "periodOverdue": "Il ciclo è in ritardo rispetto al solito — il conteggio dei giorni resta in pausa finché non registri la prossima mestruazione.", - "periodOverdueDays": "Il ciclo è in ritardo di {days} giorni rispetto al solito — il conteggio dei giorni resta in pausa finché non registri la prossima mestruazione.", + "periodOverdue": "Il ciclo è in ritardo rispetto al solito: il conteggio dei giorni resta in pausa finché non registri la prossima mestruazione.", + "periodOverdueDays": "Il ciclo è in ritardo di {days} giorni rispetto al solito: il conteggio dei giorni resta in pausa finché non registri la prossima mestruazione.", "logPeriodCta": "Registra mestruazione" }, "calendar": { @@ -8935,7 +8935,7 @@ "predictions": { "title": "Cosa arriva dopo", "nextPeriod": "Prossimo ciclo", - "nextPeriodWindow": "{low} – {high}", + "nextPeriodWindow": "{low}–{high}", "fertileWindow": "Finestra fertile", "ovulation": "Ovulazione stimata", "confidenceHigh": "Alta", @@ -8944,7 +8944,7 @@ "stillLearning": "Sto ancora imparando", "stillLearningBody": "Registra almeno tre cicli completi e le previsioni miglioreranno. Fino ad allora è una stima approssimativa.", "rawMode": "Previsione disattivata", - "rawModeBody": "Hai disattivato le previsioni — vengono mostrati solo i tuoi dati registrati, senza previsione.", + "rawModeBody": "Hai disattivato le previsioni: vengono mostrati solo i tuoi dati registrati, senza previsione.", "none": "Nessuna previsione ancora. Registra un ciclo per iniziare.", "ovulationConfirmed": "Ovulazione (confermata)" }, @@ -9073,15 +9073,15 @@ "fieldInfo": { "bbt": "La tua temperatura a riposo, misurata appena sveglia prima di alzarti. Dopo l'ovulazione sale leggermente (circa 0,2–0,3 °C).", "bbtLabel": "Cos'è la temperatura basale?", - "mucus": "Le perdite vaginali cambiano durante il ciclo — da secche o appiccicose a cremose, poi acquose e simili ad albume nei giorni più fertili.", + "mucus": "Le perdite vaginali cambiano durante il ciclo: da secche o appiccicose a cremose, poi acquose e simili ad albume nei giorni più fertili.", "mucusLabel": "Cos'è il muco cervicale?", - "ovulationTest": "Un test delle urine domestico che rileva il picco di LH — l'aumento ormonale circa 24–36 h prima dell'ovulazione. Un positivo segnala la finestra più fertile.", + "ovulationTest": "Un test delle urine domestico che rileva il picco di LH, l'aumento ormonale circa 24–36 h prima dell'ovulazione. Un positivo segnala la finestra più fertile.", "ovulationTestLabel": "Cos'è un test di ovulazione?", "spotting": "Lieve sanguinamento al di fuori delle mestruazioni.", "spottingLabel": "Cos'è lo spotting tra le mestruazioni?", "pregnancyTest": "Risultato di un test di gravidanza (hCG) domestico.", "pregnancyTestLabel": "Cos'è un test di gravidanza?", - "progesteroneTest": "Un test che conferma l'avvenuta ovulazione — il progesterone sale dopo.", + "progesteroneTest": "Un test che conferma l'avvenuta ovulazione: il progesterone sale dopo.", "progesteroneTestLabel": "Cos'è un test del progesterone?", "intercourse": "Se in questo giorno ci sono stati rapporti sessuali.", "intercourseLabel": "Cosa registra i rapporti?", @@ -9134,14 +9134,14 @@ "postpone": { "menuItem": "Rimanda…", "title": "Rimanda la scadenza", - "description": "Sposta solo la scadenza attuale — il ritmo regolare resta invariato.", + "description": "Sposta solo la scadenza attuale. Il ritmo regolare resta invariato.", "chip": "+{days} giorni", "dateLabel": "Nuova data", "confirm": "Rimanda" }, "skip": { "heading": "Salta questa scadenza", - "explainer": "Registrato onestamente come saltato — non come fatto. L'intervallo riparte da oggi.", + "explainer": "Registrato onestamente come saltato, non come fatto. L'intervallo riparte da oggi.", "action": "Salta", "confirmTitle": "Saltare questa scadenza?" }, @@ -9282,7 +9282,7 @@ "localOcr": { "heading": "Leggi le scansioni su questo dispositivo", "description": "Legge la foto sul tuo dispositivo e invia al provider solo il testo estratto.", - "detail": "Utile quando il tuo provider IA non legge le immagini. Meno preciso — controlla ogni valore prima di salvare." + "detail": "Utile quando il tuo provider IA non legge le immagini. Meno preciso: controlla ogni valore prima di salvare." }, "sort": { "heading": "Ordinamento", @@ -9344,7 +9344,7 @@ "emptyDescription": "Aggiungi un valore per seguire questo biomarcatore nel tempo.", "title": "Biomarcatore", "genericDescription": "Un biomarcatore di laboratorio che monitori. Aggiungi misurazioni per seguirne l'andamento rispetto all'intervallo di riferimento.", - "valuesTitle": "{marker} — tutte le letture", + "valuesTitle": "{marker}: tutte le letture", "valuesDescription": "Ogni lettura di questo biomarcatore. Modifica o rimuovi una voce direttamente.", "backToMarker": "Torna a {marker}", "latestResult": "Ultimo risultato" @@ -9364,7 +9364,7 @@ }, "biomarker": { "manageTitle": "Biomarcatori", - "managerDescription": "Definisci un marcatore una volta — unità e intervallo valgono per ogni misurazione.", + "managerDescription": "Definisci un marcatore una volta: unità e intervallo valgono per ogni misurazione.", "define": "Definisci", "defineFirst": "Definisci il tuo primo biomarcatore", "defineTitle": "Definisci biomarcatore", @@ -9383,7 +9383,7 @@ "form": { "seedLabel": "Parti da un marcatore comune", "seedPlaceholder": "Scegli un marcatore (facoltativo)", - "seedHint": "Sceglierne uno compila i campi — adatta l'intervallo al tuo laboratorio.", + "seedHint": "Sceglierne uno compila i campi. Adatta l'intervallo al tuo laboratorio.", "name": "Nome", "namePlaceholder": "es. Colesterolo LDL", "unit": "Unità", @@ -9397,7 +9397,7 @@ "upperPlaceholder": "Limite superiore", "context": "Contesto", "contextPlaceholder": "Nota facoltativa su questo marcatore", - "rangeHint": "Entrambi i limiti sono facoltativi — lasciane uno vuoto per un intervallo aperto (es. LDL < 116).", + "rangeHint": "Entrambi i limiti sono facoltativi: lasciane uno vuoto per un intervallo aperto (es. LDL < 116).", "requiredError": "Nome e unità sono obbligatori.", "rangeOrderError": "Il limite inferiore non deve superare quello superiore.", "save": "Salva biomarcatore", @@ -9463,16 +9463,16 @@ "ft3": "Il T3 libero (triiodotironina) è la forma non legata e biologicamente attiva dell'ormone tiroideo più potente, la frazione disponibile ad agire sui tessuti. La maggior parte del T3 circolante è legata a proteine di trasporto e inattiva, perciò la quota libera riflette la reale disponibilità dell'ormone. Si misura per caratterizzare la funzione tiroidea, soprattutto insieme a TSH e T4 libero quando i risultati non sono chiari. I valori dipendono molto dal metodo di analisi e si leggono nel loro contesto clinico.", "ft4": "Il T4 libero (tiroxina) è la forma non legata del principale ormone che la tiroide rilascia nel sangue e funge da riserva che i tessuti convertono nel T3 più attivo secondo necessità. La frazione libera riflette ciò che è realmente disponibile per il corpo, indipendentemente dal livello delle proteine di trasporto. Di solito si misura insieme al TSH per distinguere i problemi della tiroide da quelli della segnalazione ipofisaria. La gravidanza e alcuni farmaci possono spostarlo.", "ferritin": "La ferritina è la principale proteina di deposito del ferro dell'organismo e il suo valore nel sangue rispecchia a grandi linee le riserve totali di ferro. Un valore basso indica riserve esaurite, mentre uno alto può riflettere un sovraccarico di ferro, oppure semplicemente un'infiammazione, perché la ferritina sale anche come reattante della fase acuta. Per questo si interpreta spesso insieme ad altri marcatori del ferro e a segni di infiammazione. È una delle misure centrali per valutare lo stato del ferro.", - "transferrin-saturation": "La saturazione della transferrina è la percentuale di transferrina — la proteina che trasporta il ferro nel sangue — attualmente carica di ferro. Collega la quantità di ferro in transito alla capacità di trasporto dell'organismo, offrendo un'istantanea della disponibilità di ferro che completa la visione delle riserve data dalla ferritina. Una saturazione bassa suggerisce un ferro scarso, mentre un valore alto può indicare un sovraccarico. Si legge insieme alla ferritina e all'assetto marziale completo.", + "transferrin-saturation": "La saturazione della transferrina è la percentuale di transferrina (la proteina che trasporta il ferro nel sangue) attualmente carica di ferro. Collega la quantità di ferro in transito alla capacità di trasporto dell'organismo, offrendo un'istantanea della disponibilità di ferro che completa la visione delle riserve data dalla ferritina. Una saturazione bassa suggerisce un ferro scarso, mentre un valore alto può indicare un sovraccarico. Si legge insieme alla ferritina e all'assetto marziale completo.", "vitamin-d": "La vitamina D si misura come 25-idrossivitamina D, la forma di deposito circolante e il marcatore standard dello stato complessivo di vitamina D. Il corpo la produce nella pelle esposta alla luce solare e ne assorbe una parte dagli alimenti; sostiene l'equilibrio del calcio, la salute delle ossa e la funzione immunitaria. I valori variano con la stagione, la latitudine, il tono della pelle e l'integrazione. Viene rilevata per stimare nel tempo se le riserve sono adeguate.", - "vitamin-b12": "La vitamina B12 (cobalamina) è una vitamina essenziale, ottenuta soprattutto da alimenti di origine animale e immagazzinata in gran parte nel fegato. È necessaria per la formazione dei globuli rossi, la sintesi del DNA e la salute del sistema nervoso. Una carenza prolungata — da scarso apporto o assorbimento alterato — può portare ad anemia e a sintomi neurologici. Si misura per valutare lo stato nutrizionale, in particolare quando apporto o assorbimento possono essere limitati.", + "vitamin-b12": "La vitamina B12 (cobalamina) è una vitamina essenziale, ottenuta soprattutto da alimenti di origine animale e immagazzinata in gran parte nel fegato. È necessaria per la formazione dei globuli rossi, la sintesi del DNA e la salute del sistema nervoso. Una carenza prolungata, da scarso apporto o assorbimento alterato, può portare ad anemia e a sintomi neurologici. Si misura per valutare lo stato nutrizionale, in particolare quando apporto o assorbimento possono essere limitati.", "folate": "Il folato (vitamina B9) è una vitamina del gruppo B presente nelle verdure a foglia verde, nei legumi e negli alimenti fortificati, centrale per la formazione dei globuli rossi e la sintesi del DNA. Lavora a stretto contatto con la vitamina B12 e una carenza dell'uno o dell'altra può produrre un tipo simile di anemia. Un folato adeguato è particolarmente importante intorno all'inizio della gravidanza per uno sviluppo sano del feto. Si misura per valutare lo stato nutrizionale e la causa di alcune anemie.", "hs-crp": "La PCR ad alta sensibilità misura la proteina C-reattiva, un marcatore che il fegato rilascia in risposta all'infiammazione, con una tecnica affinata per rilevare le basse concentrazioni rilevanti per il rischio cardiovascolare. A differenza della PCR standard usata per le infezioni acute, la versione ad alta sensibilità coglie l'infiammazione lieve e cronica legata alla malattia vascolare. Poiché qualsiasi infezione o lesione recente può aumentarla, si interpreta lontano da una malattia acuta e spesso si conferma con un prelievo ripetuto. Si legge come uno dei fattori del rischio cardiovascolare complessivo.", "creatinine": "La creatinina è un prodotto di scarto del normale metabolismo muscolare che i reni filtrano dal sangue a un ritmo abbastanza costante. Poiché la produzione è relativamente stabile, il suo valore nel sangue funge da misura pratica di quanto bene i reni eliminano gli scarti. I valori dipendono anche dalla massa muscolare, dall'idratazione e dalla dieta, perciò si interpretano di solito insieme alla velocità di filtrazione stimata. È un marcatore centrale della funzione renale.", "egfr": "L'eGFR (velocità di filtrazione glomerulare stimata) stima quanto sangue i reni filtrano ogni minuto, calcolata dalla creatinina insieme a età e sesso. Traduce un valore grezzo di creatinina in una misura della funzione renale più immediatamente interpretabile. Un eGFR in calo nel tempo è il modo principale per classificare e seguire le alterazioni renali croniche. Essendo una stima, si legge come una tendenza e non come un'unica cifra esatta.", "alt": "L'ALT (alanina aminotransferasi) è un enzima concentrato nelle cellule del fegato, rilasciato nel sangue quando queste cellule sono sotto stress o danneggiate. Essendo relativamente specifico del fegato, è uno dei principali marcatori per rilevare un danno o un'infiammazione epatica. I valori possono salire con il fegato grasso, l'epatite virale, l'alcol o alcuni farmaci. Di solito si legge insieme all'AST e agli altri marcatori del profilo epatico.", "ast": "L'AST (aspartato aminotransferasi) è un enzima presente nel fegato ma anche nel muscolo, nel cuore e nei globuli rossi, rilasciato quando uno di questi tessuti subisce un danno. Essendo meno specifico del fegato rispetto all'ALT, i due si interpretano insieme e il loro rapporto può orientare sull'origine e sulla natura del problema. Un esercizio intenso o una lesione muscolare possono aumentarlo indipendentemente dal fegato. È uno degli enzimi standard del profilo epatico.", - "ggt": "La GGT (gamma-glutamil transferasi) è un enzima del fegato e delle vie biliari che sale in particolare quando il flusso della bile è ostruito o in caso di esposizione all'alcol. Spesso si usa per chiarire perché un altro marcatore epatico è elevato — per esempio, per distinguere un'origine epatica o biliare. È sensibile ma poco specifica, perciò si legge nel contesto del resto del profilo epatico. È uno dei vari marcatori usati per valutare la salute del fegato e delle vie biliari.", + "ggt": "La GGT (gamma-glutamil transferasi) è un enzima del fegato e delle vie biliari che sale in particolare quando il flusso della bile è ostruito o in caso di esposizione all'alcol. Spesso si usa per chiarire perché un altro marcatore epatico è elevato, per esempio per distinguere un'origine epatica o biliare. È sensibile ma poco specifica, perciò si legge nel contesto del resto del profilo epatico. È uno dei vari marcatori usati per valutare la salute del fegato e delle vie biliari.", "sodium": "Il sodio è il principale elettrolita del liquido al di fuori delle cellule del corpo e il motore fondamentale dell'equilibrio dei liquidi e del volume del sangue. L'organismo lo regola in modo stretto tramite la sete, gli ormoni e i reni, perciò il suo valore nel sangue riflette più l'equilibrio tra acqua e sale che il solo apporto alimentare. Valori anomali segnalano di solito un disturbo dell'equilibrio idrico più che del sodio stesso. È una parte centrale del pannello metabolico di base e degli elettroliti.", "potassium": "Il potassio è il principale elettrolita all'interno delle cellule del corpo ed è essenziale per la trasmissione nervosa e per il ritmo regolare del muscolo cardiaco. Il suo valore nel sangue è mantenuto entro un intervallo ristretto dai reni e dai segnali ormonali, perché sia i valori alti sia quelli bassi possono disturbare l'attività elettrica del cuore. I valori possono essere influenzati dalla funzione renale, dall'idratazione e da diversi farmaci comuni. È una misura centrale del pannello degli elettroliti.", "hemoglobin": "L'emoglobina è la proteina contenente ferro dei globuli rossi che lega l'ossigeno nei polmoni e lo trasporta ai tessuti. La sua concentrazione è la principale misura della capacità del sangue di trasportare ossigeno e il marcatore centrale per rilevare l'anemia. Valori bassi possono riflettere perdita di sangue, carenza di ferro o di vitamine, o una produzione ridotta, mentre valori alti possono seguire una disidratazione o condizioni di scarso ossigeno. È un pilastro dell'emocromo completo.", @@ -9481,8 +9481,8 @@ "platelets": "Le piastrine sono piccoli frammenti cellulari del sangue che si aggregano e formano il tappo iniziale che arresta il sanguinamento da un vaso danneggiato. Il loro numero riflette l'equilibrio tra la produzione nel midollo osseo e il consumo o la distruzione. Un numero basso può aumentare la tendenza al sanguinamento, mentre uno alto può seguire un'infiammazione o altri stimoli. Fanno parte dell'emocromo completo e sono una misura di base della capacità di coagulazione.", "apob": "L'apolipoproteina B è la proteina strutturale presente su ciascuna delle particelle di lipoproteine aterogene, quindi misurarla significa contare direttamente quelle particelle anziché il colesterolo che trasportano. Poiché c'è una molecola di ApoB su ogni particella di LDL, VLDL e affini, può cogliere un rischio cardiovascolare che un valore di colesterolo LDL non rileva, soprattutto quando il numero di particelle e il loro contenuto di colesterolo divergono. Per questo è sempre più usata per affinare la valutazione del rischio basata sui lipidi. Si interpreta insieme al consueto profilo lipidico.", "lp-a": "La lipoproteina(a) è una particella simile all'LDL con una proteina aggiuntiva attaccata, il cui livello è in gran parte determinato dalla genetica e resta piuttosto stabile per tutta la vita. Una Lp(a) elevata è un fattore di rischio indipendente ed ereditario di malattia cardiovascolare e di restringimento della valvola aortica. Poiché varia poco, di solito si misura una sola volta per stabilire il rischio di una persona lungo l'arco della vita, anziché seguirla ripetutamente. Si esprime in unità molari e si legge nell'ambito del rischio cardiovascolare complessivo.", - "fasting-insulin": "L'insulina a digiuno è il livello di insulina — l'ormone che fa passare il glucosio dal sangue alle cellule — misurato dopo un digiuno notturno. Insieme alla glicemia a digiuno, aiuta a stimare la resistenza all'insulina, lo stato in cui il corpo ha bisogno di più insulina per mantenere il glucosio nel suo intervallo. Un'insulina a digiuno alta con una glicemia normale può essere un segno precoce che questa compensazione è in atto. Si legge nell'ambito di un quadro di salute metabolica e non isolatamente.", - "omega-3-index": "L'indice omega-3 è la quota di EPA e DHA — i due acidi grassi omega-3 marini a catena lunga — tra gli acidi grassi delle membrane dei globuli rossi. Poiché i globuli rossi si rinnovano lentamente, riflette l'apporto di omega-3 a lungo termine anziché un pasto recente. Un indice più alto è stato associato, in studi osservazionali, a un rischio cardiovascolare più basso. Si segue come un marcatore stabile dello stato di omega-3 che risponde alla dieta nell'arco di mesi." + "fasting-insulin": "L'insulina a digiuno è il livello di insulina (l'ormone che fa passare il glucosio dal sangue alle cellule) misurato dopo un digiuno notturno. Insieme alla glicemia a digiuno, aiuta a stimare la resistenza all'insulina, lo stato in cui il corpo ha bisogno di più insulina per mantenere il glucosio nel suo intervallo. Un'insulina a digiuno alta con una glicemia normale può essere un segno precoce che questa compensazione è in atto. Si legge nell'ambito di un quadro di salute metabolica e non isolatamente.", + "omega-3-index": "L'indice omega-3 è la quota di EPA e DHA (i due acidi grassi omega-3 marini a catena lunga) tra gli acidi grassi delle membrane dei globuli rossi. Poiché i globuli rossi si rinnovano lentamente, riflette l'apporto di omega-3 a lungo termine anziché un pasto recente. Un indice più alto è stato associato, in studi osservazionali, a un rischio cardiovascolare più basso. Si segue come un marcatore stabile dello stato di omega-3 che risponde alla dieta nell'arco di mesi." }, "apob": "Apolipoproteina B (ApoB)", "lp-a": "Lipoproteina(a)", @@ -9515,12 +9515,12 @@ "dateLabel": "Data", "refLowLabel": "Riferimento inferiore", "refHighLabel": "Riferimento superiore", - "newBiomarker": "Nuovo biomarcatore — verrà creato", + "newBiomarker": "Nuovo biomarcatore, verrà creato", "linksExisting": "Collegato a {name} esistente", "duplicateWarning": "Esiste già un valore corrispondente", "lowConfidence": "Controlla questo valore", "lowConfidenceBadge": "Bassa attendibilità", - "valueUnreadable": "Valore illeggibile — inseriscilo manualmente", + "valueUnreadable": "Valore illeggibile: inseriscilo manualmente", "saveSelected": "Salva {count} selezionati", "discardAll": "Scarta tutto", "savedToast": "{count} risultati di laboratorio salvati", @@ -10004,7 +10004,7 @@ "dismiss": "Non ora", "applied": "Aggiunto", "dismissed": "Ignorato", - "failed": "Impossibile aggiungere — riprova", + "failed": "Impossibile aggiungere. Riprova", "checkup": { "title": "Aggiungere un promemoria di controllo?" }, @@ -10056,7 +10056,7 @@ }, "refusal": { "outOfScope": "Posso aiutarti solo con i dati di salute del tuo registro: misurazioni, farmaci, umore, tendenze. Non rispondo a domande al di fuori di questo ambito.", - "promptInjection": "Ho notato istruzioni che cercano di aggirare le mie direttive. Sono il Coach di HealthLog e riassumo soltanto i tuoi dati di salute — riformula la domanda in questi termini, per favore.", + "promptInjection": "Ho notato istruzioni che cercano di aggirare le mie direttive. Sono il Coach di HealthLog e riassumo soltanto i tuoi dati di salute: riformula la domanda in questi termini, per favore.", "conversationPoisoned": "Un messaggio precedente di questa conversazione contiene istruzioni che cercano di aggirare le mie direttive. Inizia una nuova conversazione, per favore." }, "noRecordedData": "Non hai misurazioni registrate su quello che chiedi, quindi non posso darti alcun valore. Appena ne inserisci qualcuna, richiedimelo e userò i tuoi dati.", @@ -10307,7 +10307,7 @@ "2": "Molto difficile", "3": "Estremamente difficile" }, - "functionalOptionalHint": "Facoltativo — puoi inviare anche senza rispondere a questa domanda.", + "functionalOptionalHint": "Facoltativo: puoi inviare anche senza rispondere a questa domanda.", "result": { "title": "Il tuo risultato", "totalLabel": "Punteggio totale", @@ -11186,7 +11186,7 @@ "genericDescription": "Una misurazione che monitori. Aggiungi valori per seguirla nel tempo.", "emptyTitle": "Ancora nessun valore", "emptyDescription": "Aggiungi il primo valore per iniziare a rappresentare questa metrica.", - "valuesTitle": "{metric} — tutti i valori", + "valuesTitle": "{metric}: tutti i valori", "valuesDescription": "Tutti i valori registrati per questa metrica.", "backToMetric": "Torna a {metric}" } @@ -11252,7 +11252,7 @@ "emptyTitle": "Nessun dato sui micronutrienti ancora sincronizzato", "loadError": "Non è stato possibile caricare i tuoi dati sui nutrienti" }, - "sparseNote": "Un valore basso qui di solito indica una registrazione poco frequente, non una carenza — i totali giornalieri di Apple Health riflettono ciò che le tue app hanno registrato, non l'apporto alimentare totale." + "sparseNote": "Un valore basso qui di solito indica una registrazione poco frequente, non una carenza: i totali giornalieri di Apple Health riflettono ciò che le tue app hanno registrato, non l'apporto alimentare totale." }, "daily": { "line": { @@ -11279,7 +11279,7 @@ }, "syncIssue": { "title": "La sincronizzazione richiede attenzione", - "body": "{integration} non si sincronizza — riconnettilo per mantenere aggiornati i tuoi dati." + "body": "{integration} non si sincronizza. Riconnettilo per mantenere aggiornati i tuoi dati." }, "coachCheckin": { "title": "È il momento di rivedere un piano", @@ -11291,10 +11291,10 @@ "tensionWindow": { "title": "Forse un po' di tensione oggi", "body": { - "morning": "La tua frequenza cardiaca è rimasta sopra il valore a riposo per un tratto prolungato stamattina mentre eri fermo — forse un po' di tensione.", - "afternoon": "La tua frequenza cardiaca è rimasta sopra il valore a riposo per un tratto prolungato questo pomeriggio mentre eri fermo — forse un po' di tensione.", - "evening": "La tua frequenza cardiaca è rimasta sopra il valore a riposo per un tratto prolungato stasera mentre eri fermo — forse un po' di tensione.", - "night": "La tua frequenza cardiaca è rimasta sopra il valore a riposo per un tratto prolungato durante la notte mentre eri fermo — forse un po' di tensione." + "morning": "La tua frequenza cardiaca è rimasta sopra il valore a riposo per un tratto prolungato stamattina mentre eri fermo: forse un po' di tensione.", + "afternoon": "La tua frequenza cardiaca è rimasta sopra il valore a riposo per un tratto prolungato questo pomeriggio mentre eri fermo: forse un po' di tensione.", + "evening": "La tua frequenza cardiaca è rimasta sopra il valore a riposo per un tratto prolungato stasera mentre eri fermo: forse un po' di tensione.", + "night": "La tua frequenza cardiaca è rimasta sopra il valore a riposo per un tratto prolungato durante la notte mentre eri fermo: forse un po' di tensione." } }, "ecgNewRecording": { @@ -11319,9 +11319,9 @@ }, "upcomingVisit": { "title": "Appuntamento in arrivo", - "bodyToday": "{what} — oggi", - "bodyTomorrow": "{what} — domani", - "bodyDayAfterTomorrow": "{what} — dopodomani" + "bodyToday": "{what}, oggi", + "bodyTomorrow": "{what}, domani", + "bodyDayAfterTomorrow": "{what}, dopodomani" } }, "action": { @@ -11926,7 +11926,7 @@ "notFound": "Questo accesso non esiste più.", "revokeFailed": "Non è stato possibile terminare l'accesso.", "renounceFailed": "Non è stato possibile restituire l'accesso.", - "profileNotFound": "Quel profilo non c'è più — potrebbe essere già stato eliminato, o il tuo accesso è terminato.", + "profileNotFound": "Quel profilo non c'è più: potrebbe essere già stato eliminato, o il tuo accesso è terminato.", "deleteProfileFailed": "Non è stato possibile eliminare il profilo.", "removeGuardianFailed": "Non è stato possibile terminare quell'accesso." }, @@ -12260,15 +12260,11 @@ "rugLegend": "I punti sotto l’asse indicano i giorni con voci, un anello un giorno rilevante.", "sheetExpand": "Espandi a tutta altezza", "sheetShrink": "Riduci", - "usualLabel": "I tuoi 30 giorni precedenti", "valuesLegend": "Punto per questo giorno, barra per i 30 giorni precedenti", "valuesAllOne": "Tutti i valori", "valuesAllFew": "Tutti i {count} valori", "valuesAllOther": "Tutti i {count} valori", "valuesFewer": "Meno valori", - "countValuesOne": "1 valore", - "countValuesFew": "{count} valori", - "countValuesOther": "{count} valori", "countEntriesOne": "1 voce", "countEntriesFew": "{count} voci", "countEntriesOther": "{count} voci", @@ -12308,7 +12304,6 @@ "subtitle": "Cosa è successo e quando, accanto ai tuoi valori.", "standing": "Permanente", "startUnknown": "inizio sconosciuto", - "openDay": "Apri {date}", "zoom": { "all": "Tutto", "year": "12 mesi", diff --git a/messages/ko.json b/messages/ko.json index e1693c749..627fb3d31 100644 --- a/messages/ko.json +++ b/messages/ko.json @@ -167,7 +167,7 @@ "anamnesisShiftSchedule": "근무 일정", "anamnesisColFact": "프로필 항목", "anamnesisColValue": "기록된 값", - "subtitle": "HealthLog — 개인 건강 리포트", + "subtitle": "HealthLog: 개인 건강 리포트", "patient": "환자", "dateOfBirth": "생년월일", "gender": "성별", @@ -213,18 +213,18 @@ "contacts": "비상 연락처", "notes": "추가 메모" }, - "vitalsTitle": "활력징후 — 요약", + "vitalsTitle": "활력징후: 요약", "colParameter": "항목", "colCurrent": "현재", "colAvgPeriod": "기간 평균", "colMin": "최소", "colMax": "최대", "colN": "건수", - "bpClassificationTitle": "혈압 — ESH 분류 (2023)", + "bpClassificationTitle": "혈압: ESH 분류 (2023)", "avgBp": "평균 혈압", "classification": "분류", "bmiTitle": "체질량지수 (BMI)", - "bmiRow": "BMI: {bmi} kg/m² — 분류: {class} (WHO)", + "bmiRow": "BMI: {bmi} kg/m², 분류: {class} (WHO)", "complianceTitle": "복약 순응도", "glp1Title": "GLP-1 치료", "glp1WeightSummary": "리포트 기간 체중: {start} kg → {end} kg ({delta} kg)", @@ -272,8 +272,8 @@ "typeGlucoseRandom": "혈당 (임의)", "typeGlucoseBedtime": "혈당 (취침 전)", "typeGlucoseUnspecified": "혈당 (미지정)", - "glucoseClassificationTitle": "혈당 — 참고 범위 (ADA 2024 / DDG)", - "glucoseRow": "{label}: 평균 {avg} {unit} (목표 {rangeMin}–{rangeMax}) — {class}", + "glucoseClassificationTitle": "혈당: 참고 범위 (ADA 2024 / DDG)", + "glucoseRow": "{label}: 평균 {avg} {unit} (목표 {rangeMin}–{rangeMax}), {class}", "glucoseInTarget": "목표 범위 내", "glucoseBelowTarget": "목표 미만", "glucoseAboveTarget": "목표 초과", @@ -378,12 +378,12 @@ "backToDashboard": "대시보드로 돌아가기" }, "offlineBanner": { - "message": "연결 없음 — 온라인으로 돌아올 때까지 저장할 수 없어요.", - "saveFailed": "저장하지 못했어요 — 오프라인 상태예요. 온라인으로 돌아온 뒤 다시 시도해 주세요.", + "message": "연결이 없어요. 온라인으로 돌아올 때까지 저장할 수 없어요.", + "saveFailed": "저장하지 못했어요. 오프라인 상태예요. 온라인으로 돌아온 뒤 다시 시도해 주세요.", "showingCached": "마지막으로 동기화한 데이터를 보여주고 있어요." }, "demoBanner": { - "message": "데모 모드 — 변경 내용은 저장되지 않아요." + "message": "데모 모드: 변경 내용은 저장되지 않아요." }, "nav": { "dashboard": "대시보드", @@ -458,7 +458,7 @@ "hasAccount": "이미 계정이 있나요?", "loginFailed": "로그인 실패", "registerFailed": "회원가입 실패", - "invitedBanner": "초대를 받았어요 — 회원가입이 닫혀 있어도 계정을 만들 수 있어요.", + "invitedBanner": "초대를 받았어요. 회원가입이 닫혀 있어도 계정을 만들 수 있어요.", "alreadySignedIn": { "title": "이미 로그인되어 있습니다", "body": "{username} 계정으로 로그인되어 있습니다. 초대는 새 계정을 만듭니다. 초대를 수락하려면 로그아웃하세요.", @@ -775,7 +775,7 @@ "formReset": "양식 초기화", "saveError": "저장하지 못했어요", "duplicateTimestamp": "선택한 시각에 같은 유형의 측정이 이미 있어요.", - "serverOwnedSource": "연동된 출처의 값은 수정할 수 없어요 — 시간과 메모는 수정할 수 있어요.", + "serverOwnedSource": "연동된 출처의 값은 수정할 수 없어요. 시간과 메모는 수정할 수 있어요.", "deleteError": "삭제하지 못했어요", "deletedToast": "측정을 삭제했어요", "restoredToast": "측정을 복원했어요", @@ -887,7 +887,7 @@ }, "watchdog": { "title": "자동 감시", - "description": "HealthLog는 백그라운드에서도 조용히 지켜봐요 — 연결된 워치의 불규칙 리듬·호흡 장애 알림, 기준값 이탈 건강 상태 경고, 최근 두 번의 검사 패널 사이의 눈에 띄는 변화를 보고, 특별한 게 있을 때만 카드를 보여줘요. 이런 원본이 하나라도 연결돼 있다면 카드가 없는 건 기능 누락이 아니라 좋은 신호예요. 아직 아무것도 연결하지 않았다면 감시할 대상 자체가 없어요." + "description": "HealthLog는 백그라운드에서도 조용히 지켜봐요. 연결된 워치의 불규칙 리듬·호흡 장애 알림, 기준값 이탈 건강 상태 경고, 최근 두 번의 검사 패널 사이의 눈에 띄는 변화를 보고, 특별한 게 있을 때만 카드를 보여줘요. 이런 원본이 하나라도 연결돼 있다면 카드가 없는 건 기능 누락이 아니라 좋은 신호예요. 아직 아무것도 연결하지 않았다면 감시할 대상 자체가 없어요." } }, "mood": { @@ -1069,7 +1069,7 @@ }, "sectionMoreTags": "태그 더 보기", "sectionNoteDetails": "메모·상세", - "quickTagsHelp": "자주 쓰는 태그 — 한 번만 누르면 돼요", + "quickTagsHelp": "자주 쓰는 태그: 한 번만 누르면 돼요", "quickTagsExpand": "더 보기", "loadError": "기분 기록을 불러오지 못했어요.", "sectionLevelA": "마음 상태", @@ -1247,8 +1247,8 @@ "dialogDescription": "지금 복용할 약이에요. 확인하면 모두 복용으로 기록해요.", "confirm": "모두 복용 ({count})", "successToast": "{count}건 복용을 기록했어요", - "partialToast": "{taken}건 기록, {failed}건 실패 – 다시 시도해 주세요", - "failedToast": "복용을 기록하지 못했어요 – 다시 시도해 주세요" + "partialToast": "{taken}건 기록, {failed}건 실패. 다시 시도해 주세요", + "failedToast": "복용을 기록하지 못했어요. 다시 시도해 주세요" }, "logIntake": { "dialogTitle": "복용 기록", @@ -1346,10 +1346,10 @@ "skipped": "건너뜀", "intakeToastTaken": "복용으로 기록함: {name}", "intakeToastSkipped": "건너뜀: {name}", - "intakeToastFailed": "기록하지 못했어요: {name} — 다시 시도해 주세요", + "intakeToastFailed": "기록하지 못했어요: {name}. 다시 시도해 주세요", "intakeUndo": "실행 취소", "intakeUndone": "기록을 되돌렸어요", - "intakeUndoFailed": "되돌리지 못했어요 — 기록에서 수정해 주세요", + "intakeUndoFailed": "되돌리지 못했어요. 기록에서 수정해 주세요", "glp1LastInjection": "{label}", "glp1NextInjectionDays": "{label} ({days}일 후)", "glp1NextInjectionToday": "오늘", @@ -1431,10 +1431,10 @@ "error": { "empty": "설명을 먼저 입력해 주세요.", "tooLong": "설명은 2000자 이내로 적어 주세요.", - "rateLimit": "요청이 너무 많아요 — 잠시 후 다시 시도해 주세요.", - "noProvider": "AI 제공자가 설정되지 않았어요 — 설정에서 등록해 주세요.", - "budget": "오늘 AI 사용 한도를 다 썼어요 — 내일 다시 시도해 주세요.", - "network": "AI 제공자에 연결하지 못했어요 — 다시 시도해 주세요.", + "rateLimit": "요청이 너무 많아요. 잠시 후 다시 시도해 주세요.", + "noProvider": "AI 제공자가 설정되지 않았어요. 설정에서 등록해 주세요.", + "budget": "오늘 AI 사용 한도를 다 썼어요. 내일 다시 시도해 주세요.", + "network": "AI 제공자에 연결하지 못했어요. 다시 시도해 주세요.", "consent": "AI로 설명을 읽으려면 먼저 동의가 필요합니다.", "unavailable": "지금 여기에서는 AI로 설명을 읽을 수 없습니다." } @@ -1508,7 +1508,7 @@ "night": "밤" }, "max": { - "reached": "최대 개수에 도달했어요 — 다른 시각을 삭제한 뒤 추가하세요." + "reached": "최대 개수에 도달했어요. 다른 시각을 삭제한 뒤 추가하세요." } }, "courseWindow": { @@ -1584,7 +1584,7 @@ }, "dosesPerUnitLabel": "단위당 투여 횟수", "dosesPerUnitPlaceholder": "예: 4", - "dosesPerUnitHint": "펜/바이알당 투여 횟수 — 재고 추적이 필요 없으면 비워 두세요.", + "dosesPerUnitHint": "펜/바이알당 투여 횟수예요. 재고 추적이 필요 없으면 비워 두세요.", "short": "용량", "unitsPerDoseLabel": "1회 복용 단위 수", "unitsPerDoseHint": "예: 4mg 용량이면 2mg 2정, 반으로 나눠 먹으면 ½정" @@ -1596,7 +1596,7 @@ }, "step5": { "title": "얼마나 자주 복용하나요?", - "subline": "주기를 고르세요 — 세부 설정은 다음 단계에서 해요.", + "subline": "주기를 고르세요. 세부 설정은 다음 단계에서 해요.", "short": "주기" }, "step6": { @@ -1618,7 +1618,7 @@ }, "step7": { "title": "하루 중 언제 복용하나요?", - "subline": "하루 한 번 이상 — 알림은 이 목록을 따라요.", + "subline": "하루 한 번 이상이에요. 알림은 이 목록을 따라요.", "presetsLabel": "시간대 프리셋", "presets": { "morning": "아침", @@ -1626,7 +1626,7 @@ "evening": "저녁", "night": "밤" }, - "overrideHint": "선택 사항 — 이 시간대에만 다른 용량이나 단위 수를 지정해요. 비워 두면 약의 기본값을 써요.", + "overrideHint": "선택 사항: 이 시간대에만 다른 용량이나 단위 수를 지정해요. 비워 두면 약의 기본값을 써요.", "doseOverrideLabel": "이 시간대 용량 (선택)", "doseOverridePlaceholder": "예: 반 알", "unitsOverrideLabel": "이 시간대에 복용하는 단위 수", @@ -1634,10 +1634,10 @@ "short": "시간" }, "step8": { - "title": "다 됐어요 — HealthLog가 알림을 보낼까요?", + "title": "다 됐어요. HealthLog가 알림을 보낼까요?", "subline": "저장하기 전에 아래 내용을 확인해 주세요.", "remindersLabel": "알림 켜기", - "remindersDescription": "푸시, Telegram, ntfy — 설정에 따라 보내요.", + "remindersDescription": "푸시, Telegram, ntfy 중 설정에 따라 보내요.", "noChannelHint": "알림을 보내려면 알림 채널이 필요한데, 지금은 켜진 채널이 없어요.", "noChannelHintLink": "알림 설정하기", "short": "완료" @@ -1722,7 +1722,7 @@ } }, "errors": { - "submitFailed": "약을 저장하지 못했어요 — 다시 시도해 주세요." + "submitFailed": "약을 저장하지 못했어요. 다시 시도해 주세요." } }, "doseStrength": { @@ -1742,7 +1742,7 @@ }, "injectionSiteBodyOutlineAriaLabel": "신체 윤곽", "injectionSitePickerAriaLabel": "주사 부위 선택기", - "injectionSiteRecommendedAriaLabel": "{site} — 다음 권장 부위", + "injectionSiteRecommendedAriaLabel": "{site}: 다음 권장 부위", "injectionSiteLegendAriaLabel": "마커 범례", "injectionSiteLegendRecommended": "다음 권장 부위", "injectionSiteLegendLastUsed": "마지막 사용 부위", @@ -1818,7 +1818,7 @@ "emptyState": "아직 복용 기록이 없어요.", "emptyStateCta": "용량을 기록하면 예상 농도 곡선이 그려져요.", "estimateNote": "EMA가 공개한 집단 약동학 자료를 바탕으로 한 참고용 추정치예요. 실제 측정값이 아니에요.", - "unknownDrug": "{name} — EMA 승인 GLP-1 목록에 없어서 HealthLog가 집단 약동학 곡선을 그릴 수 없어요." + "unknownDrug": "{name}: EMA 승인 GLP-1 목록에 없어서 HealthLog가 집단 약동학 곡선을 그릴 수 없어요." } }, "detail": { @@ -1830,7 +1830,7 @@ "cadence": { "oneShotOn": "{date}에 1회 복용해요.", "oneShotPending": "1회 복용 예정이에요.", - "asNeeded": "필요시 복용 — 정해진 일정 없어요." + "asNeeded": "필요시 복용: 정해진 일정 없어요." }, "intake": { "title": "복용 기록", @@ -1857,7 +1857,7 @@ "dialogTitle": "복용 기록 편집", "takenAtLabel": "복용 시각", "scheduledForHint": "예정: {dateTime}", - "farFromScheduledWarning": "예정 시각과 많이 떨어져 있어요 — 날짜를 확인해 주세요.", + "farFromScheduledWarning": "예정 시각과 많이 떨어져 있어요. 날짜를 확인해 주세요.", "skippedLabel": "건너뜀", "save": "저장", "cancel": "취소", @@ -1901,10 +1901,10 @@ }, "addDialog": { "title": "복용 기록 추가", - "description": "복용을 기록해요 — 지난 날짜나 일정 외 복용도 괜찮아요.", + "description": "복용을 기록해요. 지난 날짜나 일정 외 복용도 괜찮아요.", "takenAtLabel": "복용 시각", "skippedLabel": "건너뜀", - "nudgeHint": "{slot} 시간대와 가까워요 — 저장할 때 그 시간대에 배정할지 물어볼게요.", + "nudgeHint": "{slot} 시간대와 가까워요. 저장할 때 그 시간대에 배정할지 물어볼게요.", "cancel": "취소", "submit": "저장" }, @@ -1973,7 +1973,7 @@ "title": "복약 종료", "helper": "알림을 끄고 이 약을 종료 상태로 표시해요. 기록은 계속 볼 수 있어요.", "button": "종료", - "dialogTitle": "종료: {name} — 알림을 끄고, 기록은 계속 볼 수 있어요", + "dialogTitle": "종료: {name} (알림을 끄고, 기록은 계속 볼 수 있어요)", "dialogBody": "알림이 더 이상 오지 않아요. 이전 기록은 타임라인에 남아요.", "toast": "복약을 종료했어요", "failed": "복약을 종료하지 못했어요." @@ -1991,7 +1991,7 @@ "title": "약 삭제", "helper": "약과 관련된 모든 기록을 삭제해요.", "button": "삭제", - "dialogTitle": "{name} — 삭제할까요?", + "dialogTitle": "{name}: 삭제할까요?", "dialogBody": "약과 일정, 복용 기록, API 토큰, 단계 설정, 알림이 모두 영구히 삭제돼요.", "toast": "약을 삭제했어요", "failed": "약을 삭제하지 못했어요." @@ -2011,7 +2011,7 @@ "copyFailed": "복사하지 못했어요.", "tokenCopied": "토큰을 복사했어요", "copyToken": "토큰 복사", - "mintedHint": "지금 토큰을 복사해 주세요 — 한 번만 보여줘요." + "mintedHint": "지금 토큰을 복사해 주세요. 한 번만 보여줘요." }, "advanced": { "dataPortability": { @@ -2051,9 +2051,9 @@ "statusTitle": "상태", "nextDoseLabel": "다음 복용", "nextDoseNone": "예정된 복용이 없어요.", - "nextDoseAsNeeded": "필요시 복용 — 예정된 복용이 없어요.", + "nextDoseAsNeeded": "필요시 복용: 예정된 복용이 없어요.", "nextDoseNotTracked": "복용을 기록하지 않아요. 기록으로만 남겨요.", - "pausedHint": "일시중지 — 알림이 오지 않아요.", + "pausedHint": "일시중지: 알림이 오지 않아요.", "reminderLabel": "알림", "reminderOn": "켜짐", "reminderOff": "꺼짐", @@ -2124,7 +2124,7 @@ "packagingDefaultPack": "기본 포장 크기: {units}개", "packagingNoDefaultPack": "기본 포장 크기가 설정되지 않았어요", "packagingEdit": "편집", - "packagingDescription": "1회분에 몇 개를 쓰는지, 새 포장이 보통 몇 개인지 설정해요 — 예를 들어 제조사가 바뀌어 포장 크기가 달라졌을 때요.", + "packagingDescription": "1회분에 몇 개를 쓰는지, 새 포장이 보통 몇 개인지 설정해요. 예를 들어 제조사가 바뀌어 포장 크기가 달라졌을 때요.", "packagingUnitsPerDoseLabel": "1회분당 개수", "packagingUnitsPerDoseHelper": "예: 4mg 복용에 2mg 정제 2개, 한 알 반이면 1.5 (0 초과, 100 이하). 이미 기록된 복용은 그대로예요.", "packagingDefaultPackLabel": "기본 포장 크기 (개)", @@ -2175,11 +2175,11 @@ "hideEras": "이전 구간 숨기기", "addEra": "이전 구간 추가", "addEraTitle": "이전 구간 추가", - "addEraDescription": "예전에 이 약을 복용하던 시각을 기록해요 — 예를 들어 여기서 일정을 바꾸기 전 시각이요.", + "addEraDescription": "예전에 이 약을 복용하던 시각을 기록해요. 예를 들어 여기서 일정을 바꾸기 전 시각이요.", "editAria": "구간 편집", "editEraTitle": "구간 편집", "editEraDescription": "이 구간의 복용 시각과 기간을 조정해요.", - "archivedEditHint": "이 구간은 자동으로 기록됐어요 — 수정하면 기록된 이력이 바로잡히고, 원본은 내부에 기록으로 남아요.", + "archivedEditHint": "이 구간은 자동으로 기록됐어요. 수정하면 기록된 이력이 바로잡히고, 원본은 내부에 기록으로 남아요.", "updatedToast": "구간을 수정했어요", "updateError": "구간을 수정하지 못했어요. 다른 구간과 겹치지 않고, 현재 일정보다 먼저 끝나야 해요.", "timesLabel": "복용 시각", @@ -2205,7 +2205,7 @@ "saved": "일정을 저장했어요", "failed": "일정을 저장하지 못했어요", "window": { - "intro": "복용마다 정시로 인정되는 범위를 정해요 — 정확한 시각(±1h)이나 07:00–09:00 같은 직접 지정 범위로요.", + "intro": "복용마다 정시로 인정되는 범위를 정해요. 정확한 시각(±1h)이나 07:00–09:00 같은 직접 지정 범위로요.", "explicitToggle": "직접 범위 지정", "startLabel": "범위 시작", "endLabel": "범위 종료", @@ -2218,10 +2218,10 @@ } }, "logInjectionSiteTitle": "주사 부위 기록", - "logInjectionSiteDescription": "{name} — 어디에 주사했나요? 선택 사항이라 건너뛰어도 돼요.", + "logInjectionSiteDescription": "{name}: 어디에 주사했나요? 선택 사항이라 건너뛰어도 돼요.", "logInjectionSiteSkip": "건너뛰기", "logInjectionSiteConfirm": "부위 저장", - "logInjectionSiteNoneAvailable": "쓸 수 있는 주사 부위가 없어요 — 설정에서 모든 부위를 제외했어요.", + "logInjectionSiteNoneAvailable": "쓸 수 있는 주사 부위가 없어요. 설정에서 모든 부위를 제외했어요.", "logInjectionSiteSaveFailed": "주사 부위를 저장하지 못했어요. 다시 시도해 주세요.", "perSlotUnits": "1회분당 {units}", "trackInjectionSitesToggle": "주사 부위 기록하기", @@ -2246,9 +2246,9 @@ "tableStockDoses": "{count}회분", "tableStockRunway": "약 {days}일 남음", "cardLowStockRunway": "재고: 약 {days}일", - "takeActionFor": "복용 – {name}", - "skipActionFor": "건너뛰기 – {name}", - "reorderDescription": "약의 순서를 정하세요 – 카드 보기와 표 보기 모두에 적용돼요.", + "takeActionFor": "복용: {name}", + "skipActionFor": "건너뛰기: {name}", + "reorderDescription": "카드 보기와 표 보기 모두에 적용되는 약의 순서를 정하세요.", "reorderSaved": "순서를 저장했어요", "reorderSaveFailed": "순서를 저장하지 못했어요", "customize": "복약 맞춤 설정", @@ -2267,7 +2267,7 @@ "levelShift": "{date} 무렵에 수준 변화가 감지됐어요.", "plateau": { "title": "현재 용량에서 체중 정체", - "evidence": "최근 {window}일 동안 체중이 {delta}{unit} 움직였어요({readings}개 측정값) — {dose}로 {days}일." + "evidence": "최근 {window}일 동안 체중이 {delta}{unit} 움직였어요({readings}개 측정값). {dose}로 {days}일째예요." }, "retarget": { "label": "맞는 측정값이 아닌가요?", @@ -2277,16 +2277,16 @@ "error": "변경 내용을 저장하지 못했어요. 다시 시도해 주세요." }, "beforeAfter": { - "summary": "시작 전 평균 {before} → 이후 평균 {after} — {delta} 변화.", + "summary": "시작 전 평균 {before} → 이후 평균 {after}, {delta} 변화.", "counts": "시작 전 {beforeCount}개, 이후 {afterCount}개 측정값을 기준으로 했어요.", - "needBefore": "시작 전 측정값이 아직 부족해요 — 비교하려면 전후로 약 {weeks}주씩 필요해요.", - "needAfter": "시작 이후 측정값이 아직 부족해요 — 비교하려면 전후로 약 {weeks}주씩 필요해요.", + "needBefore": "시작 전 측정값이 아직 부족해요. 비교하려면 전후로 약 {weeks}주씩 필요해요.", + "needAfter": "시작 이후 측정값이 아직 부족해요. 비교하려면 전후로 약 {weeks}주씩 필요해요.", "needStart": "시작일을 설정하면 복용 전후 측정값을 비교할 수 있어요.", - "needData": "측정값이 아직 부족해요 — 비교하려면 시작 전후로 약 {weeks}주씩 필요해요." + "needData": "측정값이 아직 부족해요. 비교하려면 시작 전후로 약 {weeks}주씩 필요해요." }, "insights": { "title": "약 효과", - "subtitle": "약이 목표로 하는 측정값과 무엇이 함께 움직였는지 보여줘요 — 연관성일 뿐 판단이 아니에요.", + "subtitle": "약이 목표로 하는 측정값과 무엇이 함께 움직였는지 보여줘요. 연관성일 뿐 판단이 아니에요.", "link": "효과 보기 열기", "empty": "약과 목표 측정값을 연결하기에는 데이터가 아직 부족해요." }, @@ -2320,7 +2320,7 @@ "reasonMissingMedication": "행에 약 이름이 없어요", "reasonUnreadableDosage": "복용량이 숫자가 아니에요", "reasonUnreadableRow": "행의 열 개수가 머리글보다 적어요", - "reasonStatusNoDoseInformation": "파일에 그 복용에 대한 기록이 없어요 — 응답도 없었고 기록된 것도 없어요", + "reasonStatusNoDoseInformation": "파일에 그 복용에 대한 기록이 없어요. 응답도 없었고 기록된 것도 없어요", "reasonStatusReminderEvent": "행이 미뤄 둔 알림에 관한 내용이라 복용에 대해 알려주는 게 없어요", "reasonStatusNotificationNotSent": "행은 알림이 발송되지 않았다는 기록이라 복용이 아니라 앱에 관한 내용이에요" }, @@ -2392,7 +2392,7 @@ }, "charts": { "loadingLabel": "차트 불러오는 중…", - "loadingSlowHint": "분석을 계산하는 중이에요 — 잠시 걸릴 수 있어요.", + "loadingSlowHint": "분석을 계산하는 중이에요. 잠시 걸릴 수 있어요.", "weight": "체중", "bloodPressure": "혈압", "pulse": "맥박", @@ -2471,8 +2471,8 @@ "columnDate": "날짜", "noValue": "값 없음", "captionDay": "{metric} 하루당 한 행, 차트가 그리는 값과 같아요.", - "captionWeek": "{metric} 한 주당 한 행, 그 주 일별 평균 — 차트가 그리는 값과 같아요.", - "captionMonth": "{metric} 한 달당 한 행, 그달 일별 평균 — 차트가 그리는 값과 같아요.", + "captionWeek": "{metric} 한 주당 한 행, 그 주 일별 평균이에요. 차트가 그리는 값과 같아요.", + "captionMonth": "{metric} 한 달당 한 행, 그달 일별 평균이에요. 차트가 그리는 값과 같아요.", "hourlyMeanNote": "{metric}은(는) 하루의 평균이며 각 시간을 한 번씩만 반영하므로, 운동이 하루의 나머지보다 더 크게 반영되지 않습니다." }, "personalBaseline": "내 평소값", @@ -2542,8 +2542,8 @@ }, "tooltipPrior": "이전 기간", "unavailable": { - "lastMonth": "비교 불가 — 지난달 데이터가 아직 없어요", - "lastYear": "비교 불가 — 작년 데이터가 아직 없어요" + "lastMonth": "비교 불가: 지난달 데이터가 아직 없어요", + "lastYear": "비교 불가: 작년 데이터가 아직 없어요" }, "notAvailableForCompliance": "복약 순응도는 비교 불가" }, @@ -2751,7 +2751,7 @@ "unavailable": "이 항목은 지금 반영 대상이 아니에요" }, "tension": "컨디션 신호가 엇갈려요. 좋은 쪽: {positive}. 부담이 큰 쪽: {negative}.", - "returnToBand": "{metric} — {days}일째 평소 범위 안으로 돌아와 있어요.", + "returnToBand": "{metric}: {days}일째 평소 범위 안으로 돌아와 있어요.", "weightGoal": { "title": "개인 체중 목표", "value": "지금 {current}{unit}. 목표 {min}~{max}{unit}. 목표까지 {distance}{unit}.", @@ -2841,14 +2841,14 @@ } }, "coach": { - "refusalOutOfScope": "기록에 있는 건강 지표 — 측정값, 약, 기분, 추이 — 만 도와드릴 수 있어요. 그 밖의 질문에는 답할 수 없어요.", - "refusalInjection": "제 지시를 덮어쓰려는 표현이 보였어요. 저는 HealthLog 코치이고 회원님의 건강 데이터만 정리해 드려요 — 그 범위로 질문을 다시 적어 주세요.", + "refusalOutOfScope": "기록에 있는 건강 지표(측정값, 약, 기분, 추이)만 도와드릴 수 있어요. 그 밖의 질문에는 답할 수 없어요.", + "refusalInjection": "제 지시를 덮어쓰려는 표현이 보였어요. 저는 HealthLog 코치이고 회원님의 건강 데이터만 정리해 드려요. 그 범위로 질문을 다시 적어 주세요.", "errorBudget": "오늘 코치 사용 한도에 도달했어요. 사용량은 UTC 자정에 초기화돼요.", "errorProvider": "지금은 코치가 인사이트 제공자에 연결하지 못했어요. 잠시 후 다시 시도해 주세요.", "errorDemo": "데모에서는 코치가 답하지 않아요.", - "errorNoProvider": "코치는 기록된 건강 데이터를 읽고 그에 대한 질문에 답해요(의학적 조언은 아니에요). 그러려면 HealthLog에 AI 제공자가 필요해요 — 직접 발급한 키나 로컬 모델을 연결해 주세요.", + "errorNoProvider": "코치는 기록된 건강 데이터를 읽고 그에 대한 질문에 답해요(의학적 조언은 아니에요). 그러려면 HealthLog에 AI 제공자가 필요해요. 직접 발급한 키나 로컬 모델을 연결해 주세요.", "errorNoProviderAction": "AI 제공자 연결", - "errorNetwork": "인터넷에 연결되어 있지 않아요 — 다시 연결되면 시도해 주세요.", + "errorNetwork": "인터넷에 연결되어 있지 않아요. 다시 연결되면 시도해 주세요.", "prefsSaveError": "코치 설정을 저장하지 못했어요. 다시 시도해 주세요.", "errorCredentialExpired": "AI 제공자 연결이 만료됐어요. 코치를 계속 쓰려면 설정에서 다시 연결해 주세요.", "tagline": "내 데이터에 기반한 개인 건강 코치.", @@ -2867,7 +2867,7 @@ "thinking": "생각 중…", "unverifiedFiguresNotice": "일부 수치는 데이터와 대조하지 못해 제외했어요.", "composerPlaceholder": "무엇이든 물어보세요…", - "nudgeBubbleLabel": "코치의 새 메시지 — 대화 열기", + "nudgeBubbleLabel": "코치의 새 메시지: 대화 열기", "fabLabel": "코치 열기", "readAloud": "소리내어 읽기", "readAloudStop": "읽기 중지", @@ -2891,7 +2891,7 @@ "guided": { "offerTitle": "코치가 물어볼 후속 질문이 {count}개 있어요", "offerTitleOne": "코치가 물어볼 후속 질문이 있어요", - "offerBody": "짧은 답변이 셀프 컨텍스트를 더 정확하게 만들어요 — 여기 대화에서 한 번에 하나씩 물어볼게요.", + "offerBody": "짧은 답변이 셀프 컨텍스트를 더 정확하게 만들어요. 여기 대화에서 한 번에 하나씩 물어볼게요.", "offerStart": "지금 답하기", "offerLater": "나중에", "offerDismiss": "다시 묻지 않기", @@ -2901,7 +2901,7 @@ "later": "나중에", "dismissRemaining": "다시 묻지 않기", "answerPlaceholder": "답변을 입력하세요…", - "summaryTitle": "다 됐어요 — 답변 고마워요!", + "summaryTitle": "다 됐어요. 답변 고마워요!", "summaryAnswered": "{total}개 중 {answered}개 답변", "summaryAdopted": "셀프 컨텍스트에 {adopted}개 추가", "summaryAdoptedNone": "셀프 컨텍스트에 새로 추가된 건 없어요", @@ -2983,7 +2983,7 @@ "settingsVerbosityBrief": "짧게", "settingsVerbosityDefault": "기본", "settingsVerbosityDetailed": "자세히", - "settingsVerbosityConciseHint": "간결한 말투는 이미 답변을 짧게 유지해요 — 켜 두는 동안 답변 길이는 '짧게'로 고정돼요.", + "settingsVerbosityConciseHint": "간결한 말투는 이미 답변을 짧게 유지해요. 켜 두는 동안 답변 길이는 '짧게'로 고정돼요.", "settingsSourcesSummary": "코치는 데이터 영역 {total}개 중 {count}개를 {window} 전까지 봐요.", "settingsSourcesSummaryAll": "코치는 데이터 영역 {total}개 중 {count}개를 처음 기록부터 봐요.", "settingsSourcesPointerLink": "코치 설정 열기", @@ -3075,22 +3075,22 @@ "askAboutThis": "코치에게 물어보기", "readStrip": { "label": "평소 범위", - "baselineWithin": "평소 범위: {low}–{high} {unit}. 오늘 값 {value} — 범위 안이에요.", - "baselineAbove": "평소 범위: {low}–{high} {unit}. 오늘 값 {value} — 범위 위예요.", - "baselineBelow": "평소 범위: {low}–{high} {unit}. 오늘 값 {value} — 범위 아래예요.", - "sameHoursWithin": "이 시간대까지 평소 범위: {low}–{high} {unit}. 오늘 지금까지 {value} — 범위 안이에요.", - "sameHoursAbove": "이 시간대까지 평소 범위: {low}–{high} {unit}. 오늘 지금까지 {value} — 범위 위예요.", - "sameHoursBelow": "이 시간대까지 평소 범위: {low}–{high} {unit}. 오늘 지금까지 {value} — 범위 아래예요.", - "steadyWithin": "평소 값: {low} {unit}. 오늘 값 {value} — 평소와 같아요.", - "steadyAbove": "평소 값: {low} {unit}. 오늘 값 {value} — 평소보다 높아요.", - "steadyBelow": "평소 값: {low} {unit}. 오늘 값 {value} — 평소보다 낮아요.", - "latestWithin": "평소 범위: {low}–{high} {unit}. 마지막 측정({date}) 값 {value} — 범위 안이었어요.", - "latestAbove": "평소 범위: {low}–{high} {unit}. 마지막 측정({date}) 값 {value} — 범위보다 높았어요.", - "latestBelow": "평소 범위: {low}–{high} {unit}. 마지막 측정({date}) 값 {value} — 범위 아래였어요.", - "steadyLatestWithin": "평소 값: {low} {unit}. 마지막 측정({date}) 값 {value} — 평소와 같았어요.", - "steadyLatestAbove": "평소 값: {low} {unit}. 마지막 측정({date}) 값 {value} — 평소보다 높았어요.", - "steadyLatestBelow": "평소 값: {low} {unit}. 마지막 측정({date}) 값 {value} — 평소보다 낮았어요.", - "insufficient": "아직 평소 범위를 배우는 중이에요 — 며칠 더 기록해 주세요.", + "baselineWithin": "평소 범위: {low}–{high} {unit}. 오늘 값 {value}, 범위 안이에요.", + "baselineAbove": "평소 범위: {low}–{high} {unit}. 오늘 값 {value}, 범위 위예요.", + "baselineBelow": "평소 범위: {low}–{high} {unit}. 오늘 값 {value}, 범위 아래예요.", + "sameHoursWithin": "이 시간대까지 평소 범위: {low}–{high} {unit}. 오늘 지금까지 {value}, 범위 안이에요.", + "sameHoursAbove": "이 시간대까지 평소 범위: {low}–{high} {unit}. 오늘 지금까지 {value}, 범위 위예요.", + "sameHoursBelow": "이 시간대까지 평소 범위: {low}–{high} {unit}. 오늘 지금까지 {value}, 범위 아래예요.", + "steadyWithin": "평소 값: {low} {unit}. 오늘 값 {value}, 평소와 같아요.", + "steadyAbove": "평소 값: {low} {unit}. 오늘 값 {value}, 평소보다 높아요.", + "steadyBelow": "평소 값: {low} {unit}. 오늘 값 {value}, 평소보다 낮아요.", + "latestWithin": "평소 범위: {low}–{high} {unit}. 마지막 측정({date}) 값 {value}, 범위 안이었어요.", + "latestAbove": "평소 범위: {low}–{high} {unit}. 마지막 측정({date}) 값 {value}, 범위보다 높았어요.", + "latestBelow": "평소 범위: {low}–{high} {unit}. 마지막 측정({date}) 값 {value}, 범위 아래였어요.", + "steadyLatestWithin": "평소 값: {low} {unit}. 마지막 측정({date}) 값 {value}, 평소와 같았어요.", + "steadyLatestAbove": "평소 값: {low} {unit}. 마지막 측정({date}) 값 {value}, 평소보다 높았어요.", + "steadyLatestBelow": "평소 값: {low} {unit}. 마지막 측정({date}) 값 {value}, 평소보다 낮았어요.", + "insufficient": "아직 평소 범위를 배우는 중이에요. 며칠 더 기록해 주세요.", "driver": "{note}" }, "scope": { @@ -3104,39 +3104,39 @@ "groupEarlier": "이전" }, "seed": { - "bloodPressure": "최근 30일 혈압 추이를 설명해 주세요 — 눈여겨볼 게 있나요?", + "bloodPressure": "최근 30일 혈압 추이를 설명해 주세요. 눈여겨볼 게 있나요?", "weight": "요즘 체중 추이가 어떤가요? 그 방향이 신경 쓸 만한가요?", "bmi": "제 BMI 추이는 무엇을 말해 주나요? 어떻게 읽어야 하나요?", - "pulse": "제 맥박 측정값을 설명해 주세요 — 평소와 다른 점이 있나요?", + "pulse": "제 맥박 측정값을 설명해 주세요. 평소와 다른 점이 있나요?", "restingHr": "안정 시 심박수 추이는 어떤가요? 제 체력에 대해 뭘 알려 주나요?", "hrv": "요즘 제 심박변이도는 회복과 스트레스에 대해 뭘 말해 주나요?", - "sleep": "최근 수면을 설명해 주세요 — 수면 시간, 규칙성, 바꿀 만한 점까지.", + "sleep": "최근 수면을 설명해 주세요. 수면 시간, 규칙성, 바꿀 만한 점까지.", "mood": "최근 몇 주 동안 제 기분에서 어떤 패턴이 보이나요?", "medications": "제 복약 순응도는 어떤가요? 요즘 컨디션과 맞물리나요?", "steps": "걸음 수로 볼 때 요즘 얼마나 활동적이었나요? 건강한 기준값과 비교하면 어떤가요?", "activeEnergy": "활동 에너지 추이는 요즘 제 활동량에 대해 뭘 말해 주나요?", "cardioFitness": "심폐 체력(VO₂ max) 추이는 무슨 뜻인가요? 어떻게 하면 좋은 방향으로 올릴 수 있나요?", - "bloodGlucose": "최근 혈당 측정값을 설명해 주세요 — 건강한 범위 안인가요?", + "bloodGlucose": "최근 혈당 측정값을 설명해 주세요. 건강한 범위 안인가요?", "oxygenSaturation": "제 산소포화도(SpO₂) 추이는 무엇을 말해 주나요?", "respiratoryRate": "제 호흡수 추이는 건강에 대해 뭘 말해 주나요?", - "workouts": "최근 운동을 설명해 주세요 — 운동량, 빈도, 사이사이 회복까지.", + "workouts": "최근 운동을 설명해 주세요. 운동량, 빈도, 사이사이 회복까지.", "recoveryPage": "지금 제 회복 상태가 이런 이유는 뭔가요? 무엇이 영향을 주고 있나요?", - "briefing": "오늘 브리핑을 설명해 주세요 — 무엇에 집중해야 하고, 지금 할 만한 일이 있나요?", + "briefing": "오늘 브리핑을 설명해 주세요. 무엇에 집중해야 하고, 지금 할 만한 일이 있나요?", "healthScore": "제 건강 점수가 100점 중 {score}점인 이유는 뭔가요? 무엇을 바꾸면 가장 크게 오를까요?", - "periodWeek": "지난주 건강 지표들이 어땠는지 설명해 주세요 — 눈에 띄는 게 있나요?", - "periodMonth": "지난달 건강 지표들이 어땠는지 설명해 주세요 — 눈에 띄는 게 있나요?", + "periodWeek": "지난주 건강 지표들이 어땠는지 설명해 주세요. 눈에 띄는 게 있나요?", + "periodMonth": "지난달 건강 지표들이 어땠는지 설명해 주세요. 눈에 띄는 게 있나요?", "correlationBpCompliance": "제 복약 순응도가 혈압과 어떤 관계인가요? 이 상관관계가 저에게 어떤 의미인지 설명해 주세요.", "correlationMoodPulse": "제 기분과 맥박 사이에 실제로 연관이 있나요? 이 상관관계를 읽는 법을 알려 주세요.", "correlationWeightWeekday": "제 체중이 주간 패턴을 따르나요? 이 요일별 상관관계는 무엇을 말해 주나요?", - "recommendation": "이 추천에 대해 더 알려 주세요: '{text}' — 왜 저에게 해당하고, 무엇을 하면 되나요?" + "recommendation": "이 추천에 대해 더 알려 주세요: '{text}'. 왜 저에게 해당하고, 무엇을 하면 되나요?" }, - "assessmentPrompt": "제 {metric} 평가를 설명해 주세요 — 무슨 뜻이고 무엇을 하면 되나요?", + "assessmentPrompt": "제 {metric} 평가를 설명해 주세요. 무슨 뜻이고 무엇을 하면 되나요?", "attach": { "menuChooseFromDocuments": "문서에서 선택", "menuUploadNew": "새 문서 업로드", "trigger": "문서 첨부", "pickerTitle": "문서 첨부", - "pickerDescription": "코치는 첨부한 문서만 읽어요 — 건강 데이터는 읽지 않아요.", + "pickerDescription": "코치는 첨부한 문서만 읽어요. 건강 데이터는 읽지 않아요.", "pickerSearchPlaceholder": "문서 검색…", "pickerEmpty": "보관함에 문서가 아직 없어요.", "pickerNotIndexed": "아직 색인되지 않음", @@ -3144,13 +3144,13 @@ "pickerConfirm": "첨부 ({count})", "pillRemove": "제거: {title}", "indexing": "색인 중…", - "indexingHint": "아직 색인 중인 문서가 있어요 — 준비되면 보낼 수 있어요.", - "fencedHint": "이 대화는 건강 데이터에 접근하지 않아요 — 코치는 첨부한 문서만 읽어요.", + "indexingHint": "아직 색인 중인 문서가 있어요. 준비되면 보낼 수 있어요.", + "fencedHint": "이 대화는 건강 데이터에 접근하지 않아요. 코치는 첨부한 문서만 읽어요.", "documentsAttachedOne": "문서 1개 첨부됨", "documentsAttachedOther": "문서 {count}개 첨부됨", "railBadge": "문서 전용 대화", "uploadError": "업로드하지 못했어요. 다시 시도해 주세요.", - "notFoundError": "그 문서 링크는 더 이상 유효하지 않아요 — 일반 대화로 시작할게요." + "notFoundError": "그 문서 링크는 더 이상 유효하지 않아요. 일반 대화로 시작할게요." }, "interrupted": { "note": "이 답변은 끝나기 전에 중단됐어요.", @@ -3321,7 +3321,7 @@ }, "hrv": { "title": "심박변이도", - "description": "시간에 따른 심박변이도 — 신경계 회복 신호로, Apple Watch 등 호환 웨어러블이 수면 중에 측정해요.", + "description": "시간에 따른 심박변이도예요. 신경계 회복 신호로, Apple Watch 등 호환 웨어러블이 수면 중에 측정해요.", "chartTitle": "심박변이도", "emptyState": { "title": "아직 심박변이도 기록이 없어요", @@ -3330,17 +3330,17 @@ }, "restingHr": { "title": "안정 시 심박수", - "description": "심장이 하루 중 내려앉는 최저치예요 — 맥박 페이지의 단발 측정값과는 달라요. Apple Health는 하루에 한 값을 제공해요.", + "description": "심장이 하루 중 내려앉는 최저치예요. 맥박 페이지의 단발 측정값과는 달라요. Apple Health는 하루에 한 값을 제공해요.", "chartTitle": "안정 시 심박수", "emptyState": { "title": "아직 안정 시 심박수가 없어요", "description": "Apple Watch나 호환 Withings 기기를 조용한 하루 동안 착용하면 안정 시 심박수가 들어와요." }, - "coachPrefill": "아직 안정 시 심박수를 기록한 적이 없어요 — 하루 안정 시 값이 단발 맥박과 왜 다른가요? 어떻게 개선하나요?" + "coachPrefill": "아직 안정 시 심박수를 기록한 적이 없어요. 하루 안정 시 값이 단발 맥박과 왜 다른가요? 어떻게 개선하나요?" }, "oxygenSaturation": { "title": "산소포화도", - "description": "혈중 산소(SpO₂) — 임상 정상 범위는 95–100 %이고, 목표 구간을 차트에 음영으로 표시해요.", + "description": "혈중 산소(SpO₂)예요. 임상 정상 범위는 95–100 %이고, 목표 구간을 차트에 음영으로 표시해요.", "chartTitle": "산소포화도", "emptyState": { "title": "아직 SpO₂ 기록이 없어요", @@ -3349,7 +3349,7 @@ }, "bodyTemperature": { "title": "체온", - "description": "심부 체온 추이 — 섭씨. Withings의 피부 온도 측정값은 별도 지표로 따로 있어요.", + "description": "심부 체온 추이(섭씨)예요. Withings의 피부 온도 측정값은 별도 지표로 따로 있어요.", "chartTitle": "체온", "emptyState": { "title": "아직 체온 기록이 없어요", @@ -3359,7 +3359,7 @@ }, "steps": { "title": "걸음 수", - "description": "하루 걸음 수 — 하루에 한 줄씩, Apple Health나 연결된 활동 기기에서 가져와요.", + "description": "하루 걸음 수예요. 하루에 한 줄씩, Apple Health나 연결된 활동 기기에서 가져와요.", "chartTitle": "하루 걸음 수", "emptyState": { "title": "아직 걸음 수 데이터가 없어요", @@ -3368,7 +3368,7 @@ }, "activeEnergy": { "title": "활동 에너지", - "description": "하루 활동 에너지 합계(kcal) — 하루에 한 줄씩, Apple Health나 Withings 활동에서 가져와요.", + "description": "하루 활동 에너지 합계(kcal)예요. 하루에 한 줄씩, Apple Health나 Withings 활동에서 가져와요.", "chartTitle": "활동 에너지", "emptyState": { "title": "아직 활동 에너지 데이터가 없어요", @@ -3388,27 +3388,27 @@ }, "explainer": { "bloodPressureBody": "혈압은 혈액이 동맥 벽에 가하는 힘이고, 수축기 분의 이완기로 적어요(심박 중 최고치와 박동 사이의 안정값). 높은 측정값이 계속되면 시간이 지나며 심장과 혈관에 부담이 쌓여요.", - "pulseBody": "맥박은 심장이 1분에 몇 번 뛰는지예요. 한 번의 측정값은 그 순간 무엇을 하고 있었는지를 반영해요 — 안정 시에는 보통 분당 60~100회이고, 움직임·스트레스·카페인에 따라 자연스럽게 올라가요.", + "pulseBody": "맥박은 심장이 1분에 몇 번 뛰는지예요. 한 번의 측정값은 그 순간 무엇을 하고 있었는지를 반영해요. 안정 시에는 보통 분당 60~100회이고, 움직임·스트레스·카페인에 따라 자연스럽게 올라가요.", "weightBody": "체중은 장기적인 에너지 균형과 전반적인 건강을 보여주는 가장 단순한 신호 중 하나예요. 수분·음식·시간대에 따라 흔들리는 한 번의 측정값보다 몇 주에 걸친 추이가 훨씬 중요해요.", "bmiBody": "BMI는 체중을 키의 제곱으로 나눈 값으로, 넓은 체중 범주를 알려주는 하나의 숫자예요. 진단이 아니라 인구 집단 수준의 선별 지표이고, 근육과 지방을 구분하지 못해요.", "sleepBody": "수면 시간은 밤새 실제로 잠든 시간이고, 얕은 수면·깊은 수면·REM 단계로 나뉘어요. 대부분의 성인은 대략 7~9시간이 필요하고, 꾸준한 양과 질 모두가 회복·기분·대사를 뒷받침해요.", "moodBody": "기분 기록은 간단한 척도로 시간에 따른 기분을 남겨요. 꾸준히 기록하면 수면·활동·약이 기분과 어떻게 맞물리는지, 하루만 봐서는 절대 보이지 않는 패턴이 드러나요.", "medicationsBody": "복약 순응도는 처방대로 약을 얼마나 꾸준히 복용하는지이고, 여기서는 예정된 복용 중 실제로 기록한 비율로 보여줘요. 치료가 의도대로 효과를 내려면 꾸준한 복용이 관건인 경우가 많아요.", - "restingHrBody": "안정 시 심박수는 완전히 쉬고 있을 때의 심박수로, 보통 밤사이에 측정해요 — 활동 중 맥박과는 달라요. 안정 시 심박수가 낮을수록 대체로 심폐 체력이 좋다는 뜻이고, 올라가는 추이는 스트레스나 질병의 초기 신호일 수 있어요. 일반적인 기준으로 성인의 정상 안정 시 심박수는 분당 60~100회예요(AHA 2024). 단련된 심장은 40~60회에 머물러도 문제없어요.", + "restingHrBody": "안정 시 심박수는 완전히 쉬고 있을 때의 심박수로, 보통 밤사이에 측정해요. 활동 중 맥박과는 달라요. 안정 시 심박수가 낮을수록 대체로 심폐 체력이 좋다는 뜻이고, 올라가는 추이는 스트레스나 질병의 초기 신호일 수 있어요. 일반적인 기준으로 성인의 정상 안정 시 심박수는 분당 60~100회예요(AHA 2024). 단련된 심장은 40~60회에 머물러도 문제없어요.", "hrvBody": "심박변이도는 연속된 심장 박동 사이 시간의 미세한 변동이에요. 변동이 클수록 대체로 잘 회복되고 적응력 있는 신경계를 뜻하고, 지속적으로 떨어지면 피로·스트레스·회복 부족의 신호일 수 있어요.", "oxygenSaturationBody": "SpO₂는 산소를 실어 나르는 적혈구의 비율이에요. 안정 시 95~100%는 정상이고, 90% 아래에 계속 머무르면 살펴볼 필요가 있어요. 다만 밤중에 잠깐 떨어지는 건 흔해요.", "bodyTemperatureBody": "체온은 몸의 심부 열 상태를 반영해요. 일반적인 기준으로 인구 평균은 37.0°C가 아니라 약 36.6°C이고, 구강 정상 범위는 대략 35.7~37.4°C, 발열은 38.0°C부터예요(J Gen Intern Med 2019). 하루 사이 약 0.5°C 오르내리고 측정 부위에 따라 최대 1°C가량 차이 나니 어디서 쟀는지 태그해 두세요. 밤사이 손목 측정값은 임상적 발열 수치가 아니라 상대적인 변화를 따라가요.", "activeEnergyBody": "활동 에너지는 몸이 쉴 때 쓰는 기본량 위에, 움직임으로 태운 칼로리예요. 하루를 얼마나 몸을 움직였는지 직접 보여주는 지표예요.", "workoutsBody": "운동은 기기가 기록한 구조화된 운동 세션으로, 종류·시간·에너지가 함께 남아요. 기록해 두면 꾸준한 훈련이 몇 주에 걸쳐 어떻게 쌓이는지, 다른 건강 신호와 어떻게 연결되는지 보여요.", - "respiratoryRateBody": "호흡수는 1분에 숨을 몇 번 쉬는지예요. 일반적인 기준으로 안정 시 대부분의 성인은 분당 12~20회 호흡해요(American Lung Association). 정말 쉬고 있거나 잠든 상태에서만 의미가 있어요. 본인의 밤사이 기준값보다 +3 정도 지속해서 올라가면 질병의 초기 신호일 수 있어요 — 임상 경보 기준치는 병원용 도구이지 자가 경보용이 아니에요.", + "respiratoryRateBody": "호흡수는 1분에 숨을 몇 번 쉬는지예요. 일반적인 기준으로 안정 시 대부분의 성인은 분당 12~20회 호흡해요(American Lung Association). 정말 쉬고 있거나 잠든 상태에서만 의미가 있어요. 본인의 밤사이 기준값보다 +3 정도 지속해서 올라가면 질병의 초기 신호일 수 있어요. 임상 경보 기준치는 병원용 도구이지 자가 경보용이 아니에요.", "bodyWaterBody": "체수분 총량은 세포 안팎의 수분이 체중에서 차지하는 비율이에요. 수분 섭취·음식·활동에 따라 움직이니 한 번의 측정값보다 몇 주 추이가 더 많은 걸 알려줘요.", "boneMassBody": "골량은 뼈에 들어 있는 무기질의 추정 무게예요. 체중계 기반 추정은 대략적이지만, 유지되거나 올라가는 추이는 장기적인 뼈 건강에 도움이 돼요.", - "fatFreeMassBody": "제지방량은 몸에서 지방이 아닌 전부 — 근육·뼈·장기·수분이에요. 체중을 줄이면서도 이걸 유지하거나 늘리면 대체로 더 건강한 체성분을 뜻해요.", + "fatFreeMassBody": "제지방량은 몸에서 지방이 아닌 전부(근육·뼈·장기·수분)예요. 체중을 줄이면서도 이걸 유지하거나 늘리면 대체로 더 건강한 체성분을 뜻해요.", "fatMassBody": "체지방량은 몸속 지방의 총 무게예요. 지방은 호르몬과 에너지 저장에 어느 정도 꼭 필요하지만, 특히 복부에 너무 많으면 장기적인 건강 위험이 올라가요(WHO 2024).", "bodyFatBody": "체지방률은 체중 중 지방이 차지하는 비율이에요. 건강한 범위는 성별과 나이에 따라 다르고, 체중계는 생체 전기 임피던스로 추정하므로 한 번의 측정값보다 몇 주간의 추이가 더 많은 걸 알려줘요.", "muscleMassBody": "근육량은 몸속 근육의 추정 무게예요. 근육이 많을수록 근력·대사·활동성에 도움이 되고, 나이가 들수록 유지하려면 적극적인 노력이 필요해요.", "visceralFatBody": "내장지방은 복부 깊숙이 장기 주변에 쌓이는 지방이에요. 피부 밑 지방과 달리 수치가 높으면 심장병과 2형 당뇨병에 밀접하게 연결되니 대체로 낮을수록 좋아요.", - "leanBodyMassBody": "제지방 체중은 전체 체중에서 체지방을 뺀 값 — 근육·뼈·장기·수분을 합친 거예요. 체중과 함께 보면 변화가 근육에서 왔는지 지방에서 왔는지 알 수 있어요.", + "leanBodyMassBody": "제지방 체중은 전체 체중에서 체지방을 뺀 값으로, 근육·뼈·장기·수분을 합친 거예요. 체중과 함께 보면 변화가 근육에서 왔는지 지방에서 왔는지 알 수 있어요.", "flightsClimbedBody": "오른 층수는 하루에 올라간 층을 세고, 한 층은 대략 3m의 고도 상승이에요. 일상 속 활동량과 하체 사용을 보여주는 단순한 지표예요.", "walkingDistanceBody": "걷기·달리기 거리는 하루에 두 발로 이동한 거리예요. 얼마나 자주 걸었는지뿐 아니라 얼마나 멀리 움직였는지를 보여줘서 걸음 수를 보완해요.", "walkingSteadinessBody": "보행 안정성은 걸음걸이가 얼마나 안정적이고 균형 잡혔는지를 양호부터 낮음까지로 추정해요. 등급이 낮을수록 낙상 가능성이 높다는 뜻이니 임상의와 상의해 볼 만해요.", @@ -3423,30 +3423,30 @@ "headphoneAudioBody": "헤드폰 음량은 이어폰이나 헤드폰으로 얼마나 크게 듣는지를 dB로 기록해요. 볼륨을 낮추고 중간중간 쉬어 주면 오래도록 청력을 지킬 수 있어요.", "audioEventsBody": "큰 소리 이벤트는 주변 소음이 충분히 노출될 경우 청력을 해칠 수 있는 수준에 도달한 순간을 표시해요. 자주 발생한다면 더 조용한 환경을 찾거나 청력 보호구를 쓰라는 신호예요.", "daylightBody": "햇빛 노출 시간은 하루에 야외 빛 속에서 보낸 시간이에요. 규칙적인 햇빛은 건강한 수면-각성 리듬과 기분에 도움이 되고(CDC 2024), 야외에서 보내는 시간은 눈 건강과도 연결돼요.", - "bloodGlucoseBody": "혈당은 몸의 주된 에너지원인 혈액 속 당의 양이에요. 식후에 올라가고 식사 사이에 가라앉아요. 당뇨가 없는 성인의 일반적인 기준으로 공복 혈당 {prediabetesFrom} {unit} 미만이 정상, {prediabetesFrom}~{prediabetesTo}는 당뇨 전 단계, {diabetesFrom} 이상은 당뇨 범위예요(ADA 2024). 한 번 높게 나왔다고 진단되지는 않아요 — 임상의가 재검으로 확인하고, 당뇨를 관리하는 사람은 임상의가 정한 다른 목표를 써요.", + "bloodGlucoseBody": "혈당은 몸의 주된 에너지원인 혈액 속 당의 양이에요. 식후에 올라가고 식사 사이에 가라앉아요. 당뇨가 없는 성인의 일반적인 기준으로 공복 혈당 {prediabetesFrom} {unit} 미만이 정상, {prediabetesFrom}~{prediabetesTo}는 당뇨 전 단계, {diabetesFrom} 이상은 당뇨 범위예요(ADA 2024). 한 번 높게 나왔다고 진단되지는 않아요. 임상의가 재검으로 확인하고, 당뇨를 관리하는 사람은 임상의가 정한 다른 목표를 써요.", "skinTemperatureBody": "여기서 피부 온도는 절대적인 발열 수치가 아니라 본인 기준값 대비 밤사이 손목 온도의 작은 변화예요. 이 변화는 수면·환경·질병·생리 주기 단계를 반영할 수 있어요.", "cardioFitnessBody": "VO₂ max는 최대 노력에서 몸이 쓸 수 있는 산소량으로, 유산소 체력의 가장 좋은 실험실 지표이고 웨어러블은 이를 간접 추정해요. 값이 높거나 올라가는 추이는 심혈관 건강의 강력한 신호예요.", "cardioRecoveryBody": "심박 회복은 격한 운동을 멈춘 뒤 1분 동안 심박수가 분당 몇 회 떨어지는지예요. 많이 떨어질수록 심장이 더 빨리 안정된다는 뜻이고, 체력이 좋다는 신호예요.", "wristTemperatureBody": "손목 온도는 자는 동안 측정하고 절대값이 아니라 본인 기준값과의 차이로 보여줘요. 값이 일정하면 정상이고, 지속적으로 올라가면 질병·고강도 훈련·생리 주기 변화를 암시할 수 있어요.", "fallsBody": "웨어러블이 감지한 심한 낙상 횟수를 세요. 0이 목표이고, 횟수가 늘어나면 활동성 위험 신호이니 특히 고령자라면 임상의와 이야기해 볼 만해요(CDC STEADI 2024).", - "sixMinuteWalkBody": "6분 동안 걸을 수 있는 거리의 추정치예요 — 활동성과 심폐 지구력을 보는 오래된 임상 검사죠. 웨어러블 수치는 감독하에 진행하는 임상 검사가 아니라 대리 지표이니, 유지되거나 올라가는 추이를 보는 게 쓸모 있어요.", + "sixMinuteWalkBody": "6분 동안 걸을 수 있는 거리의 추정치예요. 활동성과 심폐 지구력을 보는 오래된 임상 검사죠. 웨어러블 수치는 감독하에 진행하는 임상 검사가 아니라 대리 지표이니, 유지되거나 올라가는 추이를 보는 게 쓸모 있어요.", "stairAscentSpeedBody": "계단 한 층을 얼마나 빨리 올라가는지예요. 다리 근력과 활동성을 민감하게 보여주는 지표라, 속도가 유지되거나 빨라지면 좋은 신호이고 느려지면 지켜볼 만해요.", - "stairDescentSpeedBody": "계단 한 층을 얼마나 빨리 내려가는지예요. 오르는 속도와 함께 보면 다리 조절력과 균형을 알 수 있어요 — 속도가 일정하면 좋은 신호이고 느려지면 지켜볼 만해요.", + "stairDescentSpeedBody": "계단 한 층을 얼마나 빨리 내려가는지예요. 오르는 속도와 함께 보면 다리 조절력과 균형을 알 수 있어요. 속도가 일정하면 좋은 신호이고 느려지면 지켜볼 만해요.", "breathingDisturbancesBody": "웨어러블은 자는 동안 호흡이 얼마나 자주 끊겼는지 추정할 수 있어요. 지수가 낮을수록 좋고, 여러 밤에 걸쳐 높게 표시되면 임상의와 이야기해 볼 만해요. 수면무호흡 진단이 아니라 선별용 대리 지표예요.", "stepsBody": "걸음 수는 하루에 걷는 총 걸음으로, 일상 활동량을 보는 가장 단순한 지표예요. 하루 크게 걷는 것보다 꾸준한 습관이 더 중요하고, 딱 떨어지는 1만 걸음 목표는 연구가 아니라 마케팅 문구예요.", - "readinessBody": "준비도는 안정 시 심박수·심박변이도·수면을 묶어 하루를 감당할 몸 상태가 얼마나 준비됐는지 하나로 보여줘요. 임상 지표가 아니라 본인 기준값에 맞춘 기기 대리 지표예요 — 점수가 높으면 회복됐다는 뜻이고, 낮으면 조금 쉬어 가라는 부드러운 신호예요.", - "sleepScoreBody": "수면 점수는 하룻밤 전체를 하나의 숫자로 압축해요 — 시간·효율·규칙성, 그리고 얕은 수면·깊은 수면·REM의 균형이에요. 하룻밤의 완벽한 점수를 쫓기보다 몇 주에 걸친 패턴을 보세요.", + "readinessBody": "준비도는 안정 시 심박수·심박변이도·수면을 묶어 하루를 감당할 몸 상태가 얼마나 준비됐는지 하나로 보여줘요. 임상 지표가 아니라 본인 기준값에 맞춘 기기 대리 지표예요. 점수가 높으면 회복됐다는 뜻이고, 낮으면 조금 쉬어 가라는 부드러운 신호예요.", + "sleepScoreBody": "수면 점수는 하룻밤 전체를 하나의 숫자로 압축해요: 시간·효율·규칙성, 그리고 얕은 수면·깊은 수면·REM의 균형이에요. 하룻밤의 완벽한 점수를 쫓기보다 몇 주에 걸친 패턴을 보세요.", "recoveryBody": "회복도는 심박변이도와 안정 시 심박수 같은 밤사이 신호를 바탕으로 몸이 얼마나 잘 회복했는지 보여줘요. 임상 지표가 아니라 본인 기준값에 견줘 읽는 기기 유래 대리 지표이고, 기기끼리 비교할 수 없어요. 점수가 높으면 밀어붙여도 좋다는 신호이고, 낮으면 몸이 아직 회복 중이라는 뜻이에요.", "strainBody": "부하는 운동부터 종일 서서 활동한 하루까지, 몸에 실린 심혈관·신체 부담이 얼마나 되는지 담아요. 임상 지표가 아니라 본인의 평소 노력에 견줘 판단하는 기기 유래 지수이고, 대표 숫자는 기기끼리 비교할 수 없어요.", "stressBody": "여기서 스트레스는 코르티솔 측정이나 스스로 느끼는 감정이 아니라 심박변이도 패턴에서 끌어낸 기기 추정값이고, 임상 스트레스 점수도 아니에요. 본인 기준값에 견줘 읽으세요. 기기끼리 비교할 수 없어요. 점수가 낮으면 차분하고 잘 조절된 상태이고, 높으면 회복 시간을 넣으라는 신호예요.", "recoveryPageBody": "회복도는 웨어러블이 기록한 밤사이 신호(재충전, 부하, 누적 부담, 그날의 심박·에너지 합계)를 모아 몸이 얼마나 잘 회복했는지 보여줘요. 하나의 숫자보다 며칠에 걸친 패턴을 보세요. 낮은 값은 경보가 아니라 조금 쉬어 가라는 신호예요.", "pulsePressureBody": "맥압은 수축기와 이완기 측정값의 차이예요(수축기 빼기 이완기). 일반적인 기준으로 안정 시 40mmHg 정도가 보통이고, 중년에서 약 60mmHg가 넘게 벌어지면 동맥이 뻣뻣해지고 있음을 반영할 수 있어요. 반대로 약 25mmHg 아래로 좁으면 심박출량이 적은 상태와 함께 나타날 수 있어요(StatPearls/NIH 2023). 진단이 아니라 이야기를 시작해 볼 거리예요.", "meanArterialPressureBody": "평균 동맥압은 심장 박동 한 주기 동안 장기가 받는 평균 압력으로, 대략 이완기에 수축기까지 차이의 3분의 1을 더한 값이에요. 일반적인 기준으로 안정 시 값은 70~100mmHg 정도예요(StatPearls/NIH 2023). 흔히 인용되는 60mmHg 하한선은 급성기 진료 개념이지 소비자용 자가 경보가 아니에요.", - "cycleEducationBody": "생리 주기는 호르몬 변화가 이끄는 네 단계로 흘러가고, 주기 길이와 규칙성은 전반적인 건강을 들여다보는 손쉬운 창이에요. 일반적인 기준으로 성인의 주기는 보통 21~35일(임상 자료는 24~38일)이고 출혈은 5일 안팎이에요(ACOG 2015). 황체기가 일정한 기준점이라 배란은 다음 예정 생리에서 거꾸로 세어 추정하는 게 가장 좋아요 — 고정된 '14일째'는 절대 아니에요. 예측된 가임기는 여러 주기가 기록돼야 나오는 추정치이고 여전히 대략적이에요. 기초 체온은 배란을 예측하는 게 아니라 지나간 뒤에 확인해 줘요. 이건 피임 방법이 아니에요.", + "cycleEducationBody": "생리 주기는 호르몬 변화가 이끄는 네 단계로 흘러가고, 주기 길이와 규칙성은 전반적인 건강을 들여다보는 손쉬운 창이에요. 일반적인 기준으로 성인의 주기는 보통 21~35일(임상 자료는 24~38일)이고 출혈은 5일 안팎이에요(ACOG 2015). 황체기가 일정한 기준점이라 배란은 다음 예정 생리에서 거꾸로 세어 추정하는 게 가장 좋아요. 고정된 '14일째'는 절대 아니에요. 예측된 가임기는 여러 주기가 기록돼야 나오는 추정치이고 여전히 대략적이에요. 기초 체온은 배란을 예측하는 게 아니라 지나간 뒤에 확인해 줘요. 이건 피임 방법이 아니에요.", "sleepHygieneBody": "수면에 도움이 되는 근거 기반 습관 몇 가지예요. 주말을 포함해 잠자리에 드는 시각과 일어나는 시각을 일정하게 유지하고, 아침에는 밝은 햇빛을 쬐고 저녁에는 조명을 낮추고, 방은 시원하고 어둡고 조용하게 하고, 오후 카페인·늦은 술·늦은 과식을 피하세요(CDC 2024). 규칙성은 수면 시간만큼이나 건강을 잘 예측하고, 웨어러블의 총 수면 시간은 깊은 수면·얕은 수면·REM 구분보다 훨씬 믿을 만해요." }, "bpDerived": { - "pulsePressure": "맥압(측정값 사이의 차이)은 약 {value}mmHg예요 — 안정 시에는 40 정도가 보통이에요.", + "pulsePressure": "맥압(측정값 사이의 차이)은 약 {value}mmHg예요. 안정 시에는 40 정도가 보통이에요.", "meanArterialPressure": "평균 동맥압(장기가 받는 평균)은 약 {value}mmHg로, 보통 70~100 정도예요.", "caveat": "이 값들은 가장 최근 측정값에서 계산한 일반적인 참고 정보이고, 진단이 아니에요." }, @@ -3458,7 +3458,7 @@ "mean": "평균" }, "showAllValues": "모든 측정값 보기", - "valuesPageTitle": "{metric} — 전체 측정값", + "valuesPageTitle": "{metric}: 전체 측정값", "valuesPageDescription": "이 지표를 이루는 모든 측정값이에요. 기록을 바로 편집하거나 삭제할 수 있어요.", "diversity": { "trigger": "측정 팁", @@ -3498,7 +3498,7 @@ "inBed": "침대에 있음", "nap": "낮잠", "napCount": "낮잠 {count}회", - "unavailable": "아직 단계 데이터가 없어요 — 연결된 소스가 보내주는 대로 수면 단계가 여기에 나타나요." + "unavailable": "아직 단계 데이터가 없어요. 연결된 소스가 보내주는 대로 수면 단계가 여기에 나타나요." }, "empty": { "title": "아직 수면 데이터가 없어요", @@ -3511,21 +3511,21 @@ "caption": "최근 {nights}일 밤 동안 부족한 수면", "clearValue": "모두 채웠어요", "clearCaption": "최근 {nights}일 밤 동안 부족한 수면이 없어요", - "learning": "아직 수면을 익히는 중이에요 — 지금까지 {counted}일 밤, 믿을 만한 부족분을 읽으려면 {remaining}일 밤이 더 필요해요.", + "learning": "아직 수면을 익히는 중이에요. 지금까지 {counted}일 밤, 믿을 만한 부족분을 읽으려면 {remaining}일 밤이 더 필요해요.", "computedInfo": "이건 HealthLog가 자체적으로 낸 추정치예요. 최근 밤들의 필요 수면에서 실제 수면을 뺀 누적 잔액이고, 보충 수면이 이를 갚아 나가요. 자체 필요 수면 모델을 쓰는 웨어러블의 수면 부채 수치와는 다를 수 있어요." }, "average": { "title": "밤 평균", "value": "{hours}시간 {minutes}분", "caption": "최근 {nights}일 밤의 평균 수면", - "learning": "아직 수면을 익히는 중이에요 — 지금까지 {counted}일 밤, 믿을 만한 평균을 내려면 {remaining}일 밤이 더 필요해요." + "learning": "아직 수면을 익히는 중이에요. 지금까지 {counted}일 밤, 믿을 만한 평균을 내려면 {remaining}일 밤이 더 필요해요." }, "chronotype": { "title": "크로노타입", - "learning": "아직 리듬을 익히는 중이에요 — 자유로운 밤 {total}일 중 {counted}일이에요. 크로노타입은 알람 없이 맞은 아침이 몇 번은 쌓여야 의미가 생겨요.", + "learning": "아직 리듬을 익히는 중이에요. 자유로운 밤 {total}일 중 {counted}일이에요. 크로노타입은 알람 없이 맞은 아침이 몇 번은 쌓여야 의미가 생겨요.", "advancedToggle": "고급", "socialJetlagValue": "사회적 시차 {hours}시간 {minutes}분", - "socialJetlagCaption": "일하는 날과 쉬는 날의 수면 시각 차이예요 — 매주 작은 시차를 겪는 셈이죠.", + "socialJetlagCaption": "일하는 날과 쉬는 날의 수면 시각 차이예요. 매주 작은 시차를 겪는 셈이죠.", "msfScValue": "보정 수면 중간 시각 {clock}", "msfScCaption": "주말에 보충한 수면을 반영해 보정한 값이에요(MSFsc).", "dayTypeNote": "날짜 유형 기록이 추가되기 전까지는 쉬는 날을 주말로 가정해요.", @@ -3732,10 +3732,10 @@ "clinical": { "title": "혈당 개요", "subtitle": "최근 {days}일, 측정값 {count}개를 바탕으로 읽은 결과예요.", - "spotCaveat": "연속 혈당 측정 프로필이 아니라 개별 측정에서 낸 단발 추정치예요 — 임상적 판정이 아니라 흐름의 방향으로 읽어 주세요.", + "spotCaveat": "연속 혈당 측정 프로필이 아니라 개별 측정에서 낸 단발 추정치예요. 임상적 판정이 아니라 흐름의 방향으로 읽어 주세요.", "labsLink": "검사 결과가 있나요? 채혈 HbA1c나 공복 혈당은 검사에 기록해 주세요.", "learningTitle": "아직 혈당을 익히는 중이에요", - "learningBody": "지금까지 {days} 동안 {count} — 기록이 조금만 더 쌓이면 더 온전한 그림이 잡혀요. 계속 기록하거나 연결된 기기가 채우게 두세요.", + "learningBody": "지금까지 {days} 동안 {count}. 기록이 조금만 더 쌓이면 더 온전한 그림이 잡혀요. 계속 기록하거나 연결된 기기가 채우게 두세요.", "learningBodyEmpty": "직접 기록하든 기기에서 동기화되든 측정값이 몇 개 들어오면, 목표 범위 내 시간·평균·변동성이 여기에 자리를 잡아요.", "readingsCount": "측정값 {count}개", "readingsCountOne": "측정값 1개", @@ -3774,7 +3774,7 @@ "intro": "더 깊이 들여다보는 연구 수준의 복합 지표예요. 각각 측정값을 위험 가중치를 매긴 하나의 숫자로 압축해요.", "jIndex": { "label": "J 지수", - "help": "평균과 그 퍼짐 정도를 합친 하나의 점수예요 — 낮을수록 더 촘촘한 관리로 읽혀요." + "help": "평균과 그 퍼짐 정도를 합친 하나의 점수예요. 낮을수록 더 촘촘한 관리로 읽혀요." }, "lbgi": { "label": "저혈당 위험(LBGI)", @@ -3891,7 +3891,7 @@ "navSkinTemperature": "피부 온도", "pulseWaveVelocity": { "title": "맥파 전파 속도", - "description": "시간에 따른 동맥 맥파 전파 속도예요(m/s) — 값이 높을수록 동맥이 뻣뻣하다는 뜻이에요.", + "description": "시간에 따른 동맥 맥파 전파 속도예요(m/s), 값이 높을수록 동맥이 뻣뻣하다는 뜻이에요.", "chartTitle": "맥파 전파 속도", "emptyState": { "title": "아직 맥파 전파 속도 데이터가 없어요", @@ -4084,7 +4084,7 @@ "inTargetCaption": "최근 날들 중 기분 좋음 범위에 든 비율", "narrative": { "title": "눈에 띄는 점", - "weekdayDip": "{weekday}에 기분이 가장 많이 떨어져요 — 한 주 평균보다 {delta} 낮아요.", + "weekdayDip": "{weekday}에 기분이 가장 많이 떨어져요. 한 주 평균보다 {delta} 낮아요.", "weekdayPeak": "꾸준히 가장 좋은 요일은 {weekday}, 평균 {value}.", "trendUp": "최근 {days}일 동안 기분이 올라가는 추세예요(이전 기간 대비 +{delta}).", "trendDown": "최근 {days}일 동안 기분이 내려가는 추세예요(이전 기간 대비 -{delta}).", @@ -4093,8 +4093,8 @@ "tagLift": "'{tag}' 태그가 붙은 날은 전체 평균보다 {delta} 높아요.", "tagDrop": "'{tag}' 태그가 붙은 날은 평균보다 {delta} 낮아요.", "inTarget": "최근 30일 중 {pct}%는 기분 좋음 범위에 있었어요.", - "streak": "{days}일 연속으로 기분을 기록했어요 — 계속 이어가 보세요.", - "timeOfDay": "기분이 가장 좋은 시간대는 {bucket} — 평균 {value}." + "streak": "{days}일 연속으로 기분을 기록했어요. 계속 이어가 보세요.", + "timeOfDay": "기분이 가장 좋은 시간대는 {bucket}, 평균 {value}." }, "timeOfDay": { "title": "시간대별 기분", @@ -4164,7 +4164,7 @@ "title": "눈에 띄는 점", "subheading": "발견된 관계", "footer": "모든 지표에서 검정한 일자별 조합 {tested}개 중 허위 발견 보정을 거쳐 추려낸 결과예요.", - "disclaimer": "통계로 걸러냈지만 여전히 관찰 결과예요 — 원인이 아니라 지켜볼 만한 패턴이에요.", + "disclaimer": "통계로 걸러냈지만 여전히 관찰 결과예요. 원인이 아니라 지켜볼 만한 패턴이에요.", "moodUp": "{factor} 값이 높으면 다음 날 기분도 높은 편이에요.", "moodDown": "{factor} 값이 높으면 다음 날 기분은 낮은 편이에요.", "outcomeUp": "기분이 좋으면 다음 날 {factor} 값도 높은 편이에요.", @@ -4203,8 +4203,8 @@ "deviationAbove": "내 평가는 그 범위보다 {amount}점 높아요.", "deviationBelow": "내 평가는 그 범위보다 {amount}점 낮아요.", "weightedTitle": "이날 비교에서 가장 크게 작용한 것", - "weightedUp": "{label} — 예상값을 높이는 쪽으로 작용했어요", - "weightedDown": "{label} — 예상값을 낮추는 쪽으로 작용했어요", + "weightedUp": "{label}: 예상값을 높이는 쪽으로 작용했어요", + "weightedDown": "{label}: 예상값을 낮추는 쪽으로 작용했어요", "caveat": "이건 내 지난 날들과의 비교일 뿐, 그날이 왜 그렇게 흘러갔는지에 대한 설명은 아니에요.", "learning": "학습 중이에요: {threshold}일 중 {entries}일 기록했어요. 충분히 모이면 비교가 나타나요.", "noPattern": "지금까지 기록한 {entries}일 중에는 하루를 견줄 만큼 일정한 패턴이 없어요. 하루의 맥락까지 함께 남기면 비교할 수 있는 게 늘어나요.", @@ -4221,7 +4221,7 @@ }, "scoreRing": { "aria": "점수 100점 만점에 {score}점, {band}", - "ariaProvisional": "아직 점수를 낼 수 없어요 — 데이터가 부족해요", + "ariaProvisional": "아직 점수를 낼 수 없어요. 데이터가 부족해요", "provisionalCaption": "아직 데이터가 부족해요", "band": { "green": "좋음", @@ -4245,7 +4245,7 @@ "loadingLabel": "생체 지표 불러오는 중", "loadError": "지금은 생체 지표를 불러오지 못했어요.", "infoLabel": "어떻게 계산하나요?", - "building": "내 일반 범위를 만드는 중 — {target}일 중 {count}일", + "building": "내 일반 범위를 만드는 중: {target}일 중 {count}일", "typicalRange": "내 일반 범위: {low}–{high}", "fitnessYounger": "약 {years}세 젊은 사람 수준의 심폐 체력", "fitnessOlder": "실제 나이보다 약 {years}세 높은 심폐 체력", @@ -4307,7 +4307,7 @@ } }, "VITALS_BASELINE": { - "method": "개인 일반 범위는 해당 기간 일별 값의 중앙값에 견고한 산포(중앙절대편차를 보정한 값)를 더하고 뺀 구간이에요. 인구 평균이 아니라 내 측정값을 따라가요 — 그래서 이 범위 안이면 나에게는 평소 수준이에요." + "method": "개인 일반 범위는 해당 기간 일별 값의 중앙값에 견고한 산포(중앙절대편차를 보정한 값)를 더하고 뺀 구간이에요. 인구 평균이 아니라 내 측정값을 따라가요. 그래서 이 범위 안이면 나에게는 평소 수준이에요." }, "HRV_BALANCE": { "method": "최근 심박변이도(SDNN) 평균을 내 이동 기준값(중앙값 ± 견고한 산포)과 비교해요. 균형은 개인 범위 안에 있다는 뜻이고, 이 범위는 인구 기준선이 아니라 내 데이터로 만들어요." @@ -4320,12 +4320,12 @@ }, "VASCULAR_AGE_DELTA": { "method": "기기가 추정한 혈관 나이 / 맥파 속도를 실제 나이와 비교해 연 단위 차이로 보여줘요. 추정은 기기가 하고, HealthLog는 다시 보여줄 뿐이에요.", - "caveat": "기기가 추정한 값을 다시 보여주는 것뿐이에요 — 설명용이고 임상 혈관 평가가 아니에요.", + "caveat": "기기가 추정한 값을 다시 보여주는 것뿐이에요. 설명용이고 임상 혈관 평가가 아니에요.", "description": "기기가 추정한 혈관 나이가 실제 나이와 어떻게 비교되는지 보여줘요." }, "COINCIDENT_DEVIATION": { "method": "같은 날 생체 지표 두 개 이상이 개인 일반 범위를 벗어나면 표시해요. 각 범위는 내 기록의 중앙값 ± k·MAD로 만들어서 인구 기준선이 아니라 나에게 맞춰져요.", - "caveat": "내 기준값에서 나온 알아차림 신호예요 — 설명용이고 진단이나 임상 경고가 아니에요." + "caveat": "내 기준값에서 나온 알아차림 신호예요. 설명용이고 진단이나 임상 경고가 아니에요." }, "RECOVERY_SCORE": { "method": "심박변이도, 안정 시 심박수, 수면을 내 기준값과 비교해 섞은 밤마다의 0–100 회복 지표예요. 높을수록 더 잘 회복된 거예요. 매일 밤 한 번 계산해 두고 여기서 그대로 읽어와요.", @@ -4337,7 +4337,7 @@ }, "STRAIN_SCORE": { "method": "심박수로 가중한 활동 부하(TRIMP 방식 훈련 자극 모델)로 매일 밤 내는 0–100 부하 지표예요. 높을수록 힘든 하루였다는 뜻이에요.", - "anchorPersonal": "최근 운동한 날의 부하를 기준으로 삼아요 — 평소 강도와 비교해 점수를 매기니 나에게 정말 힘든 날이 높게 나와요.", + "anchorPersonal": "최근 운동한 날의 부하를 기준으로 삼아요. 평소 강도와 비교해 점수를 매기니 나에게 정말 힘든 날이 높게 나와요.", "anchorPopulation": "운동 기록이 쌓이는 동안에는 일반 기준으로 점수를 매기고, 충분히 모이면 내 평소 강도 기준으로 바뀌어요.", "description": "심박수로 가중한 운동 강도를 평소 강도와 비교해 매일 밤 계산하는 활동 부하 지표예요.", "deviceCaption": "기기의 일일 부하: {max} 중 {value}", @@ -4345,23 +4345,23 @@ }, "WRIST_TEMPERATURE_BASELINE": { "method": "밤사이 손목 온도의 일반 범위는 해당 기간 야간 측정값의 중앙값에 견고한 산포(중앙절대편차를 보정한 값)를 더하고 뺀 구간이에요. 내 측정값을 따라가기 때문에, 지난밤은 인구 평균이 아니라 내 기준값에서 얼마나 벗어났는지로 보여줘요.", - "caveat": "개인 편차 범위일 뿐이에요 — 설명용이고 질병, 발열, 생리 주기 신호가 아니에요. 해석은 직접 해 주세요." + "caveat": "개인 편차 범위일 뿐이에요. 설명용이고 질병, 발열, 생리 주기 신호가 아니에요. 해석은 직접 해 주세요." }, "STAIR_ASCENT_SPEED_BASELINE": { "method": "계단 오르는 속도의 일반 범위는 해당 기간 일별 값의 중앙값에 견고한 산포(중앙절대편차를 보정한 값)를 더하고 뺀 구간이에요. 계단 모양과 다리 길이에 따라 속도가 달라져 인구 기준선이 없기 때문에, 범위는 내 데이터로만 만들어요.", - "caveat": "개인 이동성 추이 범위예요 — 설명용이고 노쇠나 낙상 위험 평가가 아니에요." + "caveat": "개인 이동성 추이 범위예요. 설명용이고 노쇠나 낙상 위험 평가가 아니에요." }, "STAIR_DESCENT_SPEED_BASELINE": { "method": "계단 내려가는 속도의 일반 범위는 해당 기간 일별 값의 중앙값에 견고한 산포(중앙절대편차를 보정한 값)를 더하고 뺀 구간이에요. 계단 모양과 다리 길이에 따라 속도가 달라져 인구 기준선이 없기 때문에, 범위는 내 데이터로만 만들어요.", - "caveat": "개인 이동성 추이 범위예요 — 설명용이고 노쇠나 낙상 위험 평가가 아니에요." + "caveat": "개인 이동성 추이 범위예요. 설명용이고 노쇠나 낙상 위험 평가가 아니에요." }, "SIX_MINUTE_WALK_BAND": { "method": "기기가 추정한 6분 보행 거리를 나이, 키, 체중, 성별에 맞춘 Enright & Sherrill 기준과 비교해 예측치 대비 백분율로 보여줘요. 거리는 기기의 추정값이고 여기서 다시 계산하지 않아요. 나이, 키, 체중, 성별이 없으면 백분율은 숨기고 거리와 추이만 보여줘요.", - "caveat": "발표된 기준과 비교해 다시 보여준 추정값이에요 — 신체 기능을 알아차리기 위한 신호이고 임상 6분 보행 검사나 진단이 아니에요. 이 기준은 40–80세를 대상으로 만들어졌고, 그 범위를 벗어나면 예측치는 외삽한 값이에요." + "caveat": "발표된 기준과 비교해 다시 보여준 추정값이에요. 신체 기능을 알아차리기 위한 신호이고 임상 6분 보행 검사나 진단이 아니에요. 이 기준은 40–80세를 대상으로 만들어졌고, 그 범위를 벗어나면 예측치는 외삽한 값이에요." }, "TRAJECTORY": { "method": "최근 일별 값에 최소제곱 직선을 맞춰 짧은 기간 앞으로 이어 그리고, 멀어질수록 넓어지는 표준 예측 구간을 함께 보여줘요. 최근 추이가 충분히 뚜렷하고 기록이 길고 최신일 때만 계산하고, 그렇지 않으면 선을 그리지 않아요.", - "caveat": "최근 추이를 그대로 이어 그린 것이에요 — 예측이나 목표, 임상 전망이 아니에요. 최근 패턴이 이어질 때만 맞고, 음영 구간은 그 확신이 얼마나 빨리 흐려지는지 보여줘요." + "caveat": "최근 추이를 그대로 이어 그린 것이에요. 예측이나 목표, 임상 전망이 아니에요. 최근 패턴이 이어질 때만 맞고, 음영 구간은 그 확신이 얼마나 빨리 흐려지는지 보여줘요." }, "SAME_TIME_BASELINE": { "method": "오늘 누적값을 최근 4주 동안 같은 시각의 중앙값과 비교하고, 그 주위에 중앙값 ± MAD 범위를 함께 보여줘요. 기록이 충분한 날만 계산에 넣고, 그런 날이 14일 이상 모이기 전에는 비교를 보여주지 않아요.", @@ -4390,29 +4390,29 @@ "watch": "오늘 지표 하나가 평소 범위를 벗어났어요.", "watchVital": "범위 밖: {vital}. 대개는 한 번뿐이지만 며칠 지켜볼 만해요.", "firedHeadline": "오늘 생체 지표 {count}개가 개인 범위를 벗어났어요.", - "factors": "가능한 요인 — 원인은 아니에요: 힘든 운동, 부족한 수면, 음주, 고도, 스트레스, 아픈 날. 내 기준값에서 나온 알아차림 신호이고 진단이 아니에요.", - "building": "개인 기준값을 만드는 중이에요 — 며칠 더 기록하면 여기에 표시돼요.", + "factors": "가능한 요인(원인은 아니에요): 힘든 운동, 부족한 수면, 음주, 고도, 스트레스, 아픈 날. 내 기준값에서 나온 알아차림 신호이고 진단이 아니에요.", + "building": "개인 기준값을 만드는 중이에요. 며칠 더 기록하면 여기에 표시돼요.", "illnessExplained": "이 변화는 기록해 둔 상태 때문일 가능성이 커요." }, "trajectory": { "cardTitle": "단기 전망", - "headline": "이 패턴이 이어진다면 — 앞으로 {days}일", + "headline": "이 패턴이 이어진다면: 앞으로 {days}일", "range": "{days}일 뒤 예상 범위: 약 {low}–{high} {unit}.", "caveat": "최근 추이를 그대로 이어 그린 것이고 예측이 아니에요. 음영 구간은 불확실성이 얼마나 빨리 커지는지 보여줘요.", - "insufficient": "아직 전망을 그릴 만큼 추이가 뚜렷하지 않아요 — 계속 기록해서 최근 패턴이 뚜렷해지면 전망이 표시돼요.", + "insufficient": "아직 전망을 그릴 만큼 추이가 뚜렷하지 않아요. 계속 기록해서 최근 패턴이 뚜렷해지면 전망이 표시돼요.", "daysNeeded": "전망이 나오려면 {count}일쯤 더 기록해야 해요." }, "sameTime": { "sectionTitle": "오늘 지금까지", "sectionSubtitle": "이 시각의 평소 수준과 비교한 오늘 누적값", - "learning": "평소 하루를 익히는 중 — {target}일 중 {count}일", + "learning": "평소 하루를 익히는 중: {target}일 중 {count}일", "framing": "{time}까지 평소: {typical} {unit}", "comparisonLabel": "평소 하루" } }, "cardioFitness": { "title": "심폐 체력", - "description": "시간에 따른 VO₂ max — 유산소 체력을 대표하는 지표예요.", + "description": "시간에 따른 VO₂ max로, 유산소 체력을 대표하는 지표예요.", "chartTitle": "VO₂ max (mL/(kg·min))", "emptyState": { "title": "아직 심폐 체력 데이터가 없어요", @@ -4537,13 +4537,13 @@ "detail": "숨긴 상세 페이지는 상단 탐색에서도 사라져요." }, "customize": "인사이트 맞춤 설정", - "regenerateRateLimited": "새로고침 한도에 도달했어요 — 잠시 후 다시 시도해 주세요.", - "regenerateUnavailable": "새 분석이 도착하지 않았어요 — 잠시 후 다시 시도해 주세요.", - "regenerateError": "아직 새로고침 중이에요 — 잠시 후 다시 시도해 주세요.", + "regenerateRateLimited": "새로고침 한도에 도달했어요. 잠시 후 다시 시도해 주세요.", + "regenerateUnavailable": "새 분석이 도착하지 않았어요. 잠시 후 다시 시도해 주세요.", + "regenerateError": "아직 새로고침 중이에요. 잠시 후 다시 시도해 주세요.", "regenerateSettling": "평가를 아직 준비하고 있어요", "regenerateSettleFailed": "새로고침을 마치지 못했어요. 잠시 후 다시 시도해 주세요.", "deviceScore": { - "learning": "아직 기준값을 익히는 중이에요 — 며칠 밤 더 지나면 추이가 채워져요.", + "learning": "아직 기준값을 익히는 중이에요. 며칠 밤 더 지나면 추이가 채워져요.", "average": "30일 평균 {value}", "unitScore": "점", "unitMinutes": "min", @@ -4556,14 +4556,14 @@ }, "recovery": { "title": "회복", - "description": "몸이 얼마나 회복했는지 — 웨어러블이 밤사이 기록한 회복·부하 신호예요.", + "description": "몸이 얼마나 회복했는지: 웨어러블이 밤사이 기록한 회복·부하 신호예요.", "scoreCrossLink": "종합 회복 점수 보기", "emptyTitle": "아직 회복 데이터가 없어요", "empty": "아직 회복 데이터가 없어요. WHOOP, Polar, Oura 계정을 연결하면 기기가 동기화될 때 점수가 채워져요.", "block": { - "ansChargeExplainer": "오늘 하루를 맞을 자율신경계의 충전 상태예요 — 밤사이 심장·호흡 신호에서 읽어낸 재충전 지표예요.", + "ansChargeExplainer": "오늘 하루를 맞을 자율신경계의 충전 상태예요. 밤사이 심장·호흡 신호에서 읽어낸 재충전 지표예요.", "dayStrainExplainer": "기기의 부하 척도로 본 하루 전체의 심혈관 부하예요. 그 자체를 목표로 삼지 말고 회복과 견줘 보세요.", - "workoutStrainExplainer": "같은 부하 척도에서 운동 하나가 얼마나 힘들었는지 — 그 세션의 심혈관 비용이에요.", + "workoutStrainExplainer": "같은 부하 척도에서 운동 하나가 얼마나 힘들었는지: 그 세션의 심혈관 비용이에요.", "cardioLoadExplainer": "쌓인 급성 심혈관 부하를 따라가는 훈련 부하 지표예요. 내 최근 며칠과 비교해 보세요.", "averageHeartRateExplainer": "웨어러블이 보고한 하루 또는 주기 전체의 평균 심박수예요.", "maxHeartRateExplainer": "웨어러블이 보고한 하루 또는 주기 전체의 최고 심박수예요.", @@ -4576,7 +4576,7 @@ }, "resilience": { "explainer": "최근 며칠간의 밤사이 신호로 읽은, 몸이 하루의 부하와 회복을 얼마나 잘 맞추고 있는지예요.", - "learning": "아직 회복탄력성을 익히는 중이에요 — 며칠 더 지나면 범위가 자리 잡아요.", + "learning": "아직 회복탄력성을 익히는 중이에요. 며칠 더 지나면 범위가 자리 잡아요.", "band": { "limited": "제한적", "adequate": "충분", @@ -4602,10 +4602,10 @@ "healthStatus": { "sectionTitle": "달라진 점", "subtitle": "평소 범위에서 벗어나고 있는 신호예요.", - "deviationAbove": "{vital} — 일반 범위보다 높아요.", - "deviationBelow": "{vital} — 일반 범위보다 낮아요.", - "shiftUp": "{vital} — 최근 평소 수준보다 올라갔어요.", - "shiftDown": "{vital} — 최근 평소 수준보다 내려갔어요.", + "deviationAbove": "{vital}: 일반 범위보다 높아요.", + "deviationBelow": "{vital}: 일반 범위보다 낮아요.", + "shiftUp": "{vital}: 최근 평소 수준보다 올라갔어요.", + "shiftDown": "{vital}: 최근 평소 수준보다 내려갔어요.", "rangeContext": "지금 {value}, 평소 {low}–{high}.", "rangeContextTimeOfDay": "지금 {value}, 이 시간대 평소 {low}–{high}.", "shiftContext": "이전엔 약 {before}, 이후엔 {after}." @@ -4621,7 +4621,7 @@ "nights": "{count}일 밤 기록", "indexLine": "최근 평균 지수 {value}", "eventsFlagged": "기기가 표시한 이벤트 {count}건", - "disclaimer": "진단이 아니라 선별 신호예요 — 임상의와 상의해 주세요." + "disclaimer": "진단이 아니라 선별 신호예요. 임상의와 상의해 주세요." }, "labsChanges": { "sectionTitle": "지난 검사 이후", @@ -4637,14 +4637,14 @@ "navWaistToHeight": "허리-키 비율", "gripStrength": { "title": "악력", - "description": "최대 악력 — 전신 근력을 잘 대변하는 지표예요. 성별 기준선(남성 27kg, 여성 16kg) 아래면 근감소증 가능성을 뜻해요. 해석은 내 추이가 우선이에요.", + "description": "최대 악력으로, 전신 근력을 잘 대변하는 지표예요. 성별 기준선(남성 27kg, 여성 16kg) 아래면 근감소증 가능성을 뜻해요. 해석은 내 추이가 우선이에요.", "chartTitle": "악력", "emptyState": { "title": "아직 악력 기록이 없어요", "description": "악력계로 잰 값을 기록해 보세요. 몇 번 쥐어 본 값 중 가장 좋은 값을 남기면 추이가 여기에 표시돼요.", "cta": "악력 기록" }, - "coachPrefill": "아직 악력을 기록한 적이 없어요 — 악력은 내 근육 건강에 대해 무엇을 알려주고, 어떻게 재고 어떻게 키우나요?" + "coachPrefill": "아직 악력을 기록한 적이 없어요. 악력은 내 근육 건강에 대해 무엇을 알려주고, 어떻게 재고 어떻게 키우나요?" }, "pain": { "title": "통증 (0–10)", @@ -4655,36 +4655,36 @@ "description": "지금 느끼는 통증을 0–10 척도로 기록하면 추이가 여기에 표시돼요.", "cta": "통증 점수 기록" }, - "coachPrefill": "아직 통증 점수를 기록한 적이 없어요 — 0–10 척도로 통증을 어떻게 기록해야 하고, 어느 정도가 의미 있는 변화인가요?" + "coachPrefill": "아직 통증 점수를 기록한 적이 없어요. 0–10 척도로 통증을 어떻게 기록해야 하고, 어느 정도가 의미 있는 변화인가요?" }, "waist": { "title": "허리둘레", - "description": "센티미터로 잰 허리둘레 — 복부 지방의 지표예요. WHO 위험 증가 기준선은 성별에 따라 달라요(남성 94cm, 여성 80cm). 해석은 내 추이가 우선이에요.", + "description": "센티미터로 잰 허리둘레로, 복부 지방의 지표예요. WHO 위험 증가 기준선은 성별에 따라 달라요(남성 94cm, 여성 80cm). 해석은 내 추이가 우선이에요.", "chartTitle": "허리둘레", "emptyState": { "title": "아직 허리둘레 측정값이 없어요", "description": "가장 아래 갈비뼈와 골반뼈의 중간 지점에서, 숨을 편히 내쉰 끝에 허리를 재서 기록해 주세요.", "cta": "허리둘레 기록" }, - "coachPrefill": "아직 허리둘레를 기록한 적이 없어요 — 허리둘레는 어떻게 정확히 재고, 그 숫자가 건강에 어떤 의미인가요?" + "coachPrefill": "아직 허리둘레를 기록한 적이 없어요. 허리둘레는 어떻게 정확히 재고, 그 숫자가 건강에 어떤 의미인가요?" }, "waistToHeight": { "title": "허리-키 비율", - "description": "허리둘레를 키로 나눈 값 — 인종에 관계없이 통하는 단일 지표예요. 0.5 미만(허리둘레가 키의 절반 아래)으로 유지하는 게 간단한 목표예요.", + "description": "허리둘레를 키로 나눈 값으로, 인종에 관계없이 통하는 단일 지표예요. 0.5 미만(허리둘레가 키의 절반 아래)으로 유지하는 게 간단한 목표예요.", "chartTitle": "허리-키 비율", "emptyState": { "title": "아직 허리-키 비율이 없어요", "description": "허리-키 비율을 기록하면 추이가 여기에 표시돼요. 요령은 간단해요. 허리둘레를 키의 절반 아래로 유지하세요.", "cta": "허리-키 비율 기록" }, - "coachPrefill": "아직 허리-키 비율을 기록한 적이 없어요 — 이 숫자가 왜 유용하고, 어떻게 0.5 미만으로 유지하나요?" + "coachPrefill": "아직 허리-키 비율을 기록한 적이 없어요. 이 숫자가 왜 유용하고, 어떻게 0.5 미만으로 유지하나요?" }, "ecg": { "sectionTitle": "심전도 기록", "loadError": "심전도 기록을 불러오지 못했어요.", "backToList": "기록 목록으로", "clinicianNote": "결과가 걱정된다면 이 기록을 임상의와 상의해 보세요.", - "resultAttribution": "기록된 결과: {result} — 측정 기기가 보고한 값이에요.", + "resultAttribution": "기록된 결과: {result}. 측정 기기가 보고한 값이에요.", "result": { "irregular": "심방세동 감지", "notDetected": "심방세동 징후 없음", @@ -4720,7 +4720,7 @@ "intradayPulse": { "title": "하루 동안의 맥박", "caption": "10분 단위로 평균했어요.", - "hourlyNote": "이 날짜는 시간별 평균으로 보여줘요 — 최근 며칠은 10분 단위까지 자세히 볼 수 있어요.", + "hourlyNote": "이 날짜는 시간별 평균으로 보여줘요. 최근 며칠은 10분 단위까지 자세히 볼 수 있어요.", "empty": "이 날짜는 심박수 측정값이 적어서 아직 흐름을 보여줄 수 없어요.", "coverageOne": "{hours}h 동안 모은 측정값 1개를 기준으로 했어요.", "coverageMany": "{hours}h 동안 모은 측정값 {count}개를 기준으로 했어요.", @@ -4729,10 +4729,10 @@ "previousDay": "이전 날짜", "nextDay": "다음 날짜", "tension": { - "morning": "오늘 아침에 안정 시 심박수가 높은 구간이 이어졌어요 — 긴장이 있었을 수 있어요.", - "afternoon": "오늘 오후에 안정 시 심박수가 높은 구간이 이어졌어요 — 긴장이 있었을 수 있어요.", - "evening": "오늘 저녁에 안정 시 심박수가 높은 구간이 이어졌어요 — 긴장이 있었을 수 있어요.", - "night": "밤사이 안정 시 심박수가 높은 구간이 이어졌어요 — 긴장이 있었을 수 있어요." + "morning": "오늘 아침에 안정 시 심박수가 높은 구간이 이어졌어요. 긴장이 있었을 수 있어요.", + "afternoon": "오늘 오후에 안정 시 심박수가 높은 구간이 이어졌어요. 긴장이 있었을 수 있어요.", + "evening": "오늘 저녁에 안정 시 심박수가 높은 구간이 이어졌어요. 긴장이 있었을 수 있어요.", + "night": "밤사이 안정 시 심박수가 높은 구간이 이어졌어요. 긴장이 있었을 수 있어요." } }, "navEcg": "심전도", @@ -4785,14 +4785,14 @@ "metricBodyFat": "체지방", "metricSleep": "수면 시간", "metricSteps": "하루 걸음 수", - "metricGlucoseFasting": "혈당 — 공복", - "metricGlucosePostprandial": "혈당 — 식후", - "metricGlucoseRandom": "혈당 — 임의", - "metricGlucoseBedtime": "혈당 — 취침 전", + "metricGlucoseFasting": "혈당 (공복)", + "metricGlucosePostprandial": "혈당 (식후)", + "metricGlucoseRandom": "혈당 (임의)", + "metricGlucoseBedtime": "혈당 (취침 전)", "metricBodyWater": "체수분", "metricBoneMass": "골량", "metricOxygenSaturation": "산소포화도(SpO₂)", - "unsetExplanation": "사용자 설정 없음 — 계산된 기본값을 써요.", + "unsetExplanation": "사용자 설정 없음: 계산된 기본값을 써요.", "cardTitle": "지표별 범위" }, "onboarding": { @@ -4806,7 +4806,7 @@ "steps": { "dashboardOverview": { "title": "내 대시보드", - "body": "대시보드는 모든 모듈을 한눈에 모아 보여줘요. 타일을 길게 누르면 순서를 바꾸거나 숨길 수 있어요(설정 → 대시보드 레이아웃). 타일은 그 뒤에 쌓인 데이터만큼만 말해 줘요 — 앞으로 나올 모듈들이 그 데이터를 채워요." + "body": "대시보드는 모든 모듈을 한눈에 모아 보여줘요. 타일을 길게 누르면 순서를 바꾸거나 숨길 수 있어요(설정 → 대시보드 레이아웃). 타일은 그 뒤에 쌓인 데이터만큼만 말해 줘요. 앞으로 나올 모듈들이 그 데이터를 채워요." }, "quickAdd": { "title": "몇 초면 기록 끝", @@ -4838,7 +4838,7 @@ }, "mood": { "title": "기분", - "body": "기분은 지금 느낌과 태그를 2초 만에 남겨요. 강점: 나만의 태그. 기분 추이는 수면, 약, 주기와 맞물리고 — 코치가 그 패턴을 찾아 줘요." + "body": "기분은 지금 느낌과 태그를 2초 만에 남겨요. 강점: 나만의 태그. 기분 추이는 수면, 약, 주기와 맞물리고, 코치가 그 패턴을 찾아 줘요." }, "insights": { "title": "인사이트", @@ -4850,15 +4850,15 @@ }, "integrations": { "title": "연동", - "body": "연동하면 Withings, WHOOP, Polar, Oura, Apple Health가 자동으로 동기화돼요. 체중, 수면, 회복이 직접 입력 없이 채워지고 — 그게 다시 인사이트와 코치로 이어져요." + "body": "연동하면 Withings, WHOOP, Polar, Oura, Apple Health가 자동으로 동기화돼요. 체중, 수면, 회복이 직접 입력 없이 채워지고, 그게 다시 인사이트와 코치로 이어져요." }, "export": { "title": "진료용 리포트", - "body": "진료용 리포트는 측정값, 약, 검사 수치, 건강검진을 PDF나 FHIR로 묶어 진료에 가져갈 수 있게 해 줘요. 모든 모듈이 여기서 만나요 — 잘 쌓인 데이터라야 온전한 리포트가 나와요." + "body": "진료용 리포트는 측정값, 약, 검사 수치, 건강검진을 PDF나 FHIR로 묶어 진료에 가져갈 수 있게 해 줘요. 모든 모듈이 여기서 만나요. 잘 쌓인 데이터라야 온전한 리포트가 나와요." }, "achievements": { "title": "업적", - "body": "업적은 꾸준함에 보상을 줘요 — 연속 기록과 이정표. 계속하기 쉽게 만드는 작은 동기 장치예요." + "body": "업적은 꾸준함에 보상을 줘요: 연속 기록과 이정표. 계속하기 쉽게 만드는 작은 동기 장치예요." }, "wrapUp": { "title": "둘러보기 끝", @@ -4910,13 +4910,13 @@ "anamnesis": { "title": "건강에 대해 (선택)", "subtitle": "HealthLog가 내 숫자를 더 공정하게 읽도록 약간의 맥락을 알려 주세요.", - "intro": "원하는 만큼만 알려 주세요 — 모든 항목은 선택이고, 설정에서 언제든 바꿀 수 있어요.", + "intro": "원하는 만큼만 알려 주세요. 모든 항목은 선택이고, 설정에서 언제든 바꿀 수 있어요.", "conditionsLabel": "앓고 있는 질환", "conditionsPlaceholder": "예: 고혈압, 2형 당뇨", "conditionsHint": "당연한 값을 경고로 띄우는 대신, 맥락 속에서 측정값을 보게 해 줘요.", "allergiesLabel": "알레르기나 불내성", "allergiesPlaceholder": "예: 페니실린, 유당", - "privacyNote": "암호화해 저장하고, 더 나은 맥락을 주는 데만 써요. 여기서 약은 묻지 않아요 — 복약 페이지에서 언제든 추가하면 돼요." + "privacyNote": "암호화해 저장하고, 더 나은 맥락을 주는 데만 써요. 여기서 약은 묻지 않아요. 복약 페이지에서 언제든 추가하면 돼요." }, "ai": { "panelTitle": "인사이트가 어떤 모습인지 보기", @@ -4925,18 +4925,18 @@ "sampleTitle": "데일리 브리핑", "sampleTag": "예시", "sampleAriaLabel": "데일리 브리핑 예시", - "sampleBody": "2주 동안 체중 1.2kg 감소. 안정 시 맥박은 58bpm으로 꾸준해요. 혈압은 7일 중 6일 범위 안 — 높았던 하루는 늦은 시간의 짠 저녁 식사 다음이었어요.", + "sampleBody": "2주 동안 체중 1.2kg 감소. 안정 시 맥박은 58bpm으로 꾸준해요. 혈압은 7일 중 6일 범위 안, 높았던 하루는 늦은 시간의 짠 저녁 식사 다음이었어요.", "sampleCaption": "예시일 뿐 내 데이터가 아니에요. 인사이트를 켜면 브리핑이 이런 식으로 읽혀요.", "ladderTitle": "켜는 방법 세 가지", - "ladderLocalTitle": "로컬 모델 — AI 요청이 내 네트워크 안에 머물러요", - "ladderLocalBody": "내 컴퓨터의 Ollama나 LM Studio를 HealthLog에 연결해요. 무료이고 완전히 비공개 — 가장 마음 편한 기본값이에요.", + "ladderLocalTitle": "로컬 모델: AI 요청이 내 네트워크 안에 머물러요", + "ladderLocalBody": "내 컴퓨터의 Ollama나 LM Studio를 HealthLog에 연결해요. 무료이고 완전히 비공개라서 가장 마음 편한 기본값이에요.", "ladderByokTitle": "내 API 키 사용", "ladderByokBody": "본인의 OpenAI나 Anthropic 키를 쓰면 돼요. 내 계정과 결제로 돌아가고, API 등급은 기본적으로 데이터를 학습에 쓰지 않아요.", "ladderOauthTitle": "구독 계정으로 로그인", "ladderOauthBody": "ChatGPT 계정을 연결해요. 토큰당 비용은 없지만 소비자 등급 약관은 내용을 학습에 쓸 수 있어서, 건강 데이터에는 기본값이 아니라 신중히 고를 선택이에요.", - "keylessLine": "AI 없이도 HealthLog는 충분히 쓸모 있어요. 타일, 차트, 추이, 내보내기 모두 그대로 작동하고 — AI는 그 위에 쉬운 말 해설을 더할 뿐이에요.", + "keylessLine": "AI 없이도 HealthLog는 충분히 쓸모 있어요. 타일, 차트, 추이, 내보내기 모두 그대로 작동하고, AI는 그 위에 쉬운 말 해설을 더할 뿐이에요.", "setupCta": "설정하기 (1분 정도)", - "sharedKeyNote": "이 인스턴스에는 이미 공용 AI 제공자가 있어서 지금 바로 인사이트를 쓸 수 있어요 — 따로 설정할 게 없어요.", + "sharedKeyNote": "이 인스턴스에는 이미 공용 AI 제공자가 있어서 지금 바로 인사이트를 쓸 수 있어요. 따로 설정할 게 없어요.", "offer": { "title": "이 인스턴스가 요약을 쉬운 말로 써 줄 수 있습니다.", "body": "운영자가 제공하는 공급자가 지난 24시간 안에 마지막으로 정상 동작했습니다. 한 번만 누르면 쉬운 말 요약이 켜지며, 그러면 데이터는 그 하나의 공급자에게만 전달되고 다른 어느 곳에도 가지 않습니다.", @@ -5162,7 +5162,7 @@ "dataSourceDescription": "Withings, WHOOP, Oura, Polar, Nightscout, Fitbit, Apple Health에서 체중·혈압·수면 등을 자동으로 동기화해요.", "dataSourceCta": "연결", "notificationsTitle": "알림 설정하기", - "notificationsDescription": "HealthLog가 어떻게 알려줄지 고르세요 — Telegram, ntfy, 웹 푸시.", + "notificationsDescription": "HealthLog가 어떻게 알려줄지 고르세요: Telegram, ntfy, 웹 푸시.", "notificationsCta": "알림 열기", "insightsTitle": "인사이트 켜기(선택)", "insightsDescription": "로컬 모델이나 내 AI 키를 넣으면 일일 브리핑과 코치가 열려요.", @@ -5388,7 +5388,7 @@ "resetSuccess": "소스 우선순위를 기본값으로 되돌렸어요", "perMetricToggle": "지표별 재정의 ({count})", "perMetricHelp": "기본 순서에서 직접 바꾼 지표예요. 다른 지표는 그대로 두고 하나만 기본값으로 되돌릴 때 이 목록을 쓰세요.", - "perMetricEmpty": "지표별 재정의가 없어요 — 모든 지표가 위의 전체 순서를 써요.", + "perMetricEmpty": "지표별 재정의가 없어요. 모든 지표가 위의 전체 순서를 써요.", "resetMetric": "되돌리기", "deviceTypeToggle": "기기 유형 우선순위 ({count})", "deviceTypeHelp": "한 소스 안에서 어느 기기를 쓸지예요. Apple Watch와 iPhone이 모두 걸음 수를 기록하면 순위가 높은 기기 유형의 측정값을 대표값으로 써요.", @@ -5452,7 +5452,7 @@ "daysWithData": "{days}일 중 {count}일", "moduleHint": "동기화는 영양 섭취 모듈에서 조절해요.", "moduleHintLink": "모듈 관리", - "detail": "읽기 전용 — 숫자는 원본 앱이 관리해요." + "detail": "읽기 전용이에요. 숫자는 원본 앱이 관리해요." }, "helpDetail": "나머지는 감사 기록용으로 그대로 보관해요. 연결했거나 데이터가 있는 소스만 보여요.", "noneInUse": "아직 순위를 정할 소스가 없어요. 연동에서 연결하거나 값을 기록해 보세요." @@ -5501,7 +5501,7 @@ "encryptToggle": "암호문구로 암호화", "passphrasePlaceholder": "암호문구 (12자 이상)", "passphraseHelp": "Argon2id로 보관 파일 키를 만들고 AES-256-GCM으로 봉인해요. 파일은 .hlx 확장자로 저장해 주세요.", - "noRecoveryWarning": "복구 수단이 없어요 — 이 암호문구를 잃어버리면 보관 파일을 열 수 없어요. 안전한 곳에 보관해 주세요.", + "noRecoveryWarning": "복구 수단이 없어요. 이 암호문구를 잃어버리면 보관 파일을 열 수 없어요. 안전한 곳에 보관해 주세요.", "detail": "주간 자동 백업과 같은 형식이에요. 아직 담기지 않는 기록 유형이 있고, 파일의 매니페스트에 무엇이 들었는지 적혀 있어요.", "contents": "측정, 복약, 기분, 생리 주기, 검사, 아픈 날 에피소드, 알레르기, 가족력, 영양, 운동, 건강 프로필, 사용자 지표를 JSON 파일 하나에." } @@ -5745,7 +5745,7 @@ "error": "저장하지 못했어요. 다시 시도해 주세요.", "toggleable": { "title": "기록할 항목", - "description": "끈 모듈은 내비게이션, 타일, 인사이트에서 빠져요 — 데이터는 그대로 남아요." + "description": "끈 모듈은 내비게이션, 타일, 인사이트에서 빠지지만 데이터는 그대로 남아요." }, "manageIn": "{section}에서 관리", "operatorDisabled": "서버 전체에서 꺼짐", @@ -5865,7 +5865,7 @@ "omitted": "{count}개 항목은 기록이 꺼져 있어서 목록에 없어요. 모듈을 다시 켜면 해당 항목도 돌아와요.", "omittedLink": "모듈 열기", "refusal": { - "empty": "건강 점수에는 점수를 매길 건강 영역이 최소 하나 필요해요. 하나는 선택해 두세요 — 점수가 어떤 영역을 바탕으로 하는지 알려 줘요." + "empty": "건강 점수에는 점수를 매길 건강 영역이 최소 하나 필요해요. 하나는 선택해 두세요. 점수가 어떤 영역을 바탕으로 하는지 알려 줘요." }, "notice": { "upgrade": { @@ -6048,7 +6048,7 @@ "rawDataWarning": "자세한 기록이 켜져 있어요. 분석할 때마다 최근 90일의 일별 평균, 그 이전 1년의 주별 평균, 최대 5년 전까지의 월별 평균이 추가로 전송돼요.", "regenerateInsights": "리포트 다시 생성", "regenerateSuccess": "리포트를 다시 생성했어요", - "regenerateRateLimit": "잠시만 기다려 주세요 — 시간당 분석 한도에 도달했어요.", + "regenerateRateLimit": "잠시만 기다려 주세요. 시간당 분석 한도에 도달했어요.", "lastGeneratedAt": "마지막 생성", "ai": { "chatgptConnectedBadge": "ChatGPT 연결됨", @@ -6058,11 +6058,11 @@ "deviceCodeHeading": "chatgpt.com에서 연결을 마무리하세요", "deviceCodeStep1": "아무 기기에서나 이 링크를 여세요:", "deviceCodeStep2": "이 일회용 코드를 입력하세요:", - "deviceCodeStep3": "연결을 승인하세요 — 이 페이지는 자동으로 갱신돼요.", + "deviceCodeStep3": "연결을 승인하세요. 이 페이지는 자동으로 갱신돼요.", "deviceCodeCopy": "복사", "deviceCodeWaiting": "승인을 기다리는 중…", "deviceCodeCancel": "취소", - "oauthNotConfigured": "이 인스턴스에는 ChatGPT OAuth가 설정돼 있지 않아요 — 아래에서 직접 발급한 API 키를 쓰세요.", + "oauthNotConfigured": "이 인스턴스에는 ChatGPT OAuth가 설정돼 있지 않아요. 아래에서 직접 발급한 API 키를 쓰세요.", "modelLabel": "모델", "modelOptionDefault": "— 기본값 —", "modelOptionCustom": "직접 입력…", @@ -6070,7 +6070,7 @@ "anthropicKeyLabel": "Anthropic API 키", "baseUrlLabel": "기본 URL", "localKeyLabel": "API 키 (선택)", - "localDescription": "OpenAI 호환 엔드포인트라면 무엇이든 쓸 수 있어요 — 로컬 모델(Ollama, LM Studio)은 물론 LiteLLM, OpenRouter, vLLM 같은 게이트웨이도요. 기본 URL은 /v1로 끝나고, API 키는 선택이에요.", + "localDescription": "OpenAI 호환 엔드포인트라면 무엇이든 쓸 수 있어요. 로컬 모델(Ollama, LM Studio)은 물론 LiteLLM, OpenRouter, vLLM 같은 게이트웨이도요. 기본 URL은 /v1로 끝나고, API 키는 선택이에요.", "savedPreview": "(저장됨: {preview})", "savedShort": "(저장됨)", "saveCta": "저장", @@ -6110,7 +6110,7 @@ "admin-openai": "관리자가 제공하는 OpenAI" }, "compat": { - "description": "OpenAI /v1/chat/completions API를 쓰는 엔드포인트라면 무엇이든 정식 제공자로 쓸 수 있어요: LiteLLM, OpenRouter, vLLM 같은 게이트웨이요. 기본 URL은 /v1로 끝나고, API 키는 선택이며, 모델은 게이트웨이가 연결해 주는 것을 쓰면 돼요. OpenAI 키는 이 엔드포인트에 절대 전달되지 않아요 — 이 제공자는 자체 키를 써요.", + "description": "OpenAI /v1/chat/completions API를 쓰는 엔드포인트라면 무엇이든 정식 제공자로 쓸 수 있어요: LiteLLM, OpenRouter, vLLM 같은 게이트웨이요. 기본 URL은 /v1로 끝나고, API 키는 선택이며, 모델은 게이트웨이가 연결해 주는 것을 쓰면 돼요. OpenAI 키는 이 엔드포인트에 절대 전달되지 않아요. 이 제공자는 자체 키를 써요.", "keyLabel": "API 키 (선택)", "modelHint": "게이트웨이가 기대하는 모델 이름이에요. 비워 두면 다른 제공자에 저장한 모델을 쓰고, 둘 다 없으면 이 제공자는 건너뛰어요." }, @@ -6146,13 +6146,13 @@ "notConfigured": "운영자가 이 인스턴스에 공용 OpenAI 키를 설정하지 않았어요." }, "testProvider": "사용 중인 제공자 테스트", - "testSuccess": "정상 — {provider} ({model})", + "testSuccess": "정상: {provider} ({model})", "testFailedShort": "테스트 실패: {message}", - "testUnexpectedResponse": "AI 제공자 연결에 실패했어요 — 서버에서 예상 밖의 응답이 왔어요.", - "testReasonCredentials": "제공자가 인증 정보를 거부했어요 — AI 설정에서 다시 인증해 주세요.", - "testReasonRateLimited": "제공자가 요청 빈도를 제한했어요 — 잠시 뒤 다시 시도해 주세요.", + "testUnexpectedResponse": "AI 제공자 연결에 실패했어요. 서버에서 예상 밖의 응답이 왔어요.", + "testReasonCredentials": "제공자가 인증 정보를 거부했어요. AI 설정에서 다시 인증해 주세요.", + "testReasonRateLimited": "제공자가 요청 빈도를 제한했어요. 잠시 뒤 다시 시도해 주세요.", "testReasonServerError": "AI 제공자가 서버 오류를 반환했어요.", - "testReasonBadRequest": "제공자가 요청을 거부했어요(HTTP {status}) — 엔드포인트는 응답했으니 연결 문제가 아니라 요청 형식이나 모델 이름 문제예요.", + "testReasonBadRequest": "제공자가 요청을 거부했어요(HTTP {status}), 엔드포인트는 응답했으니 연결 문제가 아니라 요청 형식이나 모델 이름 문제예요.", "testReasonUnreachable": "AI 제공자에 연결하지 못했어요.", "coachMemory": { "title": "코치가 기억하는 것", @@ -6240,15 +6240,15 @@ "autoRead": { "title": "AI로 문서 자동 읽기", "subLabel": "문서마다 따로 누르지 않아도 설정한 AI 제공자가 문서를 읽고 색인해요.", - "honesty": "켜 두면 올리는 문서마다 설정한 AI 제공자에게 전송되어 읽히고, 설명이 붙고, 검색용으로 색인돼요 — 문서별 확인 절차는 없어요. 켜는 순간 과거 문서에도 적용돼요. 이미 올렸지만 아직 요약이 없는 문서도 켤 때마다 최대 200개까지 함께 전송돼요. 이 작업은 서버에서 이뤄지고 문서 내용은 이 기기를 떠나 그 제공자에게 전달돼요. 설정한 제공자가 구독 연결(API 키가 아니라 로그인한 AI 계정)이라면 그 제공자의 데이터 정책이 적용돼요 — 구독 제공자는 내용을 모델 개선에 쓸 수 있고, 이를 보호하는 데이터 처리 계약도 없어요. 셀프 호스팅 로컬 모델이 읽은 문서는 서버 밖으로 나가지 않아요. 기본값은 꺼짐이고, 이 조건을 받아들일 때만 켜세요.", - "confirm": "이해했어요 — 켜기", + "honesty": "켜 두면 올리는 문서마다 설정한 AI 제공자에게 전송되어 읽히고, 설명이 붙고, 검색용으로 색인돼요. 문서별 확인 절차는 없어요. 켜는 순간 과거 문서에도 적용돼요. 이미 올렸지만 아직 요약이 없는 문서도 켤 때마다 최대 200개까지 함께 전송돼요. 이 작업은 서버에서 이뤄지고 문서 내용은 이 기기를 떠나 그 제공자에게 전달돼요. 설정한 제공자가 구독 연결(API 키가 아니라 로그인한 AI 계정)이라면 그 제공자의 데이터 정책이 적용돼요. 구독 제공자는 내용을 모델 개선에 쓸 수 있고, 이를 보호하는 데이터 처리 계약도 없어요. 셀프 호스팅 로컬 모델이 읽은 문서는 서버 밖으로 나가지 않아요. 기본값은 꺼짐이고, 이 조건을 받아들일 때만 켜세요.", + "confirm": "이해했어요, 켜기", "cancel": "취소" }, "centralCodex": { "title": "서버의 공용 AI 연결 사용", "subLabel": "AI 요청을 서버의 공유 연결로 보내고, 내 제공자는 대체 수단으로 써요.", - "honesty": "공용 연결은 운영자가 이 서버의 모든 사용자를 위해 연결해 둔 로그인 AI 계정 하나예요 — 내 키가 아니에요. 이 연결로 보낸 요청은 기본적으로 제공자의 학습에 쓰이고 이를 보호하는 데이터 처리 계약도 없으며, 계정의 시간당·주당 한도를 사용을 선택한 다른 모든 사용자와 나눠 써요. 내가 설정한 제공자는 여전히 먼저 시도돼요. 이 조건을 받아들일 때만 켜세요.", - "confirm": "이해했어요 — 연결 사용", + "honesty": "공용 연결은 운영자가 이 서버의 모든 사용자를 위해 연결해 둔 로그인 AI 계정 하나예요. 내 키가 아니에요. 이 연결로 보낸 요청은 기본적으로 제공자의 학습에 쓰이고 이를 보호하는 데이터 처리 계약도 없으며, 계정의 시간당·주당 한도를 사용을 선택한 다른 모든 사용자와 나눠 써요. 내가 설정한 제공자는 여전히 먼저 시도돼요. 이 조건을 받아들일 때만 켜세요.", + "confirm": "이해했어요, 연결 사용", "cancel": "취소" }, "consent": { @@ -6324,8 +6324,8 @@ "withingsClientId": "클라이언트 ID", "withingsClientSecret": "클라이언트 시크릿", "withingsCredentialsSaved": "자격 증명을 저장했어요", - "withingsCredentialsSavedPlaceholder": "저장됨 — 바꾸려면 새로 입력", - "withingsCredentialsSavedPlaceholderSecret": "저장됨 — 바꾸려면 새로 입력", + "withingsCredentialsSavedPlaceholder": "저장됨: 바꾸려면 새로 입력", + "withingsCredentialsSavedPlaceholderSecret": "저장됨: 바꾸려면 새로 입력", "withingsSaveCredentials": "저장", "configured": "설정됨", "withingsSync": "지금 동기화", @@ -6340,7 +6340,7 @@ }, "withingsFullSyncResult": "측정값 {count}개를 전체 동기화했어요", "withingsSyncFailed": "동기화에 실패했어요", - "withingsOauthConnected": "Withings를 연결했어요 — 첫 동기화가 백그라운드에서 시작돼요.", + "withingsOauthConnected": "Withings를 연결했어요. 첫 동기화가 백그라운드에서 시작돼요.", "withingsOauthFailed": "Withings 연결에 실패했어요", "withingsOauthError": { "csrf1": "브라우저 쿠키가 없어서 보안 확인에 실패했어요. 같은 브라우저에서 연결을 다시 시작해 주세요.", @@ -6365,8 +6365,8 @@ "whoopClientId": "클라이언트 ID", "whoopClientSecret": "클라이언트 시크릿", "whoopCredentialsSaved": "자격 증명을 저장했어요", - "whoopCredentialsSavedPlaceholder": "저장됨 — 바꾸려면 새로 입력", - "whoopCredentialsSavedPlaceholderSecret": "저장됨 — 바꾸려면 새로 입력", + "whoopCredentialsSavedPlaceholder": "저장됨: 바꾸려면 새로 입력", + "whoopCredentialsSavedPlaceholderSecret": "저장됨: 바꾸려면 새로 입력", "whoopSaveCredentials": "저장", "whoopSync": "지금 동기화", "whoopFullSync": "전체 데이터 동기화", @@ -6381,7 +6381,7 @@ "whoopConnect": "WHOOP으로 연결", "whoopNoCredentials": "WHOOP을 연결하려면 위에 API 자격 증명을 입력해 주세요.", "whoopBackfillInProgress": "WHOOP 기록을 백그라운드에서 가져오는 중이에요…", - "whoopOauthConnected": "WHOOP을 연결했어요 — 첫 동기화가 백그라운드에서 시작돼요.", + "whoopOauthConnected": "WHOOP을 연결했어요. 첫 동기화가 백그라운드에서 시작돼요.", "whoopOauthFailed": "WHOOP 연결에 실패했어요", "whoopOauthError": { "csrf1": "브라우저 쿠키가 없어서 보안 확인에 실패했어요. 같은 브라우저에서 연결을 다시 시작해 주세요.", @@ -6395,14 +6395,14 @@ }, "fitbit": "Fitbit", "fitbitTag": "Fitbit & Pixel", - "fitbitDescription": "Fitbit을 연결하면 Fitbit과 Pixel Watch의 건강 지표를 동기화해요 — 체중, 심박수 등.", + "fitbitDescription": "Fitbit을 연결하면 Fitbit과 Pixel Watch의 건강 지표를 동기화해요: 체중, 심박수 등.", "fitbitExperimentalBadge": "실험 기능", "fitbitCredentials": "API 자격 증명", "fitbitClientId": "클라이언트 ID", "fitbitClientSecret": "클라이언트 시크릿", "fitbitCredentialsSaved": "자격 증명을 저장했어요", - "fitbitCredentialsSavedPlaceholder": "저장됨 — 바꾸려면 새로 입력", - "fitbitCredentialsSavedPlaceholderSecret": "저장됨 — 바꾸려면 새로 입력", + "fitbitCredentialsSavedPlaceholder": "저장됨: 바꾸려면 새로 입력", + "fitbitCredentialsSavedPlaceholderSecret": "저장됨: 바꾸려면 새로 입력", "fitbitSaveCredentials": "저장", "fitbitSync": "지금 동기화", "fitbitFullSync": "전체 데이터 동기화", @@ -6417,7 +6417,7 @@ "fitbitConnect": "Fitbit으로 연결", "fitbitNoCredentials": "Fitbit을 연결하려면 위에 API 자격 증명을 입력해 주세요.", "fitbitBackfillInProgress": "Fitbit 기록을 백그라운드에서 가져오는 중이에요…", - "fitbitOauthConnected": "Fitbit을 연결했어요 — 첫 동기화가 백그라운드에서 시작돼요.", + "fitbitOauthConnected": "Fitbit을 연결했어요. 첫 동기화가 백그라운드에서 시작돼요.", "fitbitOauthFailed": "Fitbit 연결에 실패했어요", "googleHealth": "Google Health", "googleHealthTag": "Fitbit & Pixel", @@ -6427,8 +6427,8 @@ "googleHealthClientId": "클라이언트 ID", "googleHealthClientSecret": "클라이언트 시크릿", "googleHealthCredentialsSaved": "자격 증명을 저장했어요", - "googleHealthCredentialsSavedPlaceholder": "저장됨 — 바꾸려면 새로 입력", - "googleHealthCredentialsSavedPlaceholderSecret": "저장됨 — 바꾸려면 새로 입력", + "googleHealthCredentialsSavedPlaceholder": "저장됨: 바꾸려면 새로 입력", + "googleHealthCredentialsSavedPlaceholderSecret": "저장됨: 바꾸려면 새로 입력", "googleHealthSaveCredentials": "저장", "googleHealthSync": "지금 동기화", "googleHealthSyncCheckStatus": "상태 새로고침", @@ -6462,9 +6462,9 @@ "googleHealthConnect": "Google로 연결", "googleHealthNoCredentials": "Google Health를 연결하려면 위에 API 자격 증명을 입력해 주세요.", "googleHealthBackfillInProgress": "Google Health 기록을 백그라운드에서 가져오는 중이에요…", - "googleHealthReauthBanner": "Google이 연결을 만료시켰어요 — OAuth 앱이 테스트 모드로 있는 동안 주기적으로 생기는 일이에요. 다시 연결하면 동기화가 이어져요.", + "googleHealthReauthBanner": "Google이 연결을 만료시켰어요. OAuth 앱이 테스트 모드로 있는 동안 주기적으로 생기는 일이에요. 다시 연결하면 동기화가 이어져요.", "googleHealthReconnect": "다시 연결", - "googleHealthOauthConnected": "Google Health를 연결했어요 — 첫 동기화가 백그라운드에서 시작돼요.", + "googleHealthOauthConnected": "Google Health를 연결했어요. 첫 동기화가 백그라운드에서 시작돼요.", "googleHealthOauthFailed": "Google Health 연결에 실패했어요", "googleHealthOauthError": { "csrf1": "브라우저 쿠키가 없어서 보안 확인에 실패했어요. 같은 브라우저에서 연결을 다시 시작해 주세요.", @@ -6499,10 +6499,10 @@ }, "integrationPill": { "connected": "연결됨", - "errorReconnect": "오류 — 다시 연결", + "errorReconnect": "오류: 다시 연결", "warningServerError": "동기화 실패 중", "failureCount": "{count}/{threshold}", - "parkedReconnect": "일시중지 — 다시 연결", + "parkedReconnect": "일시중지: 다시 연결", "notConnected": "연결 안 됨", "justNow": "방금", "minutesAgo": "{count}분 전", @@ -6557,7 +6557,7 @@ "namePlaceholder": "이름 (예: Paperless-ngx)" }, "tokenMintMovedDescription": "토큰은 쓰이는 곳에서 발급돼요. 측정값, 운동, 문서는 위에서, 특정 약은 그 약의 API 엔드포인트에서 만들 수 있어요.", - "tokenCreated": "토큰을 만들었어요 — 지금 복사하세요! 다시 보여주지 않아요.", + "tokenCreated": "토큰을 만들었어요. 지금 복사하세요! 다시 보여주지 않아요.", "tokenCopy": "토큰 복사", "tokenCopied": "토큰을 클립보드에 복사했어요", "tokenCopyFailed": "토큰을 복사하지 못했어요", @@ -6596,7 +6596,7 @@ "deleteAccountCta": "계정 삭제", "deleteAccountConfirmTitle": "계정을 영구히 삭제할까요?", "deleteAccountConfirmDescription": "계정과 모든 건강 데이터, 패스키, 세션, 감사 기록이 영구히 삭제돼요. 삭제 직후 로그아웃돼요.", - "deleteAccountSuccess": "계정을 삭제했어요 — 로그아웃할게요.", + "deleteAccountSuccess": "계정을 삭제했어요. 로그아웃할게요.", "deleteAccountFailed": "계정을 삭제하지 못했어요", "deleteAccountFinal": "영구 삭제", "saved": "저장됨", @@ -6619,7 +6619,7 @@ "testing": "테스트 중…", "ok": "연결됨 (지연 {latency}ms)", "errors": { - "credentials_rejected": "자격 증명이 거부됐어요 — 토큰을 확인해 주세요", + "credentials_rejected": "자격 증명이 거부됐어요. 토큰을 확인해 주세요", "rate_limited": "상대 서버에서 요청 수를 제한했어요", "timeout": "요청 시간이 초과됐어요", "upstream_error": "상대 서버가 오류를 반환했어요", @@ -6630,7 +6630,7 @@ "private_origin_not_approved": "비공개 네트워크 대상이에요. 운영자가 NOTIFICATION_PRIVATE_ORIGINS에 이 출처를 등록해야 해요", "private_origin_not_grantable": "이 주소는 링크 로컬, 메타데이터 또는 미지정 주소예요. 운영자 등록으로도 열 수 없으니 릴레이가 실제로 수신하는 주소를 사용해 주세요", "url_invalid": "URL이 올바르지 않아요", - "redirected": "엔드포인트가 리디렉션돼요 — URL을 확인해 주세요", + "redirected": "엔드포인트가 리디렉션돼요. URL을 확인해 주세요", "endpoint_not_found": "해당 URL에 엔드포인트가 없어요", "credentials_unreadable": "자격 증명을 복호화할 수 없어요", "upstream_invalid_json": "상대 서버가 잘못된 JSON을 보냈어요", @@ -6641,7 +6641,7 @@ }, "notificationStatus": { "title": "발송 상태", - "description": "채널별 상태예요 — '자동 비활성화'는 영구 오류가 이어져 재시도를 멈췄다는 뜻이에요.", + "description": "채널별 상태이며, '자동 비활성화'는 영구 오류가 이어져 재시도를 멈췄다는 뜻이에요.", "emptyDescription": "설정 › 연동 › 발송 채널에서 채널을 설정해 주세요.", "stateActive": "사용 중", "stateAutoDisabled": "자동 비활성화", @@ -6667,7 +6667,7 @@ }, "healthRecord": { "title": "건강 기록 내보내기", - "description": "의사에게 보여줄 전체 기록 — PDF, FHIR, 또는 둘 다.", + "description": "의사에게 보여줄 전체 기록: PDF, FHIR, 또는 둘 다.", "format": "형식", "format_pdf": "PDF", "format_fhir": "구조화 (FHIR)", @@ -6699,7 +6699,7 @@ "createTitle": "새 공유 링크", "createDescription": "링크는 읽기 전용이고 유효 기간이 있어요.", "label": "라벨", - "labelPlaceholder": "예: 김 선생님 — 건강검진", + "labelPlaceholder": "예: 김 선생님, 건강검진", "range": "공유할 기록 기간(일)", "rangeHint": "공유 범위가 과거 며칠까지 포함될지 정해요.", "expiry": "만료까지(일)", @@ -6719,7 +6719,7 @@ "statusRevoked": "해지됨", "statusExpired": "만료됨", "inactiveTitle": "해지·만료됨 ({count})", - "shownOnce": "한 번만 보여줘요. 지금 QR 코드와 암호를 저장해 두세요 — 나중에는 둘 다 복구할 수 없어요.", + "shownOnce": "한 번만 보여줘요. 지금 QR 코드와 암호를 저장해 두세요. 나중에는 둘 다 복구할 수 없어요.", "qrAlt": "공유 링크와 암호가 담긴 QR 코드", "linkLabel": "링크", "passphraseLabel": "암호", @@ -6730,12 +6730,12 @@ "attachTitle": "문서 첨부", "attachButton": "문서 선택", "attachCount": "{max}개 중 {count}개 선택됨", - "attachFrozen": "링크를 만들면 문서 구성이 고정돼요 — 나중에 문서를 추가하거나 뺄 수 없어요.", + "attachFrozen": "링크를 만들면 문서 구성이 고정돼요. 나중에 문서를 추가하거나 뺄 수 없어요.", "attachRemove": "제거: {title}", "exifNote": "공유할 때 JPEG, PNG, WebP 이미지에서는 카메라 메타데이터(EXIF/GPS)를 제거해요. PDF, TIFF, HEIC, Office 파일은 그대로 전달돼요.", "documentCount": "첨부한 문서: {count}개", "qrScanTitle": "다른 기기에서 열려면 스캔하세요", - "qrScanHint": "휴대폰 카메라로 코드를 비추면 공유된 기록이 열려요 — 암호는 이미 포함돼 있어요.", + "qrScanHint": "휴대폰 카메라로 코드를 비추면 공유된 기록이 열려요. 암호는 이미 포함돼 있어요.", "pickerTitle": "문서 첨부", "pickerDescription": "보관함에서 검색해 공유할 문서를 고르세요. 최대 {max}개예요.", "pickerSearch": "문서 검색", @@ -6748,7 +6748,7 @@ "statusNeedsReselect": "내용 다시 선택", "reselectReason": "이 링크는 선택한 적 없는 범위를 제공하고 있어서 닫았어요. 새로 만들고 담을 내용을 골라 주세요.", "reselectAction": "새 링크 만들기", - "createDetail": "토큰은 만들 때 한 번만 보여줘요 — 그때 저장해 두세요. 복구할 수 없어요.", + "createDetail": "토큰은 만들 때 한 번만 보여줘요. 그때 저장해 두세요. 복구할 수 없어요.", "activeDescription": "공유한 링크와 만료 시점, 열람 횟수를 보여줘요." }, "genderOther": "기타", @@ -6757,10 +6757,10 @@ "nightscoutDescription": "직접 운영하는 Nightscout 사이트를 연결해 연속 혈당 측정값을 혈당 패널로 동기화해요.", "nightscoutViewData": "혈당 보기", "nightscoutUrl": "Nightscout URL", - "nightscoutUrlSavedPlaceholder": "저장됨 — 바꾸려면 새 URL을 입력하세요", + "nightscoutUrlSavedPlaceholder": "저장됨: 바꾸려면 새 URL을 입력하세요", "nightscoutToken": "API 토큰", "nightscoutTokenOptional": "공개 사이트라면 선택 사항이에요", - "nightscoutTokenSavedPlaceholder": "저장됨 — 바꾸려면 새 토큰을 입력하세요", + "nightscoutTokenSavedPlaceholder": "저장됨: 바꾸려면 새 토큰을 입력하세요", "nightscoutTokenHelp": "Nightscout 관리자 도구에서 발급한 액세스 토큰을 붙여 넣으세요. 사이트를 누구나 읽을 수 있다면 비워 두세요.", "nightscoutPrivateOperatorTitle": "비공개 Nightscout에 접근하려면 서버 운영자의 승인이 필요해요.", "nightscoutPrivateOperatorDescription": "서버 운영자에게 이 Nightscout 출처를 그대로 승인해 달라고 요청하세요.", @@ -6781,7 +6781,7 @@ "polarClientId": "클라이언트 ID", "polarClientSecret": "클라이언트 시크릿", "polarCredentialsSaved": "자격 증명을 저장했어요", - "polarCredentialsSavedPlaceholder": "저장됨 — 바꾸려면 새로 입력하세요", + "polarCredentialsSavedPlaceholder": "저장됨: 바꾸려면 새로 입력하세요", "polarSaveCredentials": "저장", "polarUnavailable": "이 서버에는 Polar가 설정돼 있지 않아요. 위에 직접 Polar OAuth 자격 증명을 넣거나, 관리자에게 공용 앱 설정을 요청하세요.", "polarConnect": "Polar 연결", @@ -6791,7 +6791,7 @@ "polarDisconnect": "연결 해제", "polarDisconnectTitle": "Polar 연결을 해제할까요?", "polarDisconnectDescription": "앞으로 동기화가 멈춰요. 이미 가져온 측정값은 기록에 그대로 남아요.", - "polarOauthConnected": "Polar를 연결했어요 — 첫 동기화가 백그라운드에서 시작돼요.", + "polarOauthConnected": "Polar를 연결했어요. 첫 동기화가 백그라운드에서 시작돼요.", "polarOauthFailed": "Polar 연결에 실패했어요", "polarOauthError": { "csrf1": "브라우저 쿠키가 없어서 보안 확인에 실패했어요. 같은 브라우저에서 연결을 다시 시작해 주세요.", @@ -6810,7 +6810,7 @@ "ouraClientId": "클라이언트 ID", "ouraClientSecret": "클라이언트 시크릿", "ouraCredentialsSaved": "자격 증명을 저장했어요", - "ouraCredentialsSavedPlaceholder": "저장됨 — 바꾸려면 새로 입력하세요", + "ouraCredentialsSavedPlaceholder": "저장됨: 바꾸려면 새로 입력하세요", "ouraSaveCredentials": "저장", "ouraUnavailable": "이 서버에는 Oura가 설정돼 있지 않아요. 위에 직접 Oura OAuth 자격 증명을 넣거나, 관리자에게 공용 앱 설정을 요청하세요.", "ouraConnect": "Oura 연결", @@ -6820,7 +6820,7 @@ "ouraDisconnect": "연결 해제", "ouraDisconnectTitle": "Oura 연결을 해제할까요?", "ouraDisconnectDescription": "앞으로 동기화가 멈춰요. 이미 가져온 측정값은 기록에 그대로 남아요.", - "ouraOauthConnected": "Oura를 연결했어요 — 첫 동기화가 백그라운드에서 시작돼요.", + "ouraOauthConnected": "Oura를 연결했어요. 첫 동기화가 백그라운드에서 시작돼요.", "ouraOauthFailed": "Oura 연결에 실패했어요", "ouraOauthError": { "csrf1": "브라우저 쿠키가 없어서 보안 확인에 실패했어요. 같은 브라우저에서 연결을 다시 시작해 주세요.", @@ -6851,7 +6851,7 @@ } }, "integrationRedirectGuide": { - "intro": "직접 만든 {provider} 개발자 앱으로 연결해요 — 설정에 5분쯤 걸려요:", + "intro": "직접 만든 {provider} 개발자 앱으로 연결해요. 설정에 5분쯤 걸려요:", "step1": "{provider} 개발자 포털에서 앱을 만드세요.", "step2": "리디렉션/콜백 URL을 다음으로 설정하세요:", "step3": "발급받은 클라이언트 ID와 클라이언트 시크릿을 위에 붙여 넣으세요." @@ -6939,7 +6939,7 @@ }, "passkeyNudge": { "title": "패스키를 추가하면 더 빠르게 로그인해요", - "body": "패스키로 지문, 얼굴, 기기 PIN을 써서 로그인할 수 있어요 — 비밀번호를 외울 필요가 없어요." + "body": "패스키로 지문, 얼굴, 기기 PIN을 써서 로그인할 수 있어요. 비밀번호를 외울 필요가 없어요." }, "trustedDevices": { "title": "신뢰하는 기기", @@ -6958,7 +6958,7 @@ "revokeAllConfirmBody": "이 기기를 포함해 모든 기기에서 다음에 로그인할 때 2단계 인증을 다시 물어봐요." }, "revokeSessionConfirmTitle": "이 기기를 로그아웃할까요?", - "revokeSessionConfirmBody": "{device} — 다시 로그인해야 해요. 기기에 기록된 내용은 영향받지 않아요.", + "revokeSessionConfirmBody": "{device}: 다시 로그인해야 해요. 기기에 기록된 내용은 영향받지 않아요.", "signOutEverywhereConfirmTitle": "다른 기기를 모두 로그아웃할까요?", "signOutEverywhereConfirmBody": "다른 모든 기기, 연결된 모든 AI 어시스턴트와 모든 API 토큰은 다시 로그인하거나 다시 설정해야 합니다. 이 기기는 로그인 상태로 유지됩니다. 기록한 내용에는 영향이 없습니다.", "signOutEverywhereShareLinks": "의료진 공유 링크도 종료", @@ -7014,7 +7014,7 @@ "endpointLabel": "커넥터 URL", "connectDescription": "어시스턴트의 커스텀 커넥터 설정에 이 URL을 붙여 넣고, 아래 토큰으로 인증하거나 안내가 나오면 로그인하세요.", "tokensTitle": "커넥터 토큰", - "tokensDescription": "어시스턴트를 연결할 토큰을 발급하세요 — 아래에서 기록을 허용하지 않으면 읽기 전용이에요.", + "tokensDescription": "어시스턴트를 연결할 토큰을 발급하세요, 아래에서 기록을 허용하지 않으면 읽기 전용이에요.", "scopeNote": "새 토큰은 본인 기록만 읽을 수 있어요. 쓰기 권한(health:write)은 아래 토글로 토큰마다 따로 부여해요. 토큰은 관리자 기능에 절대 접근할 수 없어요.", "writeScopeToggleLabel": "기록 허용 (health:write)", "writeScopeNote": "health:write 범위를 추가해 어시스턴트가 새 측정값과 기분 기록을 계정에 남길 수 있게 해요. 모든 쓰기는 먼저 확인을 거쳐요. 그래도 토큰은 기존 기록을 삭제하거나 수정할 수 없고, 약을 바꾸거나 REST·관리자 기능에 접근할 수도 없어요. 읽기 전용으로 쓰려면 꺼 두세요.", @@ -7038,7 +7038,7 @@ "stravaClientId": "클라이언트 ID", "stravaClientSecret": "클라이언트 시크릿", "stravaCredentialsSaved": "자격 증명을 저장했어요", - "stravaCredentialsSavedPlaceholder": "저장됨 — 바꾸려면 새로 입력하세요", + "stravaCredentialsSavedPlaceholder": "저장됨: 바꾸려면 새로 입력하세요", "stravaSaveCredentials": "저장", "stravaUnavailable": "이 서버에는 Strava가 설정돼 있지 않아요. 위에 직접 Strava API 자격 증명을 넣거나, 관리자에게 공용 앱 설정을 요청하세요.", "stravaConnect": "Strava 연결", @@ -7048,7 +7048,7 @@ "stravaDisconnect": "연결 해제", "stravaDisconnectTitle": "Strava 연결을 해제할까요?", "stravaDisconnectDescription": "앞으로 동기화가 멈춰요. 이미 가져온 활동은 기록에 그대로 남아요.", - "stravaOauthConnected": "Strava를 연결했어요 — 첫 동기화가 백그라운드에서 시작돼요.", + "stravaOauthConnected": "Strava를 연결했어요. 첫 동기화가 백그라운드에서 시작돼요.", "stravaOauthFailed": "Strava 연결에 실패했어요", "stravaOauthError": { "csrf1": "브라우저 쿠키가 없어서 보안 확인에 실패했어요. 같은 브라우저에서 연결을 다시 시작해 주세요.", @@ -7190,20 +7190,20 @@ "memUsedPercent": "메모리", "diskBusyPercent": "디스크 I/O", "last2hours": "최근 2시간", - "empty": "샘플링을 시작했어요 — 1–2분 뒤에 데이터가 나타나요.", + "empty": "샘플링을 시작했어요. 1–2분 뒤에 데이터가 나타나요.", "loadError": "호스트 지표를 불러오지 못했어요. 페이지를 새로고침해 보세요." }, "aiServerKey": { "title": "AI 서버 키", "description": "자기 키를 설정하지 않은 계정을 위한 운영자 키예요.", - "byokHint": "사용자 본인 키(BYOK, ChatGPT 로그인, 로컬 제공자)가 항상 우선해요 — 서버 키는 제공자 체인의 마지막 단계예요.", + "byokHint": "사용자 본인 키(BYOK, ChatGPT 로그인, 로컬 제공자)가 항상 우선해요. 서버 키는 제공자 체인의 마지막 단계예요.", "consentHint": "서버 키로 나가는 요청에는 사용자의 유효한 AI 동의가 필요해요. 동의 기록이 없으면 아무것도 전송하지 않아요.", "baseUrlHint": "기본 URL이 API를 결정합니다. https://api.anthropic.com/v1 같은 Anthropic 주소는 인식되며, 그 밖의 호스트는 OpenAI 호환 API로 호출됩니다.", "statusConfigured": "설정됨", "statusNotConfigured": "설정 안 됨", "keyLabel": "API 키", "keyPlaceholder": "sk-...", - "keyPlaceholderSet": "저장됨 ({preview}) — 바꾸려면 새 키를 입력하세요", + "keyPlaceholderSet": "저장됨 ({preview}): 바꾸려면 새 키를 입력하세요", "modelLabel": "모델", "baseUrlLabel": "Base URL", "save": "저장", @@ -7222,7 +7222,7 @@ "title": "인사이트 품질", "loading": "피드백 요약 불러오는 중…", "loadError": "인사이트 품질 요약을 불러오지 못했어요. 페이지를 새로고침해 보세요.", - "empty": "아직 피드백이 없어요. 집계는 매일 04:00에 돌아요 — 사용자가 추천을 평가하기 시작하면 도움됨 비율 구간이 여기에 나타나요.", + "empty": "아직 피드백이 없어요. 집계는 매일 04:00에 돌아요. 사용자가 추천을 평가하기 시작하면 도움됨 비율 구간이 여기에 나타나요.", "windowLabel": "최근 {days}일", "generatedAtLabel": "생성 시각", "colSeverity": "심각도", @@ -7237,7 +7237,7 @@ "title": "코치 피드백", "loading": "코치 피드백 요약 불러오는 중…", "loadError": "코치 피드백 요약을 불러오지 못했어요. 페이지를 새로고침해 보세요.", - "empty": "아직 코치 피드백이 없어요. 집계는 매일 04:00에 돌아요 — 사용자가 코치 답변을 평가하면 도움됨 비율 구간이 여기에 나타나요.", + "empty": "아직 코치 피드백이 없어요. 집계는 매일 04:00에 돌아요. 사용자가 코치 답변을 평가하면 도움됨 비율 구간이 여기에 나타나요.", "windowLabel": "최근 {days}일", "generatedAtLabel": "생성 시각", "colPromptVersion": "프롬프트 버전", @@ -7256,7 +7256,7 @@ "appSettingsDescription": "회원가입, 언어, 새 계정 시간대의 전역 기본값이에요.", "registrationEnabled": "회원가입 허용", "registrationEnabledDescription": "끄면 새 사용자가 가입할 수 없어요.", - "registrationOpenHint": "회원가입이 열려 있어요 — 이 인스턴스에 접근할 수 있는 누구나 계정을 만들 수 있어요. 필요한 사람이 다 가입했으면 여기서 닫으세요.", + "registrationOpenHint": "회원가입이 열려 있어요. 이 인스턴스에 접근할 수 있는 누구나 계정을 만들 수 있어요. 필요한 사람이 다 가입했으면 여기서 닫으세요.", "defaultLanguage": "기본 언어", "defaultLanguageDescription": "새 사용자와 대체값으로 쓰여요.", "defaultUserTimezone": "새 계정의 기본 시간대", @@ -7270,7 +7270,7 @@ "integrationWebPush": "웹 푸시", "offlineGeoLabel": "위치 데이터", "offlineGeoEnabled": "오프라인 (GeoLite2)", - "offlineGeoFallback": "온라인 ({host}) — GeoLite2 데이터베이스를 마운트하고 GEOLITE2_DIR을 설정하세요", + "offlineGeoFallback": "온라인 ({host}). GeoLite2 데이터베이스를 마운트하고 GEOLITE2_DIR을 설정하세요", "offlineGeoOff": "꺼짐", "offlineGeoChosen": "온라인 ({host})", "apiGlobal": "API 엔드포인트와 API 토큰을 허용해요.", @@ -7363,7 +7363,7 @@ "createdToast": "초대를 만들었어요", "createError": "초대를 만들지 못했어요.", "tokenTitle": "초대 링크", - "tokenOnceHint": "지금만 복사할 수 있어요 — 링크를 복사하거나 QR 코드를 스캔하게 하세요.", + "tokenOnceHint": "지금만 복사할 수 있어요. 링크를 복사하거나 QR 코드를 스캔하게 하세요.", "hashExplainer": "링크의 해시만 저장하기 때문에 나중에 다시 보여줄 수 없어요. 잃어버렸다면 초대를 취소하고 새로 만드세요.", "copyLink": "링크 복사", "copiedToast": "링크를 복사했어요", @@ -7425,7 +7425,7 @@ "tokenName": "이름", "tokenPermissions": "권한", "tokenPermissionAll": "전체", - "tokenPermissionAllTooltip": "와일드카드 권한 — 이 토큰은 모든 API 경로를 호출할 수 있어요.", + "tokenPermissionAllTooltip": "와일드카드 권한: 이 토큰은 모든 API 경로를 호출할 수 있어요.", "tokenStatus": "상태", "tokenLastUsed": "마지막 사용", "tokenCreated": "생성", @@ -7564,7 +7564,7 @@ "forceLogout": "강제 로그아웃", "forceLogoutConfirmTitle": "{name} 강제 로그아웃할까요?", "forceLogoutConfirmBody": "이 사용자의 활성 세션이 모두 해제돼요. 모든 기기에서 다시 로그인해야 해요.", - "forceLogoutSuccess": "{name} — 세션 {count}개에서 로그아웃했어요", + "forceLogoutSuccess": "{name}: 세션 {count}개에서 로그아웃했어요", "forceLogoutFailed": "강제 로그아웃하지 못했어요", "cannotLogoutSelf": "자기 자신은 강제 로그아웃할 수 없어요", "emptyTitle": "이 화면에 사용자가 없어요", @@ -7603,7 +7603,7 @@ "app-logs": { "title": "앱 로그", "subtitle": "이 프로세스가 남긴 최근 구조화 wide-event를 실시간으로 봐요.", - "processNote": "앱 프로세스 로그만 보여줘요 — 워커 프로세스 로그는 Loki 연동을 설정하면 그쪽으로 가요.", + "processNote": "앱 프로세스 로그만 보여주며, 워커 프로세스 로그는 Loki 연동을 설정하면 그쪽으로 가요.", "filterTraceId": "추적 ID", "filterAction": "동작 포함…", "filterLevel": "레벨", @@ -7638,7 +7638,7 @@ "loading": "백업을 불러오는 중…", "loadError": "백업을 불러오지 못했어요.", "emptyTitle": "아직 백업이 없어요", - "emptyDescription": "백업은 매주 일요일 03:00에 자동으로 돌아요 — 지금 실행해서 첫 스냅샷을 만들 수도 있어요.", + "emptyDescription": "백업은 매주 일요일 03:00에 자동으로 돌아요. 지금 실행해서 첫 스냅샷을 만들 수도 있어요.", "colUser": "사용자", "colType": "유형", "typeWeeklyAuto": "주간 (자동)", @@ -7674,11 +7674,11 @@ "restoreTitle": "백업에서 복원", "restoreDescription": "{username}의 현재 데이터 전체를 {when} 스냅샷으로 바꿔요. 기존 측정, 약, 복용 기록, 기분 기록, 알림 채널, 푸시 구독, 대기 중인 Telegram 삭제 항목이 지워져요.", "restoreInstanceSettingsLabel": "인스턴스 설정도 함께 복원", - "restoreInstanceSettingsHint": "가입, MFA 필수 여부, 기본 언어, 모듈 사용 여부, 알림과 AI 설정 — 스냅샷에서 가져와 이 설치본의 모든 사용자에게 적용돼요. 이 계정만 복원하려면 선택하지 마세요.", + "restoreInstanceSettingsHint": "가입, MFA 필수 여부, 기본 언어, 모듈 사용 여부, 알림과 AI 설정은 스냅샷에서 가져와 이 설치본의 모든 사용자에게 적용돼요. 이 계정만 복원하려면 선택하지 마세요.", "restorePromptLabel": "계속하려면 RESTORE를 입력해 주세요", "previewTitle": "이 백업에 담긴 내용", "previewLoading": "내용을 읽는 중…", - "previewUnavailable": "내용을 읽지 못했어요 — 복원은 그래도 할 수 있어요.", + "previewUnavailable": "내용을 읽지 못했어요. 복원은 그래도 할 수 있어요.", "previewStillReading": "이 백업은 이전 버전에서 만들어져서 내용을 처음부터 끝까지 읽고 있어요. 기록이 많으면 시간이 좀 걸려요. 몇 분 뒤에 이 창을 다시 열면 내용이 보여요. 복원은 이것과 상관없이 할 수 있어요.", "previewEmpty": "파일에 기록이 없어요.", "previewOther": "기타 기록", @@ -7698,7 +7698,7 @@ "restoreInProgress": "복원 중…", "restoreSuccess": "복원을 마쳤어요", "restoreFailed": "복원하지 못했어요", - "restoreSkippedToast": "복원을 마쳤어요 — 되돌리지 못한 증상 연결: {links}", + "restoreSkippedToast": "복원을 마쳤어요. 되돌리지 못한 증상 연결: {links}", "restoreSkippedTitle": "복원하지 못한 연결: {links}", "restoreSkippedDescription": "파일이 이 설치본에 없는 기록을 가리키고 있어요. 나머지는 모두 복원했어요. 같은 목록이 감사 로그에도 남아 있어요.", "restoreSkippedLinks": "연결 {count}개", @@ -7721,7 +7721,7 @@ "restoreSkippedMedicationTarget": "약 목표 분석물", "restoreSkippedScheduleRevisionLink": "일정 개정 연결", "restoreSkippedAccountSetting": "계정 설정", - "restoreMissingTitle": "복원을 중단했어요 — 파일이 불완전해요", + "restoreMissingTitle": "복원을 중단했어요. 파일이 불완전해요", "restoreMissingDescription": "파일의 매니페스트에는 아래 항목이 들어 있다고 적혀 있는데 실제로는 없어요. 아무것도 바꾸지 않았어요. 복원은 해당 기록 전체를 갈아엎기 때문에, 파일에 없는 항목을 되돌리면 그 항목이 통째로 비워졌을 거예요.", "restoreMissingRemedy": "재해 복구용 스냅샷을 쓰거나, 계정을 다시 내보내서 새 파일을 업로드해 주세요. 매니페스트가 처음부터 '빠졌다'고 표시한 항목은 다른 경우라 정상적으로 복원돼요.", "restoreMissingDocuments": "문서", @@ -7845,7 +7845,7 @@ "completed": "완료", "failed": "실패" }, - "coverageDetail": "키 id와 개수만 보여줘요 — 키 자체는 절대 표시하지 않아요.", + "coverageDetail": "키 id와 개수만 보여줘요. 키 자체는 절대 표시하지 않아요.", "backupsTitle": "백업에 아직 필요한 키", "backupsDescription": "아래 백업 중 하나라도 표시하는 동안 폐기한 키는 계속 필요합니다.", "backupsStoredLine": "키 {key}: 저장된 복사본 {count}개, 가장 오래된 것은 {when}", @@ -7923,13 +7923,13 @@ "connectedSince": "연결 시작: {when}", "connected": "공용 AI 연결을 등록했어요", "disconnected": "공용 AI 연결을 해제했어요", - "error": "문제가 생겼어요 — 다시 시도해 주세요" + "error": "문제가 생겼어요. 다시 시도해 주세요" }, "failingJobs": { "title": "백그라운드 작업", "description": "재시도를 다 쓰고 포기한 작업이 있는 큐예요.", "none": "최근 {hours}시간 동안 실패한 작업이 없어요.", - "unavailable": "읽을 작업 큐가 없어요 — 이 배포본은 백그라운드 워커 없이 돌고 있어요.", + "unavailable": "읽을 작업 큐가 없어요. 이 배포본은 백그라운드 워커 없이 돌고 있어요.", "countOne": "실패 {count}건", "countFew": "실패 {count}건", "countOther": "실패 {count}건", @@ -8276,7 +8276,7 @@ }, "selfContextComplete": { "title": "자기 보고 완성", - "description": "자기 보고 항목 네 가지를 모두 채웠어요 — 코치가 상황을 알아요." + "description": "자기 보고 항목 네 가지를 모두 채웠어요. 코치가 상황을 알아요." }, "sleepLog7": { "title": "7일간 수면 기록", @@ -8307,7 +8307,7 @@ "dashboardCard": { "title": "최근 달성", "viewAll": "전체 보기", - "empty": "아직 업적이 없어요 — 기록을 이어가 첫 업적을 달성해 보세요." + "empty": "아직 업적이 없어요. 기록을 이어가 첫 업적을 달성해 보세요." } }, "notifications": { @@ -8490,7 +8490,7 @@ } }, "edit": { - "title": "목표 범위 편집 — {metric}", + "title": "목표 범위 편집: {metric}", "description": "차트·인사이트·진료용 리포트에 쓰이는 목표 범위를 조정해요. 값 단위는 {unit}.", "derivedHint": "이 카드는 다른 지표에서 계산돼요. 기준이 되는 목표(예: 혈압이나 체중)를 편집해 주세요.", "minLabel": "최소", @@ -8522,11 +8522,11 @@ "aboveTarget": "목표보다 {delta} {unit} 높음", "belowTarget": "목표보다 {delta} {unit} 낮음", "diastolic": "이완기", - "glucoseFasting": "혈당 — 공복", - "glucosePostprandial": "혈당 — 식후", - "glucoseRandom": "혈당 — 무작위", - "glucoseBedtime": "혈당 — 취침 전", - "glucoseUnspecified": "혈당 — 미지정", + "glucoseFasting": "혈당 (공복)", + "glucosePostprandial": "혈당 (식후)", + "glucoseRandom": "혈당 (무작위)", + "glucoseBedtime": "혈당 (취침 전)", + "glucoseUnspecified": "혈당 (미지정)", "status": { "underweight": "저체중", "normal": "정상", @@ -8589,11 +8589,11 @@ "errorUnknownAction": "알 수 없는 동작이에요.", "snoozeOneHour": "1시간", "snoozeThreeHours": "3시간", - "snoozedFor": "{name} — {duration} 동안 미뤘어요.", - "skipped": "{name} — 건너뛰었어요.", - "alreadyRecorded": "{name} — 이미 기록돼 있어요.", - "recordedAsTaken": "{name} — 복용으로 기록했어요.", - "confirmed": "{name} — 확인했어요.", + "snoozedFor": "{name}: {duration} 동안 미뤘어요.", + "skipped": "{name}: 건너뛰었어요.", + "alreadyRecorded": "{name}: 이미 기록돼 있어요.", + "recordedAsTaken": "{name}: 복용으로 기록했어요.", + "confirmed": "{name}: 확인했어요.", "genericConfirmed": "확인했어요.", "cancelled": "취소했어요.", "moodLogged": "기록함: {score}/5", @@ -8612,7 +8612,7 @@ "askMedicationName": "약을 지정해 주세요. 예: taken 라미프릴.", "medicationNotFoundExact": "약을 찾지 못했어요. HealthLog에 있는 이름 그대로 보내 주세요.", "helpHeader": "사용할 수 있는 명령:", - "helpBody": "/help — 이 도움말 보기\n/add — 복용 기록하기\n/start — 봇 시작하기\n\n텍스트 명령:\ntaken <이름> — 복용 확인\n\n알림 속 버튼:\n• 복용 — 복용 확인\n• 🕐 1h / 🕐 3h — 알림 미루기\n• ⏭ 건너뛰기 — 복용 건너뛰기\n• ✓ 확인 — 놓친 복용 확인", + "helpBody": "/help: 이 도움말 보기\n/add: 복용 기록하기\n/start: 봇 시작하기\n\n텍스트 명령:\ntaken <이름>: 복용 확인\n\n알림 속 버튼:\n• 복용: 복용 확인\n• 🕐 1h / 🕐 3h: 알림 미루기\n• ⏭ 건너뛰기: 복용 건너뛰기\n• ✓ 확인: 놓친 복용 확인", "measureValuePrompt": "값을 답장으로 보내면 기록해요(선택).", "buttonMeasureValue": "값…", "measureValueSaved": "측정값을 저장했어요.", @@ -8637,9 +8637,9 @@ }, "lowStockReminders": { "title": "재고 부족: {medName}", - "bodyToday": "{medName}: {units}개 남았어요 — 하루치도 안 돼요.", - "bodyReorder": "{medName}: {units}개 남았어요. {runsOutOn}쯤 소진돼요 — {reorderBy}까지 재주문하세요.", - "bodyLastDose": "{medName}: {units}개 남았어요 — 마지막 복용분이에요. {runsOutOn}쯤 소진돼요.", + "bodyToday": "{medName}: {units}개 남았어요. 하루치도 안 돼요.", + "bodyReorder": "{medName}: {units}개 남았어요. {runsOutOn}쯤 소진돼요. {reorderBy}까지 재주문하세요.", + "bodyLastDose": "{medName}: {units}개 남았어요. 마지막 복용분이에요. {runsOutOn}쯤 소진돼요.", "bodyExpired": "{medName}: 쓸 수 있는 재고가 없어요. {units}개가 유효기간 만료로 표시돼 있어요.", "bodyAsNeeded": "{medName}: {units}개만 남았어요. 다음에 필요하기 전에 재주문하세요." }, @@ -8666,11 +8666,11 @@ "questionConditions": "코치가 알아야 할 만성 질환이 있나요?", "questionFocus": "코치가 특별히 신경 써야 할 부분이 있나요?", "questionAllergies": "알레르기나 불내증이 있나요?", - "questionAboutMe": "코치에게 자신에 대해 조금 알려줄래요 — 생활 루틴, 목표, 상황 같은 것?" + "questionAboutMe": "코치에게 생활 루틴, 목표, 상황 같은 자신의 이야기를 조금 알려줄래요?" }, "clinicianView": { "title": "공유된 건강 기록", - "period": "보고 기간: {start} – {end}", + "period": "보고 기간: {start}–{end}", "expires": "이 링크는 {date}에 만료돼요.", "provenance": "본인이 직접 기록한 HealthLog 데이터에서 내보낸 읽기 전용 요약이에요. 값은 본인이 기록한 것이고 기기에서 동기화된 측정값이 섞여 있을 수 있어요. 임상 검사가 아니라 환자가 보고한 자료로 봐 주세요.", "labs": "검사 수치", @@ -8694,7 +8694,7 @@ "strain": "부하 점수", "score": "웰니스 점수" }, - "footer": "HealthLog에서 공유했어요 — 셀프 호스팅 개인 건강 기록 앱.", + "footer": "HealthLog(셀프 호스팅 개인 건강 기록 앱)에서 공유했어요.", "unlock": { "title": "암호 입력", "description": "이 공유 건강 기록은 보호돼 있어요. 전달받은 암호를 입력해 주세요.", @@ -8909,8 +8909,8 @@ "ariaUnknown": "아직 진행 중인 주기가 없어요", "caption": "주기 중", "firstPeriodCta": "첫 생리 기록하기", - "periodOverdue": "생리가 평소보다 늦어지고 있어요 — 다음 생리를 기록할 때까지 날짜 세기를 멈춰요.", - "periodOverdueDays": "생리가 평소보다 {days}일 늦어지고 있어요 — 다음 생리를 기록할 때까지 날짜 세기를 멈춰요.", + "periodOverdue": "생리가 평소보다 늦어지고 있어요. 다음 생리를 기록할 때까지 날짜 세기를 멈춰요.", + "periodOverdueDays": "생리가 평소보다 {days}일 늦어지고 있어요. 다음 생리를 기록할 때까지 날짜 세기를 멈춰요.", "logPeriodCta": "생리 기록" }, "calendar": { @@ -8922,7 +8922,7 @@ "prevMonth": "이전 달", "nextMonth": "다음 달", "loading": "캘린더를 불러오는 중…", - "learning": "주기를 배우는 중이에요 — 전체 주기를 세 번 이상 기록하면 가임기, 배란, 단계가 채워져요. 그때까지 캘린더에는 기록한 것만 보여요.", + "learning": "주기를 배우는 중이에요. 전체 주기를 세 번 이상 기록하면 가임기, 배란, 단계가 채워져요. 그때까지 캘린더에는 기록한 것만 보여요.", "legendSymptom": "증상", "legendOvulationConfirmed": "확인된 배란", "flowSpotting": "점상 출혈", @@ -8935,7 +8935,7 @@ "predictions": { "title": "다음에 올 일", "nextPeriod": "다음 생리", - "nextPeriodWindow": "{low} – {high}", + "nextPeriodWindow": "{low}–{high}", "fertileWindow": "가임기", "ovulation": "예상 배란일", "confidenceHigh": "높음", @@ -8944,7 +8944,7 @@ "stillLearning": "아직 배우는 중", "stillLearningBody": "전체 주기를 세 번 이상 기록하면 예측이 더 정확해져요. 그때까지는 대략적인 추정이에요.", "rawMode": "예측 꺼짐", - "rawModeBody": "예측을 꺼 두셨어요 — 예보 없이 기록한 데이터만 보여요.", + "rawModeBody": "예측을 꺼 두셨어요. 예보 없이 기록한 데이터만 보여요.", "none": "아직 예측이 없어요. 생리를 기록하고 시작해 보세요.", "ovulationConfirmed": "배란 (확인됨)" }, @@ -8977,7 +8977,7 @@ "symptoms": "증상", "temperature": "기초 체온", "temperatureDisturbed": "측정값을 방해받음으로 표시", - "temperatureDisturbedHint": "발열, 아픈 날, 음주, 늦은 측정 — 체온 평가에서 제외돼요.", + "temperatureDisturbedHint": "발열, 아픈 날, 음주, 늦은 측정은 체온 평가에서 제외돼요.", "ovulationTest": "배란 테스트", "mucus": "자궁경부 점액", "cervix": "자궁경부", @@ -9073,7 +9073,7 @@ "fieldInfo": { "bbt": "아침에 일어나기 전 가장 먼저 재는 안정 시 체온이에요. 배란 후에는 약 0.2~0.3°C 올라가요.", "bbtLabel": "기초 체온이 뭔가요?", - "mucus": "질 분비물은 주기에 따라 달라져요 — 건조하거나 끈적한 상태에서 크림 같은 상태로, 가장 가임력이 높은 날 무렵에는 물 같고 달걀흰자 같은 상태로 바뀌어요.", + "mucus": "질 분비물은 주기에 따라 달라져요. 건조하거나 끈적한 상태에서 크림 같은 상태로, 가장 가임력이 높은 날 무렵에는 물 같고 달걀흰자 같은 상태로 바뀌어요.", "mucusLabel": "자궁경부 점액이 뭔가요?", "ovulationTest": "LH 급상승을 잡아내는 가정용 소변 검사예요. LH는 배란 약 24~36h 전에 치솟는 호르몬이고, 양성이면 가장 가임력이 높은 시기라는 뜻이에요.", "ovulationTestLabel": "배란 테스트가 뭔가요?", @@ -9081,7 +9081,7 @@ "spottingLabel": "생리 사이 출혈이 뭔가요?", "pregnancyTest": "가정용 임신(hCG) 테스트 결과예요.", "pregnancyTestLabel": "임신 테스트가 뭔가요?", - "progesteroneTest": "배란이 일어났는지 확인하는 검사예요 — 배란 후에 프로게스테론이 올라가요.", + "progesteroneTest": "배란이 일어났는지 확인하는 검사예요. 배란 후에 프로게스테론이 올라가요.", "progesteroneTestLabel": "프로게스테론 검사가 뭔가요?", "intercourse": "이 날 성관계가 있었는지 기록해요.", "intercourseLabel": "성관계 항목은 무엇을 기록하나요?", @@ -9134,7 +9134,7 @@ "postpone": { "menuItem": "미루기…", "title": "예정일 미루기", - "description": "이번 예정일만 옮겨요 — 반복 주기는 그대로예요.", + "description": "이번 예정일만 옮겨요. 반복 주기는 그대로예요.", "chip": "+{days}일", "dateLabel": "새 날짜", "confirm": "미루기" @@ -9326,7 +9326,7 @@ "sourceRangePlaceholder": "예: 3.5 - 5.0 또는 < 5", "sourceRangeAdd": "+ 결과지의 범위 추가", "sourceRangeHint": "선택 사항이에요. 이 측정값에만 적용되고, 저장된 범위는 그대로예요.", - "sourceRangeUnparsed": "적은 그대로 뒀어요 — 수치 범위를 읽지 못했어요." + "sourceRangeUnparsed": "적은 그대로 뒀어요. 수치 범위를 읽지 못했어요." }, "backToLabs": "검사 결과로 돌아가기", "hasNote": "메모", @@ -9344,7 +9344,7 @@ "emptyDescription": "값을 추가하면 이 바이오마커의 추이를 볼 수 있어요.", "title": "바이오마커", "genericDescription": "기록 중인 검사 바이오마커예요. 측정값을 추가하면 참고 범위와 비교한 추이를 볼 수 있어요.", - "valuesTitle": "{marker} — 전체 측정값", + "valuesTitle": "{marker}: 전체 측정값", "valuesDescription": "이 바이오마커의 모든 측정값이에요. 항목을 바로 편집하거나 삭제할 수 있어요.", "backToMarker": "{marker} 화면으로 돌아가기", "latestResult": "최근 결과" @@ -9383,7 +9383,7 @@ "form": { "seedLabel": "자주 쓰는 마커에서 시작", "seedPlaceholder": "마커 선택 (선택 사항)", - "seedHint": "하나를 고르면 아래 항목이 채워져요 — 범위는 검사실에 맞게 조정하세요.", + "seedHint": "하나를 고르면 아래 항목이 채워져요. 범위는 검사실에 맞게 조정하세요.", "name": "이름", "namePlaceholder": "예: LDL 콜레스테롤", "unit": "단위", @@ -9397,7 +9397,7 @@ "upperPlaceholder": "상한값", "context": "설명", "contextPlaceholder": "이 마커에 대한 메모 (선택)", - "rangeHint": "하한과 상한 중 하나는 비워도 돼요 — 한쪽만 있는 범위가 돼요 (예: LDL < 116).", + "rangeHint": "하한과 상한 중 하나는 비워도 돼요. 한쪽만 있는 범위가 돼요 (예: LDL < 116).", "requiredError": "이름과 단위는 필수예요.", "rangeOrderError": "하한은 상한보다 클 수 없어요.", "save": "바이오마커 저장", @@ -9515,12 +9515,12 @@ "dateLabel": "날짜", "refLowLabel": "참고 하한", "refHighLabel": "참고 상한", - "newBiomarker": "새 바이오마커 — 새로 만들어요", + "newBiomarker": "새 바이오마커: 새로 만들어요", "linksExisting": "기존 {name} 항목에 연결돼요", "duplicateWarning": "같은 측정값이 이미 있어요", "lowConfidence": "이 값은 다시 확인해 주세요", "lowConfidenceBadge": "확신 낮음", - "valueUnreadable": "값을 읽지 못했어요 — 직접 입력해 주세요", + "valueUnreadable": "값을 읽지 못했어요. 직접 입력해 주세요", "saveSelected": "선택한 {count}개 저장", "discardAll": "모두 버리기", "savedToast": "검사 결과 {count}개를 저장했어요", @@ -9903,7 +9903,7 @@ }, "correlation": { "title": "어떻게 진행됐나", - "learning": "아직 학습 중이에요 — 며칠 더 기록하면 패턴이 보여요.", + "learning": "아직 학습 중이에요. 며칠 더 기록하면 패턴이 보여요.", "preOnsetTitle": "어떤 신호가 먼저 왔나", "preOnsetBody": "시작일로 표시하기 전에 기준값에서 벗어났던 신호예요.", "nadirTitle": "무엇이 달라졌나", @@ -9930,7 +9930,7 @@ "countOne": "이 기간에 에피소드를 1개 기록했어요.", "countOther": "이 기간에 에피소드를 {count}개 기록했어요.", "typicalGap": "평균 회복 시차: 몸이 나아지고 수치가 안정되기까지 {days}일.", - "typicalGapWithDriver": "평균 회복 시차: {days}일 — {vital} 안정보다 몸이 먼저 나아지는 편이에요.", + "typicalGapWithDriver": "평균 회복 시차: {days}일, {vital} 안정보다 몸이 먼저 나아지는 편이에요.", "typicalGapLearning": "종료된 에피소드가 몇 개 더 쌓이면 평균 회복 시차가 나와요.", "none": "이 기간에 기록한 에피소드가 없어요.", "analyze": "회복 시차 분석" @@ -9991,8 +9991,8 @@ "stop": "충분히 측정하고 있어요", "accepted": "알림을 설정했어요", "dismissed": "알겠어요, 다시 제안하지 않을게요", - "stopped": "알겠어요 — 알림 제안은 그만할게요", - "failed": "설정하지 못했어요 — 다시 시도해 주세요", + "stopped": "알겠어요. 알림 제안은 그만할게요", + "failed": "설정하지 못했어요. 다시 시도해 주세요", "cadence": { "weightDaily": "매일 비슷한 시간에 체중을 재세요", "bp722": "일주일 동안 하루 두 번 혈압을 재세요", @@ -10004,7 +10004,7 @@ "dismiss": "나중에", "applied": "추가했어요", "dismissed": "닫았어요", - "failed": "추가하지 못했어요 — 다시 시도해 주세요", + "failed": "추가하지 못했어요. 다시 시도해 주세요", "checkup": { "title": "건강검진 알림을 추가할까요?" }, @@ -10032,9 +10032,9 @@ "reviewPrefix": "점검: {when}", "accept": "계획 수락", "decline": "거절", - "accepted": "계획을 수락했어요 — 코치가 기억할게요.", + "accepted": "계획을 수락했어요. 코치가 기억할게요.", "declined": "제안을 거절했어요.", - "failed": "잘 안 됐어요 — 다시 시도해 주세요.", + "failed": "잘 안 됐어요. 다시 시도해 주세요.", "markMet": "목표 달성", "abandon": "계획 종료", "remove": "삭제", @@ -10055,8 +10055,8 @@ } }, "refusal": { - "outOfScope": "저는 기록에 있는 건강 지표만 도와드릴 수 있어요 — 측정값, 약, 기분, 추이 같은 것들이요. 그 범위 밖의 질문에는 답할 수 없어요.", - "promptInjection": "제 지침을 무시하게 만들려는 표현이 보였어요. 저는 HealthLog 코치이고 본인의 건강 데이터만 정리해 드려요 — 그 범위에 맞게 다시 질문해 주세요.", + "outOfScope": "저는 기록에 있는 건강 지표만 도와드릴 수 있어요. 측정값, 약, 기분, 추이 같은 것들이요. 그 범위 밖의 질문에는 답할 수 없어요.", + "promptInjection": "제 지침을 무시하게 만들려는 표현이 보였어요. 저는 HealthLog 코치이고 본인의 건강 데이터만 정리해 드려요. 그 범위에 맞게 다시 질문해 주세요.", "conversationPoisoned": "이 대화의 앞선 메시지에 제 지침을 무시하게 만드는 표현이 있어요. 새 대화를 시작해 주세요." }, "noRecordedData": "물어보신 내용에 대해 기록된 측정값이 없어서 수치를 알려드릴 수 없어요. 기록을 남기신 뒤에 다시 물어보시면 본인 수치로 답해 드릴게요.", @@ -10307,7 +10307,7 @@ "2": "많이 어려웠다", "3": "매우 많이 어려웠다" }, - "functionalOptionalHint": "선택 사항이에요 — 이 문항에 답하지 않아도 제출할 수 있어요.", + "functionalOptionalHint": "선택 사항이에요. 이 문항에 답하지 않아도 제출할 수 있어요.", "result": { "title": "내 결과", "totalLabel": "총점", @@ -10360,7 +10360,7 @@ "3": "잠이 들거나 계속 잠을 자는 것이 어려움, 또는 잠을 너무 많이 잠", "4": "피곤하다고 느끼거나 기운이 거의 없음", "5": "입맛이 없거나 과식을 함", - "6": "자신을 부정적으로 봄 — 혹은 자신이 실패자라고 느끼거나 자신 또는 가족을 실망시킴", + "6": "자신을 부정적으로 봄, 혹은 자신이 실패자라고 느끼거나 자신 또는 가족을 실망시킴", "7": "신문을 읽거나 텔레비전 보는 것과 같은 일에 집중하는 것이 어려움", "8": "다른 사람들이 주목할 정도로 너무 느리게 움직이거나 말을 함. 또는 반대로 평상시보다 많이 움직여서, 너무 안절부절 못하거나 들떠 있음", "9": "자신이 죽는 것이 더 낫다고 생각하거나 어떤 식으로든 자신을 해칠 것이라고 생각함" @@ -10497,7 +10497,7 @@ }, "openDetail": "자세히 보기", "historyLoadError": "검사 기록을 불러오지 못했어요", - "historyLoadErrorHint": "결과가 없다는 뜻은 아니에요 — 목록을 가져오지 못했을 뿐이에요. 다시 시도해 주세요.", + "historyLoadErrorHint": "결과가 없다는 뜻은 아니에요. 목록을 가져오지 못했을 뿐이에요. 다시 시도해 주세요.", "privacyNote": "답변은 암호화되어 저장되고, AI 코치에게는 전달되지 않아요." }, "records": { @@ -11186,7 +11186,7 @@ "genericDescription": "직접 기록하는 측정이에요. 값을 추가하면 시간에 따른 변화를 볼 수 있어요.", "emptyTitle": "아직 값이 없어요", "emptyDescription": "첫 값을 추가하면 이 지표를 차트로 볼 수 있어요.", - "valuesTitle": "{metric} — 전체 값", + "valuesTitle": "{metric}: 전체 값", "valuesDescription": "이 지표에 기록된 모든 값이에요.", "backToMetric": "돌아가기: {metric}" } @@ -11252,7 +11252,7 @@ "emptyTitle": "아직 동기화된 미량영양소 데이터가 없어요", "loadError": "영양소 데이터를 불러오지 못했어요" }, - "sparseNote": "여기 수치가 낮은 건 보통 결핍이 아니라 기록이 드물다는 뜻이에요 — Apple Health의 하루 합계는 앱이 기록한 양만 반영하고, 전체 식이 섭취량은 아니에요." + "sparseNote": "여기 수치가 낮은 건 보통 결핍이 아니라 기록이 드물다는 뜻이에요. Apple Health의 하루 합계는 앱이 기록한 양만 반영하고, 전체 식이 섭취량은 아니에요." }, "daily": { "line": { @@ -11267,39 +11267,39 @@ "doseWindow": { "title": "복약 시간", "body": "곧 복용할 시간이에요.", - "bodyNamed": "{name} — 곧 복용할 시간이에요.", + "bodyNamed": "{name}: 곧 복용할 시간이에요.", "overdueTitle": "복약 시간 지남", "overdueBody": "복용 시간이 지났어요.", - "overdueBodyNamed": "{name} — 복용 시간이 지났어요." + "overdueBodyNamed": "{name}: 복용 시간이 지났어요." }, "preventiveCare": { "title": "건강검진 시기", - "body": "{label} — 받을 때가 됐어요.", + "body": "{label}: 받을 때가 됐어요.", "bodyManyNamed": "받을 때가 된 건강검진: {labels}" }, "syncIssue": { "title": "동기화 확인이 필요해요", - "body": "{integration} 동기화가 멈췄어요 — 데이터를 최신으로 유지하려면 다시 연결해 주세요." + "body": "{integration} 동기화가 멈췄어요. 데이터를 최신으로 유지하려면 다시 연결해 주세요." }, "coachCheckin": { "title": "계획을 점검할 때예요", - "body": "이 계획을 세운 지 일주일쯤 됐어요 — 계속할지, 조정할지, 놓아줄지 정해 보세요. 어느 쪽이든 부담 갖지 않아도 돼요.", - "bodyPlan": "일주일쯤 전에 이렇게 정했어요: “{plan}”. 계속할지, 조정할지, 놓아줄지 정해 보세요 — 어느 쪽이든 부담 갖지 않아도 돼요.", + "body": "이 계획을 세운 지 일주일쯤 됐어요. 계속할지, 조정할지, 놓아줄지 정해 보세요. 어느 쪽이든 부담 갖지 않아도 돼요.", + "bodyPlan": "일주일쯤 전에 이렇게 정했어요: “{plan}”. 계속할지, 조정할지, 놓아줄지 정해 보세요. 어느 쪽이든 부담 갖지 않아도 돼요.", "adjustPrompt": "점검 계획을 조정하고 싶어요.", "adjustPromptPlan": "이 계획을 조정하고 싶어요: “{plan}”" }, "tensionWindow": { "title": "오늘 긴장이 있었을 수 있어요", "body": { - "morning": "오늘 아침 가만히 있는 동안에도 심박수가 안정 시 기준값 위로 한동안 유지됐어요 — 긴장이 있었을 수 있어요.", - "afternoon": "오늘 오후 가만히 있는 동안에도 심박수가 안정 시 기준값 위로 한동안 유지됐어요 — 긴장이 있었을 수 있어요.", - "evening": "오늘 저녁 가만히 있는 동안에도 심박수가 안정 시 기준값 위로 한동안 유지됐어요 — 긴장이 있었을 수 있어요.", - "night": "밤사이 가만히 있는 동안에도 심박수가 안정 시 기준값 위로 한동안 유지됐어요 — 긴장이 있었을 수 있어요." + "morning": "오늘 아침 가만히 있는 동안에도 심박수가 안정 시 기준값 위로 한동안 유지됐어요. 긴장이 있었을 수 있어요.", + "afternoon": "오늘 오후 가만히 있는 동안에도 심박수가 안정 시 기준값 위로 한동안 유지됐어요. 긴장이 있었을 수 있어요.", + "evening": "오늘 저녁 가만히 있는 동안에도 심박수가 안정 시 기준값 위로 한동안 유지됐어요. 긴장이 있었을 수 있어요.", + "night": "밤사이 가만히 있는 동안에도 심박수가 안정 시 기준값 위로 한동안 유지됐어요. 긴장이 있었을 수 있어요." } }, "ecgNewRecording": { "title": "새 심전도 기록", - "body": "기기가 새 심전도를 기록했어요 — 지금 볼 수 있어요.", + "body": "기기가 새 심전도를 기록했어요. 지금 볼 수 있어요.", "bodyVerdict": "기기가 새 심전도를 기록하고 이렇게 알렸어요: {verdict}.", "verdict": { "irregular": "불규칙한 리듬 가능성", @@ -11319,9 +11319,9 @@ }, "upcomingVisit": { "title": "다가오는 예약", - "bodyToday": "{what} — 오늘", - "bodyTomorrow": "{what} — 내일", - "bodyDayAfterTomorrow": "{what} — 모레" + "bodyToday": "{what}: 오늘", + "bodyTomorrow": "{what}: 내일", + "bodyDayAfterTomorrow": "{what}: 모레" } }, "action": { @@ -11379,7 +11379,7 @@ }, "record": { "title": "{metric} 최고 기록", - "body": "오늘 {metric} 개인 최고 기록이에요 — 조용히 적어 뒀어요, 하실 일은 없어요." + "body": "오늘 {metric} 개인 최고 기록이에요. 조용히 적어 뒀어요, 하실 일은 없어요." }, "returnToBaseline": { "title": "범위 복귀: {metric}", @@ -11541,7 +11541,7 @@ "canManage": "열람, 추가, 그리고 있는 내용의 수정·삭제까지 가능", "entireRecord": "기록 전체가 대상", "sections": "대상: {sections}", - "noSections": "대상 없음 — 이 권한으로는 기록의 어떤 부분도 열 수 없어요", + "noSections": "대상 없음: 이 권한으로는 기록의 어떤 부분도 열 수 없어요", "invited": "초대", "accepted": "수락", "expires": "만료", @@ -11983,7 +11983,7 @@ "created": "진료를 저장했어요", "updated": "진료를 수정했어요", "saveFailed": "진료를 저장하지 못했어요.", - "checkupNotClosed": "진료를 저장했어요. 건강검진은 열린 채로 남아요 — 권한이 거기까지는 미치지 않아요.", + "checkupNotClosed": "진료를 저장했어요. 건강검진은 열린 채로 남아요. 권한이 거기까지는 미치지 않아요.", "status": { "planned": "예정", "done": "방문함", @@ -12000,7 +12000,7 @@ "dateDerivesStatusHint": "미래 날짜는 잡아 둔 예약으로 처리돼요.", "status": "상태", "practitioner": "병원 또는 의사", - "practitionerHint": "선택 — 이름은 나중에 추가해도 돼요.", + "practitionerHint": "선택: 이름은 나중에 추가해도 돼요.", "practitionerNone": "지정 안 함", "practitionerSearch": "이름이나 병원 검색", "practitionerNoMatch": "항목을 찾지 못했어요.", @@ -12058,7 +12058,7 @@ }, "practitioners": { "title": "병원과 의사", - "description": "나만의 주소록이에요 — 병원을 한 번만 입력하면 어디서든 골라 쓸 수 있어요.", + "description": "나만의 주소록이에요. 병원을 한 번만 입력하면 어디서든 골라 쓸 수 있어요.", "linkLabel": "주소록", "searchPlaceholder": "이름, 병원, 진료과 검색", "loadError": "주소록을 불러오지 못했어요.", @@ -12260,15 +12260,11 @@ "rugLegend": "축 아래 점은 기록이 있는 날을, 고리는 눈에 띄는 날을 표시해요.", "sheetExpand": "전체 높이로 펼치기", "sheetShrink": "줄이기", - "usualLabel": "직전 30일", "valuesLegend": "점은 이 날, 막대는 직전 30일", "valuesAllOne": "모든 수치", "valuesAllFew": "수치 {count}개 모두", "valuesAllOther": "수치 {count}개 모두", "valuesFewer": "수치 줄여 보기", - "countValuesOne": "수치 1개", - "countValuesFew": "수치 {count}개", - "countValuesOther": "수치 {count}개", "countEntriesOne": "기록 1개", "countEntriesFew": "기록 {count}개", "countEntriesOther": "기록 {count}개", @@ -12308,7 +12304,6 @@ "subtitle": "언제 무엇이 있었는지, 내 수치와 나란히.", "standing": "지속", "startUnknown": "시작일 미상", - "openDay": "{date} 열기", "zoom": { "all": "전체", "year": "12개월", diff --git a/messages/pl.json b/messages/pl.json index 8758cf2af..00a3a665b 100644 --- a/messages/pl.json +++ b/messages/pl.json @@ -167,7 +167,7 @@ "anamnesisShiftSchedule": "Harmonogram pracy", "anamnesisColFact": "Pozycja profilu", "anamnesisColValue": "Zapisana wartość", - "subtitle": "HealthLog — Osobisty raport zdrowotny", + "subtitle": "HealthLog: osobisty raport zdrowotny", "patient": "Pacjent", "dateOfBirth": "Data urodzenia", "gender": "Płeć", @@ -177,18 +177,18 @@ "height": "Wzrost", "period": "Okres raportu", "createdOn": "Utworzono", - "vitalsTitle": "Parametry życiowe — Podsumowanie", + "vitalsTitle": "Parametry życiowe: podsumowanie", "colParameter": "Parametr", "colCurrent": "Aktualny", "colAvgPeriod": "Śr. okresu", "colMin": "Min", "colMax": "Maks", "colN": "n", - "bpClassificationTitle": "Ciśnienie tętnicze — klasyfikacja ESH (2023)", + "bpClassificationTitle": "Ciśnienie tętnicze: klasyfikacja ESH (2023)", "avgBp": "Średnie ciśnienie tętnicze", "classification": "Klasyfikacja", "bmiTitle": "Wskaźnik masy ciała (BMI)", - "bmiRow": "BMI:{bmi} kg/m² — Classification: {class} (WHO)", + "bmiRow": "BMI:{bmi} kg/m², Classification: {class} (WHO)", "complianceTitle": "Przestrzeganie leków", "glp1Title": "Terapia GLP-1", "glp1WeightSummary": "Waga w okresie raportu: {start} kg → {end} kg ({delta} kg)", @@ -236,8 +236,8 @@ "typeGlucoseRandom": "Glukoza (dowolna)", "typeGlucoseBedtime": "Glukoza (przed snem)", "typeGlucoseUnspecified": "Glukoza (bez oznaczenia)", - "glucoseClassificationTitle": "Glikemia — zakresy referencyjne (ADA 2024 / DDG)", - "glucoseRow": "{label}: śr. {avg} {unit} (cel {rangeMin}–{rangeMax}) — {class}", + "glucoseClassificationTitle": "Glikemia: zakresy referencyjne (ADA 2024 / DDG)", + "glucoseRow": "{label}: śr. {avg} {unit} (cel {rangeMin}–{rangeMax}), {class}", "glucoseInTarget": "w celu", "glucoseBelowTarget": "poniżej celu", "glucoseAboveTarget": "powyżej celu", @@ -289,7 +289,7 @@ "gmi": "Wskaźnik zarządzania glukozą (GMI)", "eA1c": "Szacowane HbA1c", "cv": "Zmienność (CV%)", - "spotCaveat": "To szacunki z pojedynczych pomiarów, nie profil z monitora ciągłego — czytaj je jako kierunek zmian, a nie kliniczny werdykt." + "spotCaveat": "To szacunki z pojedynczych pomiarów, nie profil z monitora ciągłego. Czytaj je jako kierunek zmian, a nie kliniczny werdykt." }, "illnessTitle": "Schorzenia i choroby", "illnessOngoing": "Trwająca", @@ -378,12 +378,12 @@ "backToDashboard": "Powrót do panelu" }, "offlineBanner": { - "message": "Brak połączenia — zmian nie można zapisać, dopóki nie wrócisz online.", - "saveFailed": "Nie udało się zapisać — jesteś offline. Spróbuj ponownie, gdy wrócisz online.", + "message": "Brak połączenia: zmian nie można zapisać, dopóki nie wrócisz online.", + "saveFailed": "Nie udało się zapisać, jesteś offline. Spróbuj ponownie, gdy wrócisz online.", "showingCached": "Wyświetlane są ostatnio zsynchronizowane dane." }, "demoBanner": { - "message": "Tryb demo — zmiany nie są zapisywane." + "message": "Tryb demo: zmiany nie są zapisywane." }, "nav": { "dashboard": "Panel", @@ -458,7 +458,7 @@ "hasAccount": "Masz już konto?", "loginFailed": "Logowanie nie powiodło się", "registerFailed": "Rejestracja nie powiodła się", - "invitedBanner": "Otrzymano zaproszenie — utwórz konto, nawet jeśli rejestracja jest zamknięta.", + "invitedBanner": "Otrzymano zaproszenie. Utwórz konto, nawet jeśli rejestracja jest zamknięta.", "alreadySignedIn": { "title": "Masz już zalogowaną sesję", "body": "Masz zalogowaną sesję jako {username}. Zaproszenie tworzy nowe konto. Wyloguj się, aby je przyjąć.", @@ -775,7 +775,7 @@ "formReset": "Resetuj formularz", "saveError": "Błąd zapisu", "duplicateTimestamp": "Pomiar tego typu już istnieje dla wybranej daty.", - "serverOwnedSource": "Wartości z połączonego źródła nie można edytować — znacznik czasu i notatka pozostają edytowalne.", + "serverOwnedSource": "Wartości z połączonego źródła nie można edytować. Znacznik czasu i notatka pozostają edytowalne.", "deleteError": "Błąd usuwania", "deletedToast": "Pomiar usunięty", "restoredToast": "Pomiar przywrócony", @@ -875,7 +875,7 @@ }, "metricCatalog": { "title": "Co HealthLog potrafi śledzić", - "description": "Wszystkie obszary metryk obsługiwane przez HealthLog — również te, dla których nie masz jeszcze danych — oraz co je dostarcza.", + "description": "Wszystkie obszary metryk obsługiwane przez HealthLog (również te, dla których nie masz jeszcze danych) oraz co je dostarcza.", "statusPresent": "Śledzone", "statusAbsent": "Jeszcze nieśledzone", "statusModuleOff": "Wyłączone", @@ -883,11 +883,11 @@ "connectCta": "Połącz źródło", "viewCta": "Zobacz", "ecg": { - "source": "Jednoodprowadzeniowe zapisy EKG z kompatybilnego zegarka — obecnie Withings ScanWatch — synchronizowane automatycznie." + "source": "Jednoodprowadzeniowe zapisy EKG z kompatybilnego zegarka (obecnie Withings ScanWatch), synchronizowane automatycznie." }, "watchdog": { "title": "Automatyczny nadzór", - "description": "HealthLog dyskretnie obserwuje też dane w tle — powiadomienia o nieregularnym rytmie i zaburzeniach oddychania z podłączonego zegarka, alerty o odchyleniu od Twojej wartości bazowej oraz zauważalne zmiany między dwoma ostatnimi panelami badań laboratoryjnych — i pokazuje kartę tylko wtedy, gdy coś zwraca uwagę. Jeśli podłączone jest co najmniej jedno z tych źródeł, brak karty to dobry znak, a nie brakująca funkcja; jeśli żadne nie jest jeszcze podłączone, po prostu nic nie jest jeszcze monitorowane." + "description": "HealthLog dyskretnie obserwuje też dane w tle (powiadomienia o nieregularnym rytmie i zaburzeniach oddychania z podłączonego zegarka, alerty o odchyleniu od Twojej wartości bazowej oraz zauważalne zmiany między dwoma ostatnimi panelami badań laboratoryjnych) i pokazuje kartę tylko wtedy, gdy coś zwraca uwagę. Jeśli podłączone jest co najmniej jedno z tych źródeł, brak karty to dobry znak, a nie brakująca funkcja; jeśli żadne nie jest jeszcze podłączone, po prostu nic nie jest jeszcze monitorowane." } }, "mood": { @@ -1044,7 +1044,7 @@ "archive": "Archiwizuj", "restore": "Przywróć", "archivedTitle": "Zarchiwizowane tagi", - "archivedDescription": "Zarchiwizowane tagi pozostają w Twoich wcześniejszych wpisach — znikają tylko z wyboru.", + "archivedDescription": "Zarchiwizowane tagi pozostają w Twoich wcześniejszych wpisach, znikają tylko z wyboru.", "archivedEmpty": "Nic nie zarchiwizowano.", "purgeTitle": "Usunąć tag na zawsze?", "purgeBody": "Tag zostanie usunięty z {count} wcześniejszych wpisów. Tej operacji nie można cofnąć.", @@ -1069,7 +1069,7 @@ }, "sectionMoreTags": "Więcej tagów", "sectionNoteDetails": "Notatka i szczegóły", - "quickTagsHelp": "Twoje częste tagi — jedno dotknięcie", + "quickTagsHelp": "Twoje częste tagi: jedno dotknięcie", "quickTagsExpand": "Więcej", "loadError": "Nie udało się załadować wpisów nastroju.", "sectionLevelA": "Samopoczucie", @@ -1247,8 +1247,8 @@ "dialogDescription": "Te leki są teraz do przyjęcia. Potwierdź, aby zarejestrować je wszystkie jako przyjęte.", "confirm": "Przyjmij wszystkie ({count})", "successToast": "Zarejestrowano przyjęcia: {count}", - "partialToast": "Zarejestrowano: {taken}, nieudane: {failed} – spróbuj ponownie", - "failedToast": "Nie zarejestrowano żadnego przyjęcia – spróbuj ponownie" + "partialToast": "Zarejestrowano: {taken}, nieudane: {failed}. Spróbuj ponownie", + "failedToast": "Nie zarejestrowano żadnego przyjęcia. Spróbuj ponownie" }, "logIntake": { "dialogTitle": "Zarejestruj przyjęcie", @@ -1346,10 +1346,10 @@ "skipped": "Pominięte", "intakeToastTaken": "{name} oznaczone jako przyjęte", "intakeToastSkipped": "{name} pominięte", - "intakeToastFailed": "Nie udało się zapisać {name} — spróbuj ponownie", + "intakeToastFailed": "Nie udało się zapisać {name}. Spróbuj ponownie", "intakeUndo": "Cofnij", "intakeUndone": "Wpis cofnięty", - "intakeUndoFailed": "Nie udało się cofnąć — popraw w historii", + "intakeUndoFailed": "Nie udało się cofnąć. Popraw w historii", "glp1LastInjection": "{label}", "glp1NextInjectionDays": "{label} (za {days} dni)", "glp1NextInjectionToday": "dziś", @@ -1431,10 +1431,10 @@ "error": { "empty": "Najpierw wpisz opis.", "tooLong": "Utrzymuj opis poniżej 2000 znaków.", - "rateLimit": "Zbyt wiele żądań — poczekaj chwilę i spróbuj ponownie.", - "noProvider": "Brak skonfigurowanego dostawcy AI — skonfiguruj go w Ustawieniach.", - "budget": "Osiągnięto dzienny limit AI — spróbuj jutro.", - "network": "Nie udało się połączyć z dostawcą AI — spróbuj ponownie.", + "rateLimit": "Zbyt wiele żądań. Poczekaj chwilę i spróbuj ponownie.", + "noProvider": "Brak skonfigurowanego dostawcy AI. Skonfiguruj go w Ustawieniach.", + "budget": "Osiągnięto dzienny limit AI. Spróbuj jutro.", + "network": "Nie udało się połączyć z dostawcą AI. Spróbuj ponownie.", "consent": "Odczyt Twojego opisu przez AI wymaga najpierw Twojej zgody.", "unavailable": "Odczyt opisów przez AI jest tu teraz niedostępny." } @@ -1450,7 +1450,7 @@ "everyNMonths": "Co N miesięcy w określonym dniu", "yearly": "Raz w roku", "rolling": "Co N dni od ostatniego przyjęcia (elastycznie)", - "rollingExplainer": "Liczy od ostatniego zarejestrowanego przyjęcia — wstrzymuje się, jeśli pominiesz dawkę.", + "rollingExplainer": "Liczy od ostatniego zarejestrowanego przyjęcia i wstrzymuje się, jeśli pominiesz dawkę.", "oneShot": "Dawka jednorazowa" }, "weekdays": { @@ -1508,7 +1508,7 @@ "night": "Noc" }, "max": { - "reached": "Osiągnięto maksimum — usuń jedną godzinę przed dodaniem kolejnej." + "reached": "Osiągnięto maksimum. Usuń jedną godzinę przed dodaniem kolejnej." } }, "courseWindow": { @@ -1558,7 +1558,7 @@ }, "step3": { "title": "Jaka jest dawka?", - "subline": "Tabletka, wziew, kropla — w zależności od formy.", + "subline": "Tabletka, wziew, kropla: w zależności od formy.", "amountLabel": "Ilość", "amountPlaceholder": "np. 5", "unitLabel": "Jednostka", @@ -1584,7 +1584,7 @@ }, "dosesPerUnitLabel": "Dawki na jednostkę", "dosesPerUnitPlaceholder": "np. 4", - "dosesPerUnitHint": "Dawki na wstrzykiwacz / fiolkę — zostaw puste, aby nie śledzić zapasów.", + "dosesPerUnitHint": "Dawki na wstrzykiwacz / fiolkę. Zostaw puste, aby nie śledzić zapasów.", "short": "Dawka", "unitsPerDoseLabel": "Jednostki na dawkę", "unitsPerDoseHint": "np. 2 tabletki po 2 mg na dawkę 4 mg lub ½ tabletki przy dzielonej dawce" @@ -1596,7 +1596,7 @@ }, "step5": { "title": "Jak często go przyjmujesz?", - "subline": "Wybierz częstotliwość — szczegóły w następnym kroku.", + "subline": "Wybierz częstotliwość, szczegóły w następnym kroku.", "short": "Częstotliwość" }, "step6": { @@ -1618,7 +1618,7 @@ }, "step7": { "title": "Kiedy go przyjmujesz?", - "subline": "Jedna lub więcej pór dnia — przypomnienia opierają się na tej liście.", + "subline": "Jedna lub więcej pór dnia. Przypomnienia opierają się na tej liście.", "presetsLabel": "Ustawienia wstępne pory dnia", "presets": { "morning": "Rano", @@ -1626,7 +1626,7 @@ "evening": "Wieczór", "night": "Noc" }, - "overrideHint": "Opcjonalnie — ustaw inną dawkę lub liczbę jednostek tylko dla tej pory. Pozostaw puste, aby użyć wartości domyślnej leku.", + "overrideHint": "Opcjonalnie: ustaw inną dawkę lub liczbę jednostek tylko dla tej pory. Pozostaw puste, aby użyć wartości domyślnej leku.", "doseOverrideLabel": "Dawka dla tej pory (opcjonalnie)", "doseOverridePlaceholder": "np. pół tabletki", "unitsOverrideLabel": "Jednostki zużyte o tej porze", @@ -1634,11 +1634,11 @@ "short": "Godziny" }, "step8": { - "title": "Gotowe — czy HealthLog ma Ci przypominać?", + "title": "Gotowe. Czy HealthLog ma Ci przypominać?", "subline": "Sprawdź wszystko poniżej przed zapisaniem.", "remindersLabel": "Przypomnienia włączone", - "remindersDescription": "Push, Telegram lub ntfy — w zależności od ustawień.", - "noChannelHint": "Przypomnienia wymagają kanału powiadomień — obecnie żaden nie jest aktywny.", + "remindersDescription": "Push, Telegram lub ntfy, w zależności od ustawień.", + "noChannelHint": "Przypomnienia wymagają kanału powiadomień, a obecnie żaden nie jest aktywny.", "noChannelHintLink": "Skonfiguruj powiadomienia", "short": "Gotowe" } @@ -1687,7 +1687,7 @@ }, "asNeeded": { "label": "W razie potrzeby", - "description": "Bez stałego planu — zapisz przyjęcie, gdy go potrzebujesz (np. lek przeciwbólowy)." + "description": "Bez stałego planu: zapisz przyjęcie, gdy go potrzebujesz (np. lek przeciwbólowy)." } }, "summary": { @@ -1722,7 +1722,7 @@ } }, "errors": { - "submitFailed": "Nie udało się zapisać leku — spróbuj ponownie." + "submitFailed": "Nie udało się zapisać leku. Spróbuj ponownie." } }, "doseStrength": { @@ -1742,7 +1742,7 @@ }, "injectionSiteBodyOutlineAriaLabel": "Sylwetka ciała", "injectionSitePickerAriaLabel": "Wybór miejsca iniekcji", - "injectionSiteRecommendedAriaLabel": "{site} — zalecane następne miejsce", + "injectionSiteRecommendedAriaLabel": "{site}, zalecane następne miejsce", "injectionSiteLegendAriaLabel": "Legenda oznaczeń", "injectionSiteLegendRecommended": "Zalecane następne miejsce", "injectionSiteLegendLastUsed": "Ostatnio użyte miejsce", @@ -1830,7 +1830,7 @@ "cadence": { "oneShotOn": "Dawka jednorazowa w dniu {date}.", "oneShotPending": "Dawka jednorazowa oczekuje.", - "asNeeded": "W razie potrzeby — bez stałego planu." + "asNeeded": "W razie potrzeby, bez stałego planu." }, "intake": { "title": "Historia przyjęć", @@ -1857,7 +1857,7 @@ "dialogTitle": "Edytuj przyjęcie", "takenAtLabel": "Przyjęto o", "scheduledForHint": "Zaplanowano: {dateTime}", - "farFromScheduledWarning": "Znacznie odbiega od zaplanowanego terminu — sprawdź datę.", + "farFromScheduledWarning": "Znacznie odbiega od zaplanowanego terminu. Sprawdź datę.", "skippedLabel": "Pominięto", "save": "Zapisz", "cancel": "Anuluj", @@ -1901,10 +1901,10 @@ }, "addDialog": { "title": "Dodaj przyjęcie", - "description": "Zarejestruj dawkę — także wstecznie lub poza planem.", + "description": "Zarejestruj dawkę, także wstecznie lub poza planem.", "takenAtLabel": "Przyjęto o", "skippedLabel": "Pominięte", - "nudgeHint": "Blisko slotu {slot} — przy zapisie zapytamy, czy przypisać.", + "nudgeHint": "Blisko slotu {slot}. Przy zapisie zapytamy, czy przypisać.", "cancel": "Anuluj", "submit": "Zapisz" }, @@ -1953,7 +1953,7 @@ }, "codes": { "label": "Kody kliniczne (ATC / RxNorm)", - "note": "Opcjonalne. Używane w eksporcie FHIR dokumentacji zdrowotnej. Kody są zapisywane dokładnie tak, jak wprowadzone — nigdy nie są zgadywane.", + "note": "Opcjonalne. Używane w eksporcie FHIR dokumentacji zdrowotnej. Kody są zapisywane dokładnie tak, jak wprowadzone, i nigdy nie są zgadywane.", "atcLabel": "ATC", "rxNormLabel": "RxNorm", "saved": "Kody kliniczne zapisane", @@ -1973,7 +1973,7 @@ "title": "Zakończ lek", "helper": "Zatrzymuje przypomnienia i oznacza lek jako zakończony. Historia pozostaje widoczna.", "button": "Zakończ", - "dialogTitle": "Zakończ {name} — zatrzymuje przypomnienia, historia pozostaje widoczna", + "dialogTitle": "Zakończ {name}: zatrzymuje przypomnienia, historia pozostaje widoczna", "dialogBody": "Brak kolejnych przypomnień. Stare wpisy pozostają na osi czasu.", "toast": "Lek zakończony", "failed": "Nie udało się zakończyć leku." @@ -2011,7 +2011,7 @@ "copyFailed": "Nie udało się skopiować.", "tokenCopied": "Token skopiowany", "copyToken": "Kopiuj token", - "mintedHint": "Skopiuj ten token teraz — jest pokazywany tylko raz." + "mintedHint": "Skopiuj ten token teraz. Jest pokazywany tylko raz." }, "advanced": { "dataPortability": { @@ -2051,9 +2051,9 @@ "statusTitle": "Status", "nextDoseLabel": "Następna dawka", "nextDoseNone": "Brak nadchodzącej dawki.", - "nextDoseAsNeeded": "W razie potrzeby — brak zaplanowanej dawki.", + "nextDoseAsNeeded": "W razie potrzeby, brak zaplanowanej dawki.", "nextDoseNotTracked": "Przyjęcia nie są rejestrowane, tylko zapis.", - "pausedHint": "Wstrzymano — brak przypomnień.", + "pausedHint": "Wstrzymano, brak przypomnień.", "reminderLabel": "Przypomnienie", "reminderOn": "Włączone", "reminderOff": "Wyłączone", @@ -2124,7 +2124,7 @@ "packagingDefaultPack": "Domyślny rozmiar opakowania: {units} jedn.", "packagingNoDefaultPack": "Brak domyślnego rozmiaru opakowania", "packagingEdit": "Edytuj", - "packagingDescription": "Określ, ile jednostek zużywa jedna dawka i jaki jest typowy rozmiar nowego opakowania — np. po zmianie producenta z innym blistrem.", + "packagingDescription": "Określ, ile jednostek zużywa jedna dawka i jaki jest typowy rozmiar nowego opakowania, np. po zmianie producenta z innym blistrem.", "packagingUnitsPerDoseLabel": "Jednostki na dawkę", "packagingUnitsPerDoseHelper": "Np. dwie tabletki 2 mg na dawkę 4 mg lub 1,5 dla półtorej (powyżej 0, do 100). Zarejestrowane dawki pozostają bez zmian.", "packagingDefaultPackLabel": "Domyślny rozmiar opakowania (jednostki)", @@ -2175,11 +2175,11 @@ "hideEras": "Ukryj wcześniejsze okresy", "addEra": "Dodaj wcześniejszy okres", "addEraTitle": "Dodaj wcześniejszy okres", - "addEraDescription": "Zapisz, o których godzinach ten lek był wcześniej przyjmowany — np. zanim zmieniono go tutaj.", + "addEraDescription": "Zapisz, o których godzinach ten lek był wcześniej przyjmowany, np. zanim zmieniono go tutaj.", "editAria": "Edytuj okres", "editEraTitle": "Edytuj okres", "editEraDescription": "Dostosuj godziny przyjmowania i zakres dat tego okresu.", - "archivedEditHint": "Ten okres został zapisany automatycznie — Twoja zmiana koryguje zarejestrowaną historię; oryginał pozostaje wewnętrznie jako zapis.", + "archivedEditHint": "Ten okres został zapisany automatycznie. Twoja zmiana koryguje zarejestrowaną historię; oryginał pozostaje wewnętrznie jako zapis.", "updatedToast": "Okres zaktualizowany", "updateError": "Nie udało się zaktualizować okresu. Nie może nakładać się na inne okresy i musi kończyć się przed aktualnym planem.", "timesLabel": "Godziny przyjmowania", @@ -2205,7 +2205,7 @@ "saved": "Zapisano harmonogram", "failed": "Nie udało się zapisać harmonogramu", "window": { - "intro": "Dla każdej dawki ustal, kiedy przyjęcie jest jeszcze punktualne — dokładna godzina (±1 h) lub własne okno, np. 07:00–09:00.", + "intro": "Dla każdej dawki ustal, kiedy przyjęcie jest jeszcze punktualne: dokładna godzina (±1 h) lub własne okno, np. 07:00–09:00.", "explicitToggle": "Własne okno", "startLabel": "Początek okna", "endLabel": "Koniec okna", @@ -2218,10 +2218,10 @@ } }, "logInjectionSiteTitle": "Zarejestruj miejsce iniekcji", - "logInjectionSiteDescription": "Gdzie wstrzyknięto {name}? Opcjonalnie — możesz to pominąć.", + "logInjectionSiteDescription": "Gdzie wstrzyknięto {name}? Opcjonalnie, możesz to pominąć.", "logInjectionSiteSkip": "Pomiń", "logInjectionSiteConfirm": "Zapisz miejsce", - "logInjectionSiteNoneAvailable": "Brak dostępnego miejsca iniekcji — wszystkie miejsca są wykluczone w Twoich ustawieniach.", + "logInjectionSiteNoneAvailable": "Brak dostępnego miejsca iniekcji: wszystkie miejsca są wykluczone w Twoich ustawieniach.", "logInjectionSiteSaveFailed": "Nie udało się zapisać miejsca iniekcji. Spróbuj ponownie.", "perSlotUnits": "{units} na dawkę", "trackInjectionSitesToggle": "Rejestruj miejsca iniekcji", @@ -2246,15 +2246,15 @@ "tableStockDoses": "Dawki: {count}", "tableStockRunway": "≈ {days} dni zapasu", "cardLowStockRunway": "Zapas: ≈ {days} dni", - "takeActionFor": "Przyjmij – {name}", - "skipActionFor": "Pomiń – {name}", - "reorderDescription": "Ustal kolejność swoich leków – obowiązuje w widoku kart i w tabeli.", + "takeActionFor": "Przyjmij: {name}", + "skipActionFor": "Pomiń: {name}", + "reorderDescription": "Ustal kolejność swoich leków w widoku kart i w tabeli.", "reorderSaved": "Kolejność zapisana", "reorderSaveFailed": "Nie udało się zapisać kolejności", "customize": "Dostosuj leki", "efficacy": { "title": "Działanie", - "intro": "Jak zmieniały się pomiary, na które ma wpływać ten lek, w okolicach rozpoczęcia jego przyjmowania. Pokazuje to, co zbiega się w czasie — powiązanie, nie przyczynę — i nigdy porady dotyczącej leczenia ani dawki.", + "intro": "Jak zmieniały się pomiary, na które ma wpływać ten lek, w okolicach rozpoczęcia jego przyjmowania. Pokazuje to, co zbiega się w czasie (powiązanie, nie przyczynę), i nigdy porady dotyczącej leczenia ani dawki.", "notEligible": "Brak pomiaru, który można powiązać z tym lekiem.", "startFallback": "Nie ustawiono daty rozpoczęcia, więc porównanie używa pierwszego zapisanego pomiaru jako punktu odniesienia.", "noStart": "Ustaw datę rozpoczęcia, aby porównać pomiary sprzed i po rozpoczęciu.", @@ -2267,7 +2267,7 @@ "levelShift": "Wykryto zmianę poziomu w okolicach {date}.", "plateau": { "title": "Plateau masy ciała przy obecnej dawce", - "evidence": "Zmiana masy ciała o {delta} {unit} w ciągu ostatnich {window} dni ({readings} pomiarów) — {days} dni na dawce {dose}." + "evidence": "Zmiana masy ciała o {delta} {unit} w ciągu ostatnich {window} dni ({readings} pomiarów), {days} dni na dawce {dose}." }, "retarget": { "label": "To nie ten pomiar?", @@ -2277,16 +2277,16 @@ "error": "Nie udało się zapisać tej zmiany. Spróbuj ponownie." }, "beforeAfter": { - "summary": "Ø {before} przedtem → Ø {after} od tego czasu — zmiana o {delta}.", + "summary": "Ø {before} przedtem → Ø {after} od tego czasu, zmiana o {delta}.", "counts": "Na podstawie {beforeCount} pomiarów przedtem i {afterCount} od tego czasu.", - "needBefore": "Za mało pomiarów przed rozpoczęciem — do porównania potrzeba około {weeks} tygodni przed i po.", - "needAfter": "Za mało pomiarów od rozpoczęcia — do porównania potrzeba około {weeks} tygodni przed i po.", + "needBefore": "Za mało pomiarów przed rozpoczęciem. Do porównania potrzeba około {weeks} tygodni przed i po.", + "needAfter": "Za mało pomiarów od rozpoczęcia. Do porównania potrzeba około {weeks} tygodni przed i po.", "needStart": "Ustaw datę rozpoczęcia, aby porównać pomiary sprzed i po rozpoczęciu.", - "needData": "Za mało pomiarów — do porównania potrzeba około {weeks} tygodni przed i po rozpoczęciu." + "needData": "Za mało pomiarów. Do porównania potrzeba około {weeks} tygodni przed i po rozpoczęciu." }, "insights": { "title": "Działanie leków", - "subtitle": "Co zbiega się w czasie z pomiarami, na które celują Twoje leki — tylko powiązanie, nigdy werdykt.", + "subtitle": "Co zbiega się w czasie z pomiarami, na które celują Twoje leki: tylko powiązanie, nigdy werdykt.", "link": "Otwórz widok działania", "empty": "Za mało danych, aby powiązać Twoje leki z docelowymi pomiarami." }, @@ -2320,7 +2320,7 @@ "reasonMissingMedication": "wiersz nie nazywa żadnego leku", "reasonUnreadableDosage": "dawka nie jest liczbą", "reasonUnreadableRow": "wiersz ma mniej kolumn niż nagłówek", - "reasonStatusNoDoseInformation": "plik nie zapisuje nic o tej dawce — nikt nie odpowiedział i nic nie zostało zanotowane", + "reasonStatusNoDoseInformation": "plik nie zapisuje nic o tej dawce: nikt nie odpowiedział i nic nie zostało zanotowane", "reasonStatusReminderEvent": "wiersz dotyczy odłożonego przypomnienia, co nic nie mówi o dawce", "reasonStatusNotificationNotSent": "wiersz zapisuje, że nie wysłano powiadomienia, co dotyczy aplikacji, a nie dawki" }, @@ -2392,7 +2392,7 @@ }, "charts": { "loadingLabel": "Ładowanie wykresu…", - "loadingSlowHint": "Obliczanie analiz — to może chwilę potrwać.", + "loadingSlowHint": "Obliczanie analiz, to może chwilę potrwać.", "weight": "Waga", "bloodPressure": "Ciśnienie tętnicze", "pulse": "Tętno", @@ -2479,9 +2479,9 @@ "toggle": "Punkty danych ({count})", "columnDate": "Data", "noValue": "Brak wartości", - "captionDay": "Jeden wiersz na dzień dla {metric} — dokładnie te punkty, które rysuje wykres.", - "captionWeek": "Jeden wiersz na tydzień dla {metric}, średnia z dni tego tygodnia — dokładnie te punkty, które rysuje wykres.", - "captionMonth": "Jeden wiersz na miesiąc dla {metric}, średnia z dni tego miesiąca — dokładnie te punkty, które rysuje wykres.", + "captionDay": "Jeden wiersz na dzień dla {metric}: dokładnie te punkty, które rysuje wykres.", + "captionWeek": "Jeden wiersz na tydzień dla {metric}, średnia z dni tego tygodnia: dokładnie te punkty, które rysuje wykres.", + "captionMonth": "Jeden wiersz na miesiąc dla {metric}, średnia z dni tego miesiąca: dokładnie te punkty, które rysuje wykres.", "hourlyMeanNote": "{metric} to średnia z każdego dnia, w której każda godzina liczy się raz, dzięki czemu trening nie przeważa nad resztą dnia." }, "personalBaseline": "Twoja średnia", @@ -2542,8 +2542,8 @@ }, "tooltipPrior": "Poprzedni okres", "unavailable": { - "lastMonth": "Porównanie niedostępne — brak danych z poprzedniego miesiąca", - "lastYear": "Porównanie niedostępne — brak danych z poprzedniego roku" + "lastMonth": "Porównanie niedostępne: brak danych z poprzedniego miesiąca", + "lastYear": "Porównanie niedostępne: brak danych z poprzedniego roku" }, "notAvailableForCompliance": "Porównanie niedostępne dla przestrzegania" }, @@ -2666,7 +2666,7 @@ "narrativeWeek": "Ten tydzień", "narrativeMonth": "Ten miesiąc", "narrativeUpdating": "Aktualizowanie…", - "heroFallbackSubtitle": "Codzienne spojrzenie na twoje trendy — prosto z liczb, które rejestrujesz.", + "heroFallbackSubtitle": "Codzienne spojrzenie na twoje trendy, prosto z liczb, które rejestrujesz.", "heroGreetingMorning": "Dzień dobry", "heroGreetingAfternoon": "Dzień dobry", "heroGreetingEvening": "Dobry wieczór", @@ -2777,7 +2777,7 @@ "emptyDescription": "Wygeneruj dzisiejszy briefing, aby zobaczyć podsumowanie trendów.", "emptyAction": "Wygeneruj briefing", "loadingLabel": "Przygotowanie briefingu", - "refreshFailedHint": "Nie udało się odświeżyć briefingu — pokazujemy poprzedni.", + "refreshFailedHint": "Nie udało się odświeżyć briefingu, pokazujemy poprzedni.", "retryAction": "Spróbuj ponownie", "failedTitle": "Nie udało się wygenerować briefingu", "failedDescription": "Dostawca AI przekroczył limit czasu lub zwrócił błąd. Spróbuj ponownie albo zwiększ limit czasu odpowiedzi w ustawieniach AI dla wolnego modelu lokalnego.", @@ -2841,14 +2841,14 @@ } }, "coach": { - "refusalOutOfScope": "Mogę pomóc tylko w sprawach danych zdrowotnych z twojego logu — pomiarów, leków, nastroju, trendów. Pytań spoza tego zakresu nie podejmuję.", - "refusalInjection": "Twoja wiadomość zawiera instrukcje, które próbują nadpisać moje wytyczne. Jestem coachem HealthLog i podsumowuję wyłącznie twoje własne dane zdrowotne — przeformułuj pytanie w tych ramach.", + "refusalOutOfScope": "Mogę pomóc tylko w sprawach danych zdrowotnych z twojego logu: pomiarów, leków, nastroju, trendów. Pytań spoza tego zakresu nie podejmuję.", + "refusalInjection": "Twoja wiadomość zawiera instrukcje, które próbują nadpisać moje wytyczne. Jestem coachem HealthLog i podsumowuję wyłącznie twoje własne dane zdrowotne. Przeformułuj pytanie w tych ramach.", "errorBudget": "Osiągnięto dzienny limit coacha. Limit resetuje się o północy (UTC).", "errorProvider": "Coach nie mógł teraz skontaktować się z dostawcą analizy. Spróbuj za chwilę.", "errorDemo": "W wersji demo Coach nie odpowiada.", - "errorNoProvider": "Coach czyta Twoje zapisane dane zdrowotne i odpowiada na pytania o nie (to nie porada medyczna). HealthLog potrzebuje do tego dostawcy AI — połącz własny klucz lub model lokalny.", + "errorNoProvider": "Coach czyta Twoje zapisane dane zdrowotne i odpowiada na pytania o nie (to nie porada medyczna). HealthLog potrzebuje do tego dostawcy AI: połącz własny klucz lub model lokalny.", "errorNoProviderAction": "Połącz dostawcę AI", - "errorNetwork": "Brak połączenia z Internetem — spróbuj ponownie, gdy wrócisz online.", + "errorNetwork": "Brak połączenia z Internetem. Spróbuj ponownie, gdy wrócisz online.", "prefsSaveError": "Nie udało się zapisać ustawień Coacha. Spróbuj ponownie.", "errorCredentialExpired": "Połączenie z dostawcą AI wygasło. Połącz je ponownie w Ustawieniach, aby Coach działał dalej.", "tagline": "Osobisty coach zdrowia, oparty na twoich danych.", @@ -2867,7 +2867,7 @@ "thinking": "Myślę…", "unverifiedFiguresNotice": "Niektórych liczb nie udało się zweryfikować z Twoimi danymi, więc je pominięto.", "composerPlaceholder": "Zapytaj mnie …", - "nudgeBubbleLabel": "Nowa wiadomość od trenera — otwórz czat", + "nudgeBubbleLabel": "Nowa wiadomość od trenera: otwórz czat", "fabLabel": "Otwórz trenera", "readAloud": "Czytaj na głos", "readAloudStop": "Zatrzymaj czytanie", @@ -2891,7 +2891,7 @@ "guided": { "offerTitle": "Coach ma {count} pytania do Ciebie", "offerTitleOne": "Coach ma pytanie do Ciebie", - "offerBody": "Krótkie odpowiedzi doprecyzują Twoje informacje o sobie — jedno pytanie po drugim, tutaj na czacie.", + "offerBody": "Krótkie odpowiedzi doprecyzują Twoje informacje o sobie: jedno pytanie po drugim, tutaj na czacie.", "offerStart": "Odpowiedz teraz", "offerLater": "Później", "offerDismiss": "Nie pytaj więcej", @@ -2901,7 +2901,7 @@ "later": "Później", "dismissRemaining": "Nie pytaj więcej", "answerPlaceholder": "Twoja odpowiedź…", - "summaryTitle": "Gotowe — dzięki za odpowiedzi!", + "summaryTitle": "Gotowe, dzięki za odpowiedzi!", "summaryAnswered": "odpowiedziano na {answered} z {total}", "summaryAdopted": "{adopted} dodano do informacji o sobie", "summaryAdoptedNone": "nie dodano nic nowego do informacji o sobie", @@ -2983,7 +2983,7 @@ "settingsVerbosityBrief": "Krótka", "settingsVerbosityDefault": "Standardowa", "settingsVerbosityDetailed": "Szczegółowa", - "settingsVerbosityConciseHint": "Zwięzły ton i tak skraca odpowiedzi — szczegółowość pozostaje ustawiona na „Krótko”, dopóki jest aktywny.", + "settingsVerbosityConciseHint": "Zwięzły ton i tak skraca odpowiedzi, więc szczegółowość pozostaje ustawiona na „Krótko”, dopóki jest aktywny.", "settingsSourcesSummary": "Coach widzi {count} z {total} obszarów danych i patrzy {window} wstecz.", "settingsSourcesSummaryAll": "Coach widzi {count} z {total} obszarów danych i całą historię.", "settingsSourcesPointerLink": "Otwórz ustawienia coacha", @@ -3090,7 +3090,7 @@ "steadyLatestWithin": "Twoje pomiary zwykle wynoszą {low} {unit}; ostatni pomiar, z {date}, wyniósł {value} i był taki sam.", "steadyLatestAbove": "Twoje pomiary zwykle wynoszą {low} {unit}; ostatni pomiar, z {date}, wyniósł {value} i był wyższy.", "steadyLatestBelow": "Twoje pomiary zwykle wynoszą {low} {unit}; ostatni pomiar, z {date}, wyniósł {value} i był niższy.", - "insufficient": "Wciąż poznaję twój zwykły zakres — rejestruj jeszcze przez kilka dni.", + "insufficient": "Wciąż poznaję twój zwykły zakres. Rejestruj jeszcze przez kilka dni.", "driver": "{note}" }, "scope": { @@ -3104,33 +3104,33 @@ "groupEarlier": "Wcześniej" }, "seed": { - "bloodPressure": "Przejdź ze mną przez trend mojego ciśnienia krwi z ostatnich 30 dni — czy jest coś, na co powinienem zwrócić uwagę?", + "bloodPressure": "Przejdź ze mną przez trend mojego ciśnienia krwi z ostatnich 30 dni. Czy jest coś, na co powinienem zwrócić uwagę?", "weight": "Jak zmieniała się ostatnio moja waga i czy ten kierunek wymaga reakcji?", "bmi": "Co mówi mi mój trend BMI i jak powinienem go odczytywać?", - "pulse": "Przejdź ze mną przez moje odczyty tętna — czy coś odbiega od normy?", + "pulse": "Przejdź ze mną przez moje odczyty tętna. Czy coś odbiega od normy?", "restingHr": "Jak zmieniało się moje tętno spoczynkowe i co mówi o mojej kondycji?", "hrv": "Co moja zmienność rytmu serca mówi mi o regeneracji i stresie w ostatnim czasie?", - "sleep": "Przejdź ze mną przez mój ostatni sen — długość, regularność i wszystko, co warto zmienić.", + "sleep": "Przejdź ze mną przez mój ostatni sen: długość, regularność i wszystko, co warto zmienić.", "mood": "Jakie wzorce widzisz w moim nastroju w ciągu ostatnich kilku tygodni?", "medications": "Jak wygląda moje przestrzeganie zaleceń lekowych i czy pokrywa się z tym, jak się czułem?", "steps": "Jak aktywny byłem ostatnio na podstawie moich kroków i jak wypada to na tle zdrowego punktu odniesienia?", "activeEnergy": "Co mój trend aktywnej energii mówi o moim poziomie aktywności w ostatnim czasie?", "cardioFitness": "Co oznacza trend mojej wydolności krążeniowo-oddechowej (VO₂ max) i jak skierować go we właściwą stronę?", - "bloodGlucose": "Przejdź ze mną przez moje ostatnie odczyty glukozy — czy mieszczą się w zdrowym zakresie?", + "bloodGlucose": "Przejdź ze mną przez moje ostatnie odczyty glukozy. Czy mieszczą się w zdrowym zakresie?", "oxygenSaturation": "Co mówi mi mój trend saturacji krwi tlenem (SpO₂)?", "respiratoryRate": "Co mój trend częstości oddechów mówi o moim zdrowiu?", - "workouts": "Przejdź ze mną przez moje ostatnie treningi — obciążenie, częstotliwość i jak regeneruję się między nimi.", + "workouts": "Przejdź ze mną przez moje ostatnie treningi: obciążenie, częstotliwość i jak regeneruję się między nimi.", "recoveryPage": "Dlaczego moja regeneracja jest teraz na takim poziomie i co na nią wpływa?", - "briefing": "Przejdź ze mną przez dzisiejszy briefing — na czym powinienem się skupić i czy jest coś, co warto podjąć?", + "briefing": "Przejdź ze mną przez dzisiejszy briefing. Na czym powinienem się skupić i czy jest coś, co warto podjąć?", "healthScore": "Dlaczego mój wynik zdrowia wynosi {score} na 100 i co poprawiłoby go najbardziej?", - "periodWeek": "Przejdź ze mną przez to, jak minął mój ostatni tydzień w moich wskaźnikach zdrowia — co się wyróżnia?", - "periodMonth": "Przejdź ze mną przez to, jak minął mój ostatni miesiąc w moich wskaźnikach zdrowia — co się wyróżnia?", + "periodWeek": "Przejdź ze mną przez to, jak minął mój ostatni tydzień w moich wskaźnikach zdrowia. Co się wyróżnia?", + "periodMonth": "Przejdź ze mną przez to, jak minął mój ostatni miesiąc w moich wskaźnikach zdrowia. Co się wyróżnia?", "correlationBpCompliance": "Jak moje przestrzeganie zaleceń lekowych wiąże się z moim ciśnieniem krwi? Wyjaśnij mi, co ta korelacja oznacza dla mnie.", "correlationMoodPulse": "Czy istnieje rzeczywisty związek między moim nastrojem a tętnem? Pomóż mi odczytać tę korelację.", "correlationWeightWeekday": "Czy moja waga podlega cotygodniowemu wzorcowi? Co mówi mi ta korelacja według dnia tygodnia?", - "recommendation": "Powiedz mi więcej o tej rekomendacji: \"{text}\" — dlaczego mnie dotyczy i co powinienem z nią zrobić?" + "recommendation": "Powiedz mi więcej o tej rekomendacji: \"{text}\". Dlaczego mnie dotyczy i co powinienem z nią zrobić?" }, - "assessmentPrompt": "Wyjaśnij mi moją ocenę {metric} — co oznacza i co powinienem z tym zrobić?", + "assessmentPrompt": "Wyjaśnij mi moją ocenę {metric}: co oznacza i co powinienem z tym zrobić?", "attach": { "menuChooseFromDocuments": "Wybierz z dokumentów", "menuUploadNew": "Prześlij nowy dokument", @@ -3144,13 +3144,13 @@ "pickerConfirm": "Załącz ({count})", "pillRemove": "Usuń {title}", "indexing": "Indeksowanie…", - "indexingHint": "Dokument jest jeszcze indeksowany – wyślesz, gdy będzie gotowy.", - "fencedHint": "Ta rozmowa działa bez dostępu do Twoich danych zdrowotnych – coach czyta tylko załączone dokumenty.", + "indexingHint": "Dokument jest jeszcze indeksowany. Wyślesz, gdy będzie gotowy.", + "fencedHint": "Ta rozmowa działa bez dostępu do Twoich danych zdrowotnych: coach czyta tylko załączone dokumenty.", "documentsAttachedOne": "1 załączony dokument", "documentsAttachedOther": "Załączone dokumenty: {count}", "railBadge": "Odizolowany czat dokumentu", "uploadError": "Przesyłanie nie powiodło się. Spróbuj ponownie.", - "notFoundError": "Ten link do dokumentu jest już nieprawidłowy – zamiast tego rozpoczynamy zwykły czat." + "notFoundError": "Ten link do dokumentu jest już nieprawidłowy, więc zamiast tego rozpoczynamy zwykły czat." }, "interrupted": { "note": "Ta odpowiedź została przerwana przed ukończeniem.", @@ -3321,7 +3321,7 @@ }, "hrv": { "title": "HRV", - "description": "Zmienność rytmu serca w czasie — sygnał regeneracji układu nerwowego, rejestrowany nocą przez Apple Watch i inne zgodne wearable.", + "description": "Zmienność rytmu serca w czasie: sygnał regeneracji układu nerwowego, rejestrowany nocą przez Apple Watch i inne zgodne wearable.", "chartTitle": "Zmienność rytmu serca", "emptyState": { "title": "Brak wartości HRV", @@ -3330,17 +3330,17 @@ }, "restingHr": { "title": "Tętno spoczynkowe", - "description": "Dzienna linia bazowa rytmu serca — różna od tętna punktowego na stronie Pulse. Apple Zdrowie podaje jedną wartość na dobę.", + "description": "Dzienna linia bazowa rytmu serca, różna od tętna punktowego na stronie Pulse. Apple Zdrowie podaje jedną wartość na dobę.", "chartTitle": "Tętno spoczynkowe", "emptyState": { "title": "Brak tętna spoczynkowego", "description": "Tętno spoczynkowe pojawi się, gdy Apple Watch lub zgodne urządzenie Withings spędzi spokojny dzień na nadgarstku." }, - "coachPrefill": "Nie zarejestrowałem jeszcze tętna spoczynkowego — dlaczego dzienna wartość spoczynkowa różni się od pojedynczego pomiaru tętna i jak ją poprawić?" + "coachPrefill": "Nie zarejestrowałem jeszcze tętna spoczynkowego. Dlaczego dzienna wartość spoczynkowa różni się od pojedynczego pomiaru tętna i jak ją poprawić?" }, "oxygenSaturation": { "title": "Saturacja tlenu", - "description": "Tlen we krwi (SpO₂) — kliniczny zakres normy 95–100 %, ze strefami docelowymi zacienionymi na wykresie.", + "description": "Tlen we krwi (SpO₂): kliniczny zakres normy 95–100 %, ze strefami docelowymi zacienionymi na wykresie.", "chartTitle": "Saturacja tlenu", "emptyState": { "title": "Brak próbek SpO₂", @@ -3353,13 +3353,13 @@ "chartTitle": "Temperatura ciała", "emptyState": { "title": "Brak temperatury ciała", - "description": "Zarejestruj pomiar lub pozwól wearable zsynchronizować jeden — trend pojawi się tutaj.", + "description": "Zarejestruj pomiar lub pozwól wearable zsynchronizować jeden, a trend pojawi się tutaj.", "cta": "Zarejestruj temperaturę ciała" } }, "steps": { "title": "Kroki", - "description": "Dzienna liczba kroków — jeden wiersz na dobę, z Apple Zdrowie lub podłączonego urządzenia aktywności.", + "description": "Dzienna liczba kroków: jeden wiersz na dobę, z Apple Zdrowie lub podłączonego urządzenia aktywności.", "chartTitle": "Kroki dziennie", "emptyState": { "title": "Brak danych o krokach", @@ -3368,7 +3368,7 @@ }, "activeEnergy": { "title": "Energia czynna", - "description": "Dzienna suma energii czynnej w kilokaloriach — jeden wiersz na dobę, z Apple Zdrowie lub aktywności Withings.", + "description": "Dzienna suma energii czynnej w kilokaloriach: jeden wiersz na dobę, z Apple Zdrowie lub aktywności Withings.", "chartTitle": "Energia czynna", "emptyState": { "title": "Brak danych o energii czynnej", @@ -3388,11 +3388,11 @@ }, "explainer": { "bloodPressureBody": "Ciśnienie krwi to siła, z jaką krew napiera na ściany tętnic, zapisywana jako skurczowe do rozkurczowego (szczyt podczas uderzenia serca do wartości spoczynkowej między uderzeniami). Stale wysokie wartości z czasem obciążają serce i naczynia.", - "pulseBody": "Tętno to liczba uderzeń serca na minutę. Pojedynczy pomiar odzwierciedla to, co robiłeś w danej chwili — w spoczynku wynosi zwykle 60–100 uderzeń na minutę i naturalnie rośnie przy ruchu, stresie lub kofeinie.", + "pulseBody": "Tętno to liczba uderzeń serca na minutę. Pojedynczy pomiar odzwierciedla to, co robiłeś w danej chwili. W spoczynku wynosi zwykle 60–100 uderzeń na minutę i naturalnie rośnie przy ruchu, stresie lub kofeinie.", "weightBody": "Masa ciała to jeden z najprostszych sygnałów długoterminowego bilansu energetycznego i ogólnego zdrowia. Trend na przestrzeni tygodni liczy się znacznie bardziej niż pojedynczy odczyt, który zmienia się wraz z nawodnieniem, jedzeniem i porą dnia.", - "bmiBody": "BMI to waga podzielona przez wzrost do kwadratu — jedna liczba przypisująca Cię do szerokiej kategorii wagowej. To badanie przesiewowe dla populacji, a nie diagnoza, i nie odróżnia mięśni od tłuszczu.", + "bmiBody": "BMI to waga podzielona przez wzrost do kwadratu: jedna liczba przypisująca Cię do szerokiej kategorii wagowej. To badanie przesiewowe dla populacji, a nie diagnoza, i nie odróżnia mięśni od tłuszczu.", "sleepBody": "Długość snu to czas, który faktycznie przespałeś w nocy, podzielony na fazy lekką, głęboką i REM. Większość dorosłych potrzebuje około siedmiu do dziewięciu godzin; stała ilość i jakość wspierają regenerację, nastrój i metabolizm.", - "moodBody": "Śledzenie nastroju rejestruje Twoje samopoczucie w czasie na prostej skali. Regularne zapisywanie ujawnia wzorce — jak sen, aktywność czy leki łączą się z samopoczuciem — których pojedynczy dzień nigdy nie pokaże.", + "moodBody": "Śledzenie nastroju rejestruje Twoje samopoczucie w czasie na prostej skali. Regularne zapisywanie ujawnia wzorce (jak sen, aktywność czy leki łączą się z samopoczuciem), których pojedynczy dzień nigdy nie pokaże.", "medicationsBody": "Przestrzeganie zaleceń to rzetelność przyjmowania leków zgodnie z zaleceniami, pokazana tu jako odsetek oczekiwanych dawek, które zarejestrowałeś. Regularne przyjmowanie często decyduje o tym, czy terapia działa zgodnie z zamierzeniem.", "restingHrBody": "Tętno spoczynkowe to częstość uderzeń serca w pełnym spoczynku, zwykle mierzona w nocy. Niższe tętno zwykle wskazuje na lepszą wydolność krążeniową, a rosnący trend może być wczesnym sygnałem stresu lub choroby.", "hrvBody": "HRV to drobna zmienność czasu między kolejnymi uderzeniami serca. Wyższa zmienność zwykle odzwierciedla dobrze zregenerowany, elastyczny układ nerwowy, a utrzymujący się spadek może sygnalizować zmęczenie, stres lub niewystarczającą regenerację.", @@ -3403,12 +3403,12 @@ "respiratoryRateBody": "Częstość oddechów to liczba wdechów na minutę. W spoczynku większość dorosłych oddycha około dwunastu do dwudziestu razy na minutę; utrzymujący się wzrost może towarzyszyć chorobie, wysiłkowi lub stresowi.", "bodyWaterBody": "Całkowita woda w organizmie to udział płynów w masie ciała, wewnątrz i wokół komórek. Zmienia się wraz z nawodnieniem, posiłkami i aktywnością, więc trend w ciągu tygodni mówi więcej niż pojedynczy pomiar.", "boneMassBody": "Masa kostna to szacowana waga minerałów w szkielecie. Pomiary z wagi są przybliżone, ale stabilny lub rosnący trend sprzyja długotrwałej wytrzymałości kości.", - "fatFreeMassBody": "Masa beztłuszczowa to wszystko w ciele, co nie jest tłuszczem — mięśnie, kości, narządy i woda. Utrzymanie lub jej budowanie przy spadku wagi zwykle wskazuje na zdrowszy skład ciała.", - "fatMassBody": "Masa tłuszczowa to łączna waga tłuszczu w ciele. Pewna ilość tłuszczu jest niezbędna dla hormonów i magazynowania energii, ale jego nadmiar — zwłaszcza w okolicy brzucha — zwiększa długoterminowe ryzyko zdrowotne (WHO 2024).", + "fatFreeMassBody": "Masa beztłuszczowa to wszystko w ciele, co nie jest tłuszczem: mięśnie, kości, narządy i woda. Utrzymanie lub jej budowanie przy spadku wagi zwykle wskazuje na zdrowszy skład ciała.", + "fatMassBody": "Masa tłuszczowa to łączna waga tłuszczu w ciele. Pewna ilość tłuszczu jest niezbędna dla hormonów i magazynowania energii, ale jego nadmiar (zwłaszcza w okolicy brzucha) zwiększa długoterminowe ryzyko zdrowotne (WHO 2024).", "bodyFatBody": "Procent tkanki tłuszczowej to część masy ciała, którą stanowi tłuszcz. Zdrowe zakresy zależą od płci i wieku, a wagi szacują go metodą bioimpedancji, dlatego trend z kilku tygodni mówi więcej niż pojedynczy pomiar.", "muscleMassBody": "Masa mięśniowa to szacowana waga mięśni w ciele. Więcej mięśni wspiera siłę, metabolizm i sprawność, a ich utrzymanie z wiekiem zwykle wymaga aktywnego wysiłku.", "visceralFatBody": "Tłuszcz trzewny to tłuszcz gromadzony głęboko w jamie brzusznej wokół narządów. W odróżnieniu od tłuszczu podskórnego jego wysoki poziom jest ściśle powiązany z chorobami serca i cukrzycą typu 2, więc im niżej, tym lepiej.", - "leanBodyMassBody": "Beztłuszczowa masa ciała to całkowita waga pomniejszona o tłuszcz — mięśnie, kości, narządy i woda razem. Śledzenie jej obok wagi pokazuje, czy zmiany wynikają z mięśni, czy z tłuszczu.", + "leanBodyMassBody": "Beztłuszczowa masa ciała to całkowita waga pomniejszona o tłuszcz: mięśnie, kości, narządy i woda razem. Śledzenie jej obok wagi pokazuje, czy zmiany wynikają z mięśni, czy z tłuszczu.", "flightsClimbedBody": "Pokonane piętra liczą kondygnacje, które pokonujesz w górę każdego dnia, gdzie jedno piętro to około trzech metrów wzniesienia. To prosty wskaźnik codziennej aktywności i wysiłku nóg.", "walkingDistanceBody": "Dystans marszu i biegu to droga, jaką pokonujesz pieszo każdego dnia. Uzupełnia liczbę kroków, pokazując, jak daleko się poruszałeś, a nie tylko jak często stawiałeś kroki.", "walkingSteadinessBody": "Stabilność chodu szacuje, jak stabilny i zrównoważony jest twój sposób chodzenia, w skali od dobrej do niskiej. Niski poziom wskazuje na większe ryzyko upadku i warto omówić go z lekarzem.", @@ -3425,28 +3425,28 @@ "daylightBody": "Czas w świetle dziennym to ilość czasu spędzanego w świetle na zewnątrz każdego dnia. Regularne światło dzienne wspiera zdrowy rytm snu i czuwania oraz nastrój (CDC 2024), a czas na świeżym powietrzu wiąże się ze zdrowiem oczu.", "bloodGlucoseBody": "Poziom glukozy we krwi to ilość cukru we krwi, głównego źródła energii organizmu. Rośnie po jedzeniu i ustala się między posiłkami; wartości utrzymujące się wysoko mogą sygnalizować cukrzycę lub stan przedcukrzycowy.", "skinTemperatureBody": "Temperatura skóry to tutaj niewielka nocna zmiana temperatury nadgarstka względem twojej własnej wartości bazowej, a nie bezwzględny pomiar gorączki. Zmiany mogą odzwierciedlać sen, otoczenie, chorobę lub fazę cyklu menstruacyjnego.", - "cardioFitnessBody": "VO₂ max to ilość tlenu, jaką organizm potrafi wykorzystać przy maksymalnym wysiłku — najlepszy laboratoryjny wskaźnik wydolności tlenowej, który urządzenia noszone szacują pośrednio. Wyższy lub rosnący trend to mocny sygnał dobrego zdrowia układu krążenia.", + "cardioFitnessBody": "VO₂ max to ilość tlenu, jaką organizm potrafi wykorzystać przy maksymalnym wysiłku. To najlepszy laboratoryjny wskaźnik wydolności tlenowej, który urządzenia noszone szacują pośrednio. Wyższy lub rosnący trend to mocny sygnał dobrego zdrowia układu krążenia.", "cardioRecoveryBody": "Regeneracja serca to liczba uderzeń na minutę, o jaką spada tętno w pierwszej minucie po zakończeniu intensywnego wysiłku. Większy spadek oznacza, że serce szybciej się uspokaja, co świadczy o dobrej kondycji.", "wristTemperatureBody": "Temperatura nadgarstka jest mierzona podczas snu i podawana jako różnica względem Twojej wartości bazowej, a nie jako wartość bezwzględna. Stabilny odczyt jest normalny, a utrzymujący się wzrost może wskazywać na chorobę, intensywny trening lub zmianę cyklu.", "fallsBody": "Tutaj liczone są poważne upadki wykryte przez urządzenie noszone. Celem jest zero; rosnąca liczba to sygnał ryzyka związanego z mobilnością, który warto omówić z lekarzem, zwłaszcza u osób starszych (CDC STEADI 2024).", - "sixMinuteWalkBody": "To szacunek, jak daleko mógłbyś przejść w sześć minut — klasyczny test kliniczny mobilności i wydolności krążeniowo-oddechowej. Wartość z urządzenia noszonego to przybliżenie, a nie nadzorowany test kliniczny; liczy się stały lub rosnący trend.", - "stairAscentSpeedBody": "To prędkość, z jaką pokonujesz bieg schodów. To czuły wskaźnik siły nóg i mobilności — stałe lub rosnące tempo to dobry znak, a spadające warto obserwować.", - "stairDescentSpeedBody": "To prędkość, z jaką schodzisz bieg schodów. Razem z prędkością wchodzenia odzwierciedla kontrolę nóg i równowagę — stałe tempo to dobry znak, a spadające warto obserwować.", - "breathingDisturbancesBody": "Urządzenie noszone potrafi oszacować, jak często Twój oddech był przerywany podczas snu. Niższy wskaźnik jest lepszy; poziom oznaczony jako podwyższony — zwłaszcza przez wiele nocy — warto omówić z lekarzem. To przybliżenie przesiewowe, a nie diagnoza bezdechu sennego.", - "stepsBody": "Liczba kroków to łączna liczba kroków wykonanych każdego dnia — najprostsza miara codziennego ruchu. Stały nawyk liczy się bardziej niż pojedynczy intensywny dzień, a okrągły cel 10 000 kroków to hasło reklamowe, a nie wynik badań.", - "readinessBody": "Gotowość to pojedynczy dzienny odczyt tego, jak przygotowane jest Twoje ciało, by zmierzyć się z dniem — łączy tętno spoczynkowe, zmienność rytmu serca i sen. To przybliżenie z urządzenia względem Twojej własnej bazy, nie pomiar kliniczny: wyższy wynik oznacza wypoczęcie, niższy to delikatna wskazówka, by zwolnić tempo.", - "sleepScoreBody": "Twój wynik snu streszcza całą noc w jednej liczbie — długość, efektywność, regularność pór oraz proporcje snu lekkiego, głębokiego i REM. Obserwuj wzorzec w ujęciu tygodni, zamiast gonić za idealnym wynikiem jednej nocy.", - "recoveryBody": "Regeneracja odzwierciedla, jak dobrze Twoje ciało się odbudowało — opiera się na nocnych sygnałach, takich jak zmienność rytmu serca i tętno spoczynkowe. Wysoki wynik to zielone światło, by przyspieszyć; niższy sugeruje, że organizm wciąż się regeneruje.", - "strainBody": "Obciążenie ujmuje, ile wysiłku sercowo-naczyniowego i fizycznego nałożyłeś na swoje ciało — od treningów po aktywny dzień na nogach. Gdy zbierze się wystarczająco danych, jest oceniane względem Twojego własnego typowego wysiłku, a nie cudzej miary.", + "sixMinuteWalkBody": "To szacunek, jak daleko mógłbyś przejść w sześć minut, czyli klasyczny test kliniczny mobilności i wydolności krążeniowo-oddechowej. Wartość z urządzenia noszonego to przybliżenie, a nie nadzorowany test kliniczny; liczy się stały lub rosnący trend.", + "stairAscentSpeedBody": "To prędkość, z jaką pokonujesz bieg schodów. To czuły wskaźnik siły nóg i mobilności: stałe lub rosnące tempo to dobry znak, a spadające warto obserwować.", + "stairDescentSpeedBody": "To prędkość, z jaką schodzisz bieg schodów. Razem z prędkością wchodzenia odzwierciedla kontrolę nóg i równowagę: stałe tempo to dobry znak, a spadające warto obserwować.", + "breathingDisturbancesBody": "Urządzenie noszone potrafi oszacować, jak często Twój oddech był przerywany podczas snu. Niższy wskaźnik jest lepszy; poziom oznaczony jako podwyższony, zwłaszcza przez wiele nocy, warto omówić z lekarzem. To przybliżenie przesiewowe, a nie diagnoza bezdechu sennego.", + "stepsBody": "Liczba kroków to łączna liczba kroków wykonanych każdego dnia, najprostsza miara codziennego ruchu. Stały nawyk liczy się bardziej niż pojedynczy intensywny dzień, a okrągły cel 10 000 kroków to hasło reklamowe, a nie wynik badań.", + "readinessBody": "Gotowość to pojedynczy dzienny odczyt tego, jak przygotowane jest Twoje ciało, by zmierzyć się z dniem. Łączy tętno spoczynkowe, zmienność rytmu serca i sen. To przybliżenie z urządzenia względem Twojej własnej bazy, nie pomiar kliniczny: wyższy wynik oznacza wypoczęcie, niższy to delikatna wskazówka, by zwolnić tempo.", + "sleepScoreBody": "Twój wynik snu streszcza całą noc w jednej liczbie: długość, efektywność, regularność pór oraz proporcje snu lekkiego, głębokiego i REM. Obserwuj wzorzec w ujęciu tygodni, zamiast gonić za idealnym wynikiem jednej nocy.", + "recoveryBody": "Regeneracja odzwierciedla, jak dobrze Twoje ciało się odbudowało. Opiera się na nocnych sygnałach, takich jak zmienność rytmu serca i tętno spoczynkowe. Wysoki wynik to zielone światło, by przyspieszyć; niższy sugeruje, że organizm wciąż się regeneruje.", + "strainBody": "Obciążenie ujmuje, ile wysiłku sercowo-naczyniowego i fizycznego nałożyłeś na swoje ciało, od treningów po aktywny dzień na nogach. Gdy zbierze się wystarczająco danych, jest oceniane względem Twojego własnego typowego wysiłku, a nie cudzej miary.", "stressBody": "Stres jest tu szacunkiem fizjologicznego obciążenia Twojego układu nerwowego, odczytywanym głównie ze wzorców zmienności rytmu serca, a nie z tego, jak się świadomie czujesz. Niższy wynik wskazuje na spokojny, dobrze regulowany stan; wyższy to zachęta, by wpleść regenerację.", - "recoveryPageBody": "Regeneracja łączy nocne sygnały rejestrowane przez Twoje urządzenie – recharge, obciążenie, load oraz dzienne sumy tętna i energii – aby pokazać, jak dobrze Twój organizm się zregenerował. Patrz na wzorzec w ciągu kilku dni, a nie na pojedynczą liczbę; niższy wynik to zaproszenie do zwolnienia tempa, a nie alarm.", + "recoveryPageBody": "Regeneracja łączy nocne sygnały rejestrowane przez Twoje urządzenie (recharge, obciążenie, load oraz dzienne sumy tętna i energii), aby pokazać, jak dobrze Twój organizm się zregenerował. Patrz na wzorzec w ciągu kilku dni, a nie na pojedynczą liczbę; niższy wynik to zaproszenie do zwolnienia tempa, a nie alarm.", "pulsePressureBody": "Ciśnienie tętna to różnica między wartością skurczową a rozkurczową (skurczowe minus rozkurczowe). Jako ogólna wskazówka, około 40 mmHg jest typowe w spoczynku; szeroka różnica powyżej około 60 mmHg w średnim wieku może odzwierciedlać usztywnienie tętnic, a wąska różnica poniżej około 25 mmHg może towarzyszyć niskiej objętości wyrzutowej (StatPearls/NIH 2023). To powód do rozmowy, nie diagnoza.", "meanArterialPressureBody": "Średnie ciśnienie tętnicze to przeciętne ciśnienie, jakie widzą Twoje narządy w trakcie uderzenia serca, w przybliżeniu rozkurczowe plus jedna trzecia różnicy do skurczowego. Jako ogólna wskazówka, wartość spoczynkowa mieści się w okolicy 70–100 mmHg (StatPearls/NIH 2023). Często przywoływany próg ~60 mmHg to pojęcie z medycyny ostrej, nie alarm do samodzielnego pomiaru.", "cycleEducationBody": "Twój cykl przebiega przez cztery fazy sterowane hormonami, a jego długość i regularność to dostępne okno na ogólny stan zdrowia. Jako ogólna wskazówka, u osób dorosłych cykle trwają zwykle 21–35 dni (źródła kliniczne podają 24–38), z krwawieniem około pięciu dni (ACOG 2015). Faza lutealna jest stałą kotwicą, dlatego owulację najlepiej szacować, licząc wstecz od następnej spodziewanej miesiączki, nigdy według stałego „14. dnia”. Przewidziane okno płodne to oszacowanie, które wymaga kilku zarejestrowanych cykli i pozostaje przybliżone, a podstawowa temperatura ciała potwierdza owulację po fakcie, a nie ją przewiduje. To nie jest metoda antykoncepcji.", "sleepHygieneBody": "Kilka opartych na dowodach nawyków wspiera sen: stałe pory kładzenia się i wstawania także w weekendy, jasne światło rano i przyciemnione wieczory, chłodna, ciemna i cicha sypialnia oraz unikanie kofeiny po południu, alkoholu późnym wieczorem i obfitych posiłków przed snem (CDC 2024). Regularność przewiduje zdrowie co najmniej tak silnie jak długość snu, a całkowity czas snu z urządzenia jest znacznie bardziej wiarygodny niż jego podział na sen głęboki, lekki i REM." }, "bpDerived": { - "pulsePressure": "Ciśnienie tętna (różnica między Twoimi wartościami) wynosi około {value} mmHg – około 40 jest typowe w spoczynku.", + "pulsePressure": "Ciśnienie tętna (różnica między Twoimi wartościami) wynosi około {value} mmHg; około 40 jest typowe w spoczynku.", "meanArterialPressure": "Średnie ciśnienie tętnicze (średnia, jaką widzą Twoje narządy) wynosi około {value} mmHg, zwykle w okolicy 70–100.", "caveat": "Te wartości są wyliczone z ostatniego pomiaru jako ogólna wskazówka, nie jako diagnoza." }, @@ -3458,7 +3458,7 @@ "mean": "Średnia" }, "showAllValues": "Pokaż wszystkie pomiary", - "valuesPageTitle": "{metric} — wszystkie pomiary", + "valuesPageTitle": "{metric}: wszystkie pomiary", "valuesPageDescription": "Każdy pomiar stojący za tą metryką. Edytuj lub usuń wpis bezpośrednio.", "diversity": { "trigger": "Wskazówka pomiarowa", @@ -3498,11 +3498,11 @@ "inBed": "W łóżku", "nap": "Drzemka", "napCount": "{count} drzemki/ek", - "unavailable": "Brak danych o fazach — fazy snu pojawią się tutaj, gdy tylko dostarczy je połączone źródło." + "unavailable": "Brak danych o fazach. Fazy snu pojawią się tutaj, gdy tylko dostarczy je połączone źródło." }, "empty": { "title": "Brak danych o śnie", - "description": "Połącz źródło takie jak Apple Health lub urządzenie noszone — albo zapisuj sen ręcznie — a ten widok wypełni się automatycznie.", + "description": "Połącz źródło takie jak Apple Health lub urządzenie noszone albo zapisuj sen ręcznie, a ten widok wypełni się automatycznie.", "action": "Zarządzaj urządzeniami" }, "debt": { @@ -3511,21 +3511,21 @@ "caption": "Pozostały bilans z ostatnich {nights} nocy", "clearValue": "Na bieżąco", "clearCaption": "Nic do nadrobienia w ostatnich {nights} nocach", - "learning": "Wciąż analizujemy Twój sen — {counted} nocy do tej pory, jeszcze {remaining}, aby uzyskać wiarygodny bilans.", + "learning": "Wciąż analizujemy Twój sen: {counted} nocy do tej pory, jeszcze {remaining}, aby uzyskać wiarygodny bilans.", "computedInfo": "To własne oszacowanie HealthLog: ruchomy bilans potrzeby snu minus sen z ostatnich nocy, który sen nadrabiający zmniejsza. Może różnić się od natywnego wskaźnika długu snu z urządzenia, które korzysta z własnego modelu zapotrzebowania." }, "average": { "title": "Średnia na noc", "value": "{hours} godz. {minutes} min", "caption": "Średni sen w ciągu ostatnich {nights} nocy", - "learning": "Wciąż analizujemy Twój sen — {counted} nocy do tej pory, jeszcze {remaining}, aby uzyskać wiarygodną średnią." + "learning": "Wciąż analizujemy Twój sen: {counted} nocy do tej pory, jeszcze {remaining}, aby uzyskać wiarygodną średnią." }, "chronotype": { "title": "Chronotyp", - "learning": "Wciąż poznajemy Twój rytm — {counted} z {total} wolnych nocy. Chronotyp wymaga kilku poranków bez budzika, aby coś znaczył.", + "learning": "Wciąż poznajemy Twój rytm: {counted} z {total} wolnych nocy. Chronotyp wymaga kilku poranków bez budzika, aby coś znaczył.", "advancedToggle": "Zaawansowane", "socialJetlagValue": "{hours} godz. {minutes} min jet lagu społecznego", - "socialJetlagCaption": "Różnica między porą snu w dni robocze i wolne — jak niewielka cotygodniowa zmiana strefy czasowej.", + "socialJetlagCaption": "Różnica między porą snu w dni robocze i wolne, jak niewielka cotygodniowa zmiana strefy czasowej.", "msfScValue": "Skorygowany środek snu {clock}", "msfScCaption": "Skorygowany o sen nadrabiany w weekend (MSFsc).", "dayTypeNote": "Dni wolne przyjmuje się jako weekendy, dopóki nie zostanie dodane śledzenie typu dnia.", @@ -3604,7 +3604,7 @@ "navRecovery": "Regeneracja", "workouts": { "title": "Treningi", - "description": "Ostatnie biegi, jazdy, marsze i treningi siłowe — zdeduplikowane między Apple Watch a Withings.", + "description": "Ostatnie biegi, jazdy, marsze i treningi siłowe, zdeduplikowane między Apple Watch a Withings.", "emptyState": { "title": "Brak treningów", "description": "Treningi trafiają tu z Apple Zdrowie na iPhonie i z Withings. Możesz też wpisać trening ręcznie." @@ -3732,11 +3732,11 @@ "clinical": { "title": "Przegląd glukozy", "subtitle": "Spojrzenie na ostatnie {days} dni, na podstawie {count} pomiarów.", - "spotCaveat": "To szacunki z pojedynczych pomiarów punktowych, a nie profil z czujnika ciągłego — traktuj je jako kierunek, nie jako diagnozę.", + "spotCaveat": "To szacunki z pojedynczych pomiarów punktowych, a nie profil z czujnika ciągłego. Traktuj je jako kierunek, nie jako diagnozę.", "labsLink": "Wyniki laboratoryjne? HbA1c lub glukozę na czczo z pobrania krwi zapisz w sekcji Laboratorium.", "learningTitle": "Wciąż poznajemy Twoją glukozę", - "learningBody": "Na razie to {count} w ciągu {days}. Przy nieco dłuższej historii obraz się wyostrza — rejestruj dalej lub pozwól uzupełnić to podłączonemu urządzeniu.", - "learningBodyEmpty": "Gdy pojawi się kilka pomiarów — wpisanych przez Ciebie lub zsynchronizowanych z urządzenia — czas w zakresie, średnia i zmienność nabiorą tu kształtu.", + "learningBody": "Na razie to {count} w ciągu {days}. Przy nieco dłuższej historii obraz się wyostrza, więc rejestruj dalej lub pozwól uzupełnić to podłączonemu urządzeniu.", + "learningBodyEmpty": "Gdy pojawi się kilka pomiarów (wpisanych przez Ciebie lub zsynchronizowanych z urządzenia), czas w zakresie, średnia i zmienność nabiorą tu kształtu.", "readingsCount": "{count} pomiarów", "readingsCountOne": "1 pomiar", "daysCount": "{days} dni", @@ -3774,7 +3774,7 @@ "intro": "Złożone miary o poziomie badawczym dla bliższego spojrzenia. Każda sprowadza Twoje pomiary do jednej liczby ważonej ryzykiem.", "jIndex": { "label": "Indeks J", - "help": "Pojedynczy wynik łączący średnią i jej rozrzut — niższy oznacza ściślejszą kontrolę." + "help": "Pojedynczy wynik łączący średnią i jej rozrzut. Niższy oznacza ściślejszą kontrolę." }, "lbgi": { "label": "Ryzyko niedocukrzeń (LBGI)", @@ -3891,7 +3891,7 @@ "navSkinTemperature": "Temp. skóry", "pulseWaveVelocity": { "title": "Prędkość fali tętna", - "description": "Prędkość fali tętna tętniczego w czasie, w m/s — wyższe wartości sugerują sztywniejsze tętnice.", + "description": "Prędkość fali tętna tętniczego w czasie, w m/s. Wyższe wartości sugerują sztywniejsze tętnice.", "chartTitle": "Prędkość fali tętna", "emptyState": { "title": "Brak danych", @@ -4084,7 +4084,7 @@ "inTargetCaption": "ostatnich dni w zakresie dobrego nastroju", "narrative": { "title": "Co się wyróżnia", - "weekdayDip": "Twój nastrój najbardziej spada w {weekday} — {delta} poniżej twojego tygodnia.", + "weekdayDip": "Twój nastrój najbardziej spada w {weekday}: {delta} poniżej twojego tygodnia.", "weekdayPeak": "{weekday} to zawsze twój najlepszy dzień, średnio {value}.", "trendUp": "Twój nastrój rośnie w ciągu ostatnich {days} dni (+{delta} względem poprzedniego okresu).", "trendDown": "Twój nastrój spada w ciągu ostatnich {days} dni (-{delta} względem poprzedniego okresu).", @@ -4093,7 +4093,7 @@ "tagLift": "Dni z tagiem „{tag}” są średnio o {delta} powyżej twojego ogólnego nastroju.", "tagDrop": "Dni z tagiem „{tag}” są o {delta} poniżej twojej średniej.", "inTarget": "Przez {pct}% ostatnich 30 dni byłeś w zakresie dobrego nastroju.", - "streak": "Rejestrujesz nastrój od {days} dni z rzędu — tak trzymaj.", + "streak": "Rejestrujesz nastrój od {days} dni z rzędu. Tak trzymaj.", "timeOfDay": "Najlepiej czujesz się {bucket}, średnio {value}." }, "timeOfDay": { @@ -4164,7 +4164,7 @@ "title": "Co się wyróżnia", "subheading": "Wykryte relacje", "footer": "Wyłonione z {tested} par dzień po dniu testowanych na wszystkich Twoich wskaźnikach, po korekcie fałszywych odkryć.", - "disclaimer": "Przefiltrowane statystycznie, ale wciąż obserwacyjne — wzorzec warty uwagi, nie przyczyna.", + "disclaimer": "Przefiltrowane statystycznie, ale wciąż obserwacyjne: wzorzec warty uwagi, nie przyczyna.", "moodUp": "Wyższy {factor} zwykle wiąże się z lepszym nastrojem następnego dnia w Twoich danych.", "moodDown": "Wyższy {factor} zwykle wiąże się z gorszym nastrojem następnego dnia w Twoich danych.", "outcomeUp": "Lepszy nastrój zwykle wiąże się z wyższym {factor} następnego dnia w Twoich danych.", @@ -4203,8 +4203,8 @@ "deviationAbove": "Twoja własna ocena leży {amount} punktów powyżej tego zakresu.", "deviationBelow": "Twoja własna ocena leży {amount} punktów poniżej tego zakresu.", "weightedTitle": "Co najbardziej zaważyło w porównaniu tego dnia", - "weightedUp": "{label} — liczyło się w stronę wyższej oczekiwanej wartości", - "weightedDown": "{label} — liczyło się w stronę niższej oczekiwanej wartości", + "weightedUp": "{label}: liczyło się w stronę wyższej oczekiwanej wartości", + "weightedDown": "{label}: liczyło się w stronę niższej oczekiwanej wartości", "caveat": "To porównanie z twoimi wcześniejszymi dniami, nie stwierdzenie, jak doszło do takiego przebiegu dnia.", "learning": "Faza uczenia: zapisano {entries} z {threshold} dni. Porównanie pojawi się, gdy będzie ich dość.", "noPattern": "W zapisanych dotąd {entries} dniach nic nie jest na tyle regularne, by porównać z nimi dzień. Gdy zapisujesz też kontekst dnia, więcej da się porównać.", @@ -4221,7 +4221,7 @@ }, "scoreRing": { "aria": "Wynik {score} na 100, {band}", - "ariaProvisional": "Wynik jeszcze niedostępny — za mało danych", + "ariaProvisional": "Wynik jeszcze niedostępny, za mało danych", "provisionalCaption": "Wciąż za mało danych", "band": { "green": "dobry", @@ -4245,7 +4245,7 @@ "loadingLabel": "Wczytywanie parametrów życiowych", "loadError": "Nie udało się teraz wczytać Twoich parametrów życiowych.", "infoLabel": "Jak to jest obliczane?", - "building": "Budowanie Twojego typowego zakresu — {count} z {target} dni", + "building": "Budowanie Twojego typowego zakresu: {count} z {target} dni", "typicalRange": "Typowe dla Ciebie: {low}–{high}", "fitnessYounger": "Kondycja jak u osoby ~{years} lat młodszej", "fitnessOlder": "Kondycja ~{years} lat powyżej Twojego wieku", @@ -4297,7 +4297,7 @@ "READINESS": { "title": "Gotowość", "description": "Codzienny wskaźnik samopoczucia oparty na tym, jak twoje sygnały wypadają względem twojej własnej bazy.", - "method": "Mieszanka 0–100 z odchylenia tętna spoczynkowego, odchylenia HRV (SDNN), jakości snu, stabilności częstości oddechu i stabilności nastroju — każde mierzone względem twojej osobistej bazy. Wagi są renormalizowane na komponentach wspieranych przez twoje dane. Wskaźnik samopoczucia, nie wynik regeneracji ani kliniczny.", + "method": "Mieszanka 0–100 z odchylenia tętna spoczynkowego, odchylenia HRV (SDNN), jakości snu, stabilności częstości oddechu i stabilności nastroju, każde mierzone względem twojej osobistej bazy. Wagi są renormalizowane na komponentach wspieranych przez twoje dane. Wskaźnik samopoczucia, nie wynik regeneracji ani kliniczny.", "component": { "rhr": "Tętno spoczynkowe", "hrv": "HRV (SDNN)", @@ -4307,28 +4307,28 @@ } }, "VITALS_BASELINE": { - "method": "Twój osobisty typowy zakres to mediana Twoich dziennych wartości w danym okresie ± odporne rozproszenie (skalowane medianowe odchylenie bezwzględne). Śledzi TWOJE odczyty, a nie normę populacyjną — wartość w obrębie pasma jest więc typowa dla Ciebie." + "method": "Twój osobisty typowy zakres to mediana Twoich dziennych wartości w danym okresie ± odporne rozproszenie (skalowane medianowe odchylenie bezwzględne). Śledzi TWOJE odczyty, a nie normę populacyjną, więc wartość w obrębie pasma jest typowa dla Ciebie." }, "HRV_BALANCE": { "method": "Twoja niedawna średnia HRV (SDNN) na tle Twojej własnej ruchomej linii bazowej (mediana ± odporne rozproszenie). Zrównoważone oznacza, że mieści się w Twoim osobistym zakresie; pasmo budowane jest z Twoich danych, nigdy z progu populacyjnego." }, "BMI": { - "method": "Masa ÷ wzrost², sklasyfikowane według kategorii WHO dla dorosłych (niedowaga / norma / nadwaga / otyłość). To tylko wskaźnik przesiewowy — nie odróżnia mięśni od tłuszczu." + "method": "Masa ÷ wzrost², sklasyfikowane według kategorii WHO dla dorosłych (niedowaga / norma / nadwaga / otyłość). To tylko wskaźnik przesiewowy, który nie odróżnia mięśni od tłuszczu." }, "FITNESS_AGE": { - "method": "Twoje VO₂max odniesione do percentyli wydolności krążeniowo-oddechowej według wieku i płci, wyrażone jako różnica wieku sprawnościowego. VO₂max to szacunek Twojego urządzenia — tutaj nigdy nie jest przeliczany ponownie." + "method": "Twoje VO₂max odniesione do percentyli wydolności krążeniowo-oddechowej według wieku i płci, wyrażone jako różnica wieku sprawnościowego. VO₂max to szacunek Twojego urządzenia, tutaj nigdy nie jest przeliczany ponownie." }, "VASCULAR_AGE_DELTA": { "method": "Szacunek wieku naczyniowego / prędkości fali tętna z Twojego urządzenia porównany z Twoim wiekiem metrykalnym, wyrażony jako różnica w latach. Szacunek pochodzi z urządzenia; HealthLog jedynie go przedstawia.", - "caveat": "Własny szacunek Twojego urządzenia, jedynie przedstawiony — opisowy, nie kliniczna ocena naczyniowa.", + "caveat": "Własny szacunek Twojego urządzenia, jedynie przedstawiony: opisowy, nie kliniczna ocena naczyniowa.", "description": "Jak szacunek wieku naczyniowego Twojego urządzenia wypada na tle Twojego wieku metrykalnego." }, "COINCIDENT_DEVIATION": { "method": "Sygnał pojawiający się, gdy co najmniej dwa Twoje parametry życiowe wykraczają tego samego dnia poza swój osobisty typowy zakres. Każde pasmo to odporna mediana ± k·MAD Twojej historii, więc dostosowuje się do Ciebie, a nie do progu populacyjnego.", - "caveat": "Sygnał z Twoich własnych linii bazowych — opisowy, nie diagnoza ani alarm kliniczny." + "caveat": "Sygnał z Twoich własnych linii bazowych: opisowy, nie diagnoza ani alarm kliniczny." }, "RECOVERY_SCORE": { - "method": "Nocny wskaźnik regeneracji 0–100 łączący Twoje HRV, tętno spoczynkowe i sen względem Twojej linii bazowej. Wyższy oznacza lepszą regenerację. Liczony raz na noc i tu tylko odczytywany — nigdy nieprzeliczany na bieżąco.", + "method": "Nocny wskaźnik regeneracji 0–100 łączący Twoje HRV, tętno spoczynkowe i sen względem Twojej linii bazowej. Wyższy oznacza lepszą regenerację. Liczony raz na noc i tu tylko odczytywany, nigdy nieprzeliczany na bieżąco.", "description": "Nocny wskaźnik regeneracji z Twojego HRV, tętna spoczynkowego i snu." }, "STRESS_SCORE": { @@ -4337,35 +4337,35 @@ }, "STRAIN_SCORE": { "method": "Nocny wskaźnik obciążenia 0–100 na podstawie Twojego obciążenia aktywnością ważonego tętnem (model impulsu treningowego typu TRIMP). Wyższy oznacza cięższy dzień.", - "anchorPersonal": "Zakotwiczony w Twoim własnym niedawnym obciążeniu z dni treningowych — oceniany względem Twojego typowego wysiłku, więc naprawdę ciężki dzień dla Ciebie wypada wysoko.", + "anchorPersonal": "Zakotwiczony w Twoim własnym niedawnym obciążeniu z dni treningowych. Oceniany względem Twojego typowego wysiłku, więc naprawdę ciężki dzień dla Ciebie wypada wysoko.", "anchorPopulation": "Oceniany względem ogólnego punktu odniesienia, gdy dopiero budujesz historię treningów; gdy zbierzesz jej wystarczająco, przełącza się na Twój własny typowy wysiłek.", "description": "Nocny wskaźnik obciążenia aktywnością z Twojego wysiłku ważonego tętnem, względem Twojego typowego wysiłku.", "deviceCaption": "Dzienne obciążenie z Twojego urządzenia: {value} z {max}", "deviceSource": "Dopóki HealthLog nie obliczy w nocy własnej wartości, karta pokazuje dzienne obciążenie z Twojego urządzenia, przeliczone na 0–100." }, "WRIST_TEMPERATURE_BASELINE": { - "method": "Twoja typowa nocna temperatura nadgarstka to mediana Twoich nocnych odczytów w danym okresie, ± solidny rozrzut (przeskalowane medianowe odchylenie bezwzględne). Śledzi TWOJE odczyty — ostatnia noc jest pokazana jako odchylenie od Twojej własnej bazy, a nie od normy populacyjnej.", - "caveat": "Tylko osobiste pasmo odchylenia — opisowe, nie sygnał choroby, gorączki ani fazy cyklu. Interpretujesz je samodzielnie." + "method": "Twoja typowa nocna temperatura nadgarstka to mediana Twoich nocnych odczytów w danym okresie, ± solidny rozrzut (przeskalowane medianowe odchylenie bezwzględne). Śledzi TWOJE odczyty: ostatnia noc jest pokazana jako odchylenie od Twojej własnej bazy, a nie od normy populacyjnej.", + "caveat": "Tylko osobiste pasmo odchylenia: opisowe, nie sygnał choroby, gorączki ani fazy cyklu. Interpretujesz je samodzielnie." }, "STAIR_ASCENT_SPEED_BASELINE": { - "method": "Twoje typowe tempo wchodzenia po schodach to mediana Twoich dziennych wartości w danym okresie, ± solidny rozrzut (przeskalowane medianowe odchylenie bezwzględne). Pasmo jest budowane z Twoich danych — nie ma populacyjnego progu prędkości na schodach, bo tempo zależy od geometrii schodów i długości nóg.", - "caveat": "Osobiste pasmo trendu mobilności — opisowe, nie ocena kruchości ani ryzyka upadku." + "method": "Twoje typowe tempo wchodzenia po schodach to mediana Twoich dziennych wartości w danym okresie, ± solidny rozrzut (przeskalowane medianowe odchylenie bezwzględne). Pasmo jest budowane z Twoich danych. Nie ma populacyjnego progu prędkości na schodach, bo tempo zależy od geometrii schodów i długości nóg.", + "caveat": "Osobiste pasmo trendu mobilności: opisowe, nie ocena kruchości ani ryzyka upadku." }, "STAIR_DESCENT_SPEED_BASELINE": { - "method": "Twoje typowe tempo schodzenia po schodach to mediana Twoich dziennych wartości w danym okresie, ± solidny rozrzut (przeskalowane medianowe odchylenie bezwzględne). Pasmo jest budowane z Twoich danych — nie ma populacyjnego progu prędkości na schodach, bo tempo zależy od geometrii schodów i długości nóg.", - "caveat": "Osobiste pasmo trendu mobilności — opisowe, nie ocena kruchości ani ryzyka upadku." + "method": "Twoje typowe tempo schodzenia po schodach to mediana Twoich dziennych wartości w danym okresie, ± solidny rozrzut (przeskalowane medianowe odchylenie bezwzględne). Pasmo jest budowane z Twoich danych. Nie ma populacyjnego progu prędkości na schodach, bo tempo zależy od geometrii schodów i długości nóg.", + "caveat": "Osobiste pasmo trendu mobilności: opisowe, nie ocena kruchości ani ryzyka upadku." }, "SIX_MINUTE_WALK_BAND": { - "method": "SZACOWANY przez Twoje urządzenie dystans sześciominutowego marszu odniesiony do wzorca Enrighta i Sherrilla dla Twojego wieku, wzrostu, wagi i płci, jako procent wartości przewidywanej. Dystans to szacunek urządzenia — nigdy nie jest tu przeliczany. Bez Twojego wieku, wzrostu, wagi i płci procent jest ukryty i pokazywane są tylko dystans i trend.", - "caveat": "Szacunek odniesiony do opublikowanego wzorca — sygnał wydolności funkcjonalnej, nie kliniczny test sześciominutowego marszu ani diagnoza. Wzorzec opracowano dla wieku 40–80 lat; poza tym zakresem wartość przewidywana jest ekstrapolacją." + "method": "SZACOWANY przez Twoje urządzenie dystans sześciominutowego marszu odniesiony do wzorca Enrighta i Sherrilla dla Twojego wieku, wzrostu, wagi i płci, jako procent wartości przewidywanej. Dystans to szacunek urządzenia i nigdy nie jest tu przeliczany. Bez Twojego wieku, wzrostu, wagi i płci procent jest ukryty i pokazywane są tylko dystans i trend.", + "caveat": "Szacunek odniesiony do opublikowanego wzorca: sygnał wydolności funkcjonalnej, nie kliniczny test sześciominutowego marszu ani diagnoza. Wzorzec opracowano dla wieku 40–80 lat; poza tym zakresem wartość przewidywana jest ekstrapolacją." }, "TRAJECTORY": { "method": "Prosta dopasowana metodą najmniejszych kwadratów do Twoich ostatnich wartości dziennych i rzutowana w przód na krótki horyzont, z klasycznym przedziałem predykcji, który poszerza się tym bardziej, im dalej sięga. Obliczana tylko wtedy, gdy ostatni trend jest dość wyraźny, a Twoja historia wystarczająco długa i aktualna; w przeciwnym razie linia nie jest rysowana.", - "caveat": "Rzut Twojego własnego ostatniego trendu — nie prognoza, cel ani kliniczne przewidywanie. Sprawdza się tylko, jeśli ostatni wzorzec się utrzyma; zacieniony pas pokazuje, jak szybko ta pewność maleje." + "caveat": "Rzut Twojego własnego ostatniego trendu, nie prognoza, cel ani kliniczne przewidywanie. Sprawdza się tylko, jeśli ostatni wzorzec się utrzyma; zacieniony pas pokazuje, jak szybko ta pewność maleje." }, "SAME_TIME_BASELINE": { "method": "Twoja dzisiejsza suma narastająca zestawiona z medianą tej samej godziny lokalnej z ostatnich czterech tygodni, z odpornym pasmem mediana ± MAD wokół niej. Liczą się tylko dni z wystarczającą liczbą zapisów, a porównanie nie pojawia się, dopóki nie ma ich co najmniej czternastu.", - "caveat": "Porównanie z twoją własną niedawną historią, a nie cel. Mówi, gdzie dziś jesteś względem swojego zwykłego wzorca o tej godzinie — i nic o tym, czy ten wzorzec jest dla ciebie właściwy." + "caveat": "Porównanie z twoją własną niedawną historią, a nie cel. Mówi, gdzie dziś jesteś względem swojego zwykłego wzorca o tej godzinie, i nic o tym, czy ten wzorzec jest dla ciebie właściwy." } }, "scores": { @@ -4388,31 +4388,31 @@ "allClear": "Dziś wszystkie Twoje parametry życiowe mieszczą się w osobistym zakresie.", "allClearMeta": "Sprawdzono {count} Twoich parametrów względem Twojego typowego zakresu.", "watch": "Dziś jeden parametr jest poza swoim zwykłym zakresem.", - "watchVital": "Poza zakresem: {vital}. Często to jednorazowy odczyt — warto obserwować przez kilka dni.", + "watchVital": "Poza zakresem: {vital}. Często to jednorazowy odczyt, warto obserwować przez kilka dni.", "firedHeadline": "Dziś {count} Twoich parametrów życiowych jest poza osobistym zakresem.", - "factors": "Możliwe czynniki — nigdy przyczyna: intensywny trening, słaby sen, alkohol, wysokość, stres lub choroba. To wskazówka z Twoich własnych baz, nie diagnoza.", - "building": "Budujemy Twoje osobiste bazy — zarejestruj jeszcze kilka dni, a to się pojawi.", + "factors": "Możliwe czynniki (nigdy przyczyna): intensywny trening, słaby sen, alkohol, wysokość, stres lub choroba. To wskazówka z Twoich własnych baz, nie diagnoza.", + "building": "Budujemy Twoje osobiste bazy. Zarejestruj jeszcze kilka dni, a to się pojawi.", "illnessExplained": "Te odchylenia prawdopodobnie wynikają z zapisanego schorzenia." }, "trajectory": { "cardTitle": "Krótkoterminowy rzut", - "headline": "Jeśli ten wzorzec się utrzyma — następne {days} dni", + "headline": "Jeśli ten wzorzec się utrzyma: następne {days} dni", "range": "Rzutowane na około {low}–{high} {unit} za {days} dni.", "caveat": "Rzut Twojego własnego ostatniego trendu, nie prognoza. Zacieniony pas poszerza się, pokazując, jak szybko rośnie niepewność.", - "insufficient": "Jeszcze brak wystarczająco wyraźnego trendu do rzutowania — rejestruj dalej, a rzut pojawi się, gdy ostatni wzorzec będzie dość wyraźny.", + "insufficient": "Jeszcze brak wystarczająco wyraźnego trendu do rzutowania. Rejestruj dalej, a rzut pojawi się, gdy ostatni wzorzec będzie dość wyraźny.", "daysNeeded": "Potrzeba jeszcze około {count} dni rejestrowania, zanim pojawi się rzut." }, "sameTime": { "sectionTitle": "Dziś do tej pory", "sectionSubtitle": "Twoje sumy narastające względem tego, co o tej godzinie jest u ciebie zwykłe", - "learning": "Uczę się twojego zwykłego dnia — {count} z {target} dni", + "learning": "Uczę się twojego zwykłego dnia: {count} z {target} dni", "framing": "Zwykle do {time}: {typical} {unit}", "comparisonLabel": "Twój zwykły dzień" } }, "cardioFitness": { "title": "Wydolność", - "description": "Twoje VO₂ max w czasie — główna miara wydolności tlenowej.", + "description": "Twoje VO₂ max w czasie, główna miara wydolności tlenowej.", "chartTitle": "VO₂ max (mL/(kg·min))", "emptyState": { "title": "Brak danych o wydolności", @@ -4492,7 +4492,7 @@ "navBreathingDisturbances": "Oddychanie", "rhythmEvents": { "sectionTitle": "Powiadomienia zdrowotne urządzenia", - "sectionIntro": "Powiadomienia, które zegarek wysłał samodzielnie. HealthLog jedynie je wyświetla — nie wykrywa ich, nie potwierdza ani nie interpretuje.", + "sectionIntro": "Powiadomienia, które zegarek wysłał samodzielnie. HealthLog jedynie je wyświetla: nie wykrywa ich, nie potwierdza ani nie interpretuje.", "loadError": "Nie udało się wczytać powiadomień urządzenia.", "disclaimer": "To alerty wygenerowane przez Twoje urządzenie za pomocą jego wbudowanego wykrywania. Są tu pokazywane wyłącznie dla Twojej informacji. To nie jest ocena medyczna wykonana przez HealthLog, a HealthLog nie diagnozuje żadnych schorzeń. Jeśli powiadomienie Cię niepokoi, skontaktuj się z lekarzem.", "event": { @@ -4537,13 +4537,13 @@ "detail": "Ukryte strony szczegółów znikają również z górnej nawigacji." }, "customize": "Dostosuj Analizy", - "regenerateRateLimited": "Osiągnięto limit odświeżeń — spróbuj ponownie później.", - "regenerateUnavailable": "Nie otrzymano nowej analizy — spróbuj ponownie później.", - "regenerateError": "Trwa odświeżanie — spróbuj ponownie za chwilę.", + "regenerateRateLimited": "Osiągnięto limit odświeżeń. Spróbuj ponownie później.", + "regenerateUnavailable": "Nie otrzymano nowej analizy. Spróbuj ponownie później.", + "regenerateError": "Trwa odświeżanie. Spróbuj ponownie za chwilę.", "regenerateSettling": "Ocena jest wciąż przygotowywana", "regenerateSettleFailed": "Nie udało się ukończyć odświeżania. Spróbuj ponownie później.", "deviceScore": { - "learning": "Wciąż poznajemy Twoją linię bazową – kilka kolejnych nocy uzupełni trend.", + "learning": "Wciąż poznajemy Twoją linię bazową. Kilka kolejnych nocy uzupełni trend.", "average": "Średnia z 30 dni {value}", "unitScore": "pkt", "unitMinutes": "min", @@ -4556,14 +4556,14 @@ }, "recovery": { "title": "Regeneracja", - "description": "Jak dobrze Twój organizm się zregenerował – sygnały regeneracji, obciążenia i load, które Twoje urządzenie rejestruje w nocy.", + "description": "Jak dobrze Twój organizm się zregenerował: sygnały regeneracji, obciążenia i load, które Twoje urządzenie rejestruje w nocy.", "scoreCrossLink": "Zobacz łączny wynik regeneracji", "emptyTitle": "Brak danych o regeneracji", "empty": "Brak danych o regeneracji. Połącz konto WHOOP, Polar lub Oura, a te wyniki uzupełnią się po synchronizacji urządzenia.", "block": { - "ansChargeExplainer": "Jak naładowany jest Twój autonomiczny układ nerwowy na dany dzień — odczyt regeneracji oparty na nocnych sygnałach serca i oddechu.", + "ansChargeExplainer": "Jak naładowany jest Twój autonomiczny układ nerwowy na dany dzień: odczyt regeneracji oparty na nocnych sygnałach serca i oddechu.", "dayStrainExplainer": "Dzienne obciążenie sercowo-naczyniowe na skali wysiłku Twojego urządzenia. Odczytuj je w odniesieniu do regeneracji, nie jako cel sam w sobie.", - "workoutStrainExplainer": "Jak wymagający był pojedynczy trening na tej samej skali wysiłku — koszt sercowo-naczyniowy tej sesji.", + "workoutStrainExplainer": "Jak wymagający był pojedynczy trening na tej samej skali wysiłku, czyli koszt sercowo-naczyniowy tej sesji.", "cardioLoadExplainer": "Przybliżenie obciążenia treningowego, które śledzi nagromadzone obciążenie sercowo-naczyniowe. Porównuj je z własnymi ostatnimi dniami.", "averageHeartRateExplainer": "Twoje średnie tętno w ciągu całego dnia lub cyklu, zgodnie z odczytem Twojego urządzenia.", "maxHeartRateExplainer": "Twoje maksymalne tętno w ciągu całego dnia lub cyklu, zgodnie z odczytem Twojego urządzenia.", @@ -4575,8 +4575,8 @@ "subtitle": "Nocne odchylenie od Twojej linii bazowej" }, "resilience": { - "explainer": "Jak dobrze Twój organizm równoważy codzienne obciążenie z regeneracją — odczytane z nocnych sygnałów z ostatnich dni.", - "learning": "Wciąż poznajemy Twoją odporność — kilka kolejnych dni ustali poziom.", + "explainer": "Jak dobrze Twój organizm równoważy codzienne obciążenie z regeneracją, odczytane z nocnych sygnałów z ostatnich dni.", + "learning": "Wciąż poznajemy Twoją odporność. Kilka kolejnych dni ustali poziom.", "band": { "limited": "Ograniczona", "adequate": "Wystarczająca", @@ -4621,7 +4621,7 @@ "nights": "Śledzono {count} nocy", "indexLine": "ostatni średni indeks {value}", "eventsFlagged": "{count} zdarzeń oznaczonych przez urządzenie", - "disclaimer": "To sygnał przesiewowy, a nie diagnoza — skonsultuj się z lekarzem." + "disclaimer": "To sygnał przesiewowy, a nie diagnoza. Skonsultuj się z lekarzem." }, "labsChanges": { "sectionTitle": "Od ostatnich badań", @@ -4637,14 +4637,14 @@ "navWaistToHeight": "Talia/wzrost", "gripStrength": { "title": "Siła chwytu", - "description": "Maksymalna siła chwytu dłoni — solidny wskaźnik ogólnej siły ciała. Poniżej progu zależnego od płci (mężczyźni 27 kg, kobiety 16 kg) sygnalizuje prawdopodobną sarkopenię; odczyt prowadzi Twój własny trend.", + "description": "Maksymalna siła chwytu dłoni, solidny wskaźnik ogólnej siły ciała. Poniżej progu zależnego od płci (mężczyźni 27 kg, kobiety 16 kg) sygnalizuje prawdopodobną sarkopenię; odczyt prowadzi Twój własny trend.", "chartTitle": "Siła chwytu", "emptyState": { "title": "Brak pomiarów siły chwytu", "description": "Zapisz pomiar z dynamometru ręcznego (zanotuj najlepszy z kilku ściśnięć), a trend pojawi się tutaj.", "cta": "Zapisz siłę chwytu" }, - "coachPrefill": "Nie zapisałem jeszcze siły chwytu — co mówi o zdrowiu moich mięśni i jak ją zmierzyć oraz poprawić?" + "coachPrefill": "Nie zapisałem jeszcze siły chwytu. Co mówi o zdrowiu moich mięśni i jak ją zmierzyć oraz poprawić?" }, "pain": { "title": "Ból (0–10)", @@ -4655,29 +4655,29 @@ "description": "Zapisz, jak odczuwasz ból teraz, w skali 0–10, a trend pojawi się tutaj.", "cta": "Zapisz ocenę bólu" }, - "coachPrefill": "Nie zapisałem jeszcze ocen bólu — jak śledzić ból w skali 0–10 i co liczy się jako istotna zmiana?" + "coachPrefill": "Nie zapisałem jeszcze ocen bólu. Jak śledzić ból w skali 0–10 i co liczy się jako istotna zmiana?" }, "waist": { "title": "Obwód talii", - "description": "Obwód talii w centymetrach — wskaźnik tłuszczu brzusznego. Próg zwiększonego ryzyka WHO zależy od płci (mężczyźni 94 cm, kobiety 80 cm); odczyt prowadzi Twój własny trend.", + "description": "Obwód talii w centymetrach, wskaźnik tłuszczu brzusznego. Próg zwiększonego ryzyka WHO zależy od płci (mężczyźni 94 cm, kobiety 80 cm); odczyt prowadzi Twój własny trend.", "chartTitle": "Obwód talii", "emptyState": { "title": "Brak pomiarów talii", "description": "Zmierz talię w połowie odległości między najniższym żebrem a kością biodrową, na końcu normalnego wydechu, i zapisz tutaj.", "cta": "Zapisz obwód talii" }, - "coachPrefill": "Nie zapisałem jeszcze pomiarów talii — jak prawidłowo zmierzyć talię i co oznacza ta liczba dla mojego zdrowia?" + "coachPrefill": "Nie zapisałem jeszcze pomiarów talii. Jak prawidłowo zmierzyć talię i co oznacza ta liczba dla mojego zdrowia?" }, "waistToHeight": { "title": "Stosunek talii do wzrostu", - "description": "Twoja talia podzielona przez wzrost — najbardziej uniwersalna pojedyncza liczba. Utrzymanie go poniżej 0,5 (talia mniejsza niż połowa wzrostu) to prosty cel.", + "description": "Twoja talia podzielona przez wzrost: najbardziej uniwersalna pojedyncza liczba. Utrzymanie go poniżej 0,5 (talia mniejsza niż połowa wzrostu) to prosty cel.", "chartTitle": "Stosunek talii do wzrostu", "emptyState": { "title": "Brak stosunku talii do wzrostu", "description": "Zapisz stosunek talii do wzrostu, a trend pojawi się tutaj. Zasada: utrzymuj talię poniżej połowy wzrostu.", "cta": "Zapisz stosunek talii do wzrostu" }, - "coachPrefill": "Nie zapisałem jeszcze stosunku talii do wzrostu — dlaczego to przydatna liczba i jak utrzymać ją poniżej 0,5?" + "coachPrefill": "Nie zapisałem jeszcze stosunku talii do wzrostu. Dlaczego to przydatna liczba i jak utrzymać ją poniżej 0,5?" }, "ecg": { "sectionTitle": "Zapisy EKG", @@ -4720,7 +4720,7 @@ "intradayPulse": { "title": "Tętno w ciągu dnia", "caption": "Uśrednione w krokach co 10 minut.", - "hourlyNote": "Pokazano średnią godzinową dla tego dnia — ostatnie dni pokazują pełny, 10-minutowy szczegół.", + "hourlyNote": "Pokazano średnią godzinową dla tego dnia. Ostatnie dni pokazują pełny, 10-minutowy szczegół.", "empty": "Za mało pomiarów z tego dnia, aby pokazać jego przebieg.", "coverageOne": "Na podstawie 1 pomiaru w ciągu {hours}h.", "coverageMany": "Na podstawie {count} pomiarów w ciągu {hours}h.", @@ -4729,10 +4729,10 @@ "previousDay": "Poprzedni dzień", "nextDay": "Następny dzień", "tension": { - "morning": "Utrzymujący się podwyższony spoczynek rano — możliwe napięcie.", - "afternoon": "Utrzymujący się podwyższony spoczynek po południu — możliwe napięcie.", - "evening": "Utrzymujący się podwyższony spoczynek wieczorem — możliwe napięcie.", - "night": "Utrzymujący się podwyższony spoczynek w nocy — możliwe napięcie." + "morning": "Utrzymujący się podwyższony spoczynek rano: możliwe napięcie.", + "afternoon": "Utrzymujący się podwyższony spoczynek po południu: możliwe napięcie.", + "evening": "Utrzymujący się podwyższony spoczynek wieczorem: możliwe napięcie.", + "night": "Utrzymujący się podwyższony spoczynek w nocy: możliwe napięcie." } }, "navEcg": "EKG", @@ -4785,14 +4785,14 @@ "metricBodyFat": "Tkanka tłuszczowa", "metricSleep": "Czas snu", "metricSteps": "Kroki/dzień", - "metricGlucoseFasting": "Glikemia — na czczo", - "metricGlucosePostprandial": "Glikemia — po posiłku", - "metricGlucoseRandom": "Glikemia — dowolna", - "metricGlucoseBedtime": "Glikemia — przed snem", + "metricGlucoseFasting": "Glikemia: na czczo", + "metricGlucosePostprandial": "Glikemia: po posiłku", + "metricGlucoseRandom": "Glikemia: dowolna", + "metricGlucoseBedtime": "Glikemia: przed snem", "metricBodyWater": "Woda w organizmie", "metricBoneMass": "Masa kostna", "metricOxygenSaturation": "Saturacja tlenem (SpO₂)", - "unsetExplanation": "Brak własnej wartości — aktywna jest wartość domyślna.", + "unsetExplanation": "Brak własnej wartości, aktywna jest wartość domyślna.", "cardTitle": "Zakresy według metryki" }, "onboarding": { @@ -4806,11 +4806,11 @@ "steps": { "dashboardOverview": { "title": "Twój pulpit", - "body": "Pulpit zbiera wszystkie moduły na jednym ekranie. Przytrzymaj kafelek, aby go przestawić lub ukryć (Ustawienia → Układ pulpitu). Kafelek jest wart tyle, ile dane za nim — kolejne moduły je wypełniają." + "body": "Pulpit zbiera wszystkie moduły na jednym ekranie. Przytrzymaj kafelek, aby go przestawić lub ukryć (Ustawienia → Układ pulpitu). Kafelek jest wart tyle, ile dane za nim, a kolejne moduły je wypełniają." }, "quickAdd": { "title": "Zapisane w kilka sekund", - "body": "Przez „+ Dodaj” zapiszesz każdy pomiar w sekundy — wagę, ciśnienie, tętno, glukozę. Ukryta moc: datowanie wstecz zapomnianych wartości. Wszystko, co tu wpiszesz, zasila trendy, wynik zdrowia i analizy AI." + "body": "Przez „+ Dodaj” zapiszesz każdy pomiar w sekundy: wagę, ciśnienie, tętno, glukozę. Ukryta moc: datowanie wstecz zapomnianych wartości. Wszystko, co tu wpiszesz, zasila trendy, wynik zdrowia i analizy AI." }, "measurements": { "title": "Pomiary i zakresy docelowe", @@ -4822,7 +4822,7 @@ }, "labs": { "title": "Wyniki laboratoryjne", - "body": "Laboratorium gromadzi biomarkery z zakresami referencyjnymi — morfologia, cholesterol, HbA1c. Atut: import i eksport FHIR. Wartości poza zakresem wracają jako dowody w analizach i w raporcie dla lekarza." + "body": "Laboratorium gromadzi biomarkery z zakresami referencyjnymi: morfologia, cholesterol, HbA1c. Atut: import i eksport FHIR. Wartości poza zakresem wracają jako dowody w analizach i w raporcie dla lekarza." }, "illness": { "title": "Dziennik chorób", @@ -4838,15 +4838,15 @@ }, "mood": { "title": "Nastrój", - "body": "Nastrój zapisuje samopoczucie i tagi w dwie sekundy. Atut: własne tagi. Trendy nastroju korelują ze snem, lekami i cyklem — Coach dostrzega wzorce." + "body": "Nastrój zapisuje samopoczucie i tagi w dwie sekundy. Atut: własne tagi. Trendy nastroju korelują ze snem, lekami i cyklem, a Coach dostrzega wzorce." }, "insights": { "title": "Analizy", - "body": "Analizy to serce aplikacji: dynamiczna analiza oparta na dowodach zamiast ogólnych porad — każde stwierdzenie wskazuje na Twoje realne dane. Ukryte: układ można dostosować. Analizy łączą wszystko, co dostarczają moduły powyżej." + "body": "Analizy to serce aplikacji: dynamiczna analiza oparta na dowodach zamiast ogólnych porad, a każde stwierdzenie wskazuje na Twoje realne dane. Ukryte: układ można dostosować. Analizy łączą wszystko, co dostarczają moduły powyżej." }, "coach": { "title": "Coach", - "body": "Coach odpowiada na pytania o Twoje dane w dialogu, korzystając z wywiadu, leków i wyników jako kontekstu. Dostawcę AI wybierasz sam (własny klucz lub lokalnie). Niczego nie przelicza — czyta te same liczby co pulpit." + "body": "Coach odpowiada na pytania o Twoje dane w dialogu, korzystając z wywiadu, leków i wyników jako kontekstu. Dostawcę AI wybierasz sam (własny klucz lub lokalnie). Niczego nie przelicza, czyta te same liczby co pulpit." }, "integrations": { "title": "Integracje", @@ -4854,15 +4854,15 @@ }, "export": { "title": "Raport dla lekarza", - "body": "Raport dla lekarza łączy pomiary, leki, wyniki laboratoryjne i badania w PDF lub FHIR na wizytę. Tu zbiegają się wszystkie moduły — pełny raport powstaje tylko z zadbanych danych." + "body": "Raport dla lekarza łączy pomiary, leki, wyniki laboratoryjne i badania w PDF lub FHIR na wizytę. Tu zbiegają się wszystkie moduły, więc pełny raport powstaje tylko z zadbanych danych." }, "achievements": { "title": "Osiągnięcia", - "body": "Osiągnięcia nagradzają konsekwencję — passy i kamienie milowe. Mała pętla motywacji, dzięki której łatwiej wytrwać." + "body": "Osiągnięcia nagradzają konsekwencję: passy i kamienie milowe. Mała pętla motywacji, dzięki której łatwiej wytrwać." }, "wrapUp": { "title": "To koniec przewodnika", - "body": "Ten przewodnik pokazuje się tylko raz — nie otworzy się ponownie sam. Wszystko, co pokazał, zostaje na miejscu, a funkcje możesz włączać i wyłączać w dowolnym momencie w Ustawienia → Moduły." + "body": "Ten przewodnik pokazuje się tylko raz i nie otworzy się ponownie sam. Wszystko, co pokazał, zostaje na miejscu, a funkcje możesz włączać i wyłączać w dowolnym momencie w Ustawienia → Moduły." } } }, @@ -4893,7 +4893,7 @@ "title": "Wszystko gotowe", "body": "Witaj na pokładzie. Pulpit czeka na Ciebie.", "returnCta": "Otwórz pulpit", - "learning": "Niektóre wnioski — glukoza, rytm snu, trendy ciśnienia, cykl — wyostrzają się w ciągu pierwszego tygodnia lub dwóch, w miarę gromadzenia danych. Puste kafelki oznaczają teraz tylko, że wciąż poznajemy Twój punkt odniesienia.", + "learning": "Niektóre wnioski (glukoza, rytm snu, trendy ciśnienia, cykl) wyostrzają się w ciągu pierwszego tygodnia lub dwóch, w miarę gromadzenia danych. Puste kafelki oznaczają teraz tylko, że wciąż poznajemy Twój punkt odniesienia.", "connectCta": "Połącz urządzenie", "logCta": "Zapisz pierwszy pomiar", "importCta": "Importuj istniejącą historię", @@ -4910,33 +4910,33 @@ "anamnesis": { "title": "O Twoim zdrowiu (opcjonalnie)", "subtitle": "Trochę kontekstu, aby HealthLog rzetelniej odczytywał Twoje wyniki.", - "intro": "Podziel się tym, czym chcesz — każde pole jest opcjonalne i możesz je zmienić w dowolnej chwili w Ustawieniach.", + "intro": "Podziel się tym, czym chcesz. Każde pole jest opcjonalne i możesz je zmienić w dowolnej chwili w Ustawieniach.", "conditionsLabel": "Aktualne schorzenia", "conditionsPlaceholder": "np. nadciśnienie, cukrzyca typu 2", "conditionsHint": "Pomaga HealthLog ujmować Twoje pomiary w kontekście, zamiast oznaczać to, czego należy się spodziewać.", "allergiesLabel": "Alergie lub nietolerancje", "allergiesPlaceholder": "np. penicylina, laktoza", - "privacyNote": "Przechowywane w postaci zaszyfrowanej i używane tylko po to, by dać Ci lepszy kontekst. Nie pytamy tu o leki — dodasz je w dowolnej chwili na stronie Leki." + "privacyNote": "Przechowywane w postaci zaszyfrowanej i używane tylko po to, by dać Ci lepszy kontekst. Nie pytamy tu o leki, dodasz je w dowolnej chwili na stronie Leki." }, "ai": { "panelTitle": "Zobacz, jak wyglądają insighty", - "panelIntro": "Coach, codzienny briefing i oceny dla poszczególnych metryk zamieniają Twoje własne liczby w prosty język. Oto jak to wygląda — zanim cokolwiek podłączysz.", + "panelIntro": "Coach, codzienny briefing i oceny dla poszczególnych metryk zamieniają Twoje własne liczby w prosty język. Oto jak to wygląda, zanim cokolwiek podłączysz.", "showSample": "Zobacz przykładowy briefing", "sampleTitle": "Codzienny briefing", "sampleTag": "Przykład", "sampleAriaLabel": "Przykładowy codzienny briefing", - "sampleBody": "Waga niższa o 1,2 kg w ciągu dwóch tygodni. Tętno spoczynkowe stabilne na 58 bpm. Ciśnienie w normie przez 6 z 7 dni — jedyny wysoki odczyt nastąpił po późnej, słonej kolacji.", - "sampleCaption": "Tylko przykład — to nie są Twoje dane. Tak czyta się briefing, gdy insighty są włączone.", + "sampleBody": "Waga niższa o 1,2 kg w ciągu dwóch tygodni. Tętno spoczynkowe stabilne na 58 bpm. Ciśnienie w normie przez 6 z 7 dni; jedyny wysoki odczyt nastąpił po późnej, słonej kolacji.", + "sampleCaption": "Tylko przykład, to nie są Twoje dane. Tak czyta się briefing, gdy insighty są włączone.", "ladderTitle": "Trzy sposoby, by to włączyć", - "ladderLocalTitle": "Model lokalny — zapytania do AI zostają w Twojej sieci", - "ladderLocalBody": "Skieruj HealthLog na Ollama lub LM Studio na własnej maszynie. Za darmo i w pełni prywatnie — spokojny wybór domyślny.", + "ladderLocalTitle": "Model lokalny: zapytania do AI zostają w Twojej sieci", + "ladderLocalBody": "Skieruj HealthLog na Ollama lub LM Studio na własnej maszynie. Za darmo i w pełni prywatnie: spokojny wybór domyślny.", "ladderByokTitle": "Użyj własnego klucza", "ladderByokBody": "Użyj własnego klucza OpenAI lub Anthropic. Działa na Twoim koncie i rozliczeniu, a poziom API domyślnie wyklucza Twoje dane z treningu.", "ladderOauthTitle": "Zaloguj się przez subskrypcję", - "ladderOauthBody": "Podłącz konto ChatGPT — bez kosztu za token, ale warunki poziomu konsumenckiego mogą wykorzystywać treści do treningu, więc to świadomy wybór, nigdy domyślny dla danych o zdrowiu.", - "keylessLine": "HealthLog jest w pełni użyteczny bez AI. Twoje kafelki, wykresy, trendy i eksporty działają — AI dokłada tylko odczyt prostym językiem.", + "ladderOauthBody": "Podłącz konto ChatGPT. Bez kosztu za token, ale warunki poziomu konsumenckiego mogą wykorzystywać treści do treningu, więc to świadomy wybór, nigdy domyślny dla danych o zdrowiu.", + "keylessLine": "HealthLog jest w pełni użyteczny bez AI. Twoje kafelki, wykresy, trendy i eksporty działają; AI dokłada tylko odczyt prostym językiem.", "setupCta": "Skonfiguruj (około minuty)", - "sharedKeyNote": "Ta instancja udostępnia już wspólnego dostawcę AI, więc insighty działają dla Ciebie od razu — bez konfiguracji.", + "sharedKeyNote": "Ta instancja udostępnia już wspólnego dostawcę AI, więc insighty działają dla Ciebie od razu, bez konfiguracji.", "offer": { "title": "Ta instancja potrafi już napisać twoje podsumowanie zwykłym językiem.", "body": "Operator udostępnia dostawcę, który działał po raz ostatni w ciągu ostatnich 24 godzin. Jedno dotknięcie włącza zwykły język; twoje dane trafią wtedy do tego jednego dostawcy i do nikogo więcej.", @@ -5153,7 +5153,7 @@ "profileDescription": "Wzrost, data urodzenia i płeć odblokowują spersonalizowane cele.", "profileCta": "Otwórz profil", "measurementTitle": "Zarejestruj pierwszy pomiar", - "measurementDescription": "Jeden pomiar aktywuje kafelek — trend rysuje się od 5. pomiaru.", + "measurementDescription": "Jeden pomiar aktywuje kafelek, a trend rysuje się od 5. pomiaru.", "measurementCta": "Dodaj pomiar", "medicationTitle": "Dodaj lek", "medicationDescription": "Śledź przestrzeganie i otrzymuj przypomnienia dokładnie wtedy, kiedy ich potrzebujesz.", @@ -5162,7 +5162,7 @@ "dataSourceDescription": "Automatycznie synchronizuj wagę, ciśnienie, sen i więcej z Withings, WHOOP, Oura, Polar, Nightscout, Fitbit lub Apple Health.", "dataSourceCta": "Połącz", "notificationsTitle": "Skonfiguruj powiadomienia", - "notificationsDescription": "Wybierz, jak HealthLog ma ci przypominać — Telegram, ntfy lub Web Push.", + "notificationsDescription": "Wybierz, jak HealthLog ma ci przypominać: Telegram, ntfy lub Web Push.", "notificationsCta": "Otwórz powiadomienia", "insightsTitle": "Włącz insighty (opcjonalnie)", "insightsDescription": "Dodaj model lokalny lub własny klucz AI, aby odblokować codzienny briefing i Coach.", @@ -5388,7 +5388,7 @@ "resetSuccess": "Przywrócono domyślny priorytet źródeł", "perMetricToggle": "Ustawienia dla poszczególnych metryk ({count})", "perMetricHelp": "Metryki dostosowane względem domyślnej kolejności. Użyj tej listy, aby przywrócić pojedynczą metrykę do wartości domyślnej, nie zmieniając pozostałych.", - "perMetricEmpty": "Brak indywidualnych ustawień — każda metryka korzysta z globalnej kolejności powyżej.", + "perMetricEmpty": "Brak indywidualnych ustawień. Każda metryka korzysta z globalnej kolejności powyżej.", "resetMetric": "Resetuj", "deviceTypeToggle": "Priorytet według typu urządzenia ({count})", "deviceTypeHelp": "W obrębie źródła decyduje, które urządzenie wygrywa. Gdy Apple Watch i iPhone rejestrują kroki, wyżej sklasyfikowany typ urządzenia liczy się jako odczyt kanoniczny.", @@ -5452,7 +5452,7 @@ "daysWithData": "{count} z {days} dni", "moduleHint": "Synchronizacją steruje moduł spożycia składników odżywczych.", "moduleHintLink": "Zarządzaj modułami", - "detail": "Tylko do odczytu — wartości należą do aplikacji źródłowej." + "detail": "Tylko do odczytu: wartości należą do aplikacji źródłowej." }, "helpDetail": "Pozostałe pozostają zapisane na potrzeby audytu. Widać tylko źródła, które połączono lub z których są dane.", "noneInUse": "Nie ma jeszcze źródeł do uszeregowania. Połącz jedno w Integracjach albo wpisz wartość." @@ -5497,12 +5497,12 @@ "fullBackup": { "title": "Pełna kopia zapasowa", "description": "Cała dokumentacja w jednym pliku JSON.", - "scopeNote": "Metadane dokumentów oraz podsumowanie AI, jeśli istnieje, są uwzględnione jako czysty tekst; oryginalne pliki dokumentów oraz dane tras GPS/próbek treningów nie są uwzględnione — pobierz je osobno z archiwum dokumentów lub eksportu treningów.", + "scopeNote": "Metadane dokumentów oraz podsumowanie AI, jeśli istnieje, są uwzględnione jako czysty tekst; oryginalne pliki dokumentów oraz dane tras GPS/próbek treningów nie są uwzględnione. Pobierz je osobno z archiwum dokumentów lub eksportu treningów.", "encryptToggle": "Zaszyfruj hasłem-frazą", "passphrasePlaceholder": "Hasło-fraza (min. 12 znaków)", "passphraseHelp": "Wyprowadza klucz archiwum za pomocą Argon2id i pieczętuje je AES-256-GCM. Zapisz plik z rozszerzeniem .hlx.", - "noRecoveryWarning": "Nie ma odzyskiwania — jeśli zgubisz tę frazę, archiwum nie da się otworzyć. Przechowuj ją bezpiecznie.", - "detail": "Ten sam kształt co cotygodniowa kopia automatyczna. Niektóre rodzaje wpisów nie są jeszcze przenoszone — manifest pliku wskazuje, co zawiera.", + "noRecoveryWarning": "Nie ma odzyskiwania: jeśli zgubisz tę frazę, archiwum nie da się otworzyć. Przechowuj ją bezpiecznie.", + "detail": "Ten sam kształt co cotygodniowa kopia automatyczna. Niektóre rodzaje wpisów nie są jeszcze przenoszone; manifest pliku wskazuje, co zawiera.", "contents": "Twoje pomiary, leki, nastrój, cykl, wyniki badań, epizody chorobowe, alergie, wywiad rodzinny, składniki odżywcze, treningi, Twój profil zdrowia i własne wskaźniki w jednym pliku JSON." } }, @@ -5745,7 +5745,7 @@ "error": "Nie udało się zapisać. Spróbuj ponownie.", "toggleable": { "title": "Co śledzisz", - "description": "Wyłączone moduły znikają z nawigacji, kafelków i analiz — Twoje dane pozostają nienaruszone." + "description": "Wyłączone moduły znikają z nawigacji, kafelków i analiz, a Twoje dane pozostają nienaruszone." }, "manageIn": "Zarządzaj w {section}", "operatorDisabled": "Wyłączone na całym serwerze", @@ -5865,7 +5865,7 @@ "omitted": "{count} filarów nie ma na liście, bo ich śledzenie jest wyłączone. Włącz moduł z powrotem, a jego filar wróci.", "omittedLink": "Otwórz moduły", "refusal": { - "empty": "Wynik zdrowia potrzebuje co najmniej jednego obszaru zdrowia do oceny. Zostaw wybrany przynajmniej jeden — wynik sam powie, na których obszarach się opiera." + "empty": "Wynik zdrowia potrzebuje co najmniej jednego obszaru zdrowia do oceny. Zostaw wybrany przynajmniej jeden, a wynik sam powie, na których obszarach się opiera." }, "notice": { "upgrade": { @@ -6048,7 +6048,7 @@ "rawDataWarning": "Szczegółowa historia jest włączona: każda analiza wysyła dodatkowo średnie dzienne z ostatnich 90 dni, średnie tygodniowe z roku wcześniej i średnie miesięczne do 5 lat wstecz.", "regenerateInsights": "Wygeneruj raporty ponownie", "regenerateSuccess": "Raporty wygenerowane ponownie", - "regenerateRateLimit": "Poczekaj — osiągnięto godzinny limit analiz.", + "regenerateRateLimit": "Poczekaj, osiągnięto godzinny limit analiz.", "lastGeneratedAt": "Ostatnio wygenerowano", "ai": { "chatgptConnectedBadge": "ChatGPT połączony", @@ -6058,11 +6058,11 @@ "deviceCodeHeading": "Dokończ łączenie na chatgpt.com", "deviceCodeStep1": "Otwórz ten link na dowolnym urządzeniu:", "deviceCodeStep2": "Wprowadź ten jednorazowy kod:", - "deviceCodeStep3": "Zatwierdź połączenie — ta strona zaktualizuje się automatycznie.", + "deviceCodeStep3": "Zatwierdź połączenie. Ta strona zaktualizuje się automatycznie.", "deviceCodeCopy": "Kopiuj", "deviceCodeWaiting": "Oczekiwanie na zatwierdzenie…", "deviceCodeCancel": "Anuluj", - "oauthNotConfigured": "OAuth ChatGPT nie jest skonfigurowany w tej instancji — użyj zamiast tego własnego klucza API poniżej.", + "oauthNotConfigured": "OAuth ChatGPT nie jest skonfigurowany w tej instancji. Użyj zamiast tego własnego klucza API poniżej.", "modelLabel": "Model", "modelOptionDefault": "— Domyślny —", "modelOptionCustom": "Niestandardowy…", @@ -6070,7 +6070,7 @@ "anthropicKeyLabel": "Klucz API Anthropic", "baseUrlLabel": "Base URL", "localKeyLabel": "Klucz API (opcjonalny)", - "localDescription": "Działa tu każdy punkt końcowy zgodny z OpenAI — model lokalny (Ollama, LM Studio) albo brama taka jak LiteLLM, OpenRouter czy vLLM. Adres bazowy kończy się na /v1; klucz API jest opcjonalny.", + "localDescription": "Działa tu każdy punkt końcowy zgodny z OpenAI: model lokalny (Ollama, LM Studio) albo brama taka jak LiteLLM, OpenRouter czy vLLM. Adres bazowy kończy się na /v1; klucz API jest opcjonalny.", "savedPreview": "(zapisano {preview})", "savedShort": "(zapisano)", "saveCta": "Zapisz", @@ -6110,7 +6110,7 @@ "admin-openai": "OpenAI udostępniony przez administratora" }, "compat": { - "description": "Pełnoprawny dostawca dla każdego punktu końcowego mówiącego API /v1/chat/completions OpenAI: LiteLLM, OpenRouter, vLLM lub inna brama. Adres bazowy kończy się na /v1, klucz API jest opcjonalny, a model to ten, który kieruje twoja brama. Twój klucz OpenAI nigdy nie trafia do tego punktu końcowego — ten dostawca ma własny.", + "description": "Pełnoprawny dostawca dla każdego punktu końcowego mówiącego API /v1/chat/completions OpenAI: LiteLLM, OpenRouter, vLLM lub inna brama. Adres bazowy kończy się na /v1, klucz API jest opcjonalny, a model to ten, który kieruje twoja brama. Twój klucz OpenAI nigdy nie trafia do tego punktu końcowego, bo ten dostawca ma własny.", "keyLabel": "Klucz API (opcjonalny)", "modelHint": "Nazwa modelu, której oczekuje twoja brama. Pozostawione puste, użyty zostanie model zapisany dla pozostałych dostawców; gdy nie ustawiono żadnego, ten dostawca jest pomijany." }, @@ -6146,18 +6146,18 @@ "notConfigured": "Operator nie skonfigurował współdzielonego klucza OpenAI w tej instancji." }, "testProvider": "Przetestuj aktywnego dostawcę", - "testSuccess": "OK — {provider} ({model})", + "testSuccess": "OK: {provider} ({model})", "testFailedShort": "Test nie powiódł się: {message}", - "testUnexpectedResponse": "Połączenie z dostawcą AI nie powiodło się — nieoczekiwana odpowiedź serwera.", - "testReasonCredentials": "Dostawca odrzucił dane logowania — uwierzytelnij się ponownie w ustawieniach AI.", - "testReasonRateLimited": "Dostawca ograniczył żądanie — spróbuj ponownie za chwilę.", + "testUnexpectedResponse": "Połączenie z dostawcą AI nie powiodło się: nieoczekiwana odpowiedź serwera.", + "testReasonCredentials": "Dostawca odrzucił dane logowania. Uwierzytelnij się ponownie w ustawieniach AI.", + "testReasonRateLimited": "Dostawca ograniczył żądanie. Spróbuj ponownie za chwilę.", "testReasonServerError": "Dostawca AI zwrócił błąd serwera.", - "testReasonBadRequest": "Dostawca odrzucił żądanie (HTTP {status}) — punkt końcowy odpowiedział, więc problem dotyczy formatu żądania lub nazwy modelu, a nie łączności.", + "testReasonBadRequest": "Dostawca odrzucił żądanie (HTTP {status}). Punkt końcowy odpowiedział, więc problem dotyczy formatu żądania lub nazwy modelu, a nie łączności.", "testReasonUnreachable": "Nie udało się połączyć z dostawcą AI.", "coachMemory": { "title": "Co Coach pamięta", "description": "Trwałe informacje, które przekazałeś Coachowi.", - "empty": "Coach nie zapisał jeszcze żadnych informacji. Podczas rozmowy zapamiętuje trwałe szczegóły, którymi się dzielisz — Twoje cele, dolegliwości, preferencje — i możesz je tutaj w każdej chwili usunąć.", + "empty": "Coach nie zapisał jeszcze żadnych informacji. Podczas rozmowy zapamiętuje trwałe szczegóły, którymi się dzielisz (Twoje cele, dolegliwości, preferencje), i możesz je tutaj w każdej chwili usunąć.", "learnedPrefix": "zapamiętano {when}", "categoryPreference": "Preferencje", "categoryCondition": "Dolegliwości", @@ -6173,7 +6173,7 @@ "forgetAllConfirmBody": "Spowoduje to usunięcie wszystkich zapisanych informacji. Coach zacznie od nowa przy następnej rozmowie. Tej operacji nie można cofnąć.", "forgetAllConfirmAction": "Zapomnij wszystko", "cancel": "Anuluj", - "summaryNote": "Coach może też przechowywać krótkie, bieżące podsumowanie każdej rozmowy. Nie ma dla niego osobnej kontrolki — usunięcie rozmowy usuwa jej podsumowanie.", + "summaryNote": "Coach może też przechowywać krótkie, bieżące podsumowanie każdej rozmowy. Nie ma dla niego osobnej kontrolki: usunięcie rozmowy usuwa jej podsumowanie.", "loadError": "Nie udało się wczytać tego, co Coach pamięta.", "forgotToast": "Informacja zapomniana.", "forgotError": "Nie udało się zapomnieć tej informacji. Spróbuj ponownie.", @@ -6194,7 +6194,7 @@ "markDone": "Gotowe", "dismiss": "Odrzuć", "deleteAria": "Usuń to przypomnienie", - "note": "Przypomnienia są przechowywane w postaci zaszyfrowanej. Usuń je w dowolnej chwili — znika z tego, co widzi Coach.", + "note": "Przypomnienia są przechowywane w postaci zaszyfrowanej. Usuń je w dowolnej chwili, a znikną z tego, co widzi Coach.", "status": { "proposed": "Sugerowane", "active": "Zapisane", @@ -6240,15 +6240,15 @@ "autoRead": { "title": "Automatyczne czytanie dokumentów przez AI", "subLabel": "Dokumenty są czytane i indeksowane przez skonfigurowanego dostawcę AI bez potwierdzania każdego dokumentu.", - "honesty": "Po włączeniu każdy przesłany dokument jest wysyłany do skonfigurowanego dostawcy AI, aby go odczytać, opisać i zaindeksować do wyszukiwania — bez potwierdzania każdego dokumentu. Włączenie działa też wstecz: dokumenty już przesłane, które nie mają jeszcze streszczenia, również zostaną wysłane — do 200 przy każdym włączeniu. Dzieje się to na serwerze, a treść dokumentu opuszcza to urządzenie i trafia do tego dostawcy. Jeśli skonfigurowany dostawca to połączenie subskrypcyjne (zalogowane konto AI zamiast klucza API), obowiązują jego własne ustawienia danych — dostawcy subskrypcyjni mogą wykorzystywać treść do ulepszania swoich modeli i nie obejmuje tego żadna umowa powierzenia przetwarzania danych. Dokumenty odczytywane przez samodzielnie hostowany model lokalny nigdy nie opuszczają Twojego serwera. Domyślnie wyłączone; włącz je tylko wtedy, gdy akceptujesz ten kompromis dla swoich dokumentów.", - "confirm": "Rozumiem — włącz", + "honesty": "Po włączeniu każdy przesłany dokument jest wysyłany do skonfigurowanego dostawcy AI, aby go odczytać, opisać i zaindeksować do wyszukiwania, bez potwierdzania każdego dokumentu. Włączenie działa też wstecz: dokumenty już przesłane, które nie mają jeszcze streszczenia, również zostaną wysłane (do 200 przy każdym włączeniu). Dzieje się to na serwerze, a treść dokumentu opuszcza to urządzenie i trafia do tego dostawcy. Jeśli skonfigurowany dostawca to połączenie subskrypcyjne (zalogowane konto AI zamiast klucza API), obowiązują jego własne ustawienia danych: dostawcy subskrypcyjni mogą wykorzystywać treść do ulepszania swoich modeli i nie obejmuje tego żadna umowa powierzenia przetwarzania danych. Dokumenty odczytywane przez samodzielnie hostowany model lokalny nigdy nie opuszczają Twojego serwera. Domyślnie wyłączone; włącz je tylko wtedy, gdy akceptujesz ten kompromis dla swoich dokumentów.", + "confirm": "Rozumiem, włącz", "cancel": "Anuluj" }, "centralCodex": { "title": "Użyj wspólnego dostępu AI serwera", "subLabel": "Zapytania AI idą przez wspólne połączenie serwera, a Twoi dostawcy służą jako zapas.", - "honesty": "Wspólny dostęp to jedno zalogowane konto AI, które operator podłączył dla wszystkich na tym serwerze — nie Twój własny klucz. Zapytania, które przez nie wysyłasz, są domyślnie wykorzystywane do trenowania modeli dostawcy i nie obejmuje ich żadna umowa powierzenia przetwarzania danych, godzinowe i tygodniowe limity konta dzielisz z wszystkimi innymi, którzy się zgodzili, a Twoi właśni dostawcy są próbowani jako pierwsi. Włącz to tylko, jeśli akceptujesz ten kompromis.", - "confirm": "Rozumiem — użyj połączenia", + "honesty": "Wspólny dostęp to jedno zalogowane konto AI, które operator podłączył dla wszystkich na tym serwerze, a nie Twój własny klucz. Zapytania, które przez nie wysyłasz, są domyślnie wykorzystywane do trenowania modeli dostawcy i nie obejmuje ich żadna umowa powierzenia przetwarzania danych, godzinowe i tygodniowe limity konta dzielisz z wszystkimi innymi, którzy się zgodzili, a Twoi właśni dostawcy są próbowani jako pierwsi. Włącz to tylko, jeśli akceptujesz ten kompromis.", + "confirm": "Rozumiem, użyj połączenia", "cancel": "Anuluj" }, "consent": { @@ -6324,8 +6324,8 @@ "withingsClientId": "ID klienta", "withingsClientSecret": "Sekret klienta", "withingsCredentialsSaved": "Dane logowania zapisane", - "withingsCredentialsSavedPlaceholder": "Zapisano — wprowadź nowy, aby zastąpić", - "withingsCredentialsSavedPlaceholderSecret": "Zapisano — wprowadź nowy, aby zastąpić", + "withingsCredentialsSavedPlaceholder": "Zapisano. Wprowadź nowy, aby zastąpić", + "withingsCredentialsSavedPlaceholderSecret": "Zapisano. Wprowadź nowy, aby zastąpić", "withingsSaveCredentials": "Zapisz", "configured": "Skonfigurowano", "withingsSync": "Synchronizuj teraz", @@ -6340,7 +6340,7 @@ }, "withingsFullSyncResult": "{count} pomiarów w pełni zsynchronizowano", "withingsSyncFailed": "Synchronizacja nie powiodła się", - "withingsOauthConnected": "Withings połączony — pierwsza synchronizacja rozpocznie się w tle.", + "withingsOauthConnected": "Withings połączony. Pierwsza synchronizacja rozpocznie się w tle.", "withingsOauthFailed": "Połączenie z Withings nie powiodło się", "withingsOauthError": { "csrf1": "Kontrola bezpieczeństwa nie powiodła się, ponieważ brakowało pliku cookie przeglądarki. Rozpocznij połączenie ponownie w tej samej przeglądarce.", @@ -6365,8 +6365,8 @@ "whoopClientId": "Client ID", "whoopClientSecret": "Client Secret", "whoopCredentialsSaved": "Dane zapisane", - "whoopCredentialsSavedPlaceholder": "Zapisano — wpisz nowe, aby zastąpić", - "whoopCredentialsSavedPlaceholderSecret": "Zapisano — wpisz nowe, aby zastąpić", + "whoopCredentialsSavedPlaceholder": "Zapisano. Wpisz nowe, aby zastąpić", + "whoopCredentialsSavedPlaceholderSecret": "Zapisano. Wpisz nowe, aby zastąpić", "whoopSaveCredentials": "Zapisz", "whoopSync": "Synchronizuj teraz", "whoopFullSync": "Synchronizuj wszystkie dane", @@ -6381,7 +6381,7 @@ "whoopConnect": "Połącz z WHOOP", "whoopNoCredentials": "Wprowadź powyżej swoje dane API, aby połączyć WHOOP.", "whoopBackfillInProgress": "Importowanie historii WHOOP w tle…", - "whoopOauthConnected": "WHOOP połączony — pierwsza synchronizacja startuje w tle.", + "whoopOauthConnected": "WHOOP połączony. Pierwsza synchronizacja startuje w tle.", "whoopOauthFailed": "Połączenie z WHOOP nie powiodło się", "whoopOauthError": { "csrf1": "Kontrola bezpieczeństwa nie powiodła się, ponieważ brakowało pliku cookie przeglądarki. Rozpocznij połączenie ponownie w tej samej przeglądarce.", @@ -6395,14 +6395,14 @@ }, "fitbit": "Fitbit", "fitbitTag": "Fitbit i Pixel", - "fitbitDescription": "Połącz Fitbit, aby synchronizować dane z Fitbit i Pixel Watch — wagę, tętno i więcej.", + "fitbitDescription": "Połącz Fitbit, aby synchronizować dane z Fitbit i Pixel Watch: wagę, tętno i więcej.", "fitbitExperimentalBadge": "Eksperymentalne", "fitbitCredentials": "Dane uwierzytelniające API", "fitbitClientId": "Client ID", "fitbitClientSecret": "Client Secret", "fitbitCredentialsSaved": "Dane uwierzytelniające zapisane", - "fitbitCredentialsSavedPlaceholder": "Zapisano — wpisz nowe, aby zastąpić", - "fitbitCredentialsSavedPlaceholderSecret": "Zapisano — wpisz nowe, aby zastąpić", + "fitbitCredentialsSavedPlaceholder": "Zapisano. Wpisz nowe, aby zastąpić", + "fitbitCredentialsSavedPlaceholderSecret": "Zapisano. Wpisz nowe, aby zastąpić", "fitbitSaveCredentials": "Zapisz", "fitbitSync": "Synchronizuj teraz", "fitbitFullSync": "Synchronizuj wszystkie dane", @@ -6417,18 +6417,18 @@ "fitbitConnect": "Połącz z Fitbit", "fitbitNoCredentials": "Wprowadź powyżej swoje dane uwierzytelniające API, aby połączyć Fitbit.", "fitbitBackfillInProgress": "Importowanie historii Fitbit w tle…", - "fitbitOauthConnected": "Fitbit połączony — pierwsza synchronizacja startuje w tle.", + "fitbitOauthConnected": "Fitbit połączony. Pierwsza synchronizacja startuje w tle.", "fitbitOauthFailed": "Połączenie z Fitbit nie powiodło się", "googleHealth": "Google Health", "googleHealthTag": "Fitbit i Pixel", "googleHealthBetaBadge": "Beta", - "googleHealthDescription": "Połącz Fitbit, Pixel Watch i Fitbit Air przez konto Google — waga, tętno, sen i aktywność. Zastępuje to klasyczne połączenie Fitbit, które Google wyłącza we wrześniu 2026.", + "googleHealthDescription": "Połącz Fitbit, Pixel Watch i Fitbit Air przez konto Google: waga, tętno, sen i aktywność. Zastępuje to klasyczne połączenie Fitbit, które Google wyłącza we wrześniu 2026.", "googleHealthCredentials": "Dane API", "googleHealthClientId": "Identyfikator klienta", "googleHealthClientSecret": "Sekret klienta", "googleHealthCredentialsSaved": "Dane logowania zapisane", - "googleHealthCredentialsSavedPlaceholder": "Zapisane — wpisz nowe, aby zastąpić", - "googleHealthCredentialsSavedPlaceholderSecret": "Zapisane — wpisz nowe, aby zastąpić", + "googleHealthCredentialsSavedPlaceholder": "Zapisane. Wpisz nowe, aby zastąpić", + "googleHealthCredentialsSavedPlaceholderSecret": "Zapisane. Wpisz nowe, aby zastąpić", "googleHealthSaveCredentials": "Zapisz", "googleHealthSync": "Synchronizuj teraz", "googleHealthSyncCheckStatus": "Odśwież stan", @@ -6462,9 +6462,9 @@ "googleHealthConnect": "Połącz z Google", "googleHealthNoCredentials": "Wprowadź powyżej swoje dane API, aby połączyć Google Health.", "googleHealthBackfillInProgress": "Importowanie historii Google Health w tle…", - "googleHealthReauthBanner": "Google unieważnił połączenie — dzieje się to okresowo, dopóki Twoja aplikacja OAuth pozostaje w trybie testowym. Połącz ponownie, aby wznowić synchronizację.", + "googleHealthReauthBanner": "Google unieważnił połączenie. Dzieje się to okresowo, dopóki Twoja aplikacja OAuth pozostaje w trybie testowym. Połącz ponownie, aby wznowić synchronizację.", "googleHealthReconnect": "Połącz ponownie", - "googleHealthOauthConnected": "Google Health połączony — pierwsza synchronizacja startuje w tle.", + "googleHealthOauthConnected": "Google Health połączony. Pierwsza synchronizacja startuje w tle.", "googleHealthOauthFailed": "Połączenie z Google Health nie powiodło się", "googleHealthOauthError": { "csrf1": "Kontrola bezpieczeństwa nie powiodła się, ponieważ brakowało pliku cookie przeglądarki. Rozpocznij połączenie ponownie w tej samej przeglądarce.", @@ -6499,10 +6499,10 @@ }, "integrationPill": { "connected": "Połączono", - "errorReconnect": "Błąd — połącz ponownie", + "errorReconnect": "Błąd: połącz ponownie", "warningServerError": "Synchronizacja nie działa", "failureCount": "{count}/{threshold}", - "parkedReconnect": "Wstrzymane — połącz ponownie", + "parkedReconnect": "Wstrzymane: połącz ponownie", "notConnected": "Nie połączono", "justNow": "przed chwilą", "minutesAgo": "{count} min temu", @@ -6536,7 +6536,7 @@ "title": "Tokeny pomiarów", "description": "Utwórz token, aby waga, zegarek lub automatyka domowa mogły dodawać pomiary.", "detail": "Token pokazujemy tylko raz.", - "scopeNote": "Może wyłącznie dodawać nowe pomiary do Twojej dokumentacji — nie odczyta danych, niczego nie zmieni ani nie usunie i nie utworzy kolejnego tokenu. Pomiary są oznaczane jako pochodzące z urządzenia zewnętrznego, dzięki czemu później je rozpoznasz, i nadal możesz je poprawić.", + "scopeNote": "Może wyłącznie dodawać nowe pomiary do Twojej dokumentacji: nie odczyta danych, niczego nie zmieni ani nie usunie i nie utworzy kolejnego tokenu. Pomiary są oznaczane jako pochodzące z urządzenia zewnętrznego, dzięki czemu później je rozpoznasz, i nadal możesz je poprawić.", "createFailed": "Nie udało się utworzyć tokenu. Spróbuj ponownie.", "namePlaceholder": "Nazwa, np. Home Assistant" }, @@ -6557,7 +6557,7 @@ "namePlaceholder": "Nazwa, np. Paperless-ngx" }, "tokenMintMovedDescription": "Tokeny wydajemy tam, gdzie działają: powyżej dla pomiarów, treningów i dokumentów albo w punkcie końcowym API danego leku dla tego jednego leku.", - "tokenCreated": "Token utworzony — skopiuj go teraz! Nie zostanie pokazany ponownie.", + "tokenCreated": "Token utworzony. Skopiuj go teraz! Nie zostanie pokazany ponownie.", "tokenCopy": "Kopiuj token", "tokenCopied": "Token skopiowany do schowka", "tokenCopyFailed": "Nie udało się skopiować tokenu", @@ -6596,7 +6596,7 @@ "deleteAccountCta": "Usuń konto", "deleteAccountConfirmTitle": "Trwale usunąć konto?", "deleteAccountConfirmDescription": "Twoje konto, wszystkie dane zdrowotne, klucze dostępu, sesje i wpisy audytu zostaną trwale usunięte. Zostaniesz wylogowany natychmiast po tym.", - "deleteAccountSuccess": "Konto usunięte — trwa wylogowywanie.", + "deleteAccountSuccess": "Konto usunięte, trwa wylogowywanie.", "deleteAccountFailed": "Nie udało się usunąć konta", "deleteAccountFinal": "Usuń trwale", "saved": "Zapisano", @@ -6619,7 +6619,7 @@ "testing": "Testowanie…", "ok": "Połączono (opóźnienie {latency} ms)", "errors": { - "credentials_rejected": "Dane logowania odrzucone — sprawdź token", + "credentials_rejected": "Dane logowania odrzucone, sprawdź token", "rate_limited": "Ograniczone przez usługę nadrzędną", "timeout": "Przekroczono limit czasu żądania", "upstream_error": "Usługa nadrzędna zwróciła błąd", @@ -6630,7 +6630,7 @@ "private_origin_not_approved": "Cel w sieci prywatnej. Operator musi dodać to źródło do NOTIFICATION_PRIVATE_ORIGINS", "private_origin_not_grantable": "Ten adres to link-local, adres metadanych lub nieokreślony; żadna zgoda operatora nie może go otworzyć. Użyj adresu, na którym nasłuchuje przekaźnik", "url_invalid": "Adres URL jest nieprawidłowy", - "redirected": "Punkt końcowy przekierowuje — sprawdź adres URL", + "redirected": "Punkt końcowy przekierowuje, sprawdź adres URL", "endpoint_not_found": "Nie znaleziono punktu końcowego pod adresem URL", "credentials_unreadable": "Nie można odszyfrować danych logowania", "upstream_invalid_json": "Usługa nadrzędna wysłała nieprawidłowy JSON", @@ -6641,7 +6641,7 @@ }, "notificationStatus": { "title": "Niezawodność kanałów", - "description": "Stan każdego kanału — „Automatycznie wyłączone” oznacza zatrzymanie po trwałych błędach.", + "description": "Stan każdego kanału; „Automatycznie wyłączone” oznacza zatrzymanie po trwałych błędach.", "emptyDescription": "Dodaj kanał w Ustawienia › Integracje › Kanały dostarczania.", "stateActive": "Aktywne", "stateAutoDisabled": "Automatycznie wyłączone", @@ -6667,7 +6667,7 @@ }, "healthRecord": { "title": "Eksportuj dokumentację zdrowotną", - "description": "Pełna dokumentacja dla lekarza — jako PDF, jako FHIR lub oba.", + "description": "Pełna dokumentacja dla lekarza: jako PDF, jako FHIR lub oba.", "format": "Format", "format_pdf": "PDF", "format_fhir": "Ustrukturyzowany (FHIR)", @@ -6699,7 +6699,7 @@ "createTitle": "Nowy link udostępniania", "createDescription": "Link jest tylko do odczytu i ograniczony czasowo.", "label": "Etykieta", - "labelPlaceholder": "np. dr Kowalski — kontrola roczna", + "labelPlaceholder": "np. dr Kowalski, kontrola roczna", "range": "Dni historii", "rangeHint": "Jak daleko wstecz sięga udostępnione okno.", "expiry": "Wygasa za (dni)", @@ -6719,7 +6719,7 @@ "statusRevoked": "Unieważniony", "statusExpired": "Wygasły", "inactiveTitle": "Unieważnione i wygasłe ({count})", - "shownOnce": "Wyświetlane tylko raz. Zapisz teraz kod QR i hasło — nie można ich później odzyskać.", + "shownOnce": "Wyświetlane tylko raz. Zapisz teraz kod QR i hasło, bo nie można ich później odzyskać.", "qrAlt": "Kod QR zawierający link do udostępniania i hasło", "linkLabel": "Link", "passphraseLabel": "Hasło", @@ -6730,12 +6730,12 @@ "attachTitle": "Dołącz dokumenty", "attachButton": "Wybierz dokumenty", "attachCount": "Wybrano {count} z {max}", - "attachFrozen": "Zestaw dokumentów jest ustalany przy tworzeniu linku — później nie można dodawać ani usuwać dokumentów.", + "attachFrozen": "Zestaw dokumentów jest ustalany przy tworzeniu linku. Później nie można dodawać ani usuwać dokumentów.", "attachRemove": "Usuń {title}", "exifNote": "Metadane aparatu (EXIF/GPS) są usuwane z obrazów JPEG, PNG i WebP podczas udostępniania. Pliki PDF, TIFF, HEIC i Office są przekazywane bez zmian.", "documentCount": "Dołączone dokumenty: {count}", "qrScanTitle": "Zeskanuj, aby otworzyć na innym urządzeniu", - "qrScanHint": "Skieruj aparat telefonu na kod, aby otworzyć udostępnioną dokumentację — hasło jest już dołączone.", + "qrScanHint": "Skieruj aparat telefonu na kod, aby otworzyć udostępnioną dokumentację. Hasło jest już dołączone.", "pickerTitle": "Dołącz dokumenty", "pickerDescription": "Przeszukaj swój sejf i wybierz dokumenty do udostępnienia. Maksymalnie {max}.", "pickerSearch": "Szukaj dokumentów", @@ -6748,7 +6748,7 @@ "statusNeedsReselect": "Wybierz zawartość ponownie", "reselectReason": "Ten link udostępniał zakres, którego nikt nie wybrał, więc został zamknięty. Utwórz nowy i wybierz jego zawartość.", "reselectAction": "Utwórz zamiennik", - "createDetail": "Token jest pokazywany tylko raz przy tworzeniu — zapisz go wtedy; nie można go odzyskać.", + "createDetail": "Token jest pokazywany tylko raz przy tworzeniu. Zapisz go wtedy; nie można go odzyskać.", "activeDescription": "Udostępnione linki, termin ich wygaśnięcia i liczba otwarć." }, "genderOther": "Inna", @@ -6757,10 +6757,10 @@ "nightscoutDescription": "Połącz własną stronę Nightscout, aby synchronizować ciągłe odczyty glukozy w panelu glukozy.", "nightscoutViewData": "Zobacz swoją glukozę", "nightscoutUrl": "Adres URL Nightscout", - "nightscoutUrlSavedPlaceholder": "Zapisano — wpisz nowy adres URL, aby go zastąpić", + "nightscoutUrlSavedPlaceholder": "Zapisano. Wpisz nowy adres URL, aby go zastąpić", "nightscoutToken": "Token API", "nightscoutTokenOptional": "Opcjonalny dla witryny publicznej", - "nightscoutTokenSavedPlaceholder": "Zapisano — wpisz nowy token, aby go zastąpić", + "nightscoutTokenSavedPlaceholder": "Zapisano. Wpisz nowy token, aby go zastąpić", "nightscoutTokenHelp": "Wklej token dostępu z narzędzi administracyjnych Nightscout. Pozostaw puste, jeśli witryna jest publicznie czytelna.", "nightscoutPrivateOperatorTitle": "Dostęp do prywatnego serwera Nightscout wymaga zgody administratora serwera.", "nightscoutPrivateOperatorDescription": "Poproś administratora serwera o zatwierdzenie dokładnie tego pochodzenia Nightscout.", @@ -6781,7 +6781,7 @@ "polarClientId": "Client ID", "polarClientSecret": "Client Secret", "polarCredentialsSaved": "Dane zapisane", - "polarCredentialsSavedPlaceholder": "Zapisano — wpisz nowe, aby zastąpić", + "polarCredentialsSavedPlaceholder": "Zapisano. Wpisz nowe, aby zastąpić", "polarSaveCredentials": "Zapisz", "polarUnavailable": "Polar nie jest skonfigurowany na tym serwerze. Dodaj powyżej własne dane OAuth Polar lub poproś administratora o skonfigurowanie współdzielonej aplikacji.", "polarConnect": "Połącz Polar", @@ -6791,7 +6791,7 @@ "polarDisconnect": "Rozłącz", "polarDisconnectTitle": "Rozłączyć Polar?", "polarDisconnectDescription": "Przyszłe synchronizacje zostaną zatrzymane. Już zaimportowane odczyty pozostaną w historii.", - "polarOauthConnected": "Polar połączony — pierwsza synchronizacja startuje w tle.", + "polarOauthConnected": "Polar połączony. Pierwsza synchronizacja startuje w tle.", "polarOauthFailed": "Połączenie z Polar nie powiodło się", "polarOauthError": { "csrf1": "Kontrola bezpieczeństwa nie powiodła się, ponieważ brakowało pliku cookie przeglądarki. Rozpocznij połączenie ponownie w tej samej przeglądarce.", @@ -6810,7 +6810,7 @@ "ouraClientId": "Client ID", "ouraClientSecret": "Client Secret", "ouraCredentialsSaved": "Dane zapisane", - "ouraCredentialsSavedPlaceholder": "Zapisano — wpisz nowe, aby zastąpić", + "ouraCredentialsSavedPlaceholder": "Zapisano. Wpisz nowe, aby zastąpić", "ouraSaveCredentials": "Zapisz", "ouraUnavailable": "Oura nie jest skonfigurowana na tym serwerze. Dodaj powyżej własne dane OAuth Oura lub poproś administratora o skonfigurowanie współdzielonej aplikacji.", "ouraConnect": "Połącz Oura", @@ -6820,7 +6820,7 @@ "ouraDisconnect": "Rozłącz", "ouraDisconnectTitle": "Rozłączyć Oura?", "ouraDisconnectDescription": "Przyszłe synchronizacje zostaną zatrzymane. Już zaimportowane odczyty pozostaną w historii.", - "ouraOauthConnected": "Oura połączona — pierwsza synchronizacja startuje w tle.", + "ouraOauthConnected": "Oura połączona. Pierwsza synchronizacja startuje w tle.", "ouraOauthFailed": "Połączenie z Oura nie powiodło się", "ouraOauthError": { "csrf1": "Kontrola bezpieczeństwa nie powiodła się, ponieważ brakowało pliku cookie przeglądarki. Rozpocznij połączenie ponownie w tej samej przeglądarce.", @@ -6851,7 +6851,7 @@ } }, "integrationRedirectGuide": { - "intro": "To połączenie działa przez Twoją własną aplikację deweloperską {provider} — około 5 minut konfiguracji:", + "intro": "To połączenie działa przez Twoją własną aplikację deweloperską {provider}, około 5 minut konfiguracji:", "step1": "Utwórz aplikację w portalu deweloperskim {provider}.", "step2": "Ustaw jej URL przekierowania/callback na:", "step3": "Wklej powyżej otrzymany identyfikator klienta i sekret klienta." @@ -6911,7 +6911,7 @@ }, "recovery": { "saveNow": "Zapisz teraz te kody odzyskiwania", - "saveNowHint": "Każdy kod działa raz. Są wyświetlane tylko teraz — przechowuj je w bezpiecznym miejscu. Jeśli stracisz aplikację uwierzytelniającą, kod odzyskiwania będzie jedyną drogą powrotu.", + "saveNowHint": "Każdy kod działa raz. Są wyświetlane tylko teraz, więc przechowuj je w bezpiecznym miejscu. Jeśli stracisz aplikację uwierzytelniającą, kod odzyskiwania będzie jedyną drogą powrotu.", "download": "Pobierz", "remainingOne": "Pozostał {count} kod odzyskiwania.", "remainingOther": "Pozostało {count} kodów odzyskiwania.", @@ -6939,7 +6939,7 @@ }, "passkeyNudge": { "title": "Dodaj klucz dostępu, aby logować się szybciej", - "body": "Klucze dostępu pozwalają logować się odciskiem palca, twarzą lub kodem PIN urządzenia — bez hasła do zapamiętania." + "body": "Klucze dostępu pozwalają logować się odciskiem palca, twarzą lub kodem PIN urządzenia, bez hasła do zapamiętania." }, "trustedDevices": { "title": "Zaufane urządzenia", @@ -7014,7 +7014,7 @@ "endpointLabel": "Adres URL łącznika", "connectDescription": "Wklej ten adres URL w konfiguracji własnego łącznika asystenta, a następnie autoryzuj za pomocą poniższego tokenu lub zaloguj się po wyświetleniu monitu.", "tokensTitle": "Tokeny łącznika", - "tokensDescription": "Wygeneruj token dla asystenta — tylko odczyt, chyba że pozwolisz poniżej na zapis.", + "tokensDescription": "Wygeneruj token dla asystenta: tylko odczyt, chyba że pozwolisz poniżej na zapis.", "scopeNote": "Nowe tokeny mogą tylko odczytywać Twoje dane. Dostęp do zapisu (health:write) przyznajesz dla każdego tokena przełącznikiem poniżej. Token nigdy nie może uzyskać dostępu do funkcji administracyjnych.", "writeScopeToggleLabel": "Zezwól na zapis (health:write)", "writeScopeNote": "Dodaje zakres health:write, aby asystent mógł zapisywać nowe pomiary i wpisy nastroju na Twoim koncie. Każdy zapis jest najpierw potwierdzany. Token nadal nie może usuwać ani edytować istniejących wpisów, zmieniać leków ani uzyskiwać dostępu do funkcji REST lub administracyjnych. Pozostaw wyłączone, aby uzyskać dostęp tylko do odczytu.", @@ -7038,7 +7038,7 @@ "stravaClientId": "Identyfikator klienta", "stravaClientSecret": "Sekret klienta", "stravaCredentialsSaved": "Dane zapisane", - "stravaCredentialsSavedPlaceholder": "Zapisane — wpisz nowe, aby zastąpić", + "stravaCredentialsSavedPlaceholder": "Zapisane. Wpisz nowe, aby zastąpić", "stravaSaveCredentials": "Zapisz", "stravaUnavailable": "Strava nie jest skonfigurowana na tym serwerze. Dodaj powyżej własne dane API Strava lub poproś administratora o skonfigurowanie wspólnej aplikacji.", "stravaConnect": "Połącz Strava", @@ -7048,7 +7048,7 @@ "stravaDisconnect": "Rozłącz", "stravaDisconnectTitle": "Rozłączyć Strava?", "stravaDisconnectDescription": "Przyszłe synchronizacje zostaną zatrzymane. Już zaimportowane aktywności pozostaną w historii.", - "stravaOauthConnected": "Strava połączona — pierwsza synchronizacja rusza w tle.", + "stravaOauthConnected": "Strava połączona. Pierwsza synchronizacja rusza w tle.", "stravaOauthFailed": "Połączenie ze Strava nie powiodło się", "stravaOauthError": { "csrf1": "Kontrola bezpieczeństwa nie powiodła się, ponieważ brakowało pliku cookie przeglądarki. Rozpocznij połączenie ponownie w tej samej przeglądarce.", @@ -7102,14 +7102,14 @@ }, "garminInfo": { "title": "Garmin", - "body": "Garmin nie ma tutaj bezpośredniego połączenia. Połącz przez Apple Health (iOS) lub Google Health Connect (Android). Zastrzeżone wskaźniki Garmina — Body Battery, Training Load, status HRV, VO₂ max — nie są udostępniane przez Garmina żadnej z tych platform.", + "body": "Garmin nie ma tutaj bezpośredniego połączenia. Połącz przez Apple Health (iOS) lub Google Health Connect (Android). Zastrzeżone wskaźniki Garmina (Body Battery, Training Load, status HRV, VO₂ max) nie są udostępniane przez Garmina żadnej z tych platform.", "docsLink": "Przeczytaj przewodnik" }, "glucoseReference": { "title": "Zakres referencyjny glukozy", "description": "Do jakiego zakresu porównywane są twoje wyniki glukozy we krwi.", "enable": "Użyj zakresu docelowego dla cukrzycy", - "explainer": "Wyłączone — wyniki są oceniane względem ogólnego zakresu referencyjnego dla osób bez cukrzycy. Włączone — są oceniane względem węższego zakresu docelowego glikemii z ADA Standards of Care, a Coach opiera na nim swoje uwagi o glukozie. Twoje własne wartości docelowe poniżej nadal mają pierwszeństwo.", + "explainer": "Wyłączone: wyniki są oceniane względem ogólnego zakresu referencyjnego dla osób bez cukrzycy. Włączone: są oceniane względem węższego zakresu docelowego glikemii z ADA Standards of Care, a Coach opiera na nim swoje uwagi o glukozie. Twoje własne wartości docelowe poniżej nadal mają pierwszeństwo.", "disclaimer": "To wybiera zakres referencyjny. Nie jest to diagnoza, nigdy nie jest wywnioskowane z pomiaru, a aplikacja nie podejmuje na tej podstawie działań klinicznych. O to, jakie cele dotyczą ciebie, zapytaj swojego lekarza.", "error": "Nie udało się zapisać ustawienia." }, @@ -7183,27 +7183,27 @@ "loadingStatus": "Ładowanie stanu...", "systemStatusLoadError": "Nie udało się załadować stanu systemu.", "systemStatusRetry": "Spróbuj ponownie", - "adminSettingsLoadError": "Nie udało się załadować ustawień administracyjnych. Przełączniki poniżej mogą nie odzwierciedlać bieżącego stanu — odśwież stronę.", + "adminSettingsLoadError": "Nie udało się załadować ustawień administracyjnych. Przełączniki poniżej mogą nie odzwierciedlać bieżącego stanu, odśwież stronę.", "hostMetrics": { "title": "Obciążenie hosta", "load1": "Obciążenie (1m)", "memUsedPercent": "Pamięć", "diskBusyPercent": "Disk I/O", "last2hours": "Ostatnie 2 godziny", - "empty": "Rozpoczęto próbkowanie — dane pojawią się w ciągu 1–2 minut.", + "empty": "Rozpoczęto próbkowanie. Dane pojawią się w ciągu 1–2 minut.", "loadError": "Nie udało się załadować metryk hosta. Spróbuj odświeżyć stronę." }, "aiServerKey": { "title": "Serwerowy klucz AI", "description": "Klucz operatora dla kont, które nie mają własnego.", - "byokHint": "Własny klucz użytkownika (BYOK, logowanie ChatGPT lub dostawca lokalny) zawsze ma pierwszeństwo — klucz serwera jest ostatnim ogniwem łańcucha dostawców.", + "byokHint": "Własny klucz użytkownika (BYOK, logowanie ChatGPT lub dostawca lokalny) zawsze ma pierwszeństwo; klucz serwera jest ostatnim ogniwem łańcucha dostawców.", "consentHint": "Żądania przez klucz serwera wymagają aktywnej zgody użytkownika na AI; bez potwierdzenia zgody nic nie jest wysyłane.", "baseUrlHint": "Adres bazowy decyduje o API: adres Anthropic taki jak https://api.anthropic.com/v1 jest rozpoznawany, każdy inny host jest wywoływany przez API zgodne z OpenAI.", "statusConfigured": "Skonfigurowany", "statusNotConfigured": "Nieskonfigurowany", "keyLabel": "Klucz API", "keyPlaceholder": "sk-...", - "keyPlaceholderSet": "Zapisany ({preview}) — wpisz nowy klucz, aby go zastąpić", + "keyPlaceholderSet": "Zapisany ({preview}). Wpisz nowy klucz, aby go zastąpić", "modelLabel": "Model", "baseUrlLabel": "Adres bazowy URL", "save": "Zapisz", @@ -7246,7 +7246,7 @@ "title": "Jakość analiz", "loading": "Ładowanie podsumowania opinii...", "loadError": "Nie udało się załadować podsumowania jakości analiz. Spróbuj odświeżyć stronę.", - "empty": "Brak opinii. Agregator uruchamia się codziennie o 04:00 — gdy użytkownicy zaczną oceniać rekomendacje, tutaj pojawią się wskaźniki przydatności.", + "empty": "Brak opinii. Agregator uruchamia się codziennie o 04:00. Gdy użytkownicy zaczną oceniać rekomendacje, tutaj pojawią się wskaźniki przydatności.", "windowLabel": "Ostatnie {days} dni", "generatedAtLabel": "Wygenerowano", "colSeverity": "Ważność", @@ -7261,7 +7261,7 @@ "title": "Opinie o Coachu", "loading": "Ładowanie podsumowania opinii o Coachu...", "loadError": "Nie udało się załadować podsumowania opinii o Coachu. Spróbuj odświeżyć stronę.", - "empty": "Brak opinii o Coachu. Agregator uruchamia się codziennie o 04:00 — gdy użytkownicy ocenią odpowiedzi Coacha, tutaj pojawią się wskaźniki przydatności.", + "empty": "Brak opinii o Coachu. Agregator uruchamia się codziennie o 04:00. Gdy użytkownicy ocenią odpowiedzi Coacha, tutaj pojawią się wskaźniki przydatności.", "windowLabel": "Ostatnie {days} dni", "generatedAtLabel": "Wygenerowano", "colPromptVersion": "Wersja promptu", @@ -7280,7 +7280,7 @@ "appSettingsDescription": "Globalne ustawienia domyślne rejestracji, języka i strefy czasowej nowych kont.", "registrationEnabled": "Zezwól na rejestrację", "registrationEnabledDescription": "Gdy wyłączone, nowi użytkownicy nie mogą się zarejestrować.", - "registrationOpenHint": "Rejestracja jest otwarta — każdy, kto ma dostęp do tej instancji, może założyć konto. Zamknij ją tutaj, gdy wszyscy będą mieć konto.", + "registrationOpenHint": "Rejestracja jest otwarta: każdy, kto ma dostęp do tej instancji, może założyć konto. Zamknij ją tutaj, gdy wszyscy będą mieć konto.", "defaultLanguage": "Domyślny język", "defaultLanguageDescription": "Używany dla nowych użytkowników i jako rozwiązanie zapasowe.", "defaultUserTimezone": "Domyślna strefa czasowa dla nowych kont", @@ -7294,7 +7294,7 @@ "integrationWebPush": "Web Push", "offlineGeoLabel": "Dane geograficzne", "offlineGeoEnabled": "Offline (GeoLite2)", - "offlineGeoFallback": "Online ({host}) — podłącz bazy GeoLite2 i ustaw GEOLITE2_DIR", + "offlineGeoFallback": "Online ({host}): podłącz bazy GeoLite2 i ustaw GEOLITE2_DIR", "offlineGeoOff": "Wyłączone", "offlineGeoChosen": "Online ({host})", "apiGlobal": "Zezwól na punkty końcowe API i tokeny API.", @@ -7331,7 +7331,7 @@ "webPushVapidGenerating": "Generowanie…", "webPushVapidGenerated": "Klucze VAPID wygenerowane. Zapisz temat, aby zakończyć.", "webPushVapidGenerateFailed": "Nie udało się wygenerować kluczy VAPID.", - "webPushVapidGenerateConfirm": "Klucze VAPID są już skonfigurowane. Wygenerowanie nowej pary unieważnia wszystkie subskrypcje push w przeglądarce — każde urządzenie musi zasubskrybować ponownie. Kontynuować?", + "webPushVapidGenerateConfirm": "Klucze VAPID są już skonfigurowane. Wygenerowanie nowej pary unieważnia wszystkie subskrypcje push w przeglądarce, więc każde urządzenie musi zasubskrybować ponownie. Kontynuować?", "webPushVapidGenerateConfirmTitle": "Wygenerować nowe klucze VAPID?", "webPushVapidRegenerate": "Wygeneruj ponownie", "configured": "Skonfigurowano", @@ -7387,8 +7387,8 @@ "createdToast": "Zaproszenie utworzone", "createError": "Nie udało się utworzyć zaproszenia.", "tokenTitle": "Link z zaproszeniem", - "tokenOnceHint": "Do skopiowania tylko teraz — skopiuj link lub udostępnij kod QR do zeskanowania.", - "hashExplainer": "Zapisywany jest tylko hash linku — nie można go później ponownie wyświetlić. W razie utraty unieważnij zaproszenie i utwórz nowe.", + "tokenOnceHint": "Do skopiowania tylko teraz: skopiuj link lub udostępnij kod QR do zeskanowania.", + "hashExplainer": "Zapisywany jest tylko hash linku, więc nie można go później ponownie wyświetlić. W razie utraty unieważnij zaproszenie i utwórz nowe.", "copyLink": "Kopiuj link", "copiedToast": "Link skopiowany", "copyError": "Kopiowanie nie powiodło się.", @@ -7449,7 +7449,7 @@ "tokenName": "Nazwa", "tokenPermissions": "Uprawnienia", "tokenPermissionAll": "Wszystko", - "tokenPermissionAllTooltip": "Uprawnienie wieloznaczne — ten token może wywołać każdą trasę API.", + "tokenPermissionAllTooltip": "Uprawnienie wieloznaczne: ten token może wywołać każdą trasę API.", "tokenStatus": "Stan", "tokenLastUsed": "Ostatnio użyto", "tokenCreated": "Utworzono", @@ -7627,7 +7627,7 @@ "app-logs": { "title": "Logi aplikacji", "subtitle": "Wyświetl najnowsze ustrukturyzowane wide-events emitowane przez ten proces.", - "processNote": "Wyświetlane są tylko logi procesu aplikacji — logi procesu workera trafiają do Loki, gdy ta integracja jest skonfigurowana.", + "processNote": "Wyświetlane są tylko logi procesu aplikacji; logi procesu workera trafiają do Loki, gdy ta integracja jest skonfigurowana.", "filterTraceId": "Identyfikator śladu", "filterAction": "Akcja zawiera…", "filterLevel": "Poziom", @@ -7662,7 +7662,7 @@ "loading": "Ładowanie kopii zapasowych...", "loadError": "Nie udało się załadować kopii zapasowych.", "emptyTitle": "Brak kopii zapasowych", - "emptyDescription": "Kopie zapasowe wykonują się automatycznie w każdą niedzielę o 03:00 — lub uruchom jedną teraz, aby utworzyć pierwszą migawkę.", + "emptyDescription": "Kopie zapasowe wykonują się automatycznie w każdą niedzielę o 03:00. Możesz też uruchomić jedną teraz, aby utworzyć pierwszą migawkę.", "colUser": "Użytkownik", "colType": "Typ", "typeWeeklyAuto": "Cotygodniowo (auto)", @@ -7698,11 +7698,11 @@ "restoreTitle": "Przywróć z kopii zapasowej", "restoreDescription": "Spowoduje to zastąpienie WSZYSTKICH bieżących danych {username} migawką z {when}. Istniejące pomiary, leki, zdarzenia przyjęcia, wpisy nastroju, kanały powiadomień, subskrypcje push i zakolejkowane usunięcia Telegram zostaną usunięte.", "restoreInstanceSettingsLabel": "Przywróć też ustawienia instancji", - "restoreInstanceSettingsHint": "Rejestracja, wymóg MFA, domyślny język, dostępność modułów, konfiguracja powiadomień i AI — brane z migawki i stosowane do wszystkich w tej instalacji. Zostaw niezaznaczone, aby przywrócić tylko to konto.", + "restoreInstanceSettingsHint": "Rejestracja, wymóg MFA, domyślny język, dostępność modułów, konfiguracja powiadomień i AI: brane z migawki i stosowane do wszystkich w tej instalacji. Zostaw niezaznaczone, aby przywrócić tylko to konto.", "restorePromptLabel": "Wpisz RESTORE, aby kontynuować", "previewTitle": "Zawartość kopii", "previewLoading": "Odczytywanie zawartości…", - "previewUnavailable": "Nie udało się odczytać zawartości — przywracanie jest nadal możliwe.", + "previewUnavailable": "Nie udało się odczytać zawartości, ale przywracanie jest nadal możliwe.", "previewStillReading": "Ta kopia powstała we wcześniejszej wersji, więc jej zawartość jest odczytywana w całości, co przy dużych danych chwilę trwa. Otwórz to okno ponownie za kilka minut, aby ją zobaczyć. Przywracanie od tego nie zależy.", "previewEmpty": "Plik nie zawiera rekordów.", "previewOther": "Inne rekordy", @@ -7745,7 +7745,7 @@ "restoreSkippedMedicationTarget": "Analit docelowy leku", "restoreSkippedScheduleRevisionLink": "Następstwo okresów schematu", "restoreSkippedAccountSetting": "Ustawienie konta", - "restoreMissingTitle": "Przywracanie odrzucone — plik jest niekompletny", + "restoreMissingTitle": "Przywracanie odrzucone: plik jest niekompletny", "restoreMissingDescription": "Manifest pliku mówi, że zawiera on poniższą sekcję, a jej nie zawiera. Nic nie zostało zmienione: przywracanie zastępuje całą klasę rekordów, więc brakująca sekcja by ją opróżniła.", "restoreMissingRemedy": "Użyj kopii do odtwarzania po awarii albo wyeksportuj konto ponownie i wgraj nowy plik. Sekcja, którą manifest jawnie deklaruje jako pominiętą, to co innego i przywraca się normalnie.", "restoreMissingDocuments": "Dokumenty", @@ -7869,7 +7869,7 @@ "completed": "Zakończono", "failed": "Niepowodzenie" }, - "coverageDetail": "Pokazywane są tylko identyfikatory kluczy i liczby — nigdy materiał klucza.", + "coverageDetail": "Pokazywane są tylko identyfikatory kluczy i liczby, nigdy materiał klucza.", "backupsTitle": "Klucze, których kopie nadal potrzebują", "backupsDescription": "Wycofany klucz jest potrzebny, dopóki którakolwiek kopia poniżej go wymienia.", "backupsStoredLine": "Klucz {key}: {count} zapisanych kopii, najstarsza z {when}", @@ -7935,7 +7935,7 @@ "centralCodex": { "title": "Wspólne połączenie AI", "description": "Podłącz jedno zalogowane konto ChatGPT, które każdy użytkownik tego serwera może włączyć dla funkcji AI.", - "honesty": "To jedno wspólne, zalogowane konto AI — nie klucz API. Każdy, kto je włączy, wysyła przez nie zapytania, więc godzinowe i tygodniowe limity konta są dzielone między nimi, a te same limity zasilają już Coacha. Dostawcy subskrypcyjni mogą wykorzystywać treść do ulepszania swoich modeli i nie obejmuje tego żadna umowa powierzenia przetwarzania danych, dlatego nigdy nie jest to opcja domyślna i pozostaje poniżej dostawców bez trenowania przy odczycie dokumentów. Podłącz tylko konto, które chcesz udostępniać w ten sposób.", + "honesty": "To jedno wspólne, zalogowane konto AI, a nie klucz API. Każdy, kto je włączy, wysyła przez nie zapytania, więc godzinowe i tygodniowe limity konta są dzielone między nimi, a te same limity zasilają już Coacha. Dostawcy subskrypcyjni mogą wykorzystywać treść do ulepszania swoich modeli i nie obejmuje tego żadna umowa powierzenia przetwarzania danych, dlatego nigdy nie jest to opcja domyślna i pozostaje poniżej dostawców bez trenowania przy odczycie dokumentów. Podłącz tylko konto, które chcesz udostępniać w ten sposób.", "statusConnected": "Połączono", "statusDisconnected": "Nie połączono", "statusExpired": "Wygasło", @@ -7947,13 +7947,13 @@ "connectedSince": "Połączono od {when}", "connected": "Wspólne połączenie AI podłączone", "disconnected": "Wspólne połączenie AI usunięte", - "error": "Coś poszło nie tak — spróbuj ponownie" + "error": "Coś poszło nie tak. Spróbuj ponownie" }, "failingJobs": { "title": "Zadania w tle", "description": "Kolejki, których zadania poddały się po wyczerpaniu ponowień.", "none": "W ciągu ostatnich {hours} godzin żadne zadanie nie zawiodło.", - "unavailable": "Brak kolejki zadań do odczytu — to wdrożenie działa bez workera w tle.", + "unavailable": "Brak kolejki zadań do odczytu: to wdrożenie działa bez workera w tle.", "countOne": "{count} niepowodzenie", "countFew": "{count} niepowodzenia", "countOther": "{count} niepowodzeń", @@ -8276,7 +8276,7 @@ }, "selfContextComplete": { "title": "Wywiad uzupełniony", - "description": "Wszystkie cztery pola wywiadu wypełnione — Coach zna Twój kontekst." + "description": "Wszystkie cztery pola wywiadu wypełnione. Coach zna Twój kontekst." }, "sleepLog7": { "title": "Dziennik snu przez 7 dni", @@ -8298,7 +8298,7 @@ }, "hiddenCard": { "title": "Ukryte osiągnięcie", - "description": "Śledź dalej — może na nie natrafisz.", + "description": "Śledź dalej, może na nie natrafisz.", "ariaLabel": "Ukryte zablokowane osiągnięcie" }, "hiddenUnlockToast": { @@ -8307,7 +8307,7 @@ "dashboardCard": { "title": "Ostatnio odblokowane", "viewAll": "Zobacz wszystkie", - "empty": "Brak osiągnięć — zapisuj dalej, aby odblokować pierwsze." + "empty": "Brak osiągnięć. Zapisuj dalej, aby odblokować pierwsze." } }, "notifications": { @@ -8490,7 +8490,7 @@ } }, "edit": { - "title": "Edytuj zakres docelowy — {metric}", + "title": "Edytuj zakres docelowy: {metric}", "description": "Dostosuj zakres docelowy używany w wykresach, insights i raporcie medycznym. Wartości w {unit}.", "derivedHint": "Ta karta jest wyprowadzona z innych metryk. Edytuj cele bazowe (np. ciśnienie lub waga).", "minLabel": "Min", @@ -8522,11 +8522,11 @@ "aboveTarget": "{delta} {unit} powyżej zakresu", "belowTarget": "{delta} {unit} poniżej zakresu", "diastolic": "Rozkurczowe", - "glucoseFasting": "Glikemia — na czczo", - "glucosePostprandial": "Glikemia — po posiłku", - "glucoseRandom": "Glikemia — dowolna", - "glucoseBedtime": "Glikemia — przed snem", - "glucoseUnspecified": "Glikemia — bez oznaczenia", + "glucoseFasting": "Glikemia: na czczo", + "glucosePostprandial": "Glikemia: po posiłku", + "glucoseRandom": "Glikemia: dowolna", + "glucoseBedtime": "Glikemia: przed snem", + "glucoseUnspecified": "Glikemia: bez oznaczenia", "status": { "underweight": "Niedowaga", "normal": "Normal", @@ -8612,7 +8612,7 @@ "askMedicationName": "Podaj lek, np. przyjęty Ramipril.", "medicationNotFoundExact": "Nie znaleziono leku. Wyślij nazwę dokładnie tak, jak w HealthLog.", "helpHeader": "Dostępne polecenia:", - "helpBody": "/help — pokaż tę pomoc\n/add — zapisz przyjęcie\n/start — uruchom bota\n\nPolecenia tekstowe:\ntaken <nazwa> — potwierdź przyjęcie\n\nPrzyciski w przypomnieniach:\n• Przyjęto — potwierdź przyjęcie\n• 🕐 1h / 🕐 3h — odłóż przypomnienie\n• ⏭ Pomiń — pomiń przyjęcie\n• ✓ Potwierdź — potwierdź pominięte przyjęcie", + "helpBody": "/help: pokaż tę pomoc\n/add: zapisz przyjęcie\n/start: uruchom bota\n\nPolecenia tekstowe:\ntaken <nazwa>: potwierdź przyjęcie\n\nPrzyciski w przypomnieniach:\n• Przyjęto: potwierdź przyjęcie\n• 🕐 1h / 🕐 3h: odłóż przypomnienie\n• ⏭ Pomiń: pomiń przyjęcie\n• ✓ Potwierdź: potwierdź pominięte przyjęcie", "measureValuePrompt": "Odpowiedz wartością, aby ją zapisać (opcjonalnie).", "buttonMeasureValue": "Wartość…", "measureValueSaved": "Pomiar zapisany.", @@ -8637,9 +8637,9 @@ }, "lowStockReminders": { "title": "Niski zapas: {medName}", - "bodyToday": "{medName}: pozostało {units} jednostek — mniej niż jeden dzień zapasu.", - "bodyReorder": "{medName}: pozostało {units} jednostek. Zapas skończy się około {runsOutOn} — zamów ponownie do {reorderBy}.", - "bodyLastDose": "{medName}: pozostało {units} jednostek — to mniej więcej Twoja ostatnia dawka. Zapas skończy się około {runsOutOn}.", + "bodyToday": "{medName}: pozostało {units} jednostek, czyli mniej niż jeden dzień zapasu.", + "bodyReorder": "{medName}: pozostało {units} jednostek. Zapas skończy się około {runsOutOn}. Zamów ponownie do {reorderBy}.", + "bodyLastDose": "{medName}: pozostało {units} jednostek, to mniej więcej Twoja ostatnia dawka. Zapas skończy się około {runsOutOn}.", "bodyExpired": "{medName}: brak zapasu do użycia. {units} jednostek oznaczono jako przeterminowane.", "bodyAsNeeded": "{medName}: zostało tylko {units} jednostek. Zamów ponownie, zanim będziesz potrzebować kolejnej dawki." }, @@ -8666,11 +8666,11 @@ "questionConditions": "Czy masz choroby przewlekłe, o których Coach powinien wiedzieć?", "questionFocus": "Czy jest coś konkretnego, na co Coach powinien zwracać uwagę?", "questionAllergies": "Czy masz alergie lub nietolerancje?", - "questionAboutMe": "Chcesz opowiedzieć Coachowi coś o sobie — codzienność, cele, kontekst?" + "questionAboutMe": "Chcesz opowiedzieć Coachowi coś o sobie: codzienność, cele, kontekst?" }, "clinicianView": { "title": "Udostępniona dokumentacja zdrowotna", - "period": "Okres raportu: {start} – {end}", + "period": "Okres raportu: {start}–{end}", "expires": "Ten link wygasa dnia {date}.", "provenance": "To jest tylko do odczytu podsumowanie udostępnione przez osobę, do której należy, wyeksportowane z jej samodzielnie rejestrowanych danych HealthLog. Wartości są zgłaszane samodzielnie i mogą obejmować odczyty zsynchronizowane z urządzeń; należy je traktować jako zgłoszone przez pacjenta, a nie jako badanie kliniczne.", "labs": "Wyniki laboratoryjne", @@ -8694,7 +8694,7 @@ "strain": "Wynik obciążenia", "score": "Wynik dobrostanu" }, - "footer": "Udostępnione z HealthLog — samodzielnie hostowanego trackera zdrowia.", + "footer": "Udostępnione z HealthLog, samodzielnie hostowanego trackera zdrowia.", "unlock": { "title": "Wprowadź hasło", "description": "Ta udostępniona dokumentacja zdrowotna jest chroniona. Wprowadź otrzymane hasło, aby ją wyświetlić.", @@ -8782,7 +8782,7 @@ "generic": "Twoje {metric} jest o około {delta} {unit} {dir} w fazie lutealnej niż w fazie folikularnej.", "dirHigher": "wyższe", "dirLower": "niższe", - "empty": "Za mało cykli i pomiarów, aby pokazać wzorzec fazy. Rejestruj dalej — uzupełni się to wraz z historią." + "empty": "Za mało cykli i pomiarów, aby pokazać wzorzec fazy. Rejestruj dalej, a uzupełni się to wraz z historią." }, "crosstab": { "description": "Jak każdy pomiar wypada między fazą lutealną a folikularną, na Twoich danych.", @@ -8822,7 +8822,7 @@ }, "context": { "MENSTRUAL": "Poziom hormonów jest teraz najniższy, dlatego te dni mogą sprawiać wrażenie spokojnego resetu. Niektóre osoby zauważają skurcze, lżejszy sen albo chęć zwolnienia tempa; inne przechodzą przez nie niemal bez zmian. To wszystko mieści się w normie, a odczucia potrafią zmieniać się z cyklu na cykl.", - "FOLLICULAR": "Wraz z rosnącym estrogenem wiele osób opisuje te dni jako jasne i pełne otwartości – sen często przychodzi łatwiej, a umysł wydaje się bardziej klarowny. Podstawowa temperatura ciała zwykle utrzymuje się w niższym zakresie aż do chwili tuż przed owulacją. Długość tej fazy różni się najbardziej – od osoby do osoby i od cyklu do cyklu.", + "FOLLICULAR": "Wraz z rosnącym estrogenem wiele osób opisuje te dni jako jasne i pełne otwartości: sen często przychodzi łatwiej, a umysł wydaje się bardziej klarowny. Podstawowa temperatura ciała zwykle utrzymuje się w niższym zakresie aż do chwili tuż przed owulacją. Długość tej fazy różni się najbardziej, od osoby do osoby i od cyklu do cyklu.", "OVULATORY": "Estrogen osiąga szczyt tuż przed uwolnieniem komórki jajowej, często z krótkim wzrostem nastroju i niewielkim podniesieniem podstawowej temperatury ciała w ciągu kolejnego dnia lub dwóch. Śluz szyjkowy w tym oknie zwykle staje się bardziej przejrzysty i ciągliwy. Krótkie ukłucie po jednej stronie niektóre osoby zauważają; wiele nie czuje nic, a oba warianty są zupełnie normalne.", "LUTEAL": "Progesteron prowadzi przez drugą połowę cyklu, a podstawowa temperatura ciała zwykle ustala się nieco wyżej niż wcześniej. Niektóre osoby zauważają z dnia na dzień zmiany w śnie, apetycie, nastroju czy energii, podczas gdy inne czują się stabilnie przez cały czas. Ten wzorzec jest indywidualny i często wygląda inaczej z miesiąca na miesiąc." }, @@ -8909,8 +8909,8 @@ "ariaUnknown": "Brak aktywnego cyklu", "caption": "twojego cyklu", "firstPeriodCta": "Zapisz pierwszą miesiączkę", - "periodOverdue": "Okres jest późniejszy niż zwykle — licznik dni jest wstrzymany, dopóki nie zapiszesz następnego okresu.", - "periodOverdueDays": "Okres jest {days} dni późniejszy niż zwykle — licznik dni jest wstrzymany, dopóki nie zapiszesz następnego okresu.", + "periodOverdue": "Okres jest późniejszy niż zwykle. Licznik dni jest wstrzymany, dopóki nie zapiszesz następnego okresu.", + "periodOverdueDays": "Okres jest {days} dni późniejszy niż zwykle. Licznik dni jest wstrzymany, dopóki nie zapiszesz następnego okresu.", "logPeriodCta": "Zapisz okres" }, "calendar": { @@ -8922,7 +8922,7 @@ "prevMonth": "Poprzedni miesiąc", "nextMonth": "Następny miesiąc", "loading": "Ładowanie kalendarza…", - "learning": "Uczymy się Twojego cyklu — zapisz co najmniej trzy pełne cykle, a okno płodne, owulacja i fazy się uzupełnią. Do tego czasu kalendarz pokazuje tylko to, co zapisałaś.", + "learning": "Uczymy się Twojego cyklu. Zapisz co najmniej trzy pełne cykle, a okno płodne, owulacja i fazy się uzupełnią. Do tego czasu kalendarz pokazuje tylko to, co zapisałaś.", "legendSymptom": "Objawy", "legendOvulationConfirmed": "Potwierdzona owulacja", "flowSpotting": "plamienie", @@ -8935,7 +8935,7 @@ "predictions": { "title": "Co dalej", "nextPeriod": "Następna miesiączka", - "nextPeriodWindow": "{low} – {high}", + "nextPeriodWindow": "{low}–{high}", "fertileWindow": "Okno płodne", "ovulation": "Szacowana owulacja", "confidenceHigh": "Wysoka", @@ -8944,7 +8944,7 @@ "stillLearning": "Wciąż się uczę", "stillLearningBody": "Zapisz co najmniej trzy pełne cykle, a prognozy się wyostrzą. Do tego czasu to zgrubne oszacowanie.", "rawMode": "Prognoza wyłączona", - "rawModeBody": "Wyłączyłaś prognozy — pokazywane są tylko zapisane dane, bez przewidywań.", + "rawModeBody": "Wyłączyłaś prognozy: pokazywane są tylko zapisane dane, bez przewidywań.", "none": "Brak prognozy. Zapisz miesiączkę, aby zacząć.", "ovulationConfirmed": "Owulacja (potwierdzona)" }, @@ -8977,7 +8977,7 @@ "symptoms": "Objawy", "temperature": "Podstawowa temperatura ciała", "temperatureDisturbed": "Oznacz pomiar jako zakłócony", - "temperatureDisturbedHint": "Gorączka, choroba, alkohol lub spóźniony pomiar — wykluczony z oceny temperatury.", + "temperatureDisturbedHint": "Gorączka, choroba, alkohol lub spóźniony pomiar: wykluczony z oceny temperatury.", "ovulationTest": "Test owulacyjny", "mucus": "Śluz szyjkowy", "cervix": "Szyjka macicy", @@ -9040,7 +9040,7 @@ "remindersDescription": "Włącz przypomnienia o okresie dla każdego kanału w ustawieniach powiadomień.", "remindersLink": "Ustawienia powiadomień", "fertileReminder": "Przypomnienie o oknie płodności", - "fertileReminderDescription": "Otrzymaj powiadomienie kilka dni przed szacowanym oknem płodności. Domyślnie wyłączone – włącz je dla każdego kanału w ustawieniach powiadomień." + "fertileReminderDescription": "Otrzymaj powiadomienie kilka dni przed szacowanym oknem płodności. Domyślnie wyłączone; włącz je dla każdego kanału w ustawieniach powiadomień." }, "testResult": { "POSITIVE": "Pozytywny", @@ -9073,15 +9073,15 @@ "fieldInfo": { "bbt": "Twoja temperatura spoczynkowa, mierzona rano zaraz po przebudzeniu, przed wstaniem. Po owulacji nieznacznie rośnie (o około 0,2–0,3 °C).", "bbtLabel": "Czym jest temperatura podstawowa?", - "mucus": "Wydzielina z pochwy zmienia się w cyklu — od suchej lub lepkiej do kremowej, a następnie wodnistej i przypominającej białko jaja w najbardziej płodnych dniach.", + "mucus": "Wydzielina z pochwy zmienia się w cyklu: od suchej lub lepkiej do kremowej, a następnie wodnistej i przypominającej białko jaja w najbardziej płodnych dniach.", "mucusLabel": "Czym jest śluz szyjkowy?", - "ovulationTest": "Domowy test moczu wykrywający skok LH — wyrzut hormonu około 24–36 h przed owulacją. Wynik dodatni wskazuje najbardziej płodne okno.", + "ovulationTest": "Domowy test moczu wykrywający skok LH, czyli wyrzut hormonu około 24–36 h przed owulacją. Wynik dodatni wskazuje najbardziej płodne okno.", "ovulationTestLabel": "Czym jest test owulacyjny?", "spotting": "Lekkie krwawienie poza okresem.", "spottingLabel": "Czym jest plamienie między okresami?", "pregnancyTest": "Wynik domowego testu ciążowego (hCG).", "pregnancyTestLabel": "Czym jest test ciążowy?", - "progesteroneTest": "Test potwierdzający, że doszło do owulacji — progesteron rośnie po niej.", + "progesteroneTest": "Test potwierdzający, że doszło do owulacji: progesteron rośnie po niej.", "progesteroneTestLabel": "Czym jest test progesteronu?", "intercourse": "Czy tego dnia doszło do stosunku.", "intercourseLabel": "Co śledzi stosunek?", @@ -9134,14 +9134,14 @@ "postpone": { "menuItem": "Przełóż…", "title": "Przełóż termin", - "description": "Przesuwa tylko bieżący termin — regularny rytm pozostaje bez zmian.", + "description": "Przesuwa tylko bieżący termin, a regularny rytm pozostaje bez zmian.", "chip": "+{days} dni", "dateLabel": "Nowa data", "confirm": "Przełóż" }, "skip": { "heading": "Pomiń ten termin", - "explainer": "Zapisane uczciwie jako pominięte — nie jako wykonane. Odstęp zaczyna się od nowa od dzisiaj.", + "explainer": "Zapisane uczciwie jako pominięte, nie jako wykonane. Odstęp zaczyna się od nowa od dzisiaj.", "action": "Pomiń", "confirmTitle": "Pominąć ten termin?" }, @@ -9282,7 +9282,7 @@ "localOcr": { "heading": "Odczytuj skany na tym urządzeniu", "description": "Odczytuje zdjęcie na Twoim urządzeniu i wysyła do dostawcy tylko rozpoznany tekst.", - "detail": "Przydatne, gdy dostawca AI nie odczytuje obrazów. Mniej dokładne — sprawdź każdą wartość przed zapisem." + "detail": "Przydatne, gdy dostawca AI nie odczytuje obrazów. Mniej dokładne, więc sprawdź każdą wartość przed zapisem." }, "sort": { "heading": "Sortowanie", @@ -9326,7 +9326,7 @@ "sourceRangePlaceholder": "np. 3,5 - 5,0 lub < 5", "sourceRangeAdd": "+ Dodaj zakres z wyniku", "sourceRangeHint": "Opcjonalne. Dotyczy tylko tego pomiaru; zapisany zakres pozostaje bez zmian.", - "sourceRangeUnparsed": "Zapisane bez zmian — nie odczytano z tego zakresu liczbowego." + "sourceRangeUnparsed": "Zapisane bez zmian, nie odczytano z tego zakresu liczbowego." }, "backToLabs": "Wróć do wyników", "hasNote": "Notatka", @@ -9344,7 +9344,7 @@ "emptyDescription": "Dodaj wartość, aby śledzić ten biomarker w czasie.", "title": "Biomarker", "genericDescription": "Biomarker laboratoryjny, który śledzisz. Dodaj pomiary, aby obserwować jego trend względem zakresu referencyjnego.", - "valuesTitle": "{marker} — wszystkie odczyty", + "valuesTitle": "{marker}: wszystkie odczyty", "valuesDescription": "Każdy odczyt tego biomarkera. Edytuj lub usuń wpis bezpośrednio.", "backToMarker": "Powrót do {marker}", "latestResult": "Ostatni wynik" @@ -9364,7 +9364,7 @@ }, "biomarker": { "manageTitle": "Biomarkery", - "managerDescription": "Zdefiniuj marker raz — jednostka i zakres są używane dla każdego pomiaru.", + "managerDescription": "Zdefiniuj marker raz, a jednostka i zakres będą używane dla każdego pomiaru.", "define": "Zdefiniuj", "defineFirst": "Zdefiniuj pierwszy biomarker", "defineTitle": "Zdefiniuj biomarker", @@ -9383,7 +9383,7 @@ "form": { "seedLabel": "Zacznij od popularnego markera", "seedPlaceholder": "Wybierz marker (opcjonalnie)", - "seedHint": "Wybór wypełnia pola poniżej — dopasuj zakres do swojego laboratorium.", + "seedHint": "Wybór wypełnia pola poniżej. Dopasuj zakres do swojego laboratorium.", "name": "Nazwa", "namePlaceholder": "np. Cholesterol LDL", "unit": "Jednostka", @@ -9397,7 +9397,7 @@ "upperPlaceholder": "Górna granica", "context": "Kontekst", "contextPlaceholder": "Opcjonalna notatka o tym markerze", - "rangeHint": "Obie granice są opcjonalne — zostaw jedną pustą dla zakresu otwartego (np. LDL < 116).", + "rangeHint": "Obie granice są opcjonalne. Zostaw jedną pustą dla zakresu otwartego (np. LDL < 116).", "requiredError": "Nazwa i jednostka są wymagane.", "rangeOrderError": "Dolna granica nie może przekraczać górnej.", "save": "Zapisz biomarker", @@ -9453,36 +9453,36 @@ "bloodCount": "Morfologia krwi" }, "desc": { - "total-cholesterol": "Cholesterol całkowity to suma cholesterolu przenoszonego przez wszystkie cząstki lipoprotein we krwi, w tym frakcje LDL, HDL i pozostałości. Sam cholesterol jest niezbędnym budulcem błon komórkowych, hormonów i kwasów żółciowych. Jako pojedyncza liczba pozostaje miarą zgrubną, ponieważ zarówno wysoki udział HDL, jak i wysoki udział LDL podnoszą sumę — dlatego zwykle odczytuje się go wraz z poszczególnymi frakcjami. Oznacza się go przede wszystkim w ramach długoterminowej oceny ryzyka sercowo-naczyniowego.", + "total-cholesterol": "Cholesterol całkowity to suma cholesterolu przenoszonego przez wszystkie cząstki lipoprotein we krwi, w tym frakcje LDL, HDL i pozostałości. Sam cholesterol jest niezbędnym budulcem błon komórkowych, hormonów i kwasów żółciowych. Jako pojedyncza liczba pozostaje miarą zgrubną, ponieważ zarówno wysoki udział HDL, jak i wysoki udział LDL podnoszą sumę, dlatego zwykle odczytuje się go wraz z poszczególnymi frakcjami. Oznacza się go przede wszystkim w ramach długoterminowej oceny ryzyka sercowo-naczyniowego.", "ldl": "Cholesterol LDL to cholesterol przenoszony przez cząstki lipoprotein o małej gęstości, czyli frakcja, która dostarcza cholesterol do tkanek, ale może też odkładać go w ścianach tętnic. Przez lata odkładanie to przyczynia się do blaszki miażdżycowej, dlatego LDL jest jednym z najbaczniej obserwowanych markerów lipidowych. Mniejsza ekspozycja w długim okresie zwykle wiąże się z niższym ryzykiem sercowo-naczyniowym. Interpretuje się go według kategorii ryzyka, a nie wobec jednej stałej wartości prawidłowej.", "hdl": "Cholesterol HDL to cholesterol przenoszony przez cząstki lipoprotein o dużej gęstości, które zbierają nadmiar cholesterolu z tkanek i odprowadzają go do wątroby w celu ponownego wykorzystania lub usunięcia. Z powodu tej funkcji transportowej często nazywa się go frakcją ochronną. Bardzo niskie wartości zwykle towarzyszą wyższemu ryzyku sercowo-naczyniowemu, jednak sztuczne jego podnoszenie nie obniżało ryzyka w sposób wiarygodny, dlatego odczytuje się go jako marker, a nie cel. Zwykle interpretuje się go razem z LDL i trójglicerydami.", "triglycerides": "Trójglicerydy to główna postać tłuszczu krążącego we krwi, dostarczana zarówno z dietą, jak i wytwarzana przez wątrobę, i stanowią kluczowy zapas energii. Wartości rosną po posiłkach, dlatego próbkę pobiera się zwykle na czczo, aby była porównywalna. Utrzymujące się wysokie trójglicerydy wiążą się z ryzykiem metabolicznym i sercowo-naczyniowym i często towarzyszą insulinooporności oraz niskiemu HDL. Odczytuje się je jako jeden ze składników całościowego obrazu lipidowego.", "fasting-glucose": "Glukoza na czczo to stężenie cukru we krwi mierzone po nocnym poście, odzwierciedlające, jak organizm utrzymuje swój podstawowy poziom cukru bez niedawnego posiłku. Glukoza jest głównym natychmiastowym paliwem organizmu, a insulina utrzymuje ją zwykle w wąskim zakresie. Pomiar na czczo eliminuje wpływ niedawnych posiłków, co czyni go standardowym badaniem przesiewowym działania regulacji glukozy. To jeden z markerów, którymi ocenia się zdrowie metaboliczne w czasie.", "hba1c": "HbA1c to odsetek hemoglobiny w czerwonych krwinkach, który związał się z glukozą i gromadzi się proporcjonalnie do średniej ekspozycji na cukier we krwi. Ponieważ czerwone krwinki żyją około trzech miesięcy, odzwierciedla średnie stężenie glukozy z poprzednich dwóch–trzech miesięcy, a nie pojedynczej chwili. Czyni to z niego stabilny, niezależny od posiłków obraz kontroli glikemii. Jego wiarygodność mogą zaburzać stany zmieniające czas życia czerwonych krwinek.", "tsh": "TSH (hormon tyreotropowy) jest uwalniany przez przysadkę, aby sygnalizować tarczycy wytwarzanie jej hormonów, i dostosowuje się w górę lub w dół, by utrzymać je w równowadze. Dzięki tej pętli sprzężenia zwrotnego TSH jest najczulszym badaniem przesiewowym pierwszego rzutu funkcji tarczycy: zwykle zmienia się, zanim same hormony tarczycy odbiegną od normy. Podwyższona lub obniżona wartość wskazuje na niedoczynną lub nadczynną tarczycę i zwykle prowadzi do bezpośredniego oznaczenia hormonów tarczycy. Ciąża i wiek przesuwają oczekiwany zakres.", - "ft3": "Wolne T3 (trójjodotyronina) to niezwiązana, biologicznie czynna postać silniejszego hormonu tarczycy — frakcja dostępna do działania na tkanki. Większość krążącego T3 jest związana z białkami nośnikowymi i nieaktywna, dlatego wolna część odzwierciedla rzeczywistą dostępność hormonu. Oznacza się je, aby scharakteryzować funkcję tarczycy, zwłaszcza wraz z TSH i wolnym T4, gdy wyniki są niejasne. Wartości silnie zależą od metody oznaczenia i odczytuje się je w kontekście klinicznym.", + "ft3": "Wolne T3 (trójjodotyronina) to niezwiązana, biologicznie czynna postać silniejszego hormonu tarczycy, czyli frakcja dostępna do działania na tkanki. Większość krążącego T3 jest związana z białkami nośnikowymi i nieaktywna, dlatego wolna część odzwierciedla rzeczywistą dostępność hormonu. Oznacza się je, aby scharakteryzować funkcję tarczycy, zwłaszcza wraz z TSH i wolnym T4, gdy wyniki są niejasne. Wartości silnie zależą od metody oznaczenia i odczytuje się je w kontekście klinicznym.", "ft4": "Wolne T4 (tyroksyna) to niezwiązana postać głównego hormonu, który tarczyca uwalnia do krwi; służy jako rezerwa, którą tkanki w razie potrzeby przekształcają w bardziej aktywne T3. Wolna frakcja odzwierciedla to, co jest faktycznie dostępne dla organizmu, niezależnie od poziomu białek nośnikowych. Zwykle oznacza się je wraz z TSH, aby odróżnić problemy samej tarczycy od zaburzeń sygnalizacji przysadkowej. Ciąża i niektóre leki mogą je przesuwać.", - "ferritin": "Ferrytyna to główne białko magazynujące żelazo w organizmie, a jej poziom we krwi z grubsza odzwierciedla całkowite zapasy żelaza. Niska wartość wskazuje na wyczerpane zapasy, a wysoka może odzwierciedlać przeładowanie żelazem — lub po prostu stan zapalny, ponieważ ferrytyna rośnie także jako białko ostrej fazy. Z tego powodu często interpretuje się ją wraz z innymi markerami żelaza i oznakami zapalenia. To jedna z podstawowych miar oceny gospodarki żelazem.", - "transferrin-saturation": "Wysycenie transferyny to odsetek transferyny — białka przenoszącego żelazo we krwi — który jest aktualnie obładowany żelazem. Łączy ono ilość żelaza w transporcie ze zdolnością organizmu do jego przenoszenia, dając migawkę dostępności żelaza, która uzupełnia obraz zapasów dawany przez ferrytynę. Niskie wysycenie sugeruje niedobór żelaza, a wysoka wartość może wskazywać na przeładowanie. Odczytuje się je wraz z ferrytyną i pełnym profilem żelaza.", + "ferritin": "Ferrytyna to główne białko magazynujące żelazo w organizmie, a jej poziom we krwi z grubsza odzwierciedla całkowite zapasy żelaza. Niska wartość wskazuje na wyczerpane zapasy, a wysoka może odzwierciedlać przeładowanie żelazem lub po prostu stan zapalny, ponieważ ferrytyna rośnie także jako białko ostrej fazy. Z tego powodu często interpretuje się ją wraz z innymi markerami żelaza i oznakami zapalenia. To jedna z podstawowych miar oceny gospodarki żelazem.", + "transferrin-saturation": "Wysycenie transferyny to odsetek transferyny (białka przenoszącego żelazo we krwi), który jest aktualnie obładowany żelazem. Łączy ono ilość żelaza w transporcie ze zdolnością organizmu do jego przenoszenia, dając migawkę dostępności żelaza, która uzupełnia obraz zapasów dawany przez ferrytynę. Niskie wysycenie sugeruje niedobór żelaza, a wysoka wartość może wskazywać na przeładowanie. Odczytuje się je wraz z ferrytyną i pełnym profilem żelaza.", "vitamin-d": "Witaminę D oznacza się jako 25-hydroksywitaminę D, krążącą postać magazynową i standardowy marker ogólnego stanu witaminy D. Organizm wytwarza ją w skórze wystawionej na światło słoneczne i część przyswaja z pożywienia; wspiera ona gospodarkę wapniową, zdrowie kości i funkcję odpornościową. Wartości zmieniają się wraz z porą roku, szerokością geograficzną, odcieniem skóry i suplementacją. Oznacza się ją, aby z czasem ocenić, czy zapasy są wystarczające.", - "vitamin-b12": "Witamina B12 (kobalamina) to niezbędna witamina pozyskiwana głównie z produktów pochodzenia zwierzęcego i magazynowana w dużej mierze w wątrobie. Jest potrzebna do tworzenia czerwonych krwinek, syntezy DNA i zdrowia układu nerwowego. Długotrwały niedobór — z powodu małego spożycia lub upośledzonego wchłaniania — może prowadzić do niedokrwistości i objawów neurologicznych. Oznacza się ją, aby ocenić stan odżywienia, zwłaszcza tam, gdzie spożycie lub wchłanianie mogą być ograniczone.", + "vitamin-b12": "Witamina B12 (kobalamina) to niezbędna witamina pozyskiwana głównie z produktów pochodzenia zwierzęcego i magazynowana w dużej mierze w wątrobie. Jest potrzebna do tworzenia czerwonych krwinek, syntezy DNA i zdrowia układu nerwowego. Długotrwały niedobór (z powodu małego spożycia lub upośledzonego wchłaniania) może prowadzić do niedokrwistości i objawów neurologicznych. Oznacza się ją, aby ocenić stan odżywienia, zwłaszcza tam, gdzie spożycie lub wchłanianie mogą być ograniczone.", "folate": "Foliany (witamina B9) to witamina z grupy B obecna w zielonych warzywach liściastych, roślinach strączkowych i żywności wzbogacanej, kluczowa dla tworzenia czerwonych krwinek i syntezy DNA. Działa w ścisłym powiązaniu z witaminą B12, a niedobór któregokolwiek z nich może wywołać podobny rodzaj niedokrwistości. Odpowiednia ilość folianów jest szczególnie ważna na początku ciąży dla zdrowego rozwoju płodu. Oznacza się je, aby ocenić stan odżywienia i przyczynę niektórych niedokrwistości.", "hs-crp": "Wysokoczułe CRP mierzy białko C-reaktywne, marker uwalniany przez wątrobę w odpowiedzi na stan zapalny, metodą dostrojoną do wykrywania niskich stężeń istotnych dla ryzyka sercowo-naczyniowego. W odróżnieniu od standardowego CRP stosowanego przy ostrych infekcjach wersja wysokoczuła wychwytuje subtelny, przewlekły stan zapalny powiązany z chorobą naczyń. Ponieważ każda niedawna infekcja lub uraz może je podnieść, interpretuje się je z dala od ostrej choroby i często potwierdza powtórną próbką. Odczytuje się je jako jeden z czynników całościowego ryzyka sercowo-naczyniowego.", "creatinine": "Kreatynina to produkt przemiany materii prawidłowego metabolizmu mięśni, który nerki filtrują z krwi w dość stałym tempie. Ponieważ jej wytwarzanie jest stosunkowo stałe, jej poziom we krwi służy jako praktyczna miara tego, jak dobrze nerki usuwają produkty przemiany materii. Na wartości wpływają też masa mięśniowa, nawodnienie i dieta, dlatego zwykle interpretuje się je wraz z szacowanym współczynnikiem filtracji. To podstawowy marker funkcji nerek.", "egfr": "eGFR (szacowany współczynnik filtracji kłębuszkowej) szacuje, ile krwi nerki filtrują w ciągu minuty, na podstawie kreatyniny oraz wieku i płci. Przekłada surową wartość kreatyniny na bardziej bezpośrednio zrozumiałą miarę funkcji nerek. Spadek eGFR w czasie to główny sposób klasyfikowania i śledzenia przewlekłych zmian w nerkach. Jako wartość szacunkowa odczytuje się go jako trend, a nie pojedynczą dokładną liczbę.", "alt": "ALT (aminotransferaza alaninowa) to enzym skupiony w komórkach wątroby, uwalniany do krwi, gdy komórki te są obciążone lub uszkodzone. Ponieważ jest stosunkowo swoisty dla wątroby, należy do głównych markerów wykrywania uszkodzenia lub zapalenia wątroby. Wartości mogą rosnąć przy stłuszczeniu wątroby, wirusowym zapaleniu wątroby, alkoholu lub niektórych lekach. Zwykle odczytuje się go wraz z AST i pozostałymi markerami profilu wątrobowego.", "ast": "AST (aminotransferaza asparaginianowa) to enzym obecny w wątrobie, ale także w mięśniach, sercu i czerwonych krwinkach, uwalniany przy uszkodzeniu którejkolwiek z tych tkanek. Ponieważ jest mniej swoisty dla wątroby niż ALT, oba interpretuje się razem, a ich stosunek może wskazywać na źródło i charakter problemu. Intensywny wysiłek lub uraz mięśni mogą go podnieść niezależnie od wątroby. To jeden ze standardowych enzymów profilu wątrobowego.", - "ggt": "GGT (gamma-glutamylotransferaza) to enzym wątroby i dróg żółciowych, który rośnie zwłaszcza przy utrudnionym odpływie żółci lub w wyniku ekspozycji na alkohol. Często służy do wyjaśnienia, dlaczego inny marker wątrobowy jest podwyższony — na przykład, aby odróżnić źródło wątrobowe od żółciowego. Jest czuły, ale mało swoisty, dlatego odczytuje się go w kontekście reszty profilu wątrobowego. To jeden z kilku markerów używanych do oceny zdrowia wątroby i dróg żółciowych.", + "ggt": "GGT (gamma-glutamylotransferaza) to enzym wątroby i dróg żółciowych, który rośnie zwłaszcza przy utrudnionym odpływie żółci lub w wyniku ekspozycji na alkohol. Często służy do wyjaśnienia, dlaczego inny marker wątrobowy jest podwyższony, na przykład, aby odróżnić źródło wątrobowe od żółciowego. Jest czuły, ale mało swoisty, dlatego odczytuje się go w kontekście reszty profilu wątrobowego. To jeden z kilku markerów używanych do oceny zdrowia wątroby i dróg żółciowych.", "sodium": "Sód to główny elektrolit płynu poza komórkami organizmu i podstawowy regulator gospodarki płynami oraz objętości krwi. Organizm reguluje go ściśle poprzez pragnienie, hormony i nerki, dlatego jego poziom we krwi odzwierciedla raczej równowagę między wodą a solą niż samo spożycie. Nieprawidłowe wartości zwykle sygnalizują zaburzenie gospodarki wodnej, a nie samego sodu. To podstawowy element panelu metabolicznego i elektrolitowego.", "potassium": "Potas to główny elektrolit wewnątrz komórek organizmu i jest niezbędny do przewodzenia nerwowego oraz równego rytmu mięśnia sercowego. Jego poziom we krwi utrzymywany jest w wąskim zakresie przez nerki i sygnały hormonalne, ponieważ zarówno wysokie, jak i niskie wartości mogą zaburzać aktywność elektryczną serca. Na wartości mogą wpływać funkcja nerek, nawodnienie i kilka powszechnych leków. To podstawowa miara panelu elektrolitowego.", "hemoglobin": "Hemoglobina to zawierające żelazo białko czerwonych krwinek, które wiąże tlen w płucach i przenosi go do tkanek. Jej stężenie jest główną miarą zdolności krwi do przenoszenia tlenu i centralnym markerem wykrywania niedokrwistości. Niskie wartości mogą odzwierciedlać utratę krwi, niedobór żelaza lub witamin albo zmniejszone wytwarzanie, a wysokie mogą następować po odwodnieniu lub w warunkach niedoboru tlenu. To filar pełnej morfologii krwi.", "hematocrit": "Hematokryt to udział czerwonych krwinek w objętości krwi, wyrażony w procentach. Zmienia się ściśle wraz z hemoglobiną i daje uzupełniający obraz masy czerwonych krwinek oraz zdolności krwi do przenoszenia tlenu. Wpływa na niego nawodnienie, ponieważ zmiany objętości osocza przesuwają ten udział nawet wtedy, gdy liczba czerwonych krwinek pozostaje stała. Odczytuje się go wraz z hemoglobiną i resztą morfologii.", "wbc": "Liczba białych krwinek to całkowita liczba komórek odpornościowych krążących we krwi, ruchomej obrony organizmu przed infekcjami. Rośnie w odpowiedzi na infekcję, stan zapalny lub stres i może spadać, gdy szpik kostny jest osłabiony lub w niektórych chorobach odpornościowych. Ponieważ sumuje kilka odrębnych typów komórek, wyraźną zmianę często uzupełnia się rozmazem, który rozbija ją na składowe. To podstawowy element pełnej morfologii krwi.", "platelets": "Płytki krwi to drobne fragmenty komórek we krwi, które zlepiają się i tworzą początkowy czop zatrzymujący krwawienie z uszkodzonego naczynia. Ich liczba odzwierciedla równowagę między wytwarzaniem w szpiku kostnym a zużyciem lub rozpadem. Niska liczba może zwiększać skłonność do krwawień, a wysoka może następować po stanie zapalnym lub innych bodźcach. Stanowią część pełnej morfologii krwi i są podstawową miarą zdolności krzepnięcia.", - "apob": "Apolipoproteina B to białko strukturalne obecne na każdej z aterogennych cząstek lipoprotein, więc jej pomiar zlicza te cząstki bezpośrednio, a nie cholesterol, który przenoszą. Ponieważ na każdej cząstce LDL, VLDL i pokrewnej znajduje się jedna cząsteczka ApoB, może ona wychwycić ryzyko sercowo-naczyniowe, które umyka wartości cholesterolu LDL — zwłaszcza gdy liczba cząstek i ich zawartość cholesterolu się rozchodzą. Z tego powodu coraz częściej używa się jej do uściślenia oceny ryzyka opartej na lipidach. Interpretuje się ją wraz ze zwykłym profilem lipidowym.", + "apob": "Apolipoproteina B to białko strukturalne obecne na każdej z aterogennych cząstek lipoprotein, więc jej pomiar zlicza te cząstki bezpośrednio, a nie cholesterol, który przenoszą. Ponieważ na każdej cząstce LDL, VLDL i pokrewnej znajduje się jedna cząsteczka ApoB, może ona wychwycić ryzyko sercowo-naczyniowe, które umyka wartości cholesterolu LDL, zwłaszcza gdy liczba cząstek i ich zawartość cholesterolu się rozchodzą. Z tego powodu coraz częściej używa się jej do uściślenia oceny ryzyka opartej na lipidach. Interpretuje się ją wraz ze zwykłym profilem lipidowym.", "lp-a": "Lipoproteina(a) to cząstka podobna do LDL z dodatkowo przyłączonym białkiem, której poziom jest w dużej mierze uwarunkowany genetycznie i pozostaje dość stabilny przez całe życie. Podwyższona Lp(a) jest niezależnym, dziedzicznym czynnikiem ryzyka chorób sercowo-naczyniowych i zwężenia zastawki aortalnej. Ponieważ niewiele się zmienia, zwykle oznacza się ją raz, aby ustalić ryzyko danej osoby na całe życie, a nie śledzić wielokrotnie. Podaje się ją w jednostkach molowych i odczytuje w ramach całościowego ryzyka sercowo-naczyniowego.", - "fasting-insulin": "Insulina na czczo to poziom insuliny — hormonu, który przenosi glukozę z krwi do komórek — mierzony po nocnym poście. W połączeniu z glukozą na czczo pomaga oszacować insulinooporność, czyli stan, w którym organizm potrzebuje więcej insuliny, aby utrzymać glukozę w zakresie. Wysoka insulina na czczo przy prawidłowej glukozie może być wczesnym znakiem, że ta kompensacja jest w toku. Odczytuje się ją w ramach obrazu zdrowia metabolicznego, a nie w oderwaniu.", - "omega-3-index": "Indeks omega-3 to udział EPA i DHA — dwóch długołańcuchowych morskich kwasów tłuszczowych omega-3 — wśród kwasów tłuszczowych błon czerwonych krwinek. Ponieważ czerwone krwinki odnawiają się powoli, odzwierciedla on długoterminowe spożycie omega-3, a nie niedawny posiłek. Wyższy indeks wiązano w badaniach obserwacyjnych z niższym ryzykiem sercowo-naczyniowym. Śledzi się go jako stabilny marker stanu omega-3, który reaguje na dietę w ciągu miesięcy." + "fasting-insulin": "Insulina na czczo to poziom insuliny (hormonu, który przenosi glukozę z krwi do komórek) mierzony po nocnym poście. W połączeniu z glukozą na czczo pomaga oszacować insulinooporność, czyli stan, w którym organizm potrzebuje więcej insuliny, aby utrzymać glukozę w zakresie. Wysoka insulina na czczo przy prawidłowej glukozie może być wczesnym znakiem, że ta kompensacja jest w toku. Odczytuje się ją w ramach obrazu zdrowia metabolicznego, a nie w oderwaniu.", + "omega-3-index": "Indeks omega-3 to udział EPA i DHA (dwóch długołańcuchowych morskich kwasów tłuszczowych omega-3) wśród kwasów tłuszczowych błon czerwonych krwinek. Ponieważ czerwone krwinki odnawiają się powoli, odzwierciedla on długoterminowe spożycie omega-3, a nie niedawny posiłek. Wyższy indeks wiązano w badaniach obserwacyjnych z niższym ryzykiem sercowo-naczyniowym. Śledzi się go jako stabilny marker stanu omega-3, który reaguje na dietę w ciągu miesięcy." }, "apob": "Apolipoproteina B (ApoB)", "lp-a": "Lipoproteina(a)", @@ -9500,7 +9500,7 @@ "acceptImageOnly": "JPEG, PNG lub WebP", "extracting": "Odczytywanie wyniku…", "readingOnDevice": "Odczytywanie na Twoim urządzeniu…", - "localModeHint": "Odczytywane na Twoim urządzeniu i wysyłane jako tekst. Mniej dokładne — sprawdź każdą wartość.", + "localModeHint": "Odczytywane na Twoim urządzeniu i wysyłane jako tekst. Mniej dokładne, więc sprawdź każdą wartość.", "rangeFromScan": "Zakres referencyjny pobrany ze skanu", "rangeVerify": "Zweryfikuj zakres referencyjny", "reviewTitle": "Sprawdź przed zapisaniem", @@ -9515,12 +9515,12 @@ "dateLabel": "Data", "refLowLabel": "Dolna granica", "refHighLabel": "Górna granica", - "newBiomarker": "Nowy biomarker — zostanie utworzony", + "newBiomarker": "Nowy biomarker, zostanie utworzony", "linksExisting": "Łączy z istniejącym {name}", "duplicateWarning": "Pasujący wynik już istnieje", "lowConfidence": "Sprawdź tę wartość", "lowConfidenceBadge": "Niska pewność", - "valueUnreadable": "Wartość nieczytelna — wprowadź ją ręcznie", + "valueUnreadable": "Wartość nieczytelna, wprowadź ją ręcznie", "saveSelected": "Zapisz {count} wybranych", "discardAll": "Odrzuć wszystko", "savedToast": "Zapisano {count} wyników laboratoryjnych", @@ -9903,7 +9903,7 @@ }, "correlation": { "title": "Jak przebiegało", - "learning": "Wciąż się uczę — zapisz jeszcze kilka dni, aby zobaczyć tu wzorce.", + "learning": "Wciąż się uczę. Zapisz jeszcze kilka dni, aby zobaczyć tu wzorce.", "preOnsetTitle": "Jak się zapowiadało", "preOnsetBody": "Sygnały, które odbiegły od Twojej bazy przed oznaczonym początkiem.", "nadirTitle": "Co się zmieniło", @@ -9930,7 +9930,7 @@ "countOne": "W tym okresie zapisałeś 1 epizod.", "countOther": "W tym okresie zapisałeś {count} epizodów.", "typicalGap": "Typowa luka rekonwalescencji: {days} dni między poprawą a ustabilizowaniem wartości.", - "typicalGapWithDriver": "Typowa luka rekonwalescencji: {days} dni – zwykle czujesz się lepiej, zanim {vital} się ustabilizuje.", + "typicalGapWithDriver": "Typowa luka rekonwalescencji: {days} dni. Zwykle czujesz się lepiej, zanim {vital} się ustabilizuje.", "typicalGapLearning": "Jeszcze kilka zakończonych epizodów i pojawi się tu typowa luka rekonwalescencji.", "none": "Brak epizodów zapisanych w tym okresie.", "analyze": "Przeanalizuj lukę rekonwalescencji" @@ -10004,7 +10004,7 @@ "dismiss": "Nie teraz", "applied": "Dodano", "dismissed": "Odrzucono", - "failed": "Nie udało się dodać — spróbuj ponownie", + "failed": "Nie udało się dodać. Spróbuj ponownie", "checkup": { "title": "Dodać przypomnienie o badaniu?" }, @@ -10032,9 +10032,9 @@ "reviewPrefix": "Przegląd: {when}", "accept": "Przyjmij plan", "decline": "Odrzuć", - "accepted": "Plan przyjęty — Coach będzie o nim pamiętał.", + "accepted": "Plan przyjęty. Coach będzie o nim pamiętał.", "declined": "Propozycja odrzucona.", - "failed": "Nie udało się — spróbuj ponownie.", + "failed": "Nie udało się. Spróbuj ponownie.", "markMet": "Cel osiągnięty", "abandon": "Zakończ plan", "remove": "Usuń", @@ -10056,10 +10056,10 @@ }, "refusal": { "outOfScope": "Mogę pomóc wyłącznie z danymi zdrowotnymi z Twojego dziennika: pomiarami, lekami, nastrojem, trendami. Na pytania spoza tego zakresu nie odpowiadam.", - "promptInjection": "Zauważyłem polecenia, które próbują obejść moje wytyczne. Jestem Coachem HealthLog i podsumowuję wyłącznie Twoje własne dane zdrowotne — sformułuj pytanie w tych ramach.", + "promptInjection": "Zauważyłem polecenia, które próbują obejść moje wytyczne. Jestem Coachem HealthLog i podsumowuję wyłącznie Twoje własne dane zdrowotne. Sformułuj pytanie w tych ramach.", "conversationPoisoned": "Wcześniejsza wiadomość w tej rozmowie zawiera polecenia, które próbują obejść moje wytyczne. Rozpocznij nową rozmowę." }, - "noRecordedData": "Nie masz zapisanych żadnych pomiarów dla tego, o co pytasz, więc nie mogę podać Ci żadnej liczby. Gdy coś zapiszesz, zapytaj ponownie — wtedy oprę się na Twoich własnych wartościach.", + "noRecordedData": "Nie masz zapisanych żadnych pomiarów dla tego, o co pytasz, więc nie mogę podać Ci żadnej liczby. Gdy coś zapiszesz, zapytaj ponownie, a wtedy oprę się na Twoich własnych wartościach.", "step": { "read": "Czytam: {domain}", "readWindow": "Czytam: {domain}, {window}", @@ -10272,7 +10272,7 @@ }, "mentalHealth": { "pageTitle": "Dobrostan psychiczny", - "pageDescription": "Cztery zwalidowane, dobrowolne testy — liczy się przebieg w czasie, nie pojedynczy wynik.", + "pageDescription": "Cztery zwalidowane, dobrowolne testy: liczy się przebieg w czasie, nie pojedynczy wynik.", "attributionLabel": "Źródło", "attributionShow": "Źródło i licencja: {instrument}", "choosePrompt": "Wybierz sprawdzenie", @@ -10307,7 +10307,7 @@ "2": "Bardzo utrudniły", "3": "Skrajnie utrudniły" }, - "functionalOptionalHint": "Opcjonalne — możesz wysłać bez odpowiedzi na to pytanie.", + "functionalOptionalHint": "Opcjonalne: możesz wysłać bez odpowiedzi na to pytanie.", "result": { "title": "Twój wynik", "totalLabel": "Wynik łączny", @@ -10360,9 +10360,9 @@ "3": "Kłopoty z zaśnięciem lub utrzymaniem snu albo zbyt długi sen", "4": "Uczucie zmęczenia lub brak energii", "5": "Brak apetytu lub przejadanie się", - "6": "Złe myślenie o sobie — poczucie, że jest się nieudacznikiem lub że zawiodło się siebie albo rodzinę", + "6": "Złe myślenie o sobie, poczucie, że jest się nieudacznikiem lub że zawiodło się siebie albo rodzinę", "7": "Trudności ze skupieniem się, na przykład podczas czytania gazety lub oglądania telewizji", - "8": "Poruszanie się lub mówienie tak wolno, że inni mogli to zauważyć? Albo przeciwnie — niepokój lub pobudzenie powodujące, że poruszasz się znacznie więcej niż zwykle", + "8": "Poruszanie się lub mówienie tak wolno, że inni mogli to zauważyć? Albo przeciwnie: niepokój lub pobudzenie powodujące, że poruszasz się znacznie więcej niż zwykle", "9": "Myśli, że lepiej byłoby umrzeć albo chęć zrobienia sobie w jakiś sposób krzywdy" }, "gad7": { @@ -10497,7 +10497,7 @@ }, "openDetail": "Pokaż szczegóły", "historyLoadError": "Nie udało się wczytać historii testów", - "historyLoadErrorHint": "To nie znaczy, że nie masz wyników — nie udało się pobrać listy. Spróbuj ponownie.", + "historyLoadErrorHint": "To nie znaczy, że nie masz wyników; nie udało się pobrać listy. Spróbuj ponownie.", "privacyNote": "Twoje odpowiedzi są przechowywane w postaci zaszyfrowanej i nigdy nie trafiają do Coacha AI." }, "records": { @@ -11186,7 +11186,7 @@ "genericDescription": "Pomiar, który śledzisz. Dodawaj wartości, aby obserwować go w czasie.", "emptyTitle": "Brak wartości", "emptyDescription": "Dodaj pierwszą wartość, aby zacząć przedstawiać tę metrykę na wykresie.", - "valuesTitle": "{metric} — wszystkie wartości", + "valuesTitle": "{metric}: wszystkie wartości", "valuesDescription": "Wszystkie zapisane wartości tej metryki.", "backToMetric": "Powrót do {metric}" } @@ -11233,7 +11233,7 @@ "lastAttemptReason": { "unitMismatch": "Otrzymane wartości nie pasowały do jednostek, których ta aplikacja oczekuje dla tych składników odżywczych, więc nie udało się ich zapisać.", "valueOutOfRange": "Otrzymane ilości były wyższe, niż ta aplikacja może wiarygodnie zapisać, więc nie udało się ich zapisać.", - "dayInvalid": "Wpisy zawierały datę, której serwer nie mógł zaakceptować. Może się to zdarzyć, gdy zegar lub strefa czasowa po stronie wysyłającej są nieprawidłowe — warto to sprawdzić.", + "dayInvalid": "Wpisy zawierały datę, której serwer nie mógł zaakceptować. Może się to zdarzyć, gdy zegar lub strefa czasowa po stronie wysyłającej są nieprawidłowe, więc warto to sprawdzić.", "upsertFailed": "Te wpisy dotarły do serwera, ale problem po naszej stronie uniemożliwił ich zapisanie. Nie musisz nic robić.", "unknown": "Te wpisy dotarły, ale nie udało się ich zapisać." } @@ -11252,7 +11252,7 @@ "emptyTitle": "Brak jeszcze zsynchronizowanych danych o mikroskładnikach", "loadError": "Nie udało się wczytać danych o składnikach odżywczych" }, - "sparseNote": "Niska wartość zwykle oznacza tu rzadkie zapisywanie, a nie niedobór — dzienne sumy z Apple Health odzwierciedlają to, co zapisały twoje aplikacje, a nie całkowite spożycie w diecie." + "sparseNote": "Niska wartość zwykle oznacza tu rzadkie zapisywanie, a nie niedobór. Dzienne sumy z Apple Health odzwierciedlają to, co zapisały twoje aplikacje, a nie całkowite spożycie w diecie." }, "daily": { "line": { @@ -11279,27 +11279,27 @@ }, "syncIssue": { "title": "Synchronizacja wymaga uwagi", - "body": "{integration} się nie synchronizuje — połącz ponownie, aby dane były aktualne." + "body": "{integration} się nie synchronizuje. Połącz ponownie, aby dane były aktualne." }, "coachCheckin": { "title": "Czas przyjrzeć się planowi", - "body": "Minął mniej więcej tydzień, odkąd ustaliłeś ten plan — zachowaj go, dostosuj lub odpuść. Bez presji.", - "bodyPlan": "Około tygodnia temu postanowiłeś: „{plan}”. Zachowaj to, dostosuj lub odpuść — bez presji.", + "body": "Minął mniej więcej tydzień, odkąd ustaliłeś ten plan. Zachowaj go, dostosuj lub odpuść. Bez presji.", + "bodyPlan": "Około tygodnia temu postanowiłeś: „{plan}”. Zachowaj to, dostosuj lub odpuść, bez presji.", "adjustPrompt": "Chciałbym dostosować mój plan kontrolny.", "adjustPromptPlan": "Chciałbym dostosować ten plan: „{plan}”" }, "tensionWindow": { "title": "Może chwila napięcia dzisiaj", "body": { - "morning": "Twoje tętno przez dłuższą chwilę rano utrzymywało się powyżej wartości spoczynkowej, gdy byłeś w bezruchu — możliwe napięcie.", - "afternoon": "Twoje tętno przez dłuższą chwilę po południu utrzymywało się powyżej wartości spoczynkowej, gdy byłeś w bezruchu — możliwe napięcie.", - "evening": "Twoje tętno przez dłuższą chwilę wieczorem utrzymywało się powyżej wartości spoczynkowej, gdy byłeś w bezruchu — możliwe napięcie.", - "night": "Twoje tętno przez dłuższą chwilę w nocy utrzymywało się powyżej wartości spoczynkowej, gdy byłeś w bezruchu — możliwe napięcie." + "morning": "Twoje tętno przez dłuższą chwilę rano utrzymywało się powyżej wartości spoczynkowej, gdy byłeś w bezruchu. Możliwe napięcie.", + "afternoon": "Twoje tętno przez dłuższą chwilę po południu utrzymywało się powyżej wartości spoczynkowej, gdy byłeś w bezruchu. Możliwe napięcie.", + "evening": "Twoje tętno przez dłuższą chwilę wieczorem utrzymywało się powyżej wartości spoczynkowej, gdy byłeś w bezruchu. Możliwe napięcie.", + "night": "Twoje tętno przez dłuższą chwilę w nocy utrzymywało się powyżej wartości spoczynkowej, gdy byłeś w bezruchu. Możliwe napięcie." } }, "ecgNewRecording": { "title": "Nowy zapis EKG", - "body": "Twoje urządzenie zarejestrowało nowe EKG — gotowe do podglądu.", + "body": "Twoje urządzenie zarejestrowało nowe EKG, gotowe do podglądu.", "bodyVerdict": "Twoje urządzenie zarejestrowało nowe EKG i zgłosiło: {verdict}.", "verdict": { "irregular": "możliwy nieregularny rytm", @@ -11319,9 +11319,9 @@ }, "upcomingVisit": { "title": "Zbliża się wizyta", - "bodyToday": "{what} — dzisiaj", - "bodyTomorrow": "{what} — jutro", - "bodyDayAfterTomorrow": "{what} — pojutrze" + "bodyToday": "{what}, dzisiaj", + "bodyTomorrow": "{what}, jutro", + "bodyDayAfterTomorrow": "{what}, pojutrze" } }, "action": { @@ -11340,7 +11340,7 @@ "scoreLabel": "Wynik zdrowia", "deltaVsBaseline": "{delta} wzgl. Twojej wartości bazowej", "deltaFlat": "Zgodnie z Twoją wartością bazową", - "sleepPending": "Sen z ostatniej nocy jeszcze nie dotarł — dzisiejszy odczyt jest wstępny.", + "sleepPending": "Sen z ostatniej nocy jeszcze nie dotarł, więc dzisiejszy odczyt jest wstępny.", "worthALook": "Warto sprawdzić", "allClear": "Dziś nic nie wymaga Twojej uwagi.", "ringLink": "Otwórz szczegóły: {metric}", @@ -11594,7 +11594,7 @@ "errorScope": "Tych sekcji nie da się udostępnić w ten sposób. Wybierz co najmniej jedną sekcję albo udostępnij całą kartotekę.", "errorManageBrowserOnly": "Dostęp zarządzający można przyznać tylko w przeglądarce.", "errorStepUp": "Potwierdź drugi składnik logowania i spróbuj ponownie.", - "errorOffline": "To nie dotarło do serwera. Twoje zaproszenie nadal tu jest — sprawdź połączenie i spróbuj ponownie." + "errorOffline": "To nie dotarło do serwera. Twoje zaproszenie nadal tu jest. Sprawdź połączenie i spróbuj ponownie." }, "given": { "title": "Kto może otworzyć moją kartę", @@ -11914,7 +11914,7 @@ }, "actionError": { "retry": "Spróbuj ponownie", - "offline": "To nie dotarło do serwera. Nic się nie zmieniło — sprawdź połączenie i spróbuj ponownie.", + "offline": "To nie dotarło do serwera. Nic się nie zmieniło. Sprawdź połączenie i spróbuj ponownie.", "rateLimited": "Zbyt wiele prób pod rząd. Odczekaj minutę i spróbuj ponownie.", "acceptExpired": "To zaproszenie wygasło. Poproś o nowe.", "acceptWithdrawn": "To zaproszenie zostało wycofane.", @@ -11926,7 +11926,7 @@ "notFound": "Tego dostępu już nie ma.", "revokeFailed": "Nie udało się zakończyć dostępu.", "renounceFailed": "Nie udało się zwrócić dostępu.", - "profileNotFound": "Tego profilu już nie ma — mógł zostać usunięty albo Twój dostęp do niego się zakończył.", + "profileNotFound": "Tego profilu już nie ma. Mógł zostać usunięty albo Twój dostęp do niego się zakończył.", "deleteProfileFailed": "Nie udało się usunąć profilu.", "removeGuardianFailed": "Nie udało się zakończyć tego dostępu." }, @@ -11983,7 +11983,7 @@ "created": "Wizyta zapisana", "updated": "Wizyta zaktualizowana", "saveFailed": "Nie udało się zapisać wizyty.", - "checkupNotClosed": "Wizyta zapisana. Badanie pozostaje otwarte — twój dostęp tego nie obejmuje.", + "checkupNotClosed": "Wizyta zapisana. Badanie pozostaje otwarte, bo twój dostęp tego nie obejmuje.", "status": { "planned": "Zaplanowana", "done": "Odbyta", @@ -12000,7 +12000,7 @@ "dateDerivesStatusHint": "Data w przyszłości oznacza umówiony termin.", "status": "Status", "practitioner": "Gabinet lub lekarz", - "practitionerHint": "Opcjonalne — nazwę możesz dodać później.", + "practitionerHint": "Opcjonalne: nazwę możesz dodać później.", "practitionerNone": "Nie podano", "practitionerSearch": "Szukaj nazwiska lub gabinetu", "practitionerNoMatch": "Nie znaleziono wpisu.", @@ -12058,7 +12058,7 @@ }, "practitioners": { "title": "Gabinety i lekarze", - "description": "Twoja własna książka adresowa — wpisz gabinet raz, wybieraj go wszędzie.", + "description": "Twoja własna książka adresowa: wpisz gabinet raz, wybieraj go wszędzie.", "linkLabel": "Książka adresowa", "searchPlaceholder": "Szukaj nazwiska, gabinetu lub specjalizacji", "loadError": "Nie udało się wczytać książki adresowej.", @@ -12260,15 +12260,11 @@ "rugLegend": "Punkty pod osią oznaczają dni z wpisami, pierścień dzień godny uwagi.", "sheetExpand": "Rozwiń na pełną wysokość", "sheetShrink": "Zmniejsz", - "usualLabel": "Twoje 30 dni wcześniej", "valuesLegend": "Punkt to ten dzień, pasek to 30 dni wcześniej", "valuesAllOne": "Wszystkie wartości", "valuesAllFew": "Wszystkie {count} wartości", "valuesAllOther": "Wszystkie {count} wartości", "valuesFewer": "Mniej wartości", - "countValuesOne": "1 wartość", - "countValuesFew": "{count} wartości", - "countValuesOther": "{count} wartości", "countEntriesOne": "1 wpis", "countEntriesFew": "{count} wpisy", "countEntriesOther": "{count} wpisów", @@ -12308,7 +12304,6 @@ "subtitle": "Co i kiedy się działo, obok Twoich wartości.", "standing": "Stałe", "startUnknown": "początek nieznany", - "openDay": "Otwórz {date}", "zoom": { "all": "Wszystko", "year": "12 miesięcy", diff --git a/src/__tests__/dense-measurement-read-guard.test.ts b/src/__tests__/dense-measurement-read-guard.test.ts index 7b5c01433..fa81848b6 100644 --- a/src/__tests__/dense-measurement-read-guard.test.ts +++ b/src/__tests__/dense-measurement-read-guard.test.ts @@ -81,6 +81,8 @@ const DENSE_TYPES: ReadonlySet = new Set([ * list, keyed `::`, with why each stays bounded. */ const ALLOWED: Record = { + "lib/analytics/summaries-slice.ts::(shorthand)": + "one hourly-mean type (pulse) over one local day, the latest: the same rows the day view reads for that day, bounded by a day, not by the sampling history", "lib/insights/comprehensive-generate.ts::(shorthand)": 'Only reached for SLEEP_DURATION (guarded by `type === "SLEEP_DURATION"`); a few stage rows per night.', "lib/insights/derived/vascular-age.ts::VASCULAR_AGE_TYPE": diff --git a/src/__tests__/i18n-no-dot-separator.test.ts b/src/__tests__/i18n-no-dot-separator.test.ts index ae913d92f..f464e6809 100644 --- a/src/__tests__/i18n-no-dot-separator.test.ts +++ b/src/__tests__/i18n-no-dot-separator.test.ts @@ -3,14 +3,18 @@ import { readFileSync, readdirSync } from "node:fs"; import { join } from "node:path"; /** - * No middle-dot separator in visible strings. + * No middle-dot or dash separator in visible strings. * * A value like "Added {date} · {size}" or "Weight · body fat · muscle" reads - * as a list of fragments rather than as the app's plain voice. Facts are - * joined with a comma, a colon or a real phrase instead. This guard walks - * every bundle under `messages/` and fails on any string that contains a - * space, U+00B7 and a space. A middle dot inside a unit ("mL/(kg·min)") has - * no surrounding spaces and is not matched. + * as a list of fragments rather than as the app's plain voice, and so does + * "{what} — tomorrow" or "Could not save — try again": the dash stands in + * for a comma, a colon or a full stop the sentence should have said. Facts + * are joined with a comma, a colon or a real phrase instead. This guard + * walks every bundle under `messages/` and fails on any string that contains + * a space, then U+00B7 (middle dot), U+2014 (em dash) or U+2013 (en dash), + * then a space. A middle dot inside a unit ("mL/(kg·min)") and a range + * ("70–100 mmHg", "{start}–{end}") have no surrounding spaces and are not + * matched: an unspaced en dash is how a range is written, not a pause. * * A key that genuinely needs the pattern goes into `ALLOWED` with the reason * written next to it. An allowed key that no longer contains the pattern @@ -18,7 +22,10 @@ import { join } from "node:path"; */ const MESSAGES_DIR = join(__dirname, "../../messages"); -const SEPARATOR = " · "; +const SEPARATORS = [" · ", " — ", " – "] as const; + +const hasSeparator = (value: string) => + SEPARATORS.some((separator) => value.includes(separator)); /** Key path -> why the separator is right there. Empty by intent. */ const ALLOWED: Record = {}; @@ -41,7 +48,7 @@ const bundles = readdirSync(MESSAGES_DIR) .filter((file) => file.endsWith(".json")) .sort(); -describe("message bundles carry no ' · ' separator", () => { +describe("message bundles carry no ' · ', ' — ' or ' – ' separator", () => { it("finds the bundles", () => { expect(bundles.length).toBeGreaterThanOrEqual(7); }); @@ -57,18 +64,16 @@ describe("message bundles carry no ' · ' separator", () => { expect(values.size).toBeGreaterThan(1000); }); - it(`${file} has no dot separator outside the allowlist`, () => { + it(`${file} has no dot or dash separator outside the allowlist`, () => { const offenders = [...values] - .filter( - ([key, value]) => value.includes(SEPARATOR) && !(key in ALLOWED), - ) + .filter(([key, value]) => hasSeparator(value) && !(key in ALLOWED)) .map(([key, value]) => `${key} = ${JSON.stringify(value)}`); expect(offenders).toEqual([]); }); it(`${file} has no stale allowlist entry`, () => { const stale = Object.keys(ALLOWED).filter( - (key) => !(values.get(key) ?? "").includes(SEPARATOR), + (key) => !hasSeparator(values.get(key) ?? ""), ); expect(stale).toEqual([]); }); diff --git a/src/__tests__/ui-code-no-dash-separator.test.ts b/src/__tests__/ui-code-no-dash-separator.test.ts new file mode 100644 index 000000000..92c913376 --- /dev/null +++ b/src/__tests__/ui-code-no-dash-separator.test.ts @@ -0,0 +1,66 @@ +import { describe, it, expect } from "vitest"; +import { readFileSync, readdirSync, statSync } from "node:fs"; +import { join, relative } from "node:path"; + +/** + * The code-side twin of `i18n-no-dot-separator.test.ts`: a string the code + * composes itself (an aria-label `${action} — ${name}`, a page title, a + * Coach prefill) carries no spaced em or en dash either. The bundles say + * "Move up: Ramipril" and "No connection: changes can't be saved", so a + * label put together in a component says it the same way. + * + * The matcher looks at string and template literals on one line, outside + * comments: a quote or backtick, then text, a space, U+2014 or U+2013, a + * space. A range written in code ("10–12", `${from}–${to}`) has no spaces + * around its dash and is not matched. A template literal broken across lines + * escapes the one-line matcher, which is this guard's known limit. + */ + +const ROOT = join(__dirname, ".."); +const DIRS = ["components", "app"].map((d) => join(ROOT, d)); +const LITERAL = /(["'`])[^"'`]* [—–] [^"'`]*\1/; + +function walk(dir: string, out: string[] = []): string[] { + for (const name of readdirSync(dir)) { + const path = join(dir, name); + if (statSync(path).isDirectory()) { + if (name === "__tests__") continue; + walk(path, out); + } else if (/\.(ts|tsx)$/.test(name) && !/\.test\./.test(name)) { + out.push(path); + } + } + return out; +} + +const isComment = (line: string) => /^\s*(\/\/|\*|\/\*|\{\/\*)/.test(line); + +describe("composed UI strings carry no spaced dash", () => { + const files = DIRS.flatMap((d) => walk(d)); + + it("walks the component and app trees", () => { + expect(files.length).toBeGreaterThan(500); + }); + + it("has no ' — ' or ' – ' inside a string or template literal", () => { + const offenders: string[] = []; + for (const file of files) { + readFileSync(file, "utf8") + .split("\n") + .forEach((line, i) => { + if (isComment(line)) return; + const code = line.replace(/\s\/\/\s.*$/, ""); + if (LITERAL.test(code)) { + offenders.push(`${relative(ROOT, file)}:${i + 1}: ${line.trim()}`); + } + }); + } + expect(offenders).toEqual([]); + }); + + it("catches the pattern it is written for", () => { + expect(LITERAL.test("aria-label={`${a} — ${b}`}")).toBe(true); + expect(LITERAL.test('title: "About – HealthLog"')).toBe(true); + expect(LITERAL.test("`${from}–${to}`")).toBe(false); + }); +}); diff --git a/src/app/about/page.tsx b/src/app/about/page.tsx index cbfe211f5..69e0134a6 100644 --- a/src/app/about/page.tsx +++ b/src/app/about/page.tsx @@ -44,7 +44,7 @@ export const dynamic = "force-dynamic"; const LAST_UPDATED = "2026-08-02"; export const metadata: Metadata = { - title: "About — HealthLog", + title: "About | HealthLog", description: "Open-source credits and third-party data attributions for the HealthLog project.", robots: { index: true, follow: true }, diff --git a/src/app/api/admin/backups/[id]/restore/route.ts b/src/app/api/admin/backups/[id]/restore/route.ts index 476e47073..70e40146c 100644 --- a/src/app/api/admin/backups/[id]/restore/route.ts +++ b/src/app/api/admin/backups/[id]/restore/route.ts @@ -84,7 +84,7 @@ const handler = apiHandler( details: { reason: "missing_confirmation", backupId: id }, }); return apiError( - "Confirmation token missing — replacing an account's data requires confirm: 'RESTORE'", + "Confirmation token missing. Replacing an account's data requires confirm: 'RESTORE'", 422, ); } diff --git a/src/app/api/admin/central-codex/device-poll/route.ts b/src/app/api/admin/central-codex/device-poll/route.ts index 5f8fecc65..b5e77028f 100644 --- a/src/app/api/admin/central-codex/device-poll/route.ts +++ b/src/app/api/admin/central-codex/device-poll/route.ts @@ -45,7 +45,7 @@ export const POST = apiHandler(async (request: NextRequest) => { userCode = decoded.userCode; } catch { cookieStore.delete("central_codex_device"); - return apiError("Invalid device-auth state — restart the flow", 400); + return apiError("Invalid device-auth state. Restart the flow", 400); } let result; @@ -55,7 +55,7 @@ export const POST = apiHandler(async (request: NextRequest) => { const message = err instanceof Error ? err.message : "unknown"; annotate({ meta: { central_codex_device_poll_error: message } }); return apiError( - "Central Codex device-poll failed — please restart the flow", + "Central Codex device-poll failed. Please restart the flow", 502, ); } diff --git a/src/app/api/ai/test/route.ts b/src/app/api/ai/test/route.ts index 1c6c53cca..eb8166511 100644 --- a/src/app/api/ai/test/route.ts +++ b/src/app/api/ai/test/route.ts @@ -276,13 +276,13 @@ function classifyTestFailure( return { reasonCode: "credentials", reason: - "Provider rejected the credentials — re-authenticate in AI settings.", + "Provider rejected the credentials. Re-authenticate in AI settings.", }; } if (status === 429) { return { reasonCode: "rate_limited", - reason: "Provider rate-limited the request — try again shortly.", + reason: "Provider rate-limited the request. Try again shortly.", }; } if (status >= 500) { @@ -298,7 +298,7 @@ function classifyTestFailure( if (status >= 400 && status < 500) { return { reasonCode: "bad_request", - reason: `The provider rejected the request (HTTP ${status}) — the endpoint answered, so this is a request-shape or model-name problem, not connectivity.`, + reason: `The provider rejected the request (HTTP ${status}). The endpoint answered, so this is a request-shape or model-name problem, not connectivity.`, }; } return { diff --git a/src/app/api/auth/codex/device-poll/route.ts b/src/app/api/auth/codex/device-poll/route.ts index 060b2c08c..05d148189 100644 --- a/src/app/api/auth/codex/device-poll/route.ts +++ b/src/app/api/auth/codex/device-poll/route.ts @@ -47,7 +47,7 @@ export const POST = apiHandler(async (request: NextRequest) => { userCode = decoded.userCode; } catch { cookieStore.delete("codex_device"); - return apiError("Invalid device-auth state — restart the flow", 400); + return apiError("Invalid device-auth state. Restart the flow", 400); } let result; @@ -56,7 +56,7 @@ export const POST = apiHandler(async (request: NextRequest) => { } catch (err) { const message = err instanceof Error ? err.message : "unknown"; annotate({ meta: { codex_device_poll_error: message } }); - return apiError("Codex device-poll failed — please restart the flow", 502); + return apiError("Codex device-poll failed. Please restart the flow", 502); } if (result.status === "pending") { diff --git a/src/app/api/auth/me/health-score-config/route.ts b/src/app/api/auth/me/health-score-config/route.ts index b07c53c07..f262d37a2 100644 --- a/src/app/api/auth/me/health-score-config/route.ts +++ b/src/app/api/auth/me/health-score-config/route.ts @@ -88,7 +88,7 @@ const healthScoreConfigPatchSchema = z */ const BREADTH_REFUSAL = { no_pillars_selected: - "A health score needs at least one area of health to score. Keep one selected — the score will say which areas it is built from.", + "A health score needs at least one area of health to score. Keep one selected. The score will say which areas it is built from.", } as const; export const GET = apiHandler(async () => { diff --git a/src/app/api/auth/passkeys/[id]/route.ts b/src/app/api/auth/passkeys/[id]/route.ts index b8a79f6cd..87cd24b77 100644 --- a/src/app/api/auth/passkeys/[id]/route.ts +++ b/src/app/api/auth/passkeys/[id]/route.ts @@ -135,7 +135,7 @@ export const DELETE = apiHandler( if (passkeyCount <= 1 && !hasPassword) { return apiError( - "Cannot delete — at least one authentication method must remain", + "Cannot delete. At least one authentication method must remain", 400, ); } diff --git a/src/app/api/auth/refresh/route.ts b/src/app/api/auth/refresh/route.ts index adb89145f..2bcc6fa8f 100644 --- a/src/app/api/auth/refresh/route.ts +++ b/src/app/api/auth/refresh/route.ts @@ -96,14 +96,14 @@ export const POST = apiHandler(async (request: NextRequest) => { // the token and re-authenticates. if (result.reason === "already_used") { return apiError( - "Refresh token reuse detected — please log in again.", + "Refresh token reuse detected. Please log in again.", 401, { errorCode: "auth.refresh.reuse" }, ); } if (result.reason === "revoked") { return apiError( - "Refresh token has been revoked — please log in again.", + "Refresh token has been revoked. Please log in again.", 401, { errorCode: "auth.refresh.revoked" }, ); diff --git a/src/app/api/auth/register/route.ts b/src/app/api/auth/register/route.ts index 2c4b5623c..007cb8b55 100644 --- a/src/app/api/auth/register/route.ts +++ b/src/app/api/auth/register/route.ts @@ -58,7 +58,7 @@ export const POST = apiHandler(async (request: NextRequest) => { if (existingSession) { annotate({ action: { name: "auth.register.refused_authenticated" } }); return apiError( - "Already signed in — sign out first to use an invitation", + "Already signed in. Sign out first to use an invitation", 409, { errorCode: "auth.already_authenticated" }, ); diff --git a/src/app/api/encounters/[id]/route.ts b/src/app/api/encounters/[id]/route.ts index a83c937cf..9445b6416 100644 --- a/src/app/api/encounters/[id]/route.ts +++ b/src/app/api/encounters/[id]/route.ts @@ -297,7 +297,7 @@ export const PATCH = apiHandler( if (outcome === "contradictory-reminder") { return apiError( - "A booked visit cannot also close a checkup — it has not happened yet", + "A booked visit cannot also close a checkup. It has not happened yet", 422, { errorCode: "encounter.reminder-conflict" }, ); diff --git a/src/app/api/encounters/route.ts b/src/app/api/encounters/route.ts index 87e72f062..43151980d 100644 --- a/src/app/api/encounters/route.ts +++ b/src/app/api/encounters/route.ts @@ -301,7 +301,7 @@ async function postEncounter(request: NextRequest): Promise { } if (created === "contradictory-reminder") { return apiError( - "A planned visit cannot also close a checkup — it has not happened yet", + "A planned visit cannot also close a checkup. It has not happened yet", 422, { errorCode: "encounter.reminder-conflict" }, ); diff --git a/src/app/api/import/csv/route.ts b/src/app/api/import/csv/route.ts index 37aafbf5e..e6990a216 100644 --- a/src/app/api/import/csv/route.ts +++ b/src/app/api/import/csv/route.ts @@ -149,7 +149,7 @@ export const POST = apiHandler(async (request: NextRequest) => { ); if (okRows.length > MAX_ROWS) { return apiError( - `CSV has ${okRows.length} valid rows — the limit is ${MAX_ROWS} per import`, + `CSV has ${okRows.length} valid rows. The limit is ${MAX_ROWS} per import`, 422, ); } diff --git a/src/app/api/insights/chat/__tests__/__snapshots__/golden-transcripts.test.ts.snap b/src/app/api/insights/chat/__tests__/__snapshots__/golden-transcripts.test.ts.snap index 7581c58cd..0ba896537 100644 --- a/src/app/api/insights/chat/__tests__/__snapshots__/golden-transcripts.test.ts.snap +++ b/src/app/api/insights/chat/__tests__/__snapshots__/golden-transcripts.test.ts.snap @@ -1240,7 +1240,7 @@ exports[`coach chat golden transcripts > 04 inbound refusal on a new conversatio }, { "call": "appendMessage", - "content": "I noticed wording that tries to override my instructions. I am the HealthLog Coach and only summarise your own health data — please rephrase your question in those terms.", + "content": "I noticed wording that tries to override my instructions. I am the HealthLog Coach and only summarise your own health data. Please rephrase your question in those terms.", "metricSource": { "metrics": [ "general", @@ -1256,7 +1256,7 @@ exports[`coach chat golden transcripts > 04 inbound refusal on a new conversatio "contentType": "text/event-stream; charset=utf-8", "frames": [ { - "token": "I noticed wording that tries to override my instructions. I am the HealthLog Coach and only summarise your own health data — please rephrase your question in those terms.", + "token": "I noticed wording that tries to override my instructions. I am the HealthLog Coach and only summarise your own health data. Please rephrase your question in those terms.", "type": "token", }, { @@ -1302,7 +1302,7 @@ exports[`coach chat golden transcripts > 05 replay injection in a stored user tu }, { "call": "appendMessage", - "content": "I noticed wording that tries to override my instructions. I am the HealthLog Coach and only summarise your own health data — please rephrase your question in those terms.", + "content": "I noticed wording that tries to override my instructions. I am the HealthLog Coach and only summarise your own health data. Please rephrase your question in those terms.", "metricSource": { "metrics": [ "general", @@ -1318,7 +1318,7 @@ exports[`coach chat golden transcripts > 05 replay injection in a stored user tu "contentType": "text/event-stream; charset=utf-8", "frames": [ { - "token": "I noticed wording that tries to override my instructions. I am the HealthLog Coach and only summarise your own health data — please rephrase your question in those terms.", + "token": "I noticed wording that tries to override my instructions. I am the HealthLog Coach and only summarise your own health data. Please rephrase your question in those terms.", "type": "token", }, { diff --git a/src/app/api/insights/generate/route.ts b/src/app/api/insights/generate/route.ts index 3668e2443..40a00ebb8 100644 --- a/src/app/api/insights/generate/route.ts +++ b/src/app/api/insights/generate/route.ts @@ -810,7 +810,7 @@ export const POST = apiHandler((request: NextRequest) => // bounds cost. 429 with a distinct code so the client can say so. if (e instanceof BriefingBudgetExceededError) { return apiError( - "Daily AI token budget reached — insights will be available again tomorrow.", + "Daily AI token budget reached. Insights will be available again tomorrow.", 429, { errorCode: "insights.generate.budgetExceeded" }, ); @@ -859,7 +859,7 @@ export const POST = apiHandler((request: NextRequest) => ); if (allAuth) { return apiError( - "AI provider rejected the request — check your API key in Settings > AI", + "AI provider rejected the request. Check your API key in Settings > AI", 422, ); } @@ -881,7 +881,7 @@ export const POST = apiHandler((request: NextRequest) => ); if (allTransport) { return apiError( - "AI provider connection failed — check your AI settings", + "AI provider connection failed. Check your AI settings", 422, ); } @@ -907,7 +907,7 @@ export const POST = apiHandler((request: NextRequest) => const status = err.httpStatus ?? 0; if (status === 401 || status === 403) { return apiError( - "AI provider rejected the request — check your API key in Settings > AI", + "AI provider rejected the request. Check your API key in Settings > AI", 422, ); } @@ -921,7 +921,7 @@ export const POST = apiHandler((request: NextRequest) => ); } return apiError( - "AI provider connection failed — check your AI settings", + "AI provider connection failed. Check your AI settings", 422, ); } @@ -945,7 +945,7 @@ export const POST = apiHandler((request: NextRequest) => if (result.finishReason === "length") { annotate({ meta: { insights_response_truncated: true } }); return apiError( - "AI response was cut off before the JSON completed — raise the token limit (INSIGHTS_MAX_TOKENS)", + "AI response was cut off before the JSON completed. Raise the token limit (INSIGHTS_MAX_TOKENS)", 422, { errorCode: "ai_response_truncated" }, ); diff --git a/src/app/api/labs/[id]/route.ts b/src/app/api/labs/[id]/route.ts index 34afa72a7..fa2c7b326 100644 --- a/src/app/api/labs/[id]/route.ts +++ b/src/app/api/labs/[id]/route.ts @@ -172,14 +172,14 @@ export const PUT = apiHandler( const rowIsQualitative = existing.valueText !== null; if (rowIsQualitative && d.value !== undefined) { return apiError( - "This is a qualitative reading — edit its result text, not a numeric value", + "This is a qualitative reading. Edit its result text, not a numeric value", 422, { errorCode: "labs.update.qualitativeExpected" }, ); } if (!rowIsQualitative && d.valueText !== undefined) { return apiError( - "This is a numeric reading — edit its value, not a qualitative result", + "This is a numeric reading. Edit its value, not a qualitative result", 422, { errorCode: "labs.update.numericExpected" }, ); diff --git a/src/app/api/mcp/oauth/authorize/route.ts b/src/app/api/mcp/oauth/authorize/route.ts index c8a71d9a8..f681d0a91 100644 --- a/src/app/api/mcp/oauth/authorize/route.ts +++ b/src/app/api/mcp/oauth/authorize/route.ts @@ -85,7 +85,7 @@ function badRequest(error: string, description: string): Response { function html(body: string, status = 200): Response { return new Response( - `HealthLog — Authorize access${body}`, + `HealthLog: Authorize access${body}`, { status, headers: { "content-type": "text/html; charset=utf-8" }, @@ -419,13 +419,13 @@ async function authorizeGet(request: NextRequest): Promise { const provenance = v.clientSource === "cimd" ? `

Verified origin: ${htmlEscape(v.clientOrigin)}

` - : `

Unverified application (dynamically registered — the name above is self-reported and not verified).

`; + : `

Unverified application (dynamically registered, the name above is self-reported and not verified).

`; // Plain-language access summary. When write is granted, say so explicitly — // the app will be able to READ and LOG/WRITE health data, not just read. const writeGranted = v.scope.split(/\s+/).includes(SCOPE_HEALTH_WRITE); const accessSummary = writeGranted ? `

This grants read AND write access: the application will be able to read your own health records and log new measurements and mood entries to your account on your behalf. It cannot delete or change existing entries, edit medications, or reach admin functions.

` - : `

Scope: ${htmlEscape(v.scope)} — read-only access to your own health records.

`; + : `

Scope: ${htmlEscape(v.scope)}. Read-only access to your own health records.

`; // What a read reaches, in plain words, before the person clicks Allow. // Document text is named on its own because it is the widest thing a // connection can read (v1.39.3: search and fetch reach it). diff --git a/src/app/api/medications/intake/dose-history-import/route.ts b/src/app/api/medications/intake/dose-history-import/route.ts index 3949c3479..2d3cda2ce 100644 --- a/src/app/api/medications/intake/dose-history-import/route.ts +++ b/src/app/api/medications/intake/dose-history-import/route.ts @@ -176,7 +176,7 @@ export const POST = apiHandler(async (request: NextRequest) => { if (plan.entries.length > MAX_QUEUED_ROWS) { return apiError( - `The file holds ${plan.entries.length} importable rows — the limit is ${MAX_QUEUED_ROWS} per import`, + `The file holds ${plan.entries.length} importable rows. The limit is ${MAX_QUEUED_ROWS} per import`, 422, { errorCode: "too_many_rows" }, ); diff --git a/src/app/api/withings/webhook/route.ts b/src/app/api/withings/webhook/route.ts index a5b2ea7ac..ecda2c96e 100644 --- a/src/app/api/withings/webhook/route.ts +++ b/src/app/api/withings/webhook/route.ts @@ -66,7 +66,7 @@ async function checkAndWarn( } if (auth.via === "query") { getEvent()?.addWarning( - `withings webhook secret received via legacy URL query — migrate to ${MIGRATION_URL} (re-subscribe with the path-segment token form)`, + `withings webhook secret received via legacy URL query. Migrate to ${MIGRATION_URL} (re-subscribe with the path-segment token form)`, ); } return null; diff --git a/src/app/insights/active-energy/page.tsx b/src/app/insights/active-energy/page.tsx index 8bc6d5249..2e0768bb4 100644 --- a/src/app/insights/active-energy/page.tsx +++ b/src/app/insights/active-energy/page.tsx @@ -27,7 +27,7 @@ export default function InsightsActiveEnergyPage() { yAxisUnit="kcal" emptyStateIcon={} emptyStateCtaType={null} - coachPrefill="I haven't logged any active energy yet — what's a reasonable daily target, and how does it compare to total calories?" + coachPrefill="I haven't logged any active energy yet. What's a reasonable daily target, and how does it compare to total calories?" /> ); } diff --git a/src/app/insights/audio-events/page.tsx b/src/app/insights/audio-events/page.tsx index 29dfeb833..c77ca3c68 100644 --- a/src/app/insights/audio-events/page.tsx +++ b/src/app/insights/audio-events/page.tsx @@ -26,7 +26,7 @@ export default function InsightsLaermereignissePage() { yAxisUnit="" emptyStateIcon={} emptyStateCtaType={null} - coachPrefill="I haven't logged any loud-environment events yet — what does this metric tell me about my health, and how do I improve it?" + coachPrefill="I haven't logged any loud-environment events yet. What does this metric tell me about my health, and how do I improve it?" /> ); } diff --git a/src/app/insights/blood-glucose/page.tsx b/src/app/insights/blood-glucose/page.tsx index e2acca4be..60508761c 100644 --- a/src/app/insights/blood-glucose/page.tsx +++ b/src/app/insights/blood-glucose/page.tsx @@ -60,7 +60,7 @@ export default function InsightsBlutzuckerPage() { captureType="BLOOD_GLUCOSE" targetSummarySlug="blood-glucose" afterChart={} - coachPrefill="I haven't logged any blood glucose yet — what does this metric tell me about my health, and how do I improve it?" + coachPrefill="I haven't logged any blood glucose yet. What does this metric tell me about my health, and how do I improve it?" /> ); } diff --git a/src/app/insights/blood-pressure/page.tsx b/src/app/insights/blood-pressure/page.tsx index b8e921f9d..87679fcc8 100644 --- a/src/app/insights/blood-pressure/page.tsx +++ b/src/app/insights/blood-pressure/page.tsx @@ -81,7 +81,7 @@ export default function InsightsBlutdruckPage() { } - coachPrefill="I haven't recorded any blood pressure yet — why does it matter, and what should I know before I start?" + coachPrefill="I haven't recorded any blood pressure yet. Why does it matter, and what should I know before I start?" /> ); diff --git a/src/app/insights/bmi/page.tsx b/src/app/insights/bmi/page.tsx index f9692a6b6..5ec84f3fa 100644 --- a/src/app/insights/bmi/page.tsx +++ b/src/app/insights/bmi/page.tsx @@ -69,7 +69,7 @@ export default function InsightsBmiPage() { } - coachPrefill="I haven't recorded any weight yet — why does BMI matter for me, and what should I know before I start tracking it?" + coachPrefill="I haven't recorded any weight yet. Why does BMI matter for me, and what should I know before I start tracking it?" /> ); diff --git a/src/app/insights/body-temperature/page.tsx b/src/app/insights/body-temperature/page.tsx index 7c4527b5f..9c2ed241d 100644 --- a/src/app/insights/body-temperature/page.tsx +++ b/src/app/insights/body-temperature/page.tsx @@ -24,7 +24,7 @@ export default function InsightsBodyTemperaturePage() { color="var(--chart-3)" emptyStateIcon={} emptyStateCtaType="BODY_TEMPERATURE" - coachPrefill="I haven't logged any body temperature yet — what's the healthy range, and what should I do if it drifts?" + coachPrefill="I haven't logged any body temperature yet. What's the healthy range, and what should I do if it drifts?" /> ); } diff --git a/src/app/insights/body-water/page.tsx b/src/app/insights/body-water/page.tsx index c978c8764..e5483e26c 100644 --- a/src/app/insights/body-water/page.tsx +++ b/src/app/insights/body-water/page.tsx @@ -25,7 +25,7 @@ export default function InsightsKoerperwasserPage() { emptyStateIcon={} emptyStateCtaType={null} captureType="TOTAL_BODY_WATER" - coachPrefill="I haven't logged any total body water yet — what does this metric tell me about my health, and how do I improve it?" + coachPrefill="I haven't logged any total body water yet. What does this metric tell me about my health, and how do I improve it?" /> ); } diff --git a/src/app/insights/bone-mass/page.tsx b/src/app/insights/bone-mass/page.tsx index fadeb392b..acecafe5e 100644 --- a/src/app/insights/bone-mass/page.tsx +++ b/src/app/insights/bone-mass/page.tsx @@ -25,7 +25,7 @@ export default function InsightsKnochenmassePage() { emptyStateIcon={} emptyStateCtaType={null} captureType="BONE_MASS" - coachPrefill="I haven't logged any bone mass yet — what does this metric tell me about my health, and how do I improve it?" + coachPrefill="I haven't logged any bone mass yet. What does this metric tell me about my health, and how do I improve it?" /> ); } diff --git a/src/app/insights/breathing-disturbances/page.tsx b/src/app/insights/breathing-disturbances/page.tsx index c5e1d8e7f..52d092204 100644 --- a/src/app/insights/breathing-disturbances/page.tsx +++ b/src/app/insights/breathing-disturbances/page.tsx @@ -24,7 +24,7 @@ export default function InsightsBreathingDisturbancesPage() { unitKey="insights.units.breathingEvents" emptyStateIcon={} emptyStateCtaType={null} - coachPrefill="I haven't logged any sleep-breathing-disturbance data yet — what does this metric tell me about my health, and how do I improve it?" + coachPrefill="I haven't logged any sleep-breathing-disturbance data yet. What does this metric tell me about my health, and how do I improve it?" /> ); } diff --git a/src/app/insights/cardio-fitness/page.tsx b/src/app/insights/cardio-fitness/page.tsx index 6de5d9b29..8ea2756fc 100644 --- a/src/app/insights/cardio-fitness/page.tsx +++ b/src/app/insights/cardio-fitness/page.tsx @@ -27,7 +27,7 @@ export default function InsightsCardioFitnessPage() { statIcon={Gauge} emptyStateIcon={} emptyStateCtaType={null} - coachPrefill="I haven't logged any cardio-fitness (VO₂ max) data yet — what does this metric tell me about my health, and how do I improve it?" + coachPrefill="I haven't logged any cardio-fitness (VO₂ max) data yet. What does this metric tell me about my health, and how do I improve it?" /> ); } diff --git a/src/app/insights/cardio-recovery/page.tsx b/src/app/insights/cardio-recovery/page.tsx index 16cc1fdf0..f54fdf5e1 100644 --- a/src/app/insights/cardio-recovery/page.tsx +++ b/src/app/insights/cardio-recovery/page.tsx @@ -26,7 +26,7 @@ export default function InsightsCardioRecoveryPage() { yAxisUnit="bpm" emptyStateIcon={} emptyStateCtaType={null} - coachPrefill="I haven't logged any cardio-recovery data yet — what does this metric tell me about my health, and how do I improve it?" + coachPrefill="I haven't logged any cardio-recovery data yet. What does this metric tell me about my health, and how do I improve it?" /> ); } diff --git a/src/app/insights/daylight/page.tsx b/src/app/insights/daylight/page.tsx index b5bc04555..f6b4d023f 100644 --- a/src/app/insights/daylight/page.tsx +++ b/src/app/insights/daylight/page.tsx @@ -26,7 +26,7 @@ export default function InsightsTageslichtPage() { yAxisUnit="min" emptyStateIcon={} emptyStateCtaType={null} - coachPrefill="I haven't logged any time spent in daylight yet — what does this metric tell me about my health, and how do I improve it?" + coachPrefill="I haven't logged any time spent in daylight yet. What does this metric tell me about my health, and how do I improve it?" /> ); } diff --git a/src/app/insights/double-support-time/page.tsx b/src/app/insights/double-support-time/page.tsx index c2d59baf9..021ccb94a 100644 --- a/src/app/insights/double-support-time/page.tsx +++ b/src/app/insights/double-support-time/page.tsx @@ -26,7 +26,7 @@ export default function InsightsDoppelstandphasePage() { yAxisUnit="%" emptyStateIcon={} emptyStateCtaType={null} - coachPrefill="I haven't logged any double support time yet — what does this metric tell me about my health, and how do I improve it?" + coachPrefill="I haven't logged any double support time yet. What does this metric tell me about my health, and how do I improve it?" /> ); } diff --git a/src/app/insights/environmental-audio/page.tsx b/src/app/insights/environmental-audio/page.tsx index 1259a1536..42e9e41d9 100644 --- a/src/app/insights/environmental-audio/page.tsx +++ b/src/app/insights/environmental-audio/page.tsx @@ -26,7 +26,7 @@ export default function InsightsLaermbelastungPage() { yAxisUnit="dBA" emptyStateIcon={} emptyStateCtaType={null} - coachPrefill="I haven't logged any environmental sound exposure yet — what does this metric tell me about my health, and how do I improve it?" + coachPrefill="I haven't logged any environmental sound exposure yet. What does this metric tell me about my health, and how do I improve it?" /> ); } diff --git a/src/app/insights/falls/page.tsx b/src/app/insights/falls/page.tsx index ef9c5b032..6144b740a 100644 --- a/src/app/insights/falls/page.tsx +++ b/src/app/insights/falls/page.tsx @@ -23,7 +23,7 @@ export default function InsightsFallsPage() { unitKey="insights.units.falls" emptyStateIcon={} emptyStateCtaType={null} - coachPrefill="I haven't logged any fall data yet — what does this metric tell me about my health, and how do I lower my fall risk?" + coachPrefill="I haven't logged any fall data yet. What does this metric tell me about my health, and how do I lower my fall risk?" /> ); } diff --git a/src/app/insights/fat-free-mass/page.tsx b/src/app/insights/fat-free-mass/page.tsx index 6daf8006e..c51c7f995 100644 --- a/src/app/insights/fat-free-mass/page.tsx +++ b/src/app/insights/fat-free-mass/page.tsx @@ -24,7 +24,7 @@ export default function InsightsFettfreieMassePage() { color="var(--chart-1)" emptyStateIcon={} emptyStateCtaType={null} - coachPrefill="I haven't logged any fat-free mass yet — what does this metric tell me about my health, and how do I improve it?" + coachPrefill="I haven't logged any fat-free mass yet. What does this metric tell me about my health, and how do I improve it?" /> ); } diff --git a/src/app/insights/fat-mass/page.tsx b/src/app/insights/fat-mass/page.tsx index a87f55762..835faa73d 100644 --- a/src/app/insights/fat-mass/page.tsx +++ b/src/app/insights/fat-mass/page.tsx @@ -24,7 +24,7 @@ export default function InsightsFettmassePage() { color="var(--chart-5)" emptyStateIcon={} emptyStateCtaType={null} - coachPrefill="I haven't logged any fat mass yet — what does this metric tell me about my health, and how do I improve it?" + coachPrefill="I haven't logged any fat mass yet. What does this metric tell me about my health, and how do I improve it?" /> ); } diff --git a/src/app/insights/flights-climbed/page.tsx b/src/app/insights/flights-climbed/page.tsx index 8fdfc0777..9aa247148 100644 --- a/src/app/insights/flights-climbed/page.tsx +++ b/src/app/insights/flights-climbed/page.tsx @@ -25,7 +25,7 @@ export default function InsightsStockwerkePage() { unitKey="insights.units.flights" emptyStateIcon={} emptyStateCtaType={null} - coachPrefill="I haven't logged any flights climbed yet — what does this metric tell me about my health, and how do I improve it?" + coachPrefill="I haven't logged any flights climbed yet. What does this metric tell me about my health, and how do I improve it?" /> ); } diff --git a/src/app/insights/headphone-audio/page.tsx b/src/app/insights/headphone-audio/page.tsx index ac0e7c2ed..fafcaabbb 100644 --- a/src/app/insights/headphone-audio/page.tsx +++ b/src/app/insights/headphone-audio/page.tsx @@ -26,7 +26,7 @@ export default function InsightsKopfhoererpegelPage() { yAxisUnit="dBA" emptyStateIcon={} emptyStateCtaType={null} - coachPrefill="I haven't logged any headphone audio exposure yet — what does this metric tell me about my health, and how do I improve it?" + coachPrefill="I haven't logged any headphone audio exposure yet. What does this metric tell me about my health, and how do I improve it?" /> ); } diff --git a/src/app/insights/hrv/page.tsx b/src/app/insights/hrv/page.tsx index 0ab1e33da..f46fce113 100644 --- a/src/app/insights/hrv/page.tsx +++ b/src/app/insights/hrv/page.tsx @@ -37,7 +37,7 @@ export default function InsightsHrvPage() { yAxisUnit="ms" emptyStateIcon={} emptyStateCtaType={null} - coachPrefill="I haven't logged any HRV data yet — what does heart-rate variability tell me, and how do I capture it?" + coachPrefill="I haven't logged any HRV data yet. What does heart-rate variability tell me, and how do I capture it?" // S10 / H1 — device-attributed pointer into the ECG viewer, in the // HRV / heart context. Self-gates to nothing without recordings. afterAssessment={} diff --git a/src/app/insights/lean-body-mass/page.tsx b/src/app/insights/lean-body-mass/page.tsx index e31113b3b..ac41b155f 100644 --- a/src/app/insights/lean-body-mass/page.tsx +++ b/src/app/insights/lean-body-mass/page.tsx @@ -24,7 +24,7 @@ export default function InsightsMagermassePage() { color="var(--chart-1)" emptyStateIcon={} emptyStateCtaType={null} - coachPrefill="I haven't logged any lean body mass yet — what does this metric tell me about my health, and how do I improve it?" + coachPrefill="I haven't logged any lean body mass yet. What does this metric tell me about my health, and how do I improve it?" /> ); } diff --git a/src/app/insights/mood/page-client.tsx b/src/app/insights/mood/page-client.tsx index 5a5ab039b..83defd6e6 100644 --- a/src/app/insights/mood/page-client.tsx +++ b/src/app/insights/mood/page-client.tsx @@ -132,7 +132,7 @@ export default function InsightsMoodPageClient() { {t("insights.emptyState.mood.cta")} } - coachPrefill="I haven't logged any mood entries yet — why does mood tracking matter, and how should I start?" + coachPrefill="I haven't logged any mood entries yet. Why does mood tracking matter, and how should I start?" /> ); diff --git a/src/app/insights/muscle-mass/page.tsx b/src/app/insights/muscle-mass/page.tsx index a4dc3c786..42ce5fa8f 100644 --- a/src/app/insights/muscle-mass/page.tsx +++ b/src/app/insights/muscle-mass/page.tsx @@ -24,7 +24,7 @@ export default function InsightsMuskelmassePage() { color="var(--chart-1)" emptyStateIcon={} emptyStateCtaType={null} - coachPrefill="I haven't logged any muscle mass yet — what does this metric tell me about my health, and how do I improve it?" + coachPrefill="I haven't logged any muscle mass yet. What does this metric tell me about my health, and how do I improve it?" /> ); } diff --git a/src/app/insights/oxygen/page.tsx b/src/app/insights/oxygen/page.tsx index e2d0ebcb0..02ab4d397 100644 --- a/src/app/insights/oxygen/page.tsx +++ b/src/app/insights/oxygen/page.tsx @@ -37,7 +37,7 @@ export default function InsightsOxygenSaturationPage() { emptyStateIcon={} emptyStateCtaType={null} captureType="OXYGEN_SATURATION" - coachPrefill="I haven't logged any oxygen-saturation data yet — what does SpO₂ tell me, and what range should I aim for?" + coachPrefill="I haven't logged any oxygen-saturation data yet. What does SpO₂ tell me, and what range should I aim for?" /> ); } diff --git a/src/app/insights/pulse-wave-velocity/page.tsx b/src/app/insights/pulse-wave-velocity/page.tsx index 751907c07..ae16b14b4 100644 --- a/src/app/insights/pulse-wave-velocity/page.tsx +++ b/src/app/insights/pulse-wave-velocity/page.tsx @@ -26,7 +26,7 @@ export default function InsightsPulswellengeschwindigkeitPage() { yAxisUnit="m/s" emptyStateIcon={} emptyStateCtaType={null} - coachPrefill="I haven't logged any pulse wave velocity yet — what does this metric tell me about my health, and how do I improve it?" + coachPrefill="I haven't logged any pulse wave velocity yet. What does this metric tell me about my health, and how do I improve it?" /> ); } diff --git a/src/app/insights/pulse/page.tsx b/src/app/insights/pulse/page.tsx index cb385cf7f..b07b680f2 100644 --- a/src/app/insights/pulse/page.tsx +++ b/src/app/insights/pulse/page.tsx @@ -114,7 +114,7 @@ export default function InsightsPulsPage() { } - coachPrefill="I haven't recorded any resting pulse yet — why does it matter, and what should I know before I start?" + coachPrefill="I haven't recorded any resting pulse yet. Why does it matter, and what should I know before I start?" /> ); diff --git a/src/app/insights/respiratory-rate/page.tsx b/src/app/insights/respiratory-rate/page.tsx index 7bb50a560..ac58a3568 100644 --- a/src/app/insights/respiratory-rate/page.tsx +++ b/src/app/insights/respiratory-rate/page.tsx @@ -25,7 +25,7 @@ export default function InsightsAtemfrequenzPage() { unitKey="insights.units.respiratoryRate" emptyStateIcon={} emptyStateCtaType={null} - coachPrefill="I haven't logged any respiratory rate yet — what does this metric tell me about my health, and how do I improve it?" + coachPrefill="I haven't logged any respiratory rate yet. What does this metric tell me about my health, and how do I improve it?" /> ); } diff --git a/src/app/insights/six-minute-walk/page.tsx b/src/app/insights/six-minute-walk/page.tsx index fcac5971e..3bc1905f6 100644 --- a/src/app/insights/six-minute-walk/page.tsx +++ b/src/app/insights/six-minute-walk/page.tsx @@ -25,7 +25,7 @@ export default function InsightsSixMinuteWalkPage() { yAxisUnit="m" emptyStateIcon={} emptyStateCtaType={null} - coachPrefill="I haven't logged any six-minute-walk data yet — what does this metric tell me about my health, and how do I improve it?" + coachPrefill="I haven't logged any six-minute-walk data yet. What does this metric tell me about my health, and how do I improve it?" /> ); } diff --git a/src/app/insights/skin-temperature/page.tsx b/src/app/insights/skin-temperature/page.tsx index 03b1212b5..1fff4f129 100644 --- a/src/app/insights/skin-temperature/page.tsx +++ b/src/app/insights/skin-temperature/page.tsx @@ -32,7 +32,7 @@ export default function InsightsHauttemperaturPage() { color="var(--chart-5)" emptyStateIcon={} emptyStateCtaType={null} - coachPrefill="I haven't logged any skin temperature yet — what does this metric tell me about my health, and how do I improve it?" + coachPrefill="I haven't logged any skin temperature yet. What does this metric tell me about my health, and how do I improve it?" afterChart={ } - coachPrefill="I don't have any sleep data yet — why does sleep tracking matter, and what should I know before I connect a source?" + coachPrefill="I don't have any sleep data yet. Why does sleep tracking matter, and what should I know before I connect a source?" /> ); diff --git a/src/app/insights/stair-ascent-speed/page.tsx b/src/app/insights/stair-ascent-speed/page.tsx index 9bc75909a..0d4e85b3b 100644 --- a/src/app/insights/stair-ascent-speed/page.tsx +++ b/src/app/insights/stair-ascent-speed/page.tsx @@ -25,7 +25,7 @@ export default function InsightsStairAscentSpeedPage() { yAxisUnit="m/s" emptyStateIcon={} emptyStateCtaType={null} - coachPrefill="I haven't logged any stair-ascent-speed data yet — what does this metric tell me about my health, and how do I improve it?" + coachPrefill="I haven't logged any stair-ascent-speed data yet. What does this metric tell me about my health, and how do I improve it?" /> ); } diff --git a/src/app/insights/stair-descent-speed/page.tsx b/src/app/insights/stair-descent-speed/page.tsx index aa70c09cd..948a67404 100644 --- a/src/app/insights/stair-descent-speed/page.tsx +++ b/src/app/insights/stair-descent-speed/page.tsx @@ -25,7 +25,7 @@ export default function InsightsStairDescentSpeedPage() { yAxisUnit="m/s" emptyStateIcon={} emptyStateCtaType={null} - coachPrefill="I haven't logged any stair-descent-speed data yet — what does this metric tell me about my health, and how do I improve it?" + coachPrefill="I haven't logged any stair-descent-speed data yet. What does this metric tell me about my health, and how do I improve it?" /> ); } diff --git a/src/app/insights/step-length/page.tsx b/src/app/insights/step-length/page.tsx index 92ed90069..2eed765ca 100644 --- a/src/app/insights/step-length/page.tsx +++ b/src/app/insights/step-length/page.tsx @@ -26,7 +26,7 @@ export default function InsightsSchrittlaengePage() { yAxisUnit="m" emptyStateIcon={} emptyStateCtaType={null} - coachPrefill="I haven't logged any walking step length yet — what does this metric tell me about my health, and how do I improve it?" + coachPrefill="I haven't logged any walking step length yet. What does this metric tell me about my health, and how do I improve it?" /> ); } diff --git a/src/app/insights/steps/page.tsx b/src/app/insights/steps/page.tsx index 68447b07c..57783168e 100644 --- a/src/app/insights/steps/page.tsx +++ b/src/app/insights/steps/page.tsx @@ -31,7 +31,7 @@ export default function InsightsStepsPage() { emptyStateIcon={} emptyStateCtaType={null} captureType="ACTIVITY_STEPS" - coachPrefill="I haven't logged any steps yet — what's a reasonable daily step target, and how does walking more help my health?" + coachPrefill="I haven't logged any steps yet. What's a reasonable daily step target, and how does walking more help my health?" /> ); } diff --git a/src/app/insights/vascular-age/page.tsx b/src/app/insights/vascular-age/page.tsx index 82edd06fc..db5bbeea9 100644 --- a/src/app/insights/vascular-age/page.tsx +++ b/src/app/insights/vascular-age/page.tsx @@ -25,7 +25,7 @@ export default function InsightsGefaessalterPage() { unitKey="insights.units.years" emptyStateIcon={} emptyStateCtaType={null} - coachPrefill="I haven't logged any vascular age yet — what does this metric tell me about my health, and how do I improve it?" + coachPrefill="I haven't logged any vascular age yet. What does this metric tell me about my health, and how do I improve it?" /> ); } diff --git a/src/app/insights/visceral-fat/page.tsx b/src/app/insights/visceral-fat/page.tsx index 3f5521a4d..ae22f62b8 100644 --- a/src/app/insights/visceral-fat/page.tsx +++ b/src/app/insights/visceral-fat/page.tsx @@ -26,7 +26,7 @@ export default function InsightsViszeralfettPage() { yAxisUnit="" emptyStateIcon={} emptyStateCtaType={null} - coachPrefill="I haven't logged any visceral fat yet — what does this metric tell me about my health, and how do I improve it?" + coachPrefill="I haven't logged any visceral fat yet. What does this metric tell me about my health, and how do I improve it?" /> ); } diff --git a/src/app/insights/walking-asymmetry/page.tsx b/src/app/insights/walking-asymmetry/page.tsx index 8afaef17d..640f05f06 100644 --- a/src/app/insights/walking-asymmetry/page.tsx +++ b/src/app/insights/walking-asymmetry/page.tsx @@ -26,7 +26,7 @@ export default function InsightsGangasymmetriePage() { yAxisUnit="%" emptyStateIcon={} emptyStateCtaType={null} - coachPrefill="I haven't logged any walking asymmetry yet — what does this metric tell me about my health, and how do I improve it?" + coachPrefill="I haven't logged any walking asymmetry yet. What does this metric tell me about my health, and how do I improve it?" /> ); } diff --git a/src/app/insights/walking-distance/page.tsx b/src/app/insights/walking-distance/page.tsx index 3b04069ab..5d4c4cf4b 100644 --- a/src/app/insights/walking-distance/page.tsx +++ b/src/app/insights/walking-distance/page.tsx @@ -24,7 +24,7 @@ export default function InsightsGehstreckePage() { color="var(--chart-2)" emptyStateIcon={} emptyStateCtaType={null} - coachPrefill="I haven't logged any walking and running distance yet — what does this metric tell me about my health, and how do I improve it?" + coachPrefill="I haven't logged any walking and running distance yet. What does this metric tell me about my health, and how do I improve it?" /> ); } diff --git a/src/app/insights/walking-heart-rate/page.tsx b/src/app/insights/walking-heart-rate/page.tsx index 7eb63de5b..ae4ba79d6 100644 --- a/src/app/insights/walking-heart-rate/page.tsx +++ b/src/app/insights/walking-heart-rate/page.tsx @@ -26,7 +26,7 @@ export default function InsightsGehpulsPage() { yAxisUnit="bpm" emptyStateIcon={} emptyStateCtaType={null} - coachPrefill="I haven't logged any walking heart rate average yet — what does this metric tell me about my health, and how do I improve it?" + coachPrefill="I haven't logged any walking heart rate average yet. What does this metric tell me about my health, and how do I improve it?" /> ); } diff --git a/src/app/insights/walking-speed/page.tsx b/src/app/insights/walking-speed/page.tsx index 33453cbc4..fc4b5d809 100644 --- a/src/app/insights/walking-speed/page.tsx +++ b/src/app/insights/walking-speed/page.tsx @@ -24,7 +24,7 @@ export default function InsightsGehgeschwindigkeitPage() { color="var(--chart-2)" emptyStateIcon={} emptyStateCtaType={null} - coachPrefill="I haven't logged any walking speed yet — what does this metric tell me about my health, and how do I improve it?" + coachPrefill="I haven't logged any walking speed yet. What does this metric tell me about my health, and how do I improve it?" /> ); } diff --git a/src/app/insights/walking-steadiness/page.tsx b/src/app/insights/walking-steadiness/page.tsx index 5e78873c5..0fa566184 100644 --- a/src/app/insights/walking-steadiness/page.tsx +++ b/src/app/insights/walking-steadiness/page.tsx @@ -26,7 +26,7 @@ export default function InsightsGangstabilitaetPage() { yAxisUnit="%" emptyStateIcon={} emptyStateCtaType={null} - coachPrefill="I haven't logged any walking steadiness yet — what does this metric tell me about my health, and how do I improve it?" + coachPrefill="I haven't logged any walking steadiness yet. What does this metric tell me about my health, and how do I improve it?" /> ); } diff --git a/src/app/insights/weight/page.tsx b/src/app/insights/weight/page.tsx index c1a5c25ea..8866094ff 100644 --- a/src/app/insights/weight/page.tsx +++ b/src/app/insights/weight/page.tsx @@ -129,7 +129,7 @@ export default function InsightsGewichtPage() { } - coachPrefill="I haven't recorded any weight yet — why does it matter, and what should I know before I start tracking?" + coachPrefill="I haven't recorded any weight yet. Why does it matter, and what should I know before I start tracking?" /> ); diff --git a/src/app/insights/workouts/page-client.tsx b/src/app/insights/workouts/page-client.tsx index 8dcd5efa2..539341eca 100644 --- a/src/app/insights/workouts/page-client.tsx +++ b/src/app/insights/workouts/page-client.tsx @@ -132,7 +132,7 @@ export default function InsightsWorkoutsPageClient() { ) : null } - coachPrefill="I haven't logged any workouts yet — why does tracking them matter, and what should I focus on first?" + coachPrefill="I haven't logged any workouts yet. Why does tracking them matter, and what should I focus on first?" /> ) : ( <> diff --git a/src/app/insights/wrist-temperature/page.tsx b/src/app/insights/wrist-temperature/page.tsx index f496eb15e..44a005ff2 100644 --- a/src/app/insights/wrist-temperature/page.tsx +++ b/src/app/insights/wrist-temperature/page.tsx @@ -24,7 +24,7 @@ export default function InsightsWristTemperaturePage() { color="var(--chart-5)" emptyStateIcon={} emptyStateCtaType={null} - coachPrefill="I haven't logged any wrist-temperature data yet — what does this metric tell me about my health, and how do I improve it?" + coachPrefill="I haven't logged any wrist-temperature data yet. What does this metric tell me about my health, and how do I improve it?" /> ); } diff --git a/src/app/layout.tsx b/src/app/layout.tsx index e935efd77..71de7f39c 100644 --- a/src/app/layout.tsx +++ b/src/app/layout.tsx @@ -21,7 +21,7 @@ const inter = Inter({ export const metadata: Metadata = { title: "HealthLog", description: - "Self-hosted health tracker — weight, blood pressure, glucose, mood, medications. Withings + Apple Health sync, transparent derived wellness metrics, AI Insights you own.", + "Self-hosted health tracker: weight, blood pressure, glucose, mood, medications. Withings + Apple Health sync, transparent derived wellness metrics, AI Insights you own.", manifest: "/manifest.json", icons: { icon: "/favicon.svg", @@ -51,7 +51,7 @@ export const metadata: Metadata = { url: "/logo-readme.png", width: 1000, height: 1000, - alt: "HealthLog — your health data, your server", + alt: "HealthLog: your health data, your server", }, ], }, diff --git a/src/app/page-client.tsx b/src/app/page-client.tsx index 6dc157f45..8e0bbde6a 100644 --- a/src/app/page-client.tsx +++ b/src/app/page-client.tsx @@ -1,5 +1,6 @@ "use client"; +import { MEASUREMENT_TYPE_LABEL_KEYS } from "@/lib/measurements/type-label-keys"; import { useRecordCapabilities } from "@/hooks/use-record-capabilities"; import React, { Suspense, useCallback, useMemo, useState } from "react"; import { useQuery, useQueryClient } from "@tanstack/react-query"; @@ -448,6 +449,19 @@ export default function DashboardPageClient({ const rhr = data?.summaries?.RESTING_HEART_RATE; const hasRestingHr = (rhr?.count ?? 0) > 0; const pulseTileSummary = hasRestingHr ? rhr : p; + // The pulse widget shows ONE of two statistics, and its name says which: + // with resting rows it is the resting heart rate (one figure a day, the + // same series the day view names "Resting heart rate"); without them it + // is the pulse, whose latest value is the latest day's pulse (the mean of + // its hours' means, `summaries-slice.ts`), the number the day view shows + // as "Pulse" for that day. Calling the resting figure "Pulse" put 62 on + // the dashboard beside a day view reading 77 for the same name. + const pulseLabel = hasRestingHr + ? t(MEASUREMENT_TYPE_LABEL_KEYS.RESTING_HEART_RATE) + : t("dashboard.pulseShort"); + const pulseTitle = hasRestingHr + ? t(MEASUREMENT_TYPE_LABEL_KEYS.RESTING_HEART_RATE) + : t("dashboard.pulse"); const bf = data?.summaries?.BODY_FAT; const sleepSummary = data?.summaries?.SLEEP_DURATION; // v1.11.4 — `summaries.SLEEP_DURATION` now carries per-NIGHT time-asleep @@ -1131,7 +1145,7 @@ export default function DashboardPageClient({ { expect(html).toContain("Pulse"); // The retry button carries the chart title in its accessible name // so several failed charts on one page stay distinguishable. - expect(html).toContain('aria-label="Erneut versuchen – Pulse"'); + expect(html).toContain('aria-label="Erneut versuchen: Pulse"'); // The empty-state copy must NOT paint — an outage is not "no data". expect(html).not.toContain("Keine Daten in diesem Zeitraum"); @@ -169,7 +169,7 @@ describe(" — announcement, sizing, accessible name", () => { it("joins the action context into the retry button's accessible name", async () => { const html = await renderState({ actionContext: "Pulse" }); - expect(html).toContain('aria-label="Retry – Pulse"'); + expect(html).toContain('aria-label="Retry: Pulse"'); }); it("omits the aria-label without a context so the label is the name", async () => { diff --git a/src/components/charts/chart-error-state.tsx b/src/components/charts/chart-error-state.tsx index fc9665a6f..b81af179c 100644 --- a/src/components/charts/chart-error-state.tsx +++ b/src/components/charts/chart-error-state.tsx @@ -82,7 +82,7 @@ export function ChartErrorState({ size="sm" onClick={onAction} aria-label={ - actionContext ? `${actionLabel} – ${actionContext}` : undefined + actionContext ? `${actionLabel}: ${actionContext}` : undefined } >