Files
HealthLog/messages/en.json
T
Marc-André Bombeck 0b3280c604 chore(release): v1.32.11 — native web-handoff login for self-hosted iOS
Self-hosters can sign in to the iOS app through their own domain, so the
password manager files credentials under the right site and passkeys run in
the correct origin. The app opens the instance's own web login inside an
ASWebAuthenticationSession; after an interactive login the server mints a
single-use, PKCE-locked handoff code on a compiled-in custom scheme, which the
app exchanges for the standard native token bundle. The token pair never rides
a URL — only the opaque code does.

Three endpoints mirror the OIDC native handoff and share its mint/consume core,
now extracted to native-handoff.ts (the OIDC leg keeps working unchanged, as
the default flow):

  - GET  /api/auth/native/login    validates the PKCE challenge, sets a
                                   short-lived encrypted state cookie, and
                                   redirects to /auth/login?flow=native.
  - GET  /api/auth/native/complete validates the web session, enforces the
                                   freshness binding, mints the code, and
                                   redirects to healthlog://login-callback.
  - POST /api/auth/native/token    exchanges the code under the cookie-less
                                   native transport gate for the native bundle.

The freshness binding refuses any session older than the flow start, so a
pre-existing browser session can never silently complete a handoff. The start
time is stamped from the database clock (SELECT now()) to stay comparable to
Session.createdAt with no app/DB skew, and createdAt is read through a
dedicated projection so the comparison cannot be silently dropped. A flow
discriminator on the handoff row (migration 0268) makes an OIDC code
non-redeemable at the web-login route and vice versa.

The callback scheme is a compile-time constant with no redirect_uri parameter,
requireAdmin and requireFreshMfa stay cookie-only, and the exchange mints no
wider scope than password login. The state cookie is AES-256-GCM with a fresh
IV. Adds the flow=native login-page banner in all six locales and the three
routes to the OpenAPI contract.
2026-07-24 02:28:51 +02:00

8986 lines
441 KiB
JSON
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
{
"common": {
"save": "Save",
"cancel": "Cancel",
"delete": "Delete",
"undo": "Undo",
"edit": "Edit",
"moreOptions": "More options",
"create": "Create",
"close": "Close",
"loading": "Loading…",
"loadFailed": "Could not load",
"error": "Error",
"saved": "Saved",
"pullToRefresh": "Refreshing…",
"no": "No",
"noData": "No data available",
"optional": "Optional",
"active": "Active",
"inactive": "Inactive",
"disabled": "Disabled",
"networkError": "Network error",
"openDatePicker": "Open date picker",
"openTimePicker": "Open time picker",
"hours": "Hours",
"minutes": "Minutes",
"period": "AM/PM",
"am": "AM",
"pm": "PM",
"unknownError": "Unknown error",
"copied": "Copied!",
"or": "or",
"unknown": "Unknown",
"add": "Add",
"import": "Import",
"test": "Test",
"reset": "Reset",
"copy": "Copy",
"copyDetails": "Copy details",
"retry": "Retry",
"showPassword": "Show password",
"hidePassword": "Hide password",
"learnMore": "Learn more",
"dismiss": "Dismiss",
"moreInfo": "More information",
"durationHoursMinutes": "{hours}h {minutes}m",
"durationMinutes": "{minutes}m"
},
"apiErrors": {
"measurement": {
"create": { "invalid": "Check the measurement details and try again." },
"duplicate_timestamp": "A measurement already exists for this time."
},
"mood": {
"list": { "invalid": "The mood list filters are invalid." },
"create": { "invalid": "Check the mood entry and try again." },
"update": { "invalid": "Check the mood entry and try again." },
"duplicate_timestamp": "A mood entry already exists for this time.",
"not_found": "This mood entry is no longer available.",
"ratedFactor": {
"out_of_range": "A factor rating is outside its allowed range."
}
},
"labs": {
"create": { "invalid": "Check the lab result and try again." },
"result": { "notFound": "This lab result is no longer available." },
"biomarker": {
"notFound": "This biomarker is no longer available.",
"duplicate": "A biomarker with this name already exists.",
"create": { "invalid": "Check the biomarker details and try again." },
"update": {
"invalid": "Check the biomarker details and try again.",
"referenceRangeInvalid": "The lower reference value must not exceed the upper value."
}
},
"update": {
"invalid": "Check the lab result and try again.",
"linkedFieldsImmutable": "Edit the biomarker to change its name, unit, panel, or reference range.",
"qualitativeExpected": "Enter a text result for this qualitative reading.",
"numericExpected": "Enter a number for this numeric reading.",
"referenceRangeInvalid": "The lower reference value must not exceed the upper value."
}
},
"onboarding": {
"disclaimer": {
"invalid": "Please confirm the medical disclaimer again."
},
"tour": { "invalid": "The tour progress could not be saved." },
"complete": { "invalid": "Check the profile details and try again." },
"user": { "notFound": "Your account could not be found." },
"step": {
"rateLimited": "Too many attempts. Please wait and try again.",
"invalid": "This onboarding step could not be saved.",
"completed": "Onboarding is already complete.",
"outOfOrder": "Your onboarding progress changed. Refresh and continue.",
"concurrent": "Your onboarding progress changed. Refresh and continue."
}
}
},
"doctorReport": {
"title": "Health Report",
"subtitle": "HealthLog — Personal Health Report",
"patient": "Patient",
"dateOfBirth": "Date of birth",
"gender": "Gender",
"genderMale": "Male",
"genderFemale": "Female",
"genderOther": "Non-binary",
"height": "Height",
"period": "Reporting period",
"createdOn": "Created on",
"vitalsTitle": "Vital signs — Summary",
"colParameter": "Parameter",
"colCurrent": "Current",
"colAvgPeriod": "Avg. period",
"colMin": "Min",
"colMax": "Max",
"colN": "n",
"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)",
"complianceTitle": "Medication adherence",
"glp1Title": "GLP-1 therapy",
"glp1WeightSummary": "Weight over report period: {start} kg → {end} kg ({delta} kg)",
"glp1CurrentDose": "Current dose: {value} {unit} (since {since})",
"glp1Compliance": "Adherence: {taken} / {total} ({rate}%)",
"glp1SideEffectsTitle": "Side effects logged",
"colGlp1Date": "Date",
"colGlp1Dose": "Dose",
"colGlp1Note": "Note",
"colGlp1SideEffect": "Side effect",
"colMedication": "Medication",
"colTaken": "Taken",
"colSkipped": "Skipped",
"colMissed": "Missed",
"colExpected": "Expected",
"colComplianceRate": "Adherence rate",
"moodTitle": "Mood trajectory",
"moodSummary": "Average: {avg} / 5.0 · Entries: {count} · Range: {min}–{max}",
"colMood": "Mood",
"colCount": "Count",
"colShare": "Share",
"footerDisclaimer1": "This report was generated automatically from self-tracked data and is intended to support",
"footerDisclaimer2": "the doctor–patient conversation. It does not replace a medical diagnosis. Correlations do not imply causation.",
"footerSource": "Source: HealthLog | Timezone: {timezone} | Created: {timestamp}",
"typeWeight": "Body weight",
"typeBpSys": "Systolic blood pressure",
"typeBpDia": "Diastolic blood pressure",
"typePulse": "Resting pulse",
"typeBodyFat": "Body fat",
"typeSleep": "Sleep duration",
"typeSteps": "Activity (steps)",
"typeTotalBodyWater": "Total body water",
"typeBoneMass": "Bone mass",
"typeOxygenSaturation": "Oxygen saturation",
"unitSteps": "steps",
"bmiUnderweight": "Underweight",
"bmiNormal": "Normal weight",
"bmiOverweight": "Overweight (pre-obese)",
"bmiObeseGrade1": "Obesity grade I",
"bmiObeseGrade2": "Obesity grade II",
"bmiObeseGrade3": "Obesity grade III",
"bpOptimal": "Optimal",
"bpNormal": "Normal",
"bpHighNormal": "High-normal",
"bpHypertensionGrade1": "Hypertension grade 1",
"bpHypertensionGrade2": "Hypertension grade 2",
"bpHypertensionGrade3": "Hypertension grade 3",
"moodAwful": "Very bad",
"moodBad": "Bad",
"moodNeutral": "Neutral",
"moodGood": "Good",
"moodGreat": "Very good",
"typeGlucoseFasting": "Glucose (fasting)",
"typeGlucosePostprandial": "Glucose (postprandial)",
"typeGlucoseRandom": "Glucose (random)",
"typeGlucoseBedtime": "Glucose (bedtime)",
"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",
"practiceLabel": "Practice",
"insurer": "Health insurer",
"insuranceNumber": "Insurance no.",
"summaryTitle": "Clinical summary",
"summaryReadings": "Recorded over {days} days: {count} measurements across {params} parameters.",
"summaryTrend": "{label}: latest {latest} {arrow}",
"summaryAdherence": "Medication adherence: {rate}% (weighted mean).",
"chartsTitle": "Trend charts",
"aiSummaryTitle": "AI summary — not clinically validated",
"aiSummaryDisclaimer": "This section was generated automatically by an AI model and is not clinically validated. It does not replace a medical assessment.",
"packageReadme": "HealthLog health record\n\nThis package contains:\n- report.pdf: the health report for your doctor.\n- bundle.json: the same data as an HL7 FHIR R4 document Bundle, ePA-compatible.\n\nGenerated with HealthLog.",
"wellnessTitle": "Wellness summary",
"wellnessDisclaimer": "These are descriptive wellness scores computed from your tracked signals (0–100). They are not clinical assessments or diagnoses.",
"wellnessRecovery": "Recovery",
"wellnessStress": "Stress",
"wellnessStrain": "Strain",
"cycleTitle": "Menstrual cycle",
"cycleLmp": "Last period",
"cycleAvgLength": "Average cycle length",
"cycleAvgPeriod": "Average period length",
"cyclePhase": "Current phase",
"cycleDays": "days",
"cycleColStart": "Period start",
"cycleColLength": "Cycle length (days)",
"cycleColPeriod": "Period length (days)",
"cyclePhases": {
"MENSTRUAL": "Menstrual",
"FOLLICULAR": "Follicular",
"OVULATORY": "Ovulatory",
"LUTEAL": "Luteal"
},
"labsTitle": "Lab results",
"labsColAnalyte": "Biomarker",
"labsColValue": "Value",
"labsColReference": "Reference",
"labsColStatus": "Status",
"labsColDate": "Date",
"glucoseClinical": {
"title": "Glucose overview (clinical)",
"colMetric": "Metric",
"colValue": "Value",
"tirInRange": "Time in range (70–180 mg/dL)",
"tirLow": "Low (< 70 mg/dL)",
"tirVeryLow": "Very low (< 54 mg/dL)",
"tirHigh": "High (> 180 mg/dL)",
"tirVeryHigh": "Very high (> 250 mg/dL)",
"mean": "Average glucose",
"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."
},
"illnessTitle": "Conditions & illnesses",
"illnessOngoing": "Ongoing",
"illnessColCondition": "Condition",
"illnessColType": "Type",
"illnessColLifecycle": "Course",
"illnessColOnset": "Onset",
"illnessColResolved": "Resolved",
"allergiesTitle": "Allergies & intolerances",
"reactionUnreadable": "Reaction recorded but could not be decrypted",
"allergiesColSubstance": "Substance",
"allergiesColCategory": "Category",
"allergiesColKind": "Kind",
"allergiesColSeverity": "Severity",
"allergiesColReaction": "Reaction",
"allergiesColStatus": "Status",
"familyHistoryTitle": "Family history",
"familyHistoryColRelationship": "Relative",
"familyHistoryColCondition": "Condition",
"familyHistoryColAgeAtOnset": "Age at onset"
},
"errorBoundary": {
"title": "Something went wrong",
"description": "An unexpected error occurred. You can retry, copy the technical details, or open a bug report."
},
"notFound": {
"title": "This page doesn't exist.",
"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.",
"showingCached": "Showing your last synced data."
},
"demoBanner": {
"message": "Demo mode — changes are not saved."
},
"nav": {
"dashboard": "Dashboard",
"measurements": "Measurements",
"medications": "Medications",
"insights": "Insights",
"achievements": "Achievements",
"settings": "Settings",
"admin": "Admin Console",
"logout": "Sign out",
"login": "Sign in",
"notifications": "Notifications",
"theme": "Theme",
"themeSystem": "System",
"themeDark": "Dark",
"themeLight": "Light",
"collapseSidebar": "Collapse",
"userMenu": "User menu",
"accountSettings": "Account settings",
"mood": "Mood",
"coach": "Coach",
"skipToContent": "Skip to content",
"sidebar": "Sidebar",
"mainNavigation": "Main navigation",
"mobileNavigation": "Mobile navigation",
"loadingScreen": "Loading…",
"more": "More",
"moreSheetTitle": "More",
"moreSheetDescription": "Jump to the rest of HealthLog.",
"capture": {
"title": "Log",
"description": "What would you like to record?",
"measurement": "Measurement",
"measurementDescription": "Weight, blood pressure, pulse and more",
"medication": "Medication",
"medicationDescription": "Mark a dose as taken",
"mood": "Mood",
"moodDescription": "Log your mood and tags",
"water": "Water",
"waterDescription": "Quickly add your water intake"
},
"cycle": "Cycle",
"labs": "Labs",
"vorsorge": "Checkups",
"illness": "Illness",
"documents": "Documents",
"mentalWellbeing": "Mental wellbeing"
},
"auth": {
"login": "Sign in",
"register": "Sign up",
"username": "Username",
"password": "Password",
"email": "Email address",
"emailPlaceholder": "name@example.com",
"emailOrUsername": "Email address or username",
"emailOrUsernamePlaceholder": "name@example.com or username",
"loginWithPasskey": "Sign in with Passkey",
"loginWithPassword": "Sign in with password",
"noAccount": "Don't have an account?",
"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.",
"createAccount": "Create account",
"newAccount": "Create new account",
"backToPasskey": "Back to Passkey",
"passkeySetupLater": "You can set up passkeys at any time in Settings.",
"passwordMinLength": "Min. 12 characters",
"passwordTooShort": "Password must be at least {minLength} characters long.",
"privacyPolicy": "Privacy policy",
"passwordBreached": "This password has appeared in known data breaches. Please choose a different one.",
"oidc": {
"signInDefault": "Sign in with SSO",
"errorDenied": "Sign-in was cancelled.",
"errorNoEmail": "Your identity provider did not share a verified email address.",
"errorEmailUnverified": "Your identity provider did not mark your email address as verified.",
"errorIdentityConflict": "That email address belongs to an account that is already linked to a different SSO identity.",
"errorRegistrationDisabled": "No account matches that identity, and new sign-ups are currently closed.",
"errorFailed": "Single sign-on failed. Please try again."
},
"native": {
"signingInToApp": "Signing in to the HealthLog app"
},
"mfa": {
"title": "Two-factor authentication",
"totpHint": "Enter the 6-digit code from your authenticator app.",
"recoveryHint": "Enter one of your saved recovery codes.",
"securityKeyHint": "Use your registered security key to continue.",
"codeLabel": "Authentication code",
"recoveryLabel": "Recovery code",
"verify": "Verify",
"verifyFailed": "Verification failed. Please try again.",
"useSecurityKey": "Use a security key",
"useRecoveryCode": "Use a recovery code",
"useAuthenticator": "Use your authenticator app",
"backToLogin": "Back to login",
"rememberDevice": "Trust this device for 30 days"
},
"enrollMfa": {
"title": "Set up a second factor",
"body": "Your administrator requires a second factor on this account. Add an authenticator app or a security key to continue.",
"signOut": "Sign out"
}
},
"dashboard": {
"title": "Dashboard",
"greeting": {
"morning": "Good morning",
"day": "Hello",
"evening": "Good evening"
},
"welcomeBack": "{greeting}, welcome back.",
"welcomeBackWithName": "{greeting} {name}, welcome back.",
"hero": {
"scoreLabel": "Health Score",
"ringDoses": "Doses today"
},
"greetingSalutation": "Hi, {name}",
"streakLabel": "days in a row",
"weight": "Weight",
"bloodPressure": "Blood Pressure",
"pulse": "Pulse",
"bodyFat": "Body Fat",
"sleep": "Sleep",
"steps": "Steps",
"vo2Max": "VO₂ max",
"vo2MaxUnit": "mL/(kg·min)",
"bpInTarget": "BP in Target",
"weightShort": "Weight",
"bloodPressureSysShort": "BP (Sys)",
"bloodPressureDiaShort": "BP (Dia)",
"pulseShort": "Pulse",
"bodyFatShort": "Body Fat",
"moodShort": "Mood",
"sleepShort": "Sleep",
"stepsShort": "Steps",
"vo2MaxShort": "VO₂ max",
"bpInTargetWindow90": "BP in Target · 90d",
"bpInTargetWindowDynamic": "BP in Target · {days}d",
"bpInTargetCollecting": "collecting data",
"medications": "Medications",
"quickAddMeasurement": "Log measurement",
"quickAddMood": "Log mood",
"quickAddMedicationIntake": "Log medication intake",
"quickAddWater": "Log water",
"customizeDashboard": "Customize dashboard",
"medicationIntakeQuickAdd": {
"sheetTitle": "Log medication intake",
"sheetDescription": "Record dose, time, and medication in a few taps.",
"medicationLabel": "Medication",
"medicationPlaceholder": "Select a medication",
"doseLabel": "Dose",
"dosePlaceholder": "e.g. 5 mg",
"doseHint": "Pre-filled with the standard dose. Edit it to record a deviating dose for this intake only.",
"timeLabel": "Time taken",
"saveError": "Could not save medication intake.",
"emptyTitle": "No medications yet",
"emptyDescription": "Create a medication with a schedule first, then come back here to log the intake.",
"emptyCta": "Add medication"
},
"quickEntryDiscard": {
"title": "Discard this entry?",
"description": "You have unsaved input. Close the form and lose what you typed?",
"confirm": "Discard",
"cancel": "Keep editing"
},
"compliance7d": "Adherence (7 days)",
"mood": "Mood",
"customizeTitle": "Dashboard layout",
"scoreRingsTitle": "Score rings",
"scoreRingsDescription": "Up to three additional rings next to the health score — for example readiness, recovery, sleep or adherence. Drag to reorder; the health score leads by default.",
"layoutReset": "Reset to defaults",
"layoutSaveSuccess": "Dashboard layout saved",
"layoutSaveError": "Could not save dashboard layout",
"layoutResetSuccess": "Reset to default layout",
"layoutUsingDefaults": "Using default layout",
"layoutCustomized": "Custom layout active",
"moveUp": "Move up",
"moveDown": "Move down",
"layoutTileColumn": "Tile",
"layoutChartColumn": "Chart",
"dragHandle": "Drag to reorder",
"dragHandleHint": "Drag the handle to reorder this widget. You can also use the Up and Down arrow buttons, or focus the handle and press Space and the arrow keys.",
"emptyTitle": "Your dashboard is empty",
"emptyDescription": "Log your first measurement or mood entry. Tiles and charts appear automatically as data lands.",
"emptyAddMeasurement": "Add your first measurement",
"staleHint": "Last reading {count} d ago",
"staleHintWeeksOne": "Last reading 1 week ago",
"staleHintWeeksOther": "Last reading {count} weeks ago",
"staleHintWeeksFew": "Last reading {count} weeks ago",
"staleHintMonthsOne": "Last reading 1 month ago",
"staleHintMonthsOther": "Last reading {count} months ago",
"staleHintMonthsFew": "Last reading {count} months ago",
"recentWorkouts": {
"title": "Recent workouts",
"viewAll": "View all",
"empty": {
"title": "No workouts yet",
"cta": "Open Apple Health on your iPhone to sync workouts here."
}
},
"metric": {
"title": {
"weight": "Weight",
"bloodPressure": "Blood Pressure",
"pulse": "Pulse",
"bodyFat": "Body Fat",
"glucose": "Blood Glucose",
"sleep": "Sleep",
"steps": "Steps",
"totalBodyWater": "Total Body Water",
"boneMass": "Bone Mass",
"oxygenSaturation": "Oxygen Saturation",
"mood": "Mood",
"bmi": "BMI"
},
"unit": {
"weight": "kg",
"bloodPressure": "mmHg",
"pulse": "bpm",
"bodyFat": "%",
"glucose": "mg/dL",
"sleep": "h",
"steps": "steps",
"totalBodyWater": "kg",
"boneMass": "kg",
"oxygenSaturation": "%",
"mood": "/5",
"bmi": "kg/m²"
}
}
},
"measurements": {
"title": "Measurements",
"subtitle": "Log readings and browse the full history. Trends and analysis live under Insights.",
"addMeasurement": "Add",
"editMeasurement": "Edit measurement",
"type": "Type",
"value": "Value",
"date": "Date",
"source": "Source",
"notes": "Notes",
"typeWeight": "Weight",
"typeBloodPressure": "Blood Pressure",
"typeBpSys": "Sys",
"typeBpDia": "Dia",
"typePulse": "Pulse",
"typeBodyFat": "Body Fat",
"typeSleep": "Sleep",
"typeSteps": "Steps",
"typeBloodGlucose": "Blood glucose",
"typeTotalBodyWater": "Total body water",
"typeBoneMass": "Bone mass",
"typeOxygenSaturation": "Oxygen saturation",
"typeHeartRateVariability": "Heart-rate variability",
"typeRestingHeartRate": "Resting heart rate",
"typeActiveEnergyBurned": "Active energy",
"typeFlightsClimbed": "Flights climbed",
"typeWalkingRunningDistance": "Walking + running distance",
"typeVo2Max": "VO₂ max",
"typeBodyTemperature": "Body temperature",
"typeFatFreeMass": "Fat-free mass",
"typeFatMass": "Fat mass",
"typeMuscleMass": "Muscle mass",
"typeSkinTemperature": "Skin temperature",
"typePulseWaveVelocity": "Pulse-wave velocity",
"typeVascularAge": "Vascular age",
"typeVisceralFat": "Visceral fat",
"typeAudioExposureEnv": "Audio Exposure (Environment)",
"typeAudioExposureHeadphone": "Audio Exposure (Headphones)",
"typeTimeInDaylight": "Time in Daylight",
"typeWalkingSteadiness": "Walking Steadiness",
"typeAudioExposureEvent": "Loud-Listening Event",
"typeRespiratoryRate": "Respiratory rate",
"typeBodyMassIndex": "Body-mass index",
"typeLeanBodyMass": "Lean body mass",
"typeWalkingHeartRateAverage": "Walking heart rate (avg)",
"typeWalkingAsymmetry": "Walking asymmetry",
"typeWalkingDoubleSupport": "Walking double support",
"typeWalkingStepLength": "Walking step length",
"typeWalkingSpeed": "Walking speed",
"glucoseContext": "Context",
"glucoseContextFasting": "Fasting (≥8h without food)",
"glucoseContextPostprandial": "Post-meal (2h after eating)",
"glucoseContextRandom": "Random / casual",
"glucoseContextBedtime": "Before bed",
"unitHours": "hours",
"unitSteps": "steps",
"sourceManual": "Manual",
"sourceWithings": "Withings",
"sourceImport": "Import",
"sourceAppleHealth": "Apple Health",
"systolicLabel": "Systolic (mmHg)",
"diastolicLabel": "Diastolic (mmHg)",
"pulseLabel": "Pulse (bpm)",
"valueWithUnit": "Value ({unit})",
"timestamp": "Time",
"timestampBackdateHint": "Adjust the date and time to log a past reading.",
"notesPlaceholder": "e.g. after a meal",
"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.",
"deleteError": "Error deleting",
"deletedToast": "Measurement deleted",
"restoredToast": "Measurement restored",
"restoreError": "Restore failed",
"invalidValue": "Please enter a valid value.",
"invalidTimestamp": "Please select a valid time.",
"loginRequired": "Please sign in to view measurements.",
"allTypes": "All types",
"measurementCount": "{count} measurements",
"emptyTitle": "No measurements yet",
"emptyDescription": "Log your weight, blood pressure, pulse, or other vitals to start tracking trends.",
"emptyFilteredTitle": "No measurements match this filter",
"emptyFilteredDescription": "Try a different type or clear the filter to see all measurements.",
"emptyAddFirst": "Add your first measurement",
"emptyResetFilter": "Show all types",
"comment": "Comment",
"actions": "Actions",
"deleteConfirmTitle": "Delete measurement?",
"deleteConfirmDescription": "This measurement will be deleted. You can undo this for a short moment afterwards.",
"pageInfo": "Page {page} of {total}",
"previousPage": "Previous page",
"nextPage": "Next page",
"dailyTotalCaption": "({count} samples)",
"openMetricInsights": "Open {type} insights",
"sleepNapCaption": "+{count} nap(s)",
"sleepAwakeningsCaption": "{count} awakening(s)",
"expandDay": "Show samples for this day",
"collapseDay": "Hide samples for this day",
"loadError": "Could not load measurements.",
"typeCardioRecovery": "Cardio recovery",
"typeWristTemperature": "Wrist temperature",
"typeFallCount": "Falls",
"typeSixMinuteWalkDistance": "Six-minute walk distance",
"typeStairAscentSpeed": "Stair ascent speed",
"typeStairDescentSpeed": "Stair descent speed",
"typeBreathingDisturbances": "Sleep breathing disturbances",
"typeIrregularRhythmNotification": "Irregular rhythm notification",
"typeHighHeartRateEvent": "High heart rate notification",
"typeLowHeartRateEvent": "Low heart rate notification",
"typeWalkingSteadinessEvent": "Walking steadiness alert",
"typeBreathingDisturbanceEvent": "Breathing disturbance",
"typeRecoveryScore": "Recovery score",
"typeStressScore": "Stress score",
"typeStrainScore": "Strain score",
"typeHrvRmssd": "HRV (RMSSD)",
"typeDayStrain": "Day strain",
"typeWorkoutStrain": "Workout strain",
"typeSleepPerformance": "Sleep performance",
"typeSleepEfficiency": "Sleep efficiency",
"typeSleepConsistency": "Sleep consistency",
"typeSleepNeed": "Sleep need",
"typeEnergyExpenditureKj": "Energy expenditure",
"typeAverageHeartRate": "Average heart rate",
"typeMaxHeartRate": "Maximum heart rate",
"typeSleepDisturbanceCount": "Sleep disturbances",
"typeAnsCharge": "ANS charge",
"typeCardioLoad": "Cardio load",
"typeSleepScore": "Sleep score",
"typeBodyTemperatureDeviation": "Body temperature deviation",
"typeResilience": "Resilience",
"sourceComputed": "Computed",
"sourceWhoop": "WHOOP",
"sourceFitbit": "Fitbit",
"bulkDeleteSuccess": "{count} measurements deleted",
"bulkDeleteError": "Error deleting the selected measurements",
"bulkDeleteConfirmTitle": "Delete {count} measurements?",
"bulkDeleteConfirmBody": "The {count} selected measurements will be deleted. You can undo this for a short moment afterwards.",
"typePhq9Score": "PHQ-9 score",
"typeGad7Score": "GAD-7 score",
"typeGripStrength": "Grip strength",
"typePainNrs": "Pain (0–10)",
"typeWaistCircumference": "Waist circumference",
"typeWaistToHeight": "Waist-to-height ratio",
"unitScore": "pts",
"unitRatio": "ratio",
"typeWho5Score": "WHO-5 score",
"typeSciScore": "SCI score"
},
"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.",
"statusPresent": "Tracked",
"statusAbsent": "Not tracked yet",
"statusModuleOff": "Off",
"loadError": "Could not load your tracking status.",
"connectCta": "Connect a source",
"viewCta": "View",
"ecg": {
"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."
}
},
"mood": {
"title": "Mood",
"subtitle": "Mood tracker and entries",
"mentalWellbeingLink": "Take a mental-wellbeing check-in",
"addEntry": "Add",
"editEntry": "Edit entry",
"moodLevel": "Mood",
"heroQuestion": "How are you?",
"factorYes": "Yes",
"factorNo": "No",
"factorRatingOption": "{label}: {value} of {max}",
"tags": "Tags",
"tagsPlaceholder": "e.g. Exercise, Work, Family",
"tagsHelp": "Comma-separated",
"timestamp": "Time",
"date": "Date",
"source": "Source",
"levelSuperGut": "Amazing",
"levelGut": "Good",
"levelOkay": "Okay",
"levelSchlecht": "Bad",
"levelLausig": "Terrible",
"sourceMoodlog": "moodLog",
"allMoods": "All moods",
"entryCount": "{count} entries",
"emptyTitle": "No mood entries yet",
"emptyDescription": "Log how you feel today to spot patterns over time.",
"emptyFilteredTitle": "No mood entries match this filter",
"emptyFilteredDescription": "Try a different mood level or clear the filter to see all entries.",
"emptyAddFirst": "Log your first mood",
"emptyResetFilter": "Show all moods",
"actions": "Actions",
"formReset": "Reset form",
"noteCharCount": "{count}/{max}",
"formResetConfirmTitle": "Reset this form?",
"formResetConfirmBody": "This clears the mood, tags and note you have entered. This cannot be undone.",
"formResetConfirmAction": "Reset",
"saveError": "Error saving",
"deleteError": "Error deleting",
"deletedToast": "Entry deleted",
"restoredToast": "Entry restored",
"restoreError": "Restore failed",
"invalidTimestamp": "Please select a valid time.",
"deleteConfirmTitle": "Delete entry?",
"deleteConfirmDescription": "This mood entry will be deleted. You can undo this for a short moment afterwards.",
"pageInfo": "Page {page} of {total}",
"previousPage": "Previous page",
"nextPage": "Next page",
"loginRequired": "Please sign in to view mood entries.",
"note": "Note",
"noteCollapse": "Collapse note",
"noteExpand": "Show full note",
"notePlaceholder": "Add a note about how you're feeling…",
"tagPicker": "Tags",
"tagCategory": {
"feelings": "Feelings",
"sleep": "Sleep",
"health": "Health",
"social": "Social",
"work": "Work",
"hobbies": "Hobbies",
"factors": "Factors",
"custom": "Custom"
},
"tag": {
"happy": "happy",
"excited": "excited",
"grateful": "grateful",
"relaxed": "relaxed",
"content": "content",
"tired": "tired",
"unsure": "unsure",
"bored": "bored",
"tense": "tense",
"angry": "angry",
"stressed": "stressed",
"sad": "sad",
"sleptWell": "slept well",
"sleptOk": "slept okay",
"sleptPoorly": "slept poorly",
"earlyNight": "early night",
"workedOut": "worked out",
"ateWell": "ate well",
"hydrated": "hydrated",
"walked": "walked",
"alcohol": "alcohol",
"family": "family",
"friends": "friends",
"party": "party",
"alone": "alone",
"productive": "productive",
"overtime": "overtime",
"dayOff": "day off",
"travel": "travel",
"sickDay": "sick day",
"movies": "movies",
"reading": "reading",
"gaming": "gaming",
"music": "music",
"outdoors": "outdoors",
"fastFood": "fast food",
"noSweets": "no sweets",
"bigMeal": "big meal",
"factorWork": "work",
"factorSocial": "social",
"factorSleepQuality": "sleep quality",
"factorStress": "stress",
"factorConflict": "conflict",
"factorFamily": "family",
"factorSadness": "sadness",
"praise": "praise"
},
"sourceManual": "Manual",
"sourceWeb": "Web",
"sourceTelegram": "Telegram",
"sourceDaylio": "Daylio",
"bulkDeleteSuccess": "{count} entries deleted",
"bulkDeleteError": "Error deleting the selected entries",
"bulkDeleteConfirmTitle": "Delete {count} entries?",
"bulkDeleteConfirmBody": "The {count} selected mood entries will be deleted. You can undo this for a short moment afterwards.",
"customize": "Customize mood tags",
"addTagInline": "Add tag",
"manage": {
"groupsTitle": "Groups",
"groupsDescription": "Create your own groups and set the order the picker shows them in.",
"newGroup": "New group",
"groupLabel": "Group name",
"groupIcon": "Icon",
"groupCreated": "Group created",
"groupRenamed": "Group saved",
"groupDeleteTitle": "Delete group?",
"groupDeleteBody": "Tags in this group move back to their original group. No entries are deleted.",
"groupDeleted": "Group deleted",
"groupEmpty": "No own groups yet.",
"groupLimitReached": "Group limit reached",
"tagsTitle": "Tags",
"tagsDescription": "Hide, rearrange, move, or edit the tags the picker shows.",
"newTag": "New tag",
"tagLabel": "Tag name",
"tagIcon": "Icon",
"tagGroup": "Group",
"usageCount": "{count} entries",
"hideTag": "Hide tag",
"showTag": "Show tag",
"moveToGroup": "Move to group",
"archive": "Archive",
"restore": "Restore",
"archivedTitle": "Archived tags",
"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.",
"purgeAction": "Delete permanently",
"purged": "Tag deleted",
"tagLimitReached": "Tag limit reached",
"iconPickerTitle": "Choose an icon",
"iconSearchPlaceholder": "Search icons…",
"iconSearchEmpty": "No icon matches.",
"iconSearchClear": "Clear search",
"orderSave": "Save order",
"orderSaved": "Order saved",
"moveUp": "Move up",
"moveDown": "Move down",
"iconGroupEmotions": "Emotions",
"iconGroupActivities": "Activities",
"iconGroupHealth": "Health",
"iconGroupFood": "Food & drink",
"iconGroupWeather": "Weather",
"iconGroupPlaces": "Places",
"iconGroupMisc": "Other"
},
"sectionMoreTags": "More tags",
"sectionFactors": "Factors",
"sectionNoteDetails": "Note & details",
"quickTagsHelp": "Your frequent tags — one tap",
"quickTagsExpand": "More",
"loadError": "Could not load your mood entries."
},
"medications": {
"title": "Medications",
"subtitle": "Medications, schedules & intake",
"loginRequired": "Please sign in to manage medications.",
"addMedication": "Add",
"firstMedication": "Add first medication",
"addChoice": {
"logIntake": "Log an intake",
"newMedication": "New medication"
},
"takeAllDue": {
"button": "Take all due",
"dialogTitle": "Take due medications",
"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"
},
"logIntake": {
"dialogTitle": "Log an intake",
"dialogDescription": "Record a dose against an existing medication. You can backdate it to a past date and time.",
"medicationLabel": "Medication",
"slotLabel": "Schedule slot",
"slotNone": "No specific slot",
"doseLabel": "Dose",
"doseHint": "Pre-filled with the medication or slot dose. Edit it to record a deviating dose for this intake only.",
"takenAtLabel": "Date and time",
"takenAtHint": "Defaults to now; pick an earlier date and time to log a past dose.",
"skippedLabel": "Logged as skipped",
"noMedications": "Add a medication first, then you can log intakes against it.",
"cancel": "Cancel",
"submit": "Log intake",
"slotError": "The selected slot couldn’t be matched to a time. Pick another slot or “No specific slot”."
},
"emptyTitle": "No medications yet",
"emptyDescription": "Add medications, dosages, and reminder windows to track adherence.",
"loadFailed": "Could not load medications",
"retryLoad": "Retry",
"name": "Name",
"inactive": "Paused",
"intakeHistory": "Intake history",
"openDetailPage": "Open medication detail page",
"compliance": "Adherence",
"importIntakes": "Import intakes",
"importDescription": "Paste a JSON array with intake data. Expected format:",
"importUploadFile": "Upload JSON file",
"importPaste": "Paste JSON here…",
"importSelected": "Selected: {name}",
"importFileLoaded": "File \"{name}\" loaded",
"importInvalidJson": "File does not contain valid JSON",
"importNoArray": "No array found",
"importResult": "{imported} intakes imported",
"importDuplicatesSkipped": "{count} duplicates skipped",
"importInvalidSkipped": "{count} invalid entries skipped",
"importFailed": "Import failed",
"importInvalidFormat": "Invalid JSON format",
"requestExample": "Request example",
"categoryBloodPressure": "Blood Pressure",
"categoryVitamin": "Vitamins",
"categoryThyroid": "Thyroid",
"categoryHormone": "Hormones",
"categorySupplement": "Supplement",
"categoryPainRelief": "Pain Relief",
"categoryAllergy": "Allergy",
"categoryDigestive": "Gastrointestinal",
"categorySkin": "Skincare",
"categorySleepAid": "Sleep Aid",
"categoryDiabetes": "Diabetes",
"categoryAntibiotic": "Antibiotic",
"categoryOther": "Other",
"daysSun": "Sun",
"daysMon": "Mon",
"daysTue": "Tue",
"daysWed": "Wed",
"daysThu": "Thu",
"daysFri": "Fri",
"daysSat": "Sat",
"back": "Back",
"today": "Today",
"yesterday": "Yesterday",
"tomorrow": "Tomorrow",
"asNeededMarker": "As needed",
"withoutNotification": "Without notification",
"pausedSince": "Paused since",
"takeNow": "Take now",
"lastDoseYesterday": "Last dose yesterday",
"lastDoseDaysAgo": "Last dose {count} days ago",
"overdue": "Overdue",
"veryOverdue": "Very overdue",
"complianceWindow": "Adherence ({days} days)",
"complianceUnavailable": "Adherence could not be loaded",
"complianceInfo": "Share of expected doses you logged. Weekly schedules count week by week.",
"complianceInfoLabel": "What does adherence mean?",
"lastIntake": "Last intake:",
"nextIntake": "Next intake:",
"nextIntakeOverdue": "Overdue · {time} — can still be taken",
"dayStreak": "day streak",
"dayStreakOne": "day streak",
"cycleDueToday": "Due today",
"cycleNoClosedCycles": "No closed dose cycles yet",
"taken": "Taken",
"skipped": "Skipped",
"intakeToastTaken": "{name} recorded as taken",
"intakeToastSkipped": "{name} skipped",
"intakeToastFailed": "Could not record {name} — try again",
"intakeUndo": "Undo",
"intakeUndone": "Entry reverted",
"intakeUndoFailed": "Could not undo — open the history to fix it",
"glp1LastInjection": "{label}",
"glp1NextInjectionDays": "{label} (in {days} days)",
"glp1NextInjectionToday": "today",
"glp1NextInjectionTomorrow": "tomorrow",
"glp1RotationSuggested": "Recommended next: {site}",
"glp1LogSideEffect": "Log side effect",
"sideEffects": {
"section": "Side effects",
"addCta": "Log",
"sheetTitle": "Log a side effect",
"categoryLabel": "Category",
"entryLabel": "Symptom",
"severityLabel": "Severity",
"severity": {
"mild": "Mild",
"moderate": "Moderate",
"significant": "Significant",
"severe": "Severe",
"verySevere": "Very severe"
},
"notesLabel": "Notes (optional)",
"notesPlaceholder": "Anything worth remembering, max 280 characters",
"submitCta": "Save",
"cancelCta": "Cancel",
"emptyState": "No side effects logged yet. Tracking can help your doctor and surface patterns over time.",
"recentTitle": "Last 30 days",
"loading": "Loading…",
"deleteCta": "Delete",
"deleteError": "Could not delete the entry",
"errorSeverity": "Severity must be between 1 and 5",
"errorEntry": "Pick a symptom",
"categories": {
"gi": "Gastrointestinal",
"metabolic": "Metabolic",
"injectionSite": "Injection site",
"cognitive": "Cognitive",
"glp1Specific": "GLP-1 specific"
},
"entries": {
"nausea": "Nausea",
"vomiting": "Vomiting",
"diarrhea": "Diarrhoea",
"constipation": "Constipation",
"abdominalPain": "Abdominal pain",
"hypoglycemiaSymptoms": "Low-glucose symptoms",
"dehydration": "Dehydration",
"anorexia": "Decreased appetite",
"electrolyteFatigue": "Electrolyte-imbalance fatigue",
"injectionRedness": "Injection site redness",
"injectionSwelling": "Injection site swelling",
"injectionBruising": "Injection site bruising",
"injectionInduration": "Injection site induration",
"brainFog": "Brain fog",
"dizziness": "Dizziness",
"lowMood": "Low mood",
"lowEnergy": "Low energy",
"earlySatiety": "Early satiety",
"gastroparesisLike": "Slow stomach emptying",
"dysgeusia": "Taste change",
"gallbladderDiscomfort": "Gallbladder discomfort"
},
"deleteConfirmTitle": "Delete this entry?",
"deleteConfirmBody": "This side-effect entry will be permanently removed."
},
"scheduling": {
"naturalLanguage": {
"title": "Describe your medication",
"description": "Write the medication in your own words and we will pre-fill the form for you.",
"placeholder": "e.g. Mounjaro 5mg weekly on Wednesday morning starting next Monday",
"submit": "Extract",
"submitBusy": "Extracting…",
"cancel": "Cancel",
"examples": {
"label": "Try one of these examples",
"weekly": "Mounjaro 5mg weekly on Wednesday morning",
"daily": "Ibuprofen 200mg every day, 3 times a day",
"rolling": "Methotrexate 7.5mg every 7 days from last injection"
},
"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."
}
},
"cadence": {
"section": "Cadence",
"label": "How often",
"kind": {
"daily": "Every day",
"weekdays": "Certain days of the week",
"everyNWeeks": "Every N weeks on certain days",
"monthly": "Monthly on a specific day",
"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.",
"oneShot": "One-time dose"
},
"weekdays": {
"label": "Days of the week",
"short": {
"mo": "Mo",
"tu": "Tu",
"we": "We",
"th": "Th",
"fr": "Fr",
"sa": "Sa",
"su": "Su"
},
"long": {
"mo": "Monday",
"tu": "Tuesday",
"we": "Wednesday",
"th": "Thursday",
"fr": "Friday",
"sa": "Saturday",
"su": "Sunday"
}
},
"intervalWeeks": {
"suffix": "weeks"
},
"dayOfMonth": {
"label": "Day"
},
"intervalMonths": {
"suffix": "months",
"dayOnLabel": "on day"
},
"yearly": {
"date": {
"label": "Date"
}
},
"rollingDays": {
"suffix": "days"
}
},
"timesOfDay": {
"section": "Times of day",
"label": "Times of day",
"empty": {
"cta": "Add the first time."
},
"add": "Add time",
"remove": "Remove",
"presets": {
"morning": "Morning",
"noon": "Noon",
"evening": "Evening",
"night": "Night"
},
"max": {
"reached": "Maximum reached — remove a time before adding another."
}
},
"courseWindow": {
"section": "Course window",
"startsOn": {
"label": "Starts on"
},
"endsOn": {
"label": "Ends on"
},
"noEndDate": "No end date",
"oneShotCaption": "(one-time dose)",
"invalidRange": "End date must be on or after the start date."
}
},
"wizard": {
"header": {
"stepOf": "Step {current} of {total}",
"createTitle": "New medication",
"editTitle": "Edit {name}"
},
"nav": {
"back": "Back",
"next": "Next",
"save": "Save",
"saveEdit": "Save changes",
"nextHint": "Next: {step}",
"reviewHint": "Next: Save",
"jumpFirst": "Jump to the first step",
"jumpLast": "Jump to review and save"
},
"nl": {
"button": "Describe"
},
"steps": {
"step1": {
"title": "What's the medication called?",
"subline": "Exactly as it appears on the box.",
"label": "Name",
"placeholder": "e.g. Ramipril",
"short": "Name"
},
"step2": {
"title": "What kind of medication is it?",
"subline": "We use this for the right templates and analytics.",
"short": "Type"
},
"step3": {
"title": "What's the dose?",
"subline": "A tablet, a puff, a drop — depending on the form.",
"amountLabel": "Amount",
"amountPlaceholder": "e.g. 5",
"unitLabel": "Unit",
"unit": {
"mg": "mg",
"ml": "ml",
"iu": "IU",
"mcg": "µg",
"g": "g",
"tablets": "tablet(s)",
"capsules": "capsule(s)",
"drops": "drops",
"puffs": "puff",
"sprays": "spray",
"pieces": "pieces",
"other": "other"
},
"deliveryFormLabel": "Route",
"deliveryForm": {
"ORAL": "Oral",
"INJECTION": "Injection",
"OTHER": "Other"
},
"dosesPerUnitLabel": "Doses per unit",
"dosesPerUnitPlaceholder": "e.g. 4",
"dosesPerUnitHint": "Doses per pen / vial — leave empty for no inventory tracking.",
"injectionSiteToggle": "Injection-site rotation",
"injectionSiteHint": "Optional rotation guide. The site for each dose is recorded when you log the intake.",
"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"
},
"step4": {
"title": "Over what period are you taking it?",
"subline": "A start date is enough for today. You can add an end date later.",
"short": "When"
},
"step5": {
"title": "How often do you take it?",
"subline": "Pick the cadence — the details follow on the next step.",
"short": "Cadence"
},
"step6": {
"title": "What does that look like in detail?",
"subline": "Set weekdays, intervals, or the day of the month.",
"intervalWeeks": {
"label": "Every",
"suffix": "weeks"
},
"dayOfMonth": {
"label": "On",
"suffix": "day of the month"
},
"rollingDays": {
"label": "Every",
"suffix": "days from the last intake"
},
"short": "Detail"
},
"step7": {
"title": "When do you take it?",
"subline": "One or more times of day — reminders follow this list.",
"presetsLabel": "Time-of-day presets",
"presets": {
"morning": "Morning",
"noon": "Noon",
"evening": "Evening",
"night": "Night"
},
"short": "Times"
},
"step8": {
"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.",
"noChannelHintLink": "Set up notifications",
"multiScheduleNote": "This medication has multiple schedules. The detailed editor returns in a later release.",
"short": "Done"
}
},
"classRow": {
"bloodPressure": "Blood pressure",
"diabetes": "Diabetes",
"hormone": "Hormones",
"glp1": "GLP-1 injection",
"painRelief": "Pain",
"allergy": "Allergy",
"vitamin": "Vitamins",
"supplement": "Supplement",
"antibiotic": "Antibiotic",
"other": "Other"
},
"cadence": {
"daily": {
"label": "Daily",
"description": "Every day at the same time."
},
"weekdays": {
"label": "Specific weekdays",
"description": "E.g. Monday, Wednesday, Friday."
},
"everyNWeeks": {
"label": "Every few weeks",
"description": "E.g. every 2 weeks on Thursdays (GLP-1, biologics)."
},
"monthly": {
"label": "Monthly",
"description": "On a fixed day each month (e.g. always the 1st)."
},
"rolling": {
"label": "Flexible from last dose",
"description": "Leave the next dose open. When you tap 'taken', the counter starts again from that moment."
},
"oneShot": {
"label": "Single dose",
"description": "One administration, e.g. a vaccine or an antibiotic course."
},
"asNeeded": {
"label": "As needed",
"description": "No fixed plan — log an intake whenever you need one (e.g. pain relief)."
}
},
"summary": {
"title": "Summary",
"cadence": {
"daily": "Every day",
"weekdays": "On selected days of the week",
"biweekly": "Every two weeks",
"monthly": "Monthly",
"quarterly": "Every three months",
"yearly": "Once a year",
"rolling": "Every {n} days from your last intake",
"oneShot": "A single dose",
"asNeeded": "As needed",
"everyNWeeks": "Every {n} weeks",
"everyNMonths": "Every {n} months"
},
"weekdaysDetail": ", on {days}",
"dayOfMonthDetail": ", on day {day}.",
"times": "at {times}",
"startsOn": "Starts: {date}",
"endsOn": "Ends: {date}",
"noEndDate": "No end date"
},
"compose": {
"scheduleIndex": "Schedule {n} of {total}",
"list": {
"add": "Add another schedule",
"edit": "Edit",
"remove": "Remove",
"removeDisabled": "At least one schedule is required."
}
},
"errors": {
"submitFailed": "Could not save the medication — please retry."
}
},
"doseStrength": {
"title": "Dose strength over time",
"axisLabel": "Recorded dose ({unit})",
"tooltipLabel": "Dose",
"currentDose": "Current dose: {dose} {unit}",
"noCurrentDose": "No dose recorded yet.",
"empty": "No titration history yet. Log a dose change to see the strength curve."
},
"titration": {
"title": "Titration plan",
"empty": "No dose-escalation steps recorded yet. Add dated dose changes to plot the plan.",
"youAreHere": "You are here",
"doseStep": "{dose} {unit}",
"plannedFor": "Planned · {date}"
},
"injectionSiteBodyOutlineAriaLabel": "Body outline",
"injectionSitePickerAriaLabel": "Injection site picker",
"injectionSiteRecommendedAriaLabel": "{site} — recommended next site",
"injectionSiteLegendAriaLabel": "Marker legend",
"injectionSiteLegendRecommended": "Recommended next site",
"injectionSiteLegendLastUsed": "Last used site",
"siteAbdomenLeft": "Abdomen, lower left",
"siteAbdomenRight": "Abdomen, lower right",
"siteAbdomenUpperLeft": "Abdomen, upper left",
"siteAbdomenUpperRight": "Abdomen, upper right",
"siteThighLeft": "Left thigh",
"siteThighRight": "Right thigh",
"siteUpperArmLeft": "Left upper arm",
"siteUpperArmRight": "Right upper arm",
"sideEffectTagsHelp": "Tap a chip to add it to your mood-entry tags.",
"sideEffectTagNausea": "nausea",
"sideEffectTagConstipation": "constipation",
"sideEffectTagDiarrhea": "diarrhea",
"sideEffectTagFatigue": "fatigue",
"sideEffectTagAppetiteLoss": "appetite-loss",
"sideEffectTagHeartburn": "heartburn",
"sideEffectTagHeadache": "headache",
"phaseConfig": "Reminder phases",
"phaseConfigDescription": "Configure timing for reminders.",
"phaseGreen": "Green",
"phaseYellow": "Yellow",
"phaseOrange": "Orange",
"phaseRed": "Red",
"phaseMinutes": "Min",
"phasePercent": "%",
"phaseResetDefaults": "Reset to defaults",
"phaseSaved": "Reminder phases saved",
"sourceWeb": "Web",
"sourceApi": "iOS App",
"sourceReminder": "Reminder",
"sourceImport": "Import",
"intakeSourceVia": "via {origin}",
"intakeHistoryEmptyTitle": "No intakes recorded yet",
"intakeHistoryEmptyDescription": "Log a dose on the daily intake page to start building the history.",
"intakeHistoryEmptyAction": "Open daily intake",
"intakeHistoryColTaken": "Taken",
"intakeHistoryColScheduled": "Scheduled",
"intakeHistoryColStatus": "Status",
"intakeHistoryColSource": "Source",
"intakeHistoryStatusTaken": "Taken",
"intakeHistoryStatusSkipped": "Skipped",
"intakeHistorySortByTaken": "Sort by taken time",
"intakeHistorySortByScheduled": "Sort by scheduled time",
"intakeHistoryPageInfo": "Page {page} of {total} · {count} entries",
"intakeHistoryPrev": "Previous",
"intakeHistoryNext": "Next",
"glp1": {
"drug": {
"tirzepatide": {
"name": "Tirzepatide"
},
"semaglutide": {
"name": "Semaglutide"
},
"liraglutide": {
"name": "Liraglutide"
},
"dulaglutide": {
"name": "Dulaglutide"
},
"exenatide": {
"name": "Exenatide"
}
}
},
"researchMode": {
"dialog": {
"title": "Enable Research Mode",
"intro": "Research Mode adds an estimated drug-level chart to your GLP-1 medication page. Read the boundary below before turning it on — the chart is a learning aid, never a measurement, never medical advice.",
"whatItIsHeader": "What this is",
"whatItIs": "A sawtooth curve simulating how your logged doses superimpose over time, using the one-compartment Bateman model with absorption and half-life parameters published in the EMA EPAR for each approved GLP-1 receptor agonist. The vertical axis is unit-less and unlabeled. The shape, not the number, is what the chart shows.",
"whatItIsntHeader": "What this isn't",
"whatItIsnt": "Not a blood level. Not a measurement. Not a forecast of how your body actually responds. Not a basis for any dose, timing, or escalation decision. Talk to your prescribing clinician for anything that affects how you take your medication.",
"whyEstimateHeader": "Why it's an estimate",
"whyEstimate": "Population pharmacokinetics describe the typical patient. Individual variation is large — tirzepatide's Schneck/Urva 2024 model reports ~22% inter-individual variability on absorption and ~49% on volume of distribution. A textbook curve cannot capture your weight, kidney function, injection technique, or timing accuracy. Read the curve as the rhythm of dosing, not as your level.",
"mdrBoundaryHeader": "Regulatory boundary",
"mdrBoundary": "HealthLog displays public regulatory data and your own log entries. It does not predict, diagnose, treat, or recommend any therapy. EU Regulation 2017/745 (the Medical Device Regulation, MDR) and guidance document MDCG 2021-24 draw the line at software that interprets data for medical purposes — this chart stays decisively on the educational side of that line. If you ever feel it's nudging you toward a clinical decision, close it.",
"citationsHeader": "Sources",
"citations": "EMA European Public Assessment Reports for Mounjaro, Ozempic, Wegovy, Saxenda, Trulicity, Byetta, and Bydureon (Section 5.2). Schneck K, Urva S. Population pharmacokinetics of the GIP/GLP receptor agonist tirzepatide. CPT Pharmacometrics Syst Pharmacol 2024;13(3):494-503 (DOI 10.1002/psp4.13099).",
"versionLine": "Disclaimer version: {version}",
"acknowledgeCta": "I understand — enable",
"cancelCta": "Cancel",
"successToast": "Research Mode enabled. The drug-level chart is now visible on your GLP-1 medication page.",
"errorToast": "Could not enable Research Mode. Please try again.",
"staleVersionToast": "The disclaimer was updated since this page loaded. Reload to read the current version."
},
"chart": {
"title": "Estimated drug level",
"axisLabel": "Estimated level (relative)",
"emptyState": "No intake events yet.",
"emptyStateCta": "Log a dose to see the estimated level take shape.",
"estimateNote": "Educational estimate from EMA-published population pharmacokinetics. Not a measurement.",
"unknownDrug": "{name} is not in the EMA-approved GLP-1 catalog, so HealthLog cannot render a population-PK curve for it."
}
},
"detail": {
"status": {
"active": "Active",
"paused": "Paused",
"ended": "Ended"
},
"cadence": {
"oneShotOn": "One-time dose on {date}.",
"oneShotPending": "One-time dose pending.",
"asNeeded": "As needed — no fixed plan."
},
"intake": {
"title": "Intake history",
"importButton": "Import",
"rowActions": {
"openMenu": "Open row actions",
"edit": "Edit",
"delete": "Delete"
},
"selection": {
"rowToggleLabel": "Select row"
},
"bulkDelete": {
"selectionCount": "{count} entries selected",
"deleteButton": "Delete selection",
"cancelButton": "Cancel",
"confirmTitle": "Delete the selected entries?",
"confirmBody": "{count} entries will be removed permanently. The medication itself stays.",
"confirmAction": "Delete",
"toast": "Selection deleted",
"failed": "Could not delete the selection."
},
"edit": {
"dialogTitle": "Edit intake",
"takenAtLabel": "Taken at",
"scheduledForHint": "Scheduled: {dateTime}",
"farFromScheduledWarning": "This is far from the scheduled time — check the date.",
"skippedLabel": "Skipped",
"save": "Save",
"cancel": "Cancel",
"savedToast": "Intake updated",
"failed": "Could not update the intake."
},
"deleteRow": {
"confirmTitle": "Delete this intake?",
"confirmBody": "The entry is removed permanently.",
"confirmAction": "Delete",
"toast": "Intake deleted",
"failed": "Could not delete the intake."
},
"viewRecent90": "Last 90 days",
"viewAll": "Full history",
"viewToggleLabel": "History range"
},
"verlauf": {
"loading": "Loading history…",
"loadError": "Could not load the history.",
"empty": "No intakes in this period yet.",
"summaryEmpty": "No doses to score yet.",
"adherenceLabel": "Adherence",
"adherenceBarLabel": "{onTime} on time, {late} late, {missed} missed",
"add": "Entry",
"markTaken": "Taken",
"markSkipped": "Skipped",
"rowActionsLabel": "Actions for {time}",
"markAsTaken": "Mark as taken",
"markAsSkipped": "Mark as skipped",
"adHocTag": "off-schedule",
"takenDetail": "planned {planned} · taken {taken}",
"doseTaken": "Dose: {dose}",
"status": {
"taken_on_time": "on time",
"taken_late": "late",
"skipped": "skipped",
"missed": "missed",
"upcoming": "upcoming",
"ad_hoc": "off-schedule"
},
"addDialog": {
"title": "Add intake",
"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.",
"cancel": "Cancel",
"submit": "Save"
},
"nudge": {
"title": "Attribute to this slot?",
"body": "This intake falls just outside the {slot} window. Attribute it to that slot, or keep it as an off-schedule entry?",
"keepAdHoc": "Off-schedule",
"pin": "Attribute"
},
"pin": {
"action": "Attribute to slot {time}",
"release": "Release attribution",
"pinnedTag": "attributed",
"pinnedToast": "Intake attributed to slot",
"unpinnedToast": "Attribution released",
"dueContext": "was due: {time} ({delta})",
"confirmTitle": "Attribute to slot {time}?",
"confirmBody": "The intake counts as taken late for this slot – the rate is never flattered. You can release the attribution at any time.",
"confirmCancel": "Cancel",
"confirmAction": "Attribute"
}
},
"notifications": {
"title": "Notifications",
"switchLabel": "Send a reminder when this dose is due",
"helperOn": "Reminders are on.",
"helperOff": "Reminders are off.",
"enabledToast": "Reminders on",
"disabledToast": "Reminders off",
"toggleFailed": "Could not change the reminder setting.",
"clientManagedChip": "Your iPhone manages reminders for this medication."
},
"settings": {
"title": "Settings",
"phases": {
"openButton": "Configure phases",
"requiresCourseWindow": "Phases are available once a course window is set."
},
"grace": {
"label": "Reminder window",
"appliesToAllNote": "Applies to every schedule of this medication.",
"unit": "minutes",
"saved": "Reminder window saved",
"failed": "Could not save the reminder window."
},
"codes": {
"label": "Clinical codes (ATC / RxNorm)",
"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",
"failed": "Could not save the clinical codes."
}
},
"zone": {
"title": "Manage & danger zone",
"pause": {
"title": "Pause",
"helper": "Pause reminders until you turn them back on. History stays intact.",
"pausedToast": "Reminders paused",
"resumedToast": "Reminders resumed",
"failed": "Could not change the paused state."
},
"end": {
"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",
"dialogBody": "No more reminders. Old entries remain in the timeline.",
"toast": "Medication ended",
"failed": "Could not end the medication."
},
"purge": {
"title": "Delete history",
"helper": "{count} intake events are stored for this medication.",
"button": "Delete history",
"dialogTitle": "Really delete the history?",
"dialogBody": "The {count} intake events will be removed permanently. The medication itself stays.",
"toast": "History deleted",
"failed": "Could not delete the history."
},
"delete": {
"title": "Delete medication",
"helper": "Removes the medication and every related record.",
"button": "Delete",
"dialogTitle": "Delete {name}?",
"dialogBody": "The medication, its schedules, intake history, API tokens, phase config and reminders will be removed permanently.",
"toast": "Medication deleted",
"failed": "Could not delete the medication."
}
},
"phases": {
"modeLabel": "{phase} mode",
"saveFailed": "Could not save the reminder phases."
},
"api": {
"caption": "Endpoint for \"{name}\"",
"copyUrl": "Copy URL",
"urlCopied": "URL copied",
"mintToken": "Mint token",
"mintAnotherToken": "Mint another token",
"mintFailed": "Could not mint a token.",
"copyFailed": "Could not copy.",
"tokenCopied": "Token copied",
"copyToken": "Copy token",
"mintedHint": "Copy this token now — it is shown only once."
},
"advanced": {
"dataPortability": {
"import": {
"title": "Import intakes",
"helper": "Load past intakes from a JSON file or pasted JSON.",
"button": "Import JSON"
},
"export": {
"title": "Export medication",
"helper": "Download this medication as a CSV file.",
"includeIntake": "Include intake history",
"button": "Export CSV"
}
}
},
"header": {
"historyLabel": "View intake history"
},
"history": {
"plannedSuffix": "planned"
},
"tabs": {
"uebersicht": "Overview",
"zeitplan": "Schedule",
"bestand": "Supply",
"verlauf": "History",
"injektion": "Injection",
"api": "API",
"erweitert": "Advanced",
"wirkung": "Effect"
},
"shell": {
"loadFailed": "This medication could not be loaded.",
"tablistLabel": "Medication detail sections"
},
"uebersicht": {
"statusTitle": "Status",
"nextDoseLabel": "Next dose",
"nextDoseNone": "No upcoming dose.",
"nextDoseAsNeeded": "As needed — no planned dose.",
"pausedHint": "Paused — no reminders.",
"reminderLabel": "Reminder",
"reminderOn": "On",
"reminderOff": "Off",
"supplyLabel": "Supply",
"supplyRunway": "Lasts about {days} more days",
"jumpToZeitplan": "Open schedule",
"jumpToVerlauf": "Open history",
"jumpToBestand": "Open supply",
"complianceTitle": "Adherence",
"complianceEmpty": "No adherence data yet."
},
"bestand": {
"title": "Supply",
"summary": "{remaining} of {total} doses remaining",
"itemsTitle": "Packs & containers",
"doses": "{remaining} / {total} doses",
"unknown": "Unknown",
"state": {
"ACTIVE": "Unopened",
"IN_USE": "In use",
"EXPIRED": "Expired",
"USED_UP": "Used up"
},
"empty": "No supply recorded.",
"emptyHelper": "Register a pack or container to track remaining supply and runway.",
"emptyCta": "Register a pack",
"addButton": "Register",
"lowStockLinkOn": "Low-stock notification: below {days} days",
"lowStockLinkOff": "Low-stock notification: off",
"addTitle": "Register a pack or container",
"addDescription": "Record a new supply with its unit count; the expiry date is optional.",
"addQuantityLabel": "Quantity (units)",
"addQuantityHelper": "1–1000 units per pack or container.",
"addExpiryLabel": "Expiry date (optional)",
"addSubmit": "Register",
"addSuccess": "Supply registered.",
"addFailed": "The supply could not be registered.",
"adjustButton": "Adjust",
"adjustTitle": "Correct stock",
"adjustDescription": "Set the remaining units — for corrections or a withdrawal. 0 marks the item as used up.",
"adjustQuantityLabel": "Remaining units",
"adjustHelper": "Capacity: {total} units.",
"adjustSubmit": "Save",
"adjustSuccess": "Stock updated.",
"adjustFailed": "The stock could not be updated.",
"deleteTitle": "Delete container?",
"deleteDescription": "Permanently removes this pack or container from the stock. Logged intakes stay unchanged.",
"deleteSuccess": "Stock entry deleted.",
"deleteFailed": "The stock entry could not be deleted.",
"containerTypeLabel": "Container type",
"containerType": {
"PEN": "Pen",
"AMPOULE": "Ampoule",
"BLISTER": "Tablet pack",
"INHALER": "Inhaler",
"BOTTLE": "Bottle",
"OTHER": "Other"
},
"unitsDetail": "{remaining} / {total} units",
"quantityModeDoses": "Doses",
"quantityModeUnits": "Units",
"quantityInUnits": "= {units} units",
"quantityInDoses": "≈ {doses} doses",
"quantityUnderOneDose": "< 1 dose",
"expiredSuffix": "+ {units} units expired",
"packagingTitle": "Packaging & dose",
"packagingUnitsPerDose": "1 dose = {units} units",
"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.",
"packagingUnitsPerDoseLabel": "Units per dose",
"packagingUnitsPerDoseHelper": "E.g. two 2 mg tablets for a 4 mg dose (1–100). Doses already recorded stay unchanged.",
"packagingDefaultPackLabel": "Default pack size (units)",
"packagingDefaultPackHelper": "Prefills the quantity when registering new packs (1–1000). Leave empty if none applies.",
"packagingSuccess": "Packaging details saved",
"packagingFailed": "Saving failed",
"addManufacturerLabel": "Manufacturer",
"addDoseStrengthLabel": "Strength",
"addDoseStrengthHint": "As printed on the container, e.g. 5 mg/0.5 ml."
},
"erweitert": {
"group": {
"lifecycle": "Lifecycle",
"externalApi": "External API",
"data": "Data",
"danger": "Danger zone"
},
"editor": {
"title": "Edit medication in the editor",
"helper": "Change name, treatment class, frequency and schedules in the step-by-step editor.",
"button": "Open editor"
}
},
"zeitplan": {
"title": "Schedule",
"timesTitle": "Dose times",
"timesNote": "Adjust each dose's time and on-time window. The frequency (daily, weekly…) is edited in the editor under Advanced.",
"scheduleLabel": "Schedule {index}",
"fullEditNote": "Frequency, treatment class and course window are edited in the editor under Advanced → Lifecycle.",
"graceEcho": "Reminder window: {minutes} minutes",
"reminderTitle": "Reminder",
"manageChannels": "Manage notification channels",
"history": {
"title": "Plan history",
"currentSince": "Current plan since {date}",
"noTimes": "No fixed times",
"manualChip": "Added manually",
"showErasOne": "Show 1 earlier era",
"showErasOther": "Show {count} earlier eras",
"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.",
"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.",
"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",
"fromLabel": "From",
"untilLabel": "Until",
"untilHint": "\"Until\" is the day the following plan took over (exclusive).",
"validationTimes": "Add at least one time.",
"validationRangeMissing": "Set both the from and until dates.",
"validationRangeOrder": "The from date must lie before the until date.",
"cancel": "Cancel",
"submit": "Save era",
"createdToast": "Earlier era saved",
"createError": "Could not save the era. It must not overlap existing eras and must end before the current plan.",
"deletedToast": "Era deleted",
"deleteError": "Could not delete the era",
"deleteAria": "Delete era",
"deleteConfirmTitle": "Delete era?",
"deleteConfirmBody": "History and adherence for this period will be computed against the current plan again.",
"deleteConfirmAction": "Delete",
"loadError": "Could not load the plan history"
},
"save": "Save schedule",
"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.",
"explicitToggle": "Custom window",
"startLabel": "Window start",
"endLabel": "Window end",
"onTimeBand": "On time: {start}–{end}",
"lateUntil": "late until {time}",
"lateDays": "late until {days} days after",
"orderError": "The start must be before the end.",
"noTimes": "No dose times set yet."
}
}
},
"logInjectionSiteTitle": "Log injection site",
"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.",
"logInjectionSiteSaveFailed": "Could not save the injection site. Please try again.",
"trackInjectionSitesToggle": "Track injection sites",
"trackInjectionSitesHint": "After a dose is taken, ask which site was used and suggest the next rotation.",
"allowedSitesLabel": "Allowed sites",
"allowedSitesHint": "Leave all selected for no restriction. Sites you excluded globally are never offered.",
"viewToggleLabel": "View",
"viewToggleHint": "Choose whether your medications appear as cards or as a table.",
"viewCards": "Card view",
"viewTable": "Table view",
"viewSaveFailed": "View could not be saved",
"tableCaption": "Medications as a table with status, next dose, adherence and stock",
"tableColName": "Name",
"tableColStatus": "Status",
"tableColNextDose": "Next dose",
"tableColCompliance": "Adherence",
"tableColStock": "Stock",
"tableColActions": "Actions",
"tableSortBy": "Sort by {column}",
"tableComplianceDays": "{days} d",
"tableStockDoseOne": "1 dose",
"tableStockDoses": "{count} doses",
"tableStockRunway": "≈ {days} days left",
"cardLowStockRunway": "Supply: ≈ {days} days",
"takeActionFor": "Take – {name}",
"skipActionFor": "Skip – {name}",
"reorderTitle": "Adjust order",
"reorderDescription": "Set the order of your medications – it applies to 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.",
"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.",
"disclaimer": "Association only: these figures show what changed over the same period, not that the medication caused the change. Discuss any decision about your treatment with your doctor.",
"primaryBadge": "Main target",
"noSeries": "No readings recorded for this target yet.",
"startMarker": "Start",
"adherenceLane": "Adherence",
"typicalRange": "Typical range",
"levelShift": "A shift in the level was detected around {date}.",
"plateau": {
"title": "Weight plateau on the current dose",
"evidence": "Weight moved by {delta} kg over the last {window} days ({readings} readings) — {days} days on {dose}."
},
"retarget": {
"label": "Not the right measurement?",
"placeholder": "Track against…",
"apply": "Apply",
"reset": "Reset to default",
"error": "Could not save that change. Try again."
},
"beforeAfter": {
"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.",
"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."
},
"insights": {
"title": "Medication effect",
"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."
},
"scaleAbsolute": "Absolute",
"scalePercentSinceStart": "% since start",
"scaleToggleLabel": "Chart scale"
}
},
"charts": {
"loadingLabel": "Loading chart…",
"loadingSlowHint": "Computing analytics — this can take a moment.",
"weight": "Weight",
"bloodPressure": "Blood Pressure",
"pulse": "Pulse",
"bodyFat": "Body Fat",
"sleep": "Sleep",
"steps": "Steps",
"hrv": "HRV",
"restingHeartRate": "Resting heart rate",
"activeEnergy": "Active energy",
"flights": "Flights climbed",
"distance": "Walking + running distance",
"vo2Max": "VO₂ max",
"bodyTemperature": "Body temperature",
"noData": "No data in selected time range",
"bucketWeekly": "Weekly avg",
"bucketMonthly": "Monthly avg",
"points7Label": "7 pts",
"points7Title": "Last 7 data points",
"points30Label": "30 pts",
"points30Title": "Last 30 data points",
"points90Label": "90 pts",
"points90Title": "Last 90 data points",
"pointsAllLabel": "All",
"pointsAllTitle": "All available data points",
"systolic": "Systolic",
"diastolic": "Diastolic",
"bodyWater": "Body water",
"boneMass": "Bone mass",
"spo2": "SpO₂",
"movingAverage7d": "7-day trend",
"avg7dShort": "7d",
"avg30dShort": "30d",
"trend7dShort": "7-day trend",
"trend": "Trend",
"perWeek": "/week",
"totalDelta": "Total",
"colorGreen": "Green:",
"colorOrange": "Orange:",
"colorRed": "Red:",
"mood": "Mood",
"moodScore": "Mood Score",
"weekdays": {
"mon": "Mon",
"wed": "Wed",
"fri": "Fri",
"sun": "Sun"
},
"months": {
"jan": "Jan",
"feb": "Feb",
"mar": "Mar",
"apr": "Apr",
"may": "May",
"jun": "Jun",
"jul": "Jul",
"aug": "Aug",
"sep": "Sep",
"oct": "Oct",
"nov": "Nov",
"dec": "Dec"
},
"heatmapOnTime": "on time",
"heatmapLate": "late",
"heatmapVeryLate": "very late",
"legendOnTime": "On time",
"legendLate": "Late",
"legendVeryLate": "Very late",
"legendMissed": "Missed",
"emptyStateTitle": "Add more measurements to see trends",
"emptyStateDescription": "Log at least 3 entries to unlock the trend line.",
"needMoreDistinctDaysTitle": "More distinct days needed",
"needMoreDistinctDaysDescription": "Log on more days to unlock the trend line.",
"noDataInRangeTitle": "No data in this range",
"noDataInRangeDescription": "No measurements fall inside the selected range. Switch the range or log a new measurement.",
"errorTitle": "Data could not be loaded",
"loadErrorTitle": "Chart could not be loaded",
"loadErrorReload": "Reload",
"sparseDataCaption": "More days will fill out the trend.",
"personalBaseline": "Your normal",
"deltaVsBaseline": "{delta} vs. your normal",
"deltaUnchanged": "matches your normal",
"deltaVsTarget": "{delta} vs. target",
"weekdaysFull": {
"mon": "Monday",
"tue": "Tuesday",
"wed": "Wednesday",
"thu": "Thursday",
"fri": "Friday",
"sat": "Saturday",
"sun": "Sunday"
},
"rangeBand": "Range",
"a11y": {
"summary": "{metric} chart. Range {min} to {max}, latest {latest}, trend {trend}.",
"noData": "{metric} chart. No data available.",
"trendUp": "rising",
"trendDown": "falling",
"trendFlat": "steady",
"scatterSummary": "Correlation chart, {count} points plotting {xLabel} against {yLabel}.",
"scatterNoData": "Correlation chart of {xLabel} against {yLabel}. No data available.",
"moodHeatmap": "Mood heatmap from {start} to {end}, {days} days logged.",
"moodHeatmapEmpty": "Mood heatmap, no days logged yet.",
"complianceHeatmap": "Medication compliance heatmap from {start} to {end}, {days} active days.",
"complianceHeatmapEmpty": "Medication compliance heatmap, no active days yet."
}
},
"chart": {
"overlay": {
"controls": {
"title": "Chart overlays",
"trendIndicator": "7-day trend",
"trendArrow": "Trend arrow",
"targetRange": "Target range",
"comparisonBaseline": "Comparison",
"comparisonUnavailable": "No prior-period data yet",
"tooltip": {
"openSettings": "Chart overlay settings"
}
}
}
},
"comparison": {
"toggleLabel": "Compare to",
"toggleHint": "Show the same period from last year alongside today's chart.",
"baseline": {
"none": "None",
"lastMonth": "Last month",
"lastYear": "Last year"
},
"captionLastMonth": "vs. last month",
"captionLastYear": "vs. last year",
"deltaVs": {
"lastMonth": "{delta} vs. last month",
"lastYear": "{delta} vs. last year"
},
"tooltipPrior": "Prior period",
"unavailable": {
"lastMonth": "Comparison unavailable — no data from last month yet",
"lastYear": "Comparison unavailable — no data from last year yet"
},
"notAvailableForCompliance": "Comparison N/A for adherence"
},
"insights": {
"correlation": {
"direction": {
"higher": "higher",
"lower": "lower"
},
"weekdayDirection": {
"above": "above",
"below": "below"
},
"channelFactor": "rated {factor}",
"channel": {
"WEIGHT": "weight",
"BLOOD_GLUCOSE": "blood glucose",
"BLOOD_PRESSURE_SYS": "systolic blood pressure",
"BLOOD_PRESSURE_DIA": "diastolic blood pressure",
"ACTIVITY_STEPS": "daily steps",
"SLEEP_DURATION": "sleep duration",
"HEART_RATE_VARIABILITY": "heart-rate variability",
"RESTING_HEART_RATE": "resting heart rate",
"TIME_IN_DAYLIGHT": "time in daylight",
"MOOD": "mood",
"PULSE": "resting pulse",
"MEDICATION_COMPLIANCE": "medication compliance",
"SYMPTOM_SEVERITY": "symptom severity",
"ENV_TEMP_MEAN": "daily temperature",
"ENV_TEMP_MIN": "overnight low temperature",
"ENV_SUNSHINE": "sunshine",
"ENV_DAYLIGHT": "daylight",
"ENV_PRECIP": "precipitation",
"ENV_PRESSURE_MEAN": "barometric pressure",
"ENV_PRESSURE_DELTA": "intraday pressure swing"
},
"daily": {
"high": "Higher {behaviour} tends to go with {direction} next-day {outcome} in your data — a pattern worth watching, not a cause.",
"moderate": "Higher {behaviour} looks like it goes with {direction} next-day {outcome} in your data, on the evidence so far — a pattern worth watching, not a cause.",
"faint": "Higher {behaviour} shows a faint hint, if anything, of {direction} next-day {outcome} in your data — too small to lean on, never a cause."
},
"lab": {
"default": "Higher {lab} readings line up with {direction} {outcome} over the same periods in your data — an association worth watching with your clinician, never a cause.",
"faint": "Higher {lab} readings show a faint hint, if anything, of {direction} {outcome} over the same periods in your data — too small to lean on, an association to raise with your clinician, never a cause."
},
"hypothesis": {
"bpCompliance": {
"support": "Higher medication compliance lines up with lower systolic readings — a pattern worth watching.",
"surprising": "Compliance and systolic move together in your data — surprising; talk to your doctor before adjusting anything.",
"none": "Compliance and systolic do not move together strongly in this window."
},
"moodPulse": {
"support": "Lower-mood days line up with higher resting pulse — a pattern worth watching.",
"surprising": "Higher-mood days line up with higher resting pulse in your data — surprising.",
"none": "Mood and resting pulse do not move together strongly in this window."
},
"weightWeekday": "{weekday} weights run {delta} kg {direction} your other-day average — a pattern worth watching."
}
},
"noAnalysisYet": "No assessment yet.",
"assessmentPreparing": "Preparing your assessment…",
"emptyTitle": "Not enough data yet",
"emptyDescription": "Insights light up once you've logged a handful of measurements. Start with weight or blood pressure.",
"emptyAddMeasurement": "Add a measurement",
"editMode": {
"open": "Customize",
"done": "Done",
"reset": "Reset",
"title": "Customize overview",
"description": "Drag to reorder, tap the eye to show or hide.",
"dragHandle": "Drag to reorder",
"show": "Show",
"hide": "Hide",
"manageInSettings": "Manage pills & detail pages in Settings",
"groupSleep": "Sleep",
"groupMood": "Mood",
"groupEvents": "Events",
"gatedHint": "Appears once data or the feature is available",
"allHiddenHint": "Every section is hidden. Show at least one to see your overview.",
"saveSuccess": "Overview layout saved",
"saveError": "Could not save your overview layout",
"resetSuccess": "Overview reset to defaults",
"emptyTitle": "Every card is hidden",
"emptyDescription": "You've hidden every section. Open customize to bring cards back."
},
"bmiEmptyTitle": "Set your height to see BMI",
"bmiEmptyDescription": "BMI needs your height. Add it under Settings → Account.",
"bmiEmptyAction": "Open account settings",
"noProviderConfigured": "Connect an AI provider to see an assessment of your readings here.",
"noProviderAction": "Open AI settings",
"startAnalysis": "Start assessment",
"refreshAnalysis": "Refresh assessment",
"keyTakeaway": "Key Takeaway",
"findingsTitle": "Findings",
"heroFindingPositive": "Top finding",
"heroFindingNeutral": "Top finding",
"heroFindingAttention": "Worth attention",
"heroFindingWarning": "Top alert",
"correlationsTitle": "Correlations",
"recommendationsTitle": "Recommendations",
"personalRecord": {
"badge": "PR",
"tooltip": "Personal record: {value} {unit} on {date}"
},
"recommendation": {
"source": "Source",
"viewSource": "Open guideline in a new tab",
"rationale": "Why this recommendation",
"rationaleWindow": "Window",
"rationaleComparedTo": "Compared to",
"rationaleDeviation": "Deviation",
"rationaleExpand": "Show why",
"rationaleCollapse": "Hide why",
"legacyPayloadCta": "Insights updated — regenerate for new explainability features",
"feedbackHelpful": "Helpful",
"feedbackNotHelpful": "Not helpful",
"feedbackThanks": "Thanks for your feedback",
"feedbackConfirmed": "Feedback recorded",
"feedbackAlreadyRated": "Already rated",
"feedbackError": "Could not save your feedback. Please try again.",
"confidence": "Confidence",
"confidenceAria": "Confidence: {value} of 100",
"confidenceHigh": "High confidence",
"confidenceMedium": "Moderate confidence",
"confidenceLow": "Low confidence — based on limited data",
"confidenceDraft": "Draft"
},
"dataFoundation": "Data coverage",
"dataGaps": "Data gaps:",
"lastUpdated": "Last updated",
"confidenceHoch": "High",
"confidenceMittel": "Medium",
"confidenceGering": "Low",
"loadError": "Failed to load insights",
"heroPersonalBaseline": "Based on your last 90 days",
"heroRegenerate": "Regenerate",
"heroRegenerating": "Regenerating",
"regenerateAnalysis": "Re-run assessment",
"regenerateSuccess": "Assessment refreshed",
"warmStarted": "Assessments are being prepared in the background",
"narrativeTitle": "In review",
"narrativeWeek": "This week",
"narrativeMonth": "This month",
"narrativePreparing": "Preparing your summary…",
"narrativeUpdating": "Updating…",
"narrativeProvenanceLabel": "How this was put together",
"narrativeProvenanceMethod": "A plain-language summary of the period, drawn only from your logged numbers and the associations that survived statistical multiple-comparison control. Descriptive, never a cause.",
"narrativeProvenanceMetrics": "Based on: {metrics}",
"narrativeProvenanceWindow": "Window: {from} to {to}",
"heroFallbackSubtitle": "A daily read of your trends, drawn straight from the numbers you've logged.",
"heroGreetingMorning": "Good morning",
"heroGreetingAfternoon": "Good afternoon",
"heroGreetingEvening": "Good evening",
"heroComingSoonTooltip": "Coming soon",
"heroActionAskCoach": "Ask the coach",
"healthScore": {
"label": "Health Score",
"progressAria": "Health Score progress",
"deltaVsLastWeek": "{delta} vs last week",
"deltaUnavailable": "No history yet — check back next week.",
"restModePaused": "Paused during illness — your score isn't being judged today.",
"componentBp": "BP",
"componentWeight": "Weight",
"componentMood": "Mood",
"componentCompliance": "Adherence",
"deltaExplainer": {
"trigger": "What does this delta mean?",
"title": "How the delta is computed",
"description": "Change vs last week: {delta}",
"body": "The score combines BP, weight, mood and medication adherence. We compare today's score with the same time last week. Log a fresh reading or a mood check to nudge it up."
},
"provenance": {
"toggle": "Driven by",
"weightLabel": "share",
"mixedBanner": "Some components blend multiple sources. The breakdown shows the most recent value per component.",
"footnote": "Weights are rescaled to the data that's actually available.",
"asOfLabel": "as of {date}",
"provisional": "Provisional — only {count} of {total} inputs available",
"provisionalBadge": "Provisional",
"sourceAria": "Source: {source}",
"sources": {
"manual": "Manual",
"withings": "Withings",
"appleHealth": "Apple Health",
"mixed": "Mixed",
"none": "No data"
}
}
},
"suggestedPrompts": {
"label": "Try asking",
"tellMyDoctor": "What should I tell my doctor?",
"medicationWorking": "Is my medication working?"
},
"dailyBriefing": {
"title": "Daily Briefing",
"keyFindingsTitle": "Key findings",
"signalsTitle": "Signals of the day",
"emptyTitle": "No briefing yet",
"emptyDescription": "Generate today's briefing to get a narrative read of your trends.",
"emptyAction": "Generate briefing",
"loadingLabel": "Synthesising today's briefing",
"noProviderTitle": "No AI provider connected",
"noProviderDescription": "Point HealthLog at a local model (Ollama, LM Studio — nothing leaves your network) or bring your own OpenAI or Anthropic key, and the daily briefing turns your own readings into a plain-language summary — for example: “weight down 1.2 kg over two weeks, resting pulse steady at 58, blood pressure in range on 6 of 7 days.” Setup takes about a minute.",
"noProviderAction": "Open AI settings",
"staleNoProviderHint": "This briefing can't refresh — no AI provider is connected.",
"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.",
"failedDescriptionTimeout": "The AI request ran out of time before the briefing was ready. For a slow local model, raise the AI response timeout in Settings, then try again.",
"failedDescriptionProvider": "The AI provider rejected the request. Re-check the provider and API key in AI settings, then try again.",
"failedDescriptionRateLimit": "The AI provider is rate-limiting requests right now. Try again in a little while.",
"omittedTitle": "Briefing withheld",
"omittedUngroundedDescription": "The generated briefing referenced a figure that couldn't be verified against your data, so it wasn't shown. Try again."
},
"trendsRow": {
"title": "Trends",
"subtitle": "Last 30 days at a glance",
"caption": {
"bp": "Systolic and diastolic readings over the last 30 days.",
"weight": "Body-weight trend over the last 30 days.",
"pulse": "Resting pulse over the last 30 days.",
"mood": "Daily mood score over the last 30 days.",
"sleep": "Nightly sleep duration over the last 30 days.",
"steps": "Daily step count over the last 30 days.",
"hrv": "Heart-rate variability over the last 30 days.",
"resting_hr": "Resting heart rate over the last 30 days.",
"active_energy": "Active energy burned over the last 30 days.",
"flights": "Flights of stairs climbed over the last 30 days.",
"distance": "Walking and running distance over the last 30 days.",
"vo2_max": "VO₂ max over the last 30 days.",
"body_temp": "Body temperature over the last 30 days."
},
"viewDetail": "View {metric} details"
},
"vo2Max": {
"statLatest": "Latest",
"statMin": "Min",
"statMax": "Max",
"empty": "No VO₂ max data yet — sync Apple Health to populate this view.",
"cardioLinkTitle": "Cardio fitness (VO₂ max)",
"cardioLinkBody": "VO₂ max is the headline measure of aerobic fitness. The full chart and assessment live on its own page.",
"cardioLinkCta": "Open cardio fitness"
},
"trendAnnotation": {
"emptyBp": "Awaiting more data to annotate this trend.",
"emptyWeight": "Awaiting more data to annotate this trend.",
"emptyMood": "Awaiting more data to annotate this trend.",
"confidenceHigh": "High confidence",
"confidenceModerate": "Moderate confidence",
"confidenceLow": "Low confidence",
"pendingLabel": "Generating trend commentary"
},
"correlationRow": {
"title": "Relationships",
"experimentCta": "Try a 7-day experiment",
"experimentTooltip": "Coming soon",
"emptyTitle": "Need more data to see this relationship",
"sourceChip": "based on {n} paired readings · {window}",
"sourceWindowLast30": "last 30 days",
"confidenceHigh": "High confidence",
"confidenceModerate": "Moderate confidence",
"confidenceLow": "Low confidence",
"card": {
"bpComplianceTitle": "BP × medication adherence",
"bpComplianceSubtitle": "Daily systolic against adherence in %",
"moodPulseTitle": "Mood × resting pulse",
"moodPulseSubtitle": "Same-day mood and resting pulse",
"weightWeekdayTitle": "Weight × weekday",
"weightWeekdaySubtitle": "Weight grouped by day of week"
}
},
"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.",
"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.",
"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.",
"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.",
"newChat": "New chat",
"docScope": {
"badge": "Document",
"chattingAbout": "Chatting about: {title}",
"chattingAboutMore": "Chatting about: {titles} and {count} more",
"notIndexedHint": "Read this document with AI first in the vault so the Coach can answer about it."
},
"actionsMenu": "Actions",
"maximizeAriaLabel": "Open in full page",
"minimizeAriaLabel": "Back to the drawer",
"send": "Send",
"stop": "Stop",
"thinking": "Thinking…",
"composerPlaceholder": "Ask me anything…",
"nudgeBubbleLabel": "New message from the Coach — open chat",
"fabLabel": "Open the Coach",
"readAloud": "Read aloud",
"readAloudStop": "Stop reading",
"messageTimeLabel": "Message sent {time}",
"copyMessage": "Copy",
"copyMessageError": "Could not copy",
"regenerate": "Try again",
"selfContextAdopt": {
"offer": "Add this answer to your self-context?",
"confirm": "Add",
"dismiss": "Dismiss",
"done": "Added to your self-context",
"duplicate": "Already part of your self-context",
"failed": "Could not add. Please try again."
},
"rememberMessage": {
"action": "Remember",
"done": "Saved to your self-context",
"duplicate": "Already part of your self-context",
"failed": "Could not save. Please try again."
},
"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.",
"offerStart": "Answer now",
"offerLater": "Later",
"offerDismiss": "Don't ask again",
"dismissError": "Could not dismiss the questions. Please try again.",
"progress": "Question {current} of {total}",
"skip": "Skip",
"later": "Later",
"dismissRemaining": "Don't ask again",
"answerPlaceholder": "Type your answer…",
"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",
"summaryLink": "Review your self-context"
},
"threadEmpty": "Ask anything about your trends, medications, or readings to start a conversation.",
"historyTitle": "Conversations",
"historySearchPlaceholder": "Search conversations…",
"historyEmpty": "Your conversations will appear here. Ask anything to start.",
"historyDeleteAria": "Delete conversation",
"historyDeleted": "Conversation deleted",
"rename": {
"action": "Rename conversation",
"input": "Conversation title",
"save": "Save title",
"cancel": "Cancel rename",
"error": "Conversation title could not be saved."
},
"historySearchEmpty": "No conversations match your search.",
"historyLoadingMore": "Loading more…",
"sourcesTitle": "What I can see",
"sourcesFresh": "Fresh",
"sourcesStale": "Stale",
"sourcesFooter": "The Coach reads only the data you've connected.",
"evidenceLabel": "What I'm looking at",
"metric": {
"bp": "Blood pressure",
"weight": "Weight",
"pulse": "Pulse",
"mood": "Mood",
"compliance": "Adherence",
"general": "General",
"hrv": "HRV",
"sleep": "Sleep",
"resting_hr": "Resting HR",
"steps": "Steps",
"active_energy": "Active energy",
"flights": "Flights climbed",
"distance": "Distance",
"vo2_max": "VO₂ max",
"body_temp": "Body temperature",
"medications": "Medications",
"anthropometrics": "Profile (height, age, gender)",
"walking_hr": "Walking heart rate",
"respiratory_rate": "Respiratory rate",
"spo2": "Blood oxygen",
"pulse_wave_velocity": "Pulse-wave velocity",
"vascular_age": "Vascular age",
"body_fat": "Body fat",
"fat_mass": "Fat mass",
"fat_free_mass": "Fat-free mass",
"muscle_mass": "Muscle mass",
"lean_body_mass": "Lean body mass",
"bone_mass": "Bone mass",
"total_body_water": "Body water",
"bmi": "BMI",
"visceral_fat": "Visceral fat",
"glucose": "Glucose",
"walking_steadiness": "Walking steadiness",
"walking_asymmetry": "Walking asymmetry",
"walking_double_support": "Double support time",
"walking_step_length": "Step length",
"walking_speed": "Walking speed",
"audio_env": "Environmental sound",
"audio_headphone": "Headphone audio",
"audio_event": "Loud-sound events",
"daylight": "Time in daylight",
"skin_temp": "Skin temperature",
"workouts": "Workouts"
},
"window": {
"last7days": "last 7 days",
"last30days": "last 30 days",
"last90days": "last 90 days",
"lastYear": "year so far",
"allTime": "all time"
},
"windowLabel": "Window",
"settingsAriaLabel": "Coach settings",
"settingsTitle": "Coach settings",
"settingsDescription": "Tune how the Coach talks with you.",
"settingsToneLabel": "Tone",
"settingsToneWarm": "Warm",
"settingsToneNeutral": "Neutral",
"settingsToneConcise": "Concise",
"settingsVerbosityLabel": "Reply length",
"settingsVerbosityBrief": "Brief",
"settingsVerbosityDefault": "Default",
"settingsVerbosityDetailed": "Detailed",
"settingsSourcesPointer": "Which data clusters the coach may draw on and the default analysis window are managed directly in the coach chat (\"What I draw on\" rail).",
"settingsSourcesPointerLink": "Open the coach",
"settingsExcludeLabel": "Exclude metrics",
"settingsExcludeHint": "The Coach will not see data for selected metrics.",
"settingsContextLabel": "Include context",
"settingsContextHint": "Optional blocks the Coach can lean on. Switch one off and the block is dropped from every turn.",
"settingsEvidenceLabel": "Show evidence by default",
"settingsEvidenceHint": "Open the disclosure under every reply automatically.",
"settingsDefaultWindowLabel": "Default analysis window",
"settingsDefaultWindowHint": "The Coach reads this much history per chat unless you override it from the drawer header.",
"settingsSave": "Save",
"settingsSaved": "Saved.",
"settingsCancel": "Cancel",
"feedbackHelpful": "Helpful",
"feedbackUnhelpful": "Not quite",
"feedbackThanks": "Thanks for the signal.",
"feedbackError": "Could not save feedback",
"dailyLimitTitle": "Daily limit reached",
"dailyLimitBody": "Daily limit reached. The budget refreshes at midnight UTC.",
"providerRateLimitTitle": "Provider rate-limited",
"providerRateLimitBody": "Provider temporarily rate-limited; retry in ~5 min.",
"cluster": {
"cardio": {
"label": "Cardiovascular",
"hint": "BP · pulse · HRV · resting & walking HR"
},
"body": {
"label": "Body composition",
"hint": "Weight · body fat · muscle · BMI"
},
"activity": {
"label": "Activity",
"hint": "Steps · energy · distance · VO₂ max"
},
"workouts": {
"label": "Workouts",
"hint": "Runs · rides · sessions"
},
"sleep": {
"label": "Sleep",
"hint": "Duration · stages"
},
"mood": {
"label": "Mood",
"hint": "Daily mood entries"
},
"glucose": {
"label": "Glucose",
"hint": "Fasting · postprandial readings"
},
"medication": {
"label": "Medication",
"hint": "Adherence · GLP-1 context"
},
"mobility": {
"label": "Mobility & gait",
"hint": "Steadiness · asymmetry · gait"
},
"environment": {
"label": "Environment",
"hint": "Noise · daylight · skin temp"
}
},
"settingsClustersLabel": "Data the Coach sees",
"settingsClustersHint": "Pick which clusters of your data the Coach can read. More data means richer answers and a larger prompt.",
"settingsClusterNoData": "No data yet",
"sourcesMemberCount": "{count} metrics",
"showConversations": "Show conversations",
"hideConversations": "Hide conversations",
"heroGreeting": "Ask me anything about your data",
"heroSubline": "Ask about your trends, medications, or readings.",
"thinkingElapsed": "{seconds}s",
"thinkingDuration": "Thought for {seconds}s",
"thinkingExpandAria": "Show what the Coach considered",
"thinkingDetail": "Answered from your health snapshot.",
"tokensUsed": "{count} tokens",
"tokensUsedWithModel": "{count} tokens · {model}",
"askAboutThis": "Ask the coach about this",
"readStrip": {
"label": "Usual range",
"baselineWithin": "Your usual range is {low}–{high} {unit}; today's {value} sits within it.",
"baselineAbove": "Your usual range is {low}–{high} {unit}; today's {value} sits above it.",
"baselineBelow": "Your usual range is {low}–{high} {unit}; today's {value} sits below it.",
"insufficient": "Still learning your usual range — keep logging for a few more days.",
"driver": "{note}"
},
"scope": {
"prefix": "The Coach is already on {metric}",
"tap": "Tap to ask",
"question": "Walk me through this metric — anything I should watch?"
},
"seeded": {
"prefix": "Worth a look today: {signal}",
"signal": {
"readiness": "readiness",
"recovery": "recovery"
},
"question": {
"readiness": "My readiness is off today — what's driving it?",
"recovery": "My recovery shifted — what's behind it?"
},
"dismiss": "Dismiss"
},
"settings": "Settings",
"history": {
"groupToday": "Today",
"groupYesterday": "Yesterday",
"groupThisWeek": "This week",
"groupEarlier": "Earlier"
},
"seed": {
"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?",
"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.",
"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?",
"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.",
"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?",
"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?",
"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?"
},
"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.",
"pickerSearchPlaceholder": "Search documents…",
"pickerEmpty": "No documents in your vault yet.",
"pickerNotIndexed": "Not yet indexed",
"pickerCap": "You can attach up to {max} more.",
"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.",
"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."
}
},
"relativeJustNow": "just now",
"relativeMinutesAgoOne": "{count} minute ago",
"relativeMinutesAgoOther": "{count} minutes ago",
"relativeMinutesAgoFew": "{count} minutes ago",
"relativeHoursAgoOne": "{count} hour ago",
"relativeHoursAgoOther": "{count} hours ago",
"relativeHoursAgoFew": "{count} hours ago",
"relativeDaysAgoOne": "{count} day ago",
"relativeDaysAgoOther": "{count} days ago",
"relativeDaysAgoFew": "{count} days ago",
"navOverview": "Overview",
"navCatalog": "All metrics",
"navBloodPressure": "Blood Pressure",
"navWeight": "Weight",
"navPulse": "Pulse",
"navMood": "Mood",
"navMedication": "Medication",
"navNutrients": "Nutrients",
"navBmi": "BMI",
"navSleep": "Sleep",
"navHrv": "HRV",
"navRestingHr": "Resting HR",
"navOxygenSaturation": "Oxygen",
"navBodyTemperature": "Temperature",
"navSteps": "Steps",
"navActiveEnergy": "Active energy",
"navAriaLabel": "Skip to section",
"pillScrollLeft": "Scroll tabs left",
"pillScrollRight": "Scroll tabs right",
"tabStrip": {
"vitalsParent": {
"label": "Vitals",
"header": "Vital signs"
},
"bodyParent": {
"label": "Body",
"header": "Body composition"
},
"activityParent": {
"label": "Activity",
"header": "Activity & mobility"
},
"heartParent": {
"label": "Heart",
"header": "Heart health"
},
"hearingParent": {
"label": "Hearing",
"header": "Hearing & audio exposure"
},
"environmentParent": {
"label": "Environment",
"header": "Environment"
},
"metabolicParent": {
"label": "Metabolic",
"header": "Metabolic"
}
},
"hrv": {
"title": "HRV",
"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",
"description": "HRV samples land here once Apple Watch (or a compatible Withings device) starts syncing nightly readings."
}
},
"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.",
"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?"
},
"oxygenSaturation": {
"title": "Oxygen saturation",
"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",
"description": "SpO₂ samples land here once a compatible wearable (Apple Watch, Withings ScanWatch) captures a reading."
}
},
"bodyTemperature": {
"title": "Body temperature",
"description": "Core body temperature trend — Celsius. Skin-temperature readings from Withings live on a separate metric.",
"chartTitle": "Body temperature",
"emptyState": {
"title": "No body temperature yet",
"description": "Log a body-temperature reading or let your wearable sync one, and the trend will appear here.",
"cta": "Log body temperature"
}
},
"steps": {
"title": "Steps",
"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",
"description": "Daily step totals appear here once Apple Health or an activity device syncs a day's worth of movement."
}
},
"activeEnergy": {
"title": "Active energy",
"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",
"description": "Active-energy totals land here once Apple Health or a Withings activity device syncs a day's worth of movement."
}
},
"subPage": {
"loadError": "Could not load this metric right now.",
"blutdruckDescription": "Your systolic / diastolic trend with age-personalised target zones and a written assessment.",
"gewichtDescription": "Weight trend mapped against your height-derived healthy band, plus a written assessment.",
"pulsDescription": "Pulse trend against the personalised Karvonen target band, plus a written assessment.",
"stimmungDescription": "Daily mood scores over time with a written assessment.",
"stimmungEmptyTitle": "Log your first mood",
"stimmungEmptyDescription": "Mood insights light up once you've logged a few entries. Tap below to get started.",
"stimmungEmptyAction": "Open mood journal",
"medikamenteDescription": "Per-medication adherence calendars and a written assessment.",
"medikamenteEmptyTitle": "Add your first medication",
"medikamenteEmptyDescription": "Adherence insights need at least one tracked medication.",
"medikamenteEmptyAction": "Open medications",
"bmiDescription": "BMI derived from your weight and height, with a written assessment.",
"target": {
"adjustLink": "Adjust target range"
},
"explainer": {
"trigger": "What is {title}?",
"bloodPressureTitle": "Blood pressure",
"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. As general guidance, European guidance (ESH 2023) calls under 120/80 optimal and 140/90 or above hypertension; US guidance (ACC/AHA 2017) sets a stricter line, labelling 130–139/80–89 as Stage 1. Categorise from a calm seated reading, never a single number.",
"pulseTitle": "Pulse",
"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.",
"weightTitle": "Weight",
"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.",
"bmiTitle": "Body mass index (BMI)",
"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.",
"sleepTitle": "Sleep",
"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.",
"moodTitle": "Mood",
"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.",
"medicationsTitle": "Medication adherence",
"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.",
"restingHrTitle": "Resting heart rate",
"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.",
"hrvTitle": "Heart rate variability (HRV)",
"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.",
"oxygenSaturationTitle": "Oxygen saturation (SpO₂)",
"oxygenSaturationBody": "SpO₂ is the percentage of your red blood cells carrying oxygen. As general guidance, readings of 95–100% are normal at rest (StatPearls/NIH 2023); values that stay below 90% warrant attention, though brief nightly dips are common and above ~98% adds no benefit. Optical readers can over-read true saturation in people with darker skin (US FDA 2024), so a single near-normal reading is not a clearance — retake when warm and still if concerned.",
"bodyTemperatureTitle": "Body temperature",
"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.",
"activeEnergyTitle": "Active energy",
"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.",
"workoutsTitle": "Workouts",
"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.",
"respiratoryRateTitle": "Respiratory rate",
"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.",
"bodyWaterTitle": "Total body water",
"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.",
"boneMassTitle": "Bone mass",
"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.",
"fatFreeMassTitle": "Fat-free mass",
"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.",
"fatMassTitle": "Fat mass",
"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).",
"muscleMassTitle": "Muscle mass",
"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.",
"visceralFatTitle": "Visceral fat",
"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 (AHA, Circulation 2021), so lower is generally better. The scale shows a unitless rating (about 1–12 is the healthy range, 13 and up elevated); this is a separate scale from the imaging cm² thresholds clinicians use and is not interchangeable with them.",
"leanBodyMassTitle": "Lean body mass",
"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.",
"flightsClimbedTitle": "Flights climbed",
"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.",
"walkingDistanceTitle": "Walking + running distance",
"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.",
"walkingSteadinessTitle": "Walking steadiness",
"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.",
"walkingHeartRateTitle": "Walking heart rate",
"walkingHeartRateBody": "Walking heart rate is your average pulse during a steady walk. A lower walking rate over time often reflects improving cardiovascular fitness for the same effort.",
"walkingAsymmetryTitle": "Walking asymmetry",
"walkingAsymmetryBody": "Walking asymmetry is the share of time your steps are uneven between the left and right leg. A higher percentage can point to pain, injury, or a gait problem worth looking into.",
"doubleSupportTimeTitle": "Double support time",
"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.",
"stepLengthTitle": "Step length",
"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.",
"walkingSpeedTitle": "Walking speed",
"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.",
"pulseWaveVelocityTitle": "Pulse wave velocity",
"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.",
"vascularAgeTitle": "Vascular age",
"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.",
"environmentalAudioTitle": "Environmental sound levels",
"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.",
"headphoneAudioTitle": "Headphone audio levels",
"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.",
"audioEventsTitle": "Loud sound events",
"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.",
"daylightTitle": "Time in daylight",
"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.",
"bloodGlucoseTitle": "Blood glucose",
"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 100 mg/dL is normal, 100–125 is prediabetes, and 126 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.",
"skinTemperatureTitle": "Skin temperature",
"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.",
"cardioFitnessTitle": "Cardio fitness (VO₂ max)",
"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. As general guidance, fitness is a graded predictor of survival: each one-MET (about 3.5 mL/kg/min) higher value associates with roughly 10–25% lower mortality (AHA, Circulation 2016). A higher or rising trend is a strong sign of cardiovascular health.",
"cardioRecoveryTitle": "Cardio recovery",
"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.",
"wristTemperatureTitle": "Wrist temperature",
"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.",
"fallsTitle": "Falls",
"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).",
"sixMinuteWalkTitle": "Six-minute walk distance",
"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.",
"stairAscentSpeedTitle": "Stair ascent speed",
"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.",
"stairDescentSpeedTitle": "Stair descent speed",
"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.",
"breathingDisturbancesTitle": "Sleep breathing disturbances",
"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.",
"stepsTitle": "Steps",
"stepsBody": "Step count is the total number of steps you take each day. It is the simplest measure of everyday movement, and a steady habit matters more than any single big day. As general guidance, mortality risk falls steeply toward about 8,000 steps a day with continued benefit through roughly 12,000 (Saint-Maurice JAMA 2020); the optimal count is lower for older adults. The '10,000' figure 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, sleep, and how steady your recent nights have been. It is a device proxy benchmarked against your own baseline, not a clinical measure, and scores are not comparable across devices. A higher score means recovered and resourced; 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.",
"recoveryPageTitle": "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.",
"pulsePressureTitle": "Pulse pressure",
"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.",
"meanArterialPressureTitle": "Mean arterial pressure",
"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.",
"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.",
"referenceGuidance": "General guidance, not medical advice. Reference ranges are population anchors that shift with your age, sex and health conditions — your own trend over time leads the read."
},
"bpDerived": {
"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."
},
"stats": {
"label": "Summary statistics",
"min": "Min",
"max": "Max",
"median": "Median",
"mean": "Mean"
},
"showAllValues": "Show all readings",
"valuesPageTitle": "{metric} — all readings",
"valuesPageDescription": "Every reading behind this metric. Edit or remove an entry directly.",
"diversity": {
"trigger": "Measurement tip",
"weekday": "Most of your {metric} readings land on one weekday. Logging on other days gives a fuller picture.",
"timeOfDay": "Most of your {metric} readings land at a similar time of day. Varying the time gives a fuller picture."
},
"valuesBack": "Back to insights",
"valuesBackToMetric": "Back to {metric}",
"scoresBack": "Back to insights",
"ecgDescription": "Single-lead ECG recordings from your device, each with the device's own result. HealthLog shows the trace and the recording — it does not interpret the waveform."
},
"sleep": {
"title": "Sleep",
"description": "Stage breakdown and nightly duration, drawn from Apple Health.",
"headlineTitle": "Average per night",
"compositionTitle": "Stage composition",
"compositionSubtitle": "Last {nights} nights",
"compositionAriaLabel": "Sleep stage composition over {nights} nights",
"hypnogram": {
"title": "Last night",
"subtitle": "{asleep} asleep",
"ariaLabel": "Sleep stage progression for last night: {asleep} asleep, {awakenings} awakenings",
"asleepTotal": "Asleep {value}",
"inBedTotal": "In bed {value}",
"awakenings": "{count} awakenings",
"source": "Source: {source}",
"estimateNote": "Stage timing is estimated — this source reports totals per stage, not a measured timeline."
},
"sourceDiscrepancy": {
"tooltipTitle": "Sources disagree"
},
"stages": {
"deep": "Deep",
"rem": "REM",
"core": "Core",
"asleep": "Asleep",
"awake": "Awake",
"inBed": "In bed",
"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.",
"action": "Manage devices"
},
"debt": {
"title": "Sleep debt",
"value": "{hours}h {minutes}m short",
"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.",
"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."
},
"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.",
"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.",
"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.",
"band": {
"extreme_early": "Strong morning type",
"early": "Morning type",
"intermediate": "Intermediate type",
"late": "Evening type",
"extreme_late": "Strong evening type"
},
"midpointHeadline": "Your natural sleep midpoint is around {clock}."
},
"rhythm": {
"loadError": "Your sleep rhythm couldn't load just now. It'll reappear once the connection settles."
}
},
"correlations": "Correlations",
"medicationCompliance": "Medication adherence",
"dayStreak": "{count} day streak",
"dayStreakOne": "{count} day streak",
"compliance7d": "Adherence (7 days)",
"compliance30d": "Adherence (30 days)",
"taken": "taken",
"skipped": "skipped",
"missed": "missed",
"generalStatusBadge": {
"good": "Good",
"watch": "Watch",
"critical": "Critical"
},
"assessmentTitle": "Assessment",
"restMode": {
"title": "Rest Mode",
"body": "An illness or condition episode is active, so this reflects a recovery window. Your score isn't lowered for it.",
"bodySince": "An illness or condition episode has been active since {since}, so this reflects a recovery window. Your score isn't lowered for it."
},
"assessmentShowMore": "Show more",
"assessmentShowLess": "Show less",
"bloodPressureSectionTitle": "Blood Pressure",
"weightSectionTitle": "Weight",
"pulseSectionTitle": "Pulse",
"bmiSectionTitle": "BMI",
"complianceNoData": "No adherence data available.",
"generate": "Generate new analysis",
"moodSectionTitle": "Mood",
"confidence": "Confidence",
"cached": "Cached",
"emptyState": {
"bloodPressure": {
"title": "No blood pressure entries yet",
"description": "Log a blood pressure reading and the trend chart, in-range share, and WHO classification will appear here.",
"cta": "Log blood pressure"
},
"weight": {
"title": "No weight entries yet",
"description": "Log a weight and the trend, moving average, and target band will appear automatically.",
"cta": "Log weight"
},
"pulse": {
"title": "No pulse entries yet",
"description": "Log a pulse reading and resting pulse, HRV and VO₂ max will appear in this view.",
"cta": "Log pulse"
},
"bmi": {
"title": "BMI not yet computed",
"description": "Once height and at least one weight entry are present, the BMI trend with WHO zones will appear here.",
"cta": "Log weight"
},
"mood": {
"title": "No mood entries yet",
"description": "Log a mood entry and the trend, stability band and correlations will appear.",
"cta": "Log mood"
},
"medication": {
"title": "No medications set up yet",
"description": "Set up a medication and adherence, drug level and titration timeline will appear here.",
"cta": "Add medication"
},
"sleep": {
"title": "No sleep entries yet",
"description": "Once sleep data lands (manual or via Withings / Apple Health), the per-night stage breakdown will appear here.",
"cta": "Connect a source"
}
},
"navWorkouts": "Workouts",
"navRecovery": "Recovery",
"workouts": {
"title": "Workouts",
"askWhy": "Ask why",
"askWhyPrompt": "Why did this session read the way it did? Walk me through my own numbers from it.",
"description": "Recent runs, rides, walks and strength sessions, deduped across Apple Watch and Withings sources.",
"emptyState": {
"title": "No workouts yet",
"description": "Open the Apple Health app on your iPhone to sync workouts here. Withings activity import keeps walking and cycling sessions flowing in too."
},
"row": {
"duration": "Duration",
"distance": "Distance",
"energy": "Active energy"
},
"detail": {
"backToList": "Back to workouts",
"statsTitle": "Stats",
"statsDuration": "Duration",
"statsDistance": "Distance",
"statsActiveEnergy": "Active energy",
"statsAvgHr": "Average HR",
"statsMaxHr": "Max HR",
"statsMinHr": "Min HR",
"statsStepCount": "Steps",
"statsElevation": "Elevation",
"statsPace": "Pace",
"statsSource": "Source",
"routeTitle": "Route",
"routeUnavailable": "No GPS route recorded for this workout.",
"hrChartTitle": "Heart rate",
"hrChartUnavailable": "Per-second heart-rate samples are not stored for this workout.",
"notFound": "Workout not found.",
"loading": "Loading workout…",
"hrFromPulse": "From your heart-rate data around this session",
"hrAxisMinutes": "min",
"sportAverageLabel": "Your recent average:",
"zonesTitle": "Effort zones",
"zonesCaption": "How your effort was distributed across heart-rate zones.",
"zonesCaptionDevice": "Time in zone as reported by your device.",
"exportGpx": "Export GPX",
"elevationTitle": "Elevation",
"splitsTitle": "Splits",
"splitsKm": "km",
"splitsTime": "Time",
"splitsPace": "Pace",
"thatDayTitle": "That day",
"dayPulse": "Pulse",
"daySleep": "Sleep",
"dayMood": "Mood",
"insightTitle": "Activity insight"
},
"sport": {
"walking": "Walking",
"running": "Running",
"cycling": "Cycling",
"hiking": "Hiking",
"swimming": "Swimming",
"rowing": "Rowing",
"elliptical": "Elliptical",
"stairClimber": "Stair climber",
"yoga": "Yoga",
"mindAndBody": "Mind and body",
"strength": "Strength",
"hiit": "HIIT",
"dance": "Dance",
"golf": "Golf",
"tennis": "Tennis",
"basketball": "Basketball",
"soccer": "Soccer",
"crossTraining": "Cross training",
"mixedCardio": "Mixed cardio",
"other": "Other"
},
"loadError": "Your workouts could not be loaded",
"loadMore": "Load more workouts",
"loadingMore": "Loading more workouts",
"loadMoreError": "More workouts could not be loaded"
},
"bloodGlucose": {
"title": "Blood Glucose",
"description": "Your blood-glucose readings over time, in mg/dL.",
"chartTitle": "Blood glucose",
"medianLabel": "Median glucose",
"emptyState": {
"title": "No glucose data yet",
"description": "Blood-glucose readings appear here once you log one or a connected device syncs."
},
"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.",
"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.",
"readingsCount": "{count} readings",
"readingsCountOne": "1 reading",
"daysCount": "{days} days",
"daysCountOne": "1 day",
"tir": {
"title": "Time in range",
"caption": "Share of readings in each band (70–180 mg/dL is the target).",
"veryLow": "Very low",
"low": "Low",
"inRange": "In range",
"high": "High",
"veryHigh": "Very high",
"ariaLabel": "Time in range: {tir}% in target, {below}% below, {above}% above.",
"empty": "No readings to chart yet."
},
"gmi": {
"label": "Glucose Management Indicator",
"help": "An A1C-like estimate derived from your average glucose."
},
"eA1c": {
"label": "Estimated A1C",
"help": "An A1C estimate from your mean glucose (ADAG)."
},
"mean": {
"label": "Average glucose"
},
"cv": {
"label": "Variability",
"steady": "Steady",
"unstable": "Unstable",
"help": "Coefficient of variation. At or above 36% glucose is considered unstable; lower is steadier."
},
"advanced": {
"toggle": "Advanced indices",
"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."
},
"lbgi": {
"label": "Low-glucose risk (LBGI)",
"help": "Kovatchev's index weighting how often and how deeply readings dip low."
},
"hbgi": {
"label": "High-glucose risk (HBGI)",
"help": "Kovatchev's index weighting how often and how high readings climb."
},
"byContext": {
"title": "By context",
"fasting": "Fasting",
"postprandial": "After meals",
"random": "Random",
"bedtime": "Bedtime",
"readingsShort": "{count} readings",
"readingsShortOne": "1 reading"
}
}
}
},
"navBloodGlucose": "Glucose",
"totalBodyWater": {
"title": "Total Body Water",
"description": "Your total body water over time, in kilograms.",
"chartTitle": "Total body water",
"emptyState": {
"title": "No body-water data yet",
"description": "Body-water readings appear here once a connected body-composition scale syncs."
}
},
"navTotalBodyWater": "Body Water",
"boneMass": {
"title": "Bone Mass",
"description": "Your bone mass over time, in kilograms.",
"chartTitle": "Bone mass",
"emptyState": {
"title": "No bone-mass data yet",
"description": "Bone-mass readings appear here once a connected body-composition scale syncs."
}
},
"navBoneMass": "Bone Mass",
"flightsClimbed": {
"title": "Flights Climbed",
"description": "Flights of stairs you climbed each day.",
"chartTitle": "Flights climbed per day",
"emptyState": {
"title": "No flights data yet",
"description": "Flights-climbed totals appear here once Apple Health syncs a day's movement."
}
},
"navFlightsClimbed": "Flights",
"walkingRunningDistance": {
"title": "Walking + Running Distance",
"description": "Walking and running distance you covered each day, in kilometres.",
"chartTitle": "Distance per day",
"emptyState": {
"title": "No distance data yet",
"description": "Daily distance appears here once Apple Health syncs a day's movement."
}
},
"navWalkingRunningDistance": "Distance",
"fatFreeMass": {
"title": "Fat-Free Mass",
"description": "Your fat-free mass over time, in kilograms.",
"chartTitle": "Fat-free mass",
"emptyState": {
"title": "No fat-free-mass data yet",
"description": "Fat-free-mass readings appear here once a connected body-composition scale syncs."
}
},
"navFatFreeMass": "Fat-Free Mass",
"fatMass": {
"title": "Fat Mass",
"description": "Your fat mass over time, in kilograms.",
"chartTitle": "Fat mass",
"emptyState": {
"title": "No fat-mass data yet",
"description": "Fat-mass readings appear here once a connected body-composition scale syncs."
}
},
"navFatMass": "Fat Mass",
"muscleMass": {
"title": "Muscle Mass",
"description": "Your muscle mass over time, in kilograms.",
"chartTitle": "Muscle mass",
"emptyState": {
"title": "No muscle-mass data yet",
"description": "Muscle-mass readings appear here once a connected body-composition scale syncs."
}
},
"navMuscleMass": "Muscle Mass",
"skinTemperature": {
"title": "Skin Temperature",
"description": "Your wrist skin temperature over time, in degrees Celsius.",
"chartTitle": "Skin temperature",
"emptyState": {
"title": "No skin-temperature data yet",
"description": "Skin-temperature readings appear here once a wearable syncs overnight wrist temperature."
}
},
"navSkinTemperature": "Skin Temp",
"pulseWaveVelocity": {
"title": "Pulse Wave Velocity",
"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",
"description": "Pulse-wave-velocity readings appear here once a compatible Withings device syncs."
}
},
"navPulseWaveVelocity": "Pulse Wave Velocity",
"vascularAge": {
"title": "Vascular Age",
"description": "Your estimated vascular age over time, in years.",
"chartTitle": "Vascular age",
"emptyState": {
"title": "No vascular-age data yet",
"description": "Vascular-age estimates appear here once a compatible Withings device syncs."
}
},
"navVascularAge": "Vascular Age",
"visceralFat": {
"title": "Visceral Fat",
"description": "Your visceral-fat rating over time.",
"chartTitle": "Visceral fat",
"emptyState": {
"title": "No visceral-fat data yet",
"description": "Visceral-fat ratings appear here once a compatible body-composition scale syncs."
}
},
"navVisceralFat": "Visceral Fat",
"audioExposureEnv": {
"title": "Environmental Audio",
"description": "Your daily average environmental sound exposure, in dBA.",
"chartTitle": "Environmental sound exposure",
"emptyState": {
"title": "No environmental-audio data yet",
"description": "Environmental sound-level readings appear here once Apple Health syncs."
}
},
"navAudioExposureEnv": "Environmental Audio",
"audioExposureHeadphone": {
"title": "Headphone Audio",
"description": "Your daily average headphone audio exposure, in dBA.",
"chartTitle": "Headphone audio exposure",
"emptyState": {
"title": "No headphone-audio data yet",
"description": "Headphone audio-level readings appear here once Apple Health syncs."
}
},
"navAudioExposureHeadphone": "Headphone Audio",
"timeInDaylight": {
"title": "Time in Daylight",
"description": "Minutes spent in daylight each day.",
"chartTitle": "Time in daylight per day",
"emptyState": {
"title": "No daylight data yet",
"description": "Daylight totals appear here once Apple Health syncs a day's exposure."
}
},
"navTimeInDaylight": "Daylight",
"walkingSteadiness": {
"title": "Walking Steadiness",
"description": "Your walking steadiness over time, as a percentage.",
"chartTitle": "Walking steadiness",
"emptyState": {
"title": "No walking-steadiness data yet",
"description": "Walking-steadiness readings appear here once Apple Health syncs."
}
},
"navWalkingSteadiness": "Walking Steadiness",
"audioExposureEvent": {
"title": "Loud Audio Events",
"description": "Days with a loud-environment exposure event.",
"chartTitle": "Loud-environment events per day",
"emptyState": {
"title": "No loud-event data yet",
"description": "Loud-environment events appear here once Apple Health syncs."
}
},
"navAudioExposureEvent": "Loud Events",
"respiratoryRate": {
"title": "Respiratory Rate",
"description": "Your respiratory rate over time, in breaths per minute.",
"chartTitle": "Respiratory rate",
"emptyState": {
"title": "No respiratory-rate data yet",
"description": "Respiratory-rate readings appear here once Apple Health syncs sleep or workout breathing."
}
},
"navRespiratoryRate": "Respiratory Rate",
"leanBodyMass": {
"title": "Lean Body Mass",
"description": "Your lean body mass over time, in kilograms.",
"chartTitle": "Lean body mass",
"emptyState": {
"title": "No lean-body-mass data yet",
"description": "Lean-body-mass readings appear here once a connected body-composition scale syncs."
}
},
"navLeanBodyMass": "Lean Body Mass",
"walkingHeartRateAverage": {
"title": "Walking Heart Rate",
"description": "Your average heart rate while walking, in bpm.",
"chartTitle": "Walking heart rate average",
"emptyState": {
"title": "No walking-heart-rate data yet",
"description": "Walking-heart-rate readings appear here once Apple Health syncs."
}
},
"navWalkingHeartRateAverage": "Walking Heart Rate",
"walkingAsymmetry": {
"title": "Walking Asymmetry",
"description": "Your walking asymmetry over time, as a percentage.",
"chartTitle": "Walking asymmetry",
"emptyState": {
"title": "No walking-asymmetry data yet",
"description": "Walking-asymmetry readings appear here once Apple Health syncs."
}
},
"navWalkingAsymmetry": "Walking Asymmetry",
"walkingDoubleSupport": {
"title": "Double Support Time",
"description": "The percentage of each stride spent with both feet on the ground.",
"chartTitle": "Double support time",
"emptyState": {
"title": "No double-support data yet",
"description": "Double-support readings appear here once Apple Health syncs."
}
},
"navWalkingDoubleSupport": "Double Support",
"walkingStepLength": {
"title": "Walking Step Length",
"description": "Your average walking step length over time, in metres.",
"chartTitle": "Step length",
"emptyState": {
"title": "No step-length data yet",
"description": "Step-length readings appear here once Apple Health syncs."
}
},
"navWalkingStepLength": "Step Length",
"walkingSpeed": {
"title": "Walking Speed",
"description": "Your average walking speed over time, in km/h.",
"chartTitle": "Walking speed (km/h)",
"emptyState": {
"title": "No walking-speed data yet",
"description": "Walking-speed readings appear here once Apple Health syncs."
}
},
"navWalkingSpeed": "Walking Speed",
"mood": {
"logLink": "Log a mood entry",
"mentalWellbeingLink": "Take a mental-wellbeing check-in",
"heatmapTitle": "Mood calendar",
"heatmapNoEntry": "No entry",
"legendGreat": "Great",
"legendGood": "Good",
"legendOkay": "Okay",
"legendLow": "Low",
"distributionTitle": "Mood distribution",
"distributionDaysUnit": "days",
"weekdayTitle": "Average by weekday",
"weekdayNoData": "No data",
"weekdayBestWorst": "Best day: {best} · Toughest day: {worst}",
"tagsTitle": "Tags and triggers",
"tagAvgMood": "Average mood when tagged",
"correlationsTitle": "Mood and other metrics",
"correlationsDescription": "How your mood moves with sleep, activity, and pulse on the same day.",
"correlation": {
"sleepTitle": "Mood vs. sleep",
"stepsTitle": "Mood vs. activity",
"pulseTitle": "Mood vs. pulse",
"sleepAxis": "Sleep (min)",
"stepsAxis": "Steps",
"pulseAxis": "Pulse (bpm)",
"strengthStrong": "Strong",
"strengthModerate": "Moderate",
"strengthWeak": "Weak",
"strengthNone": "None",
"source": "{n} paired days · r = {r}",
"sourceLabel": "How this was computed",
"emptyTitle": "Not enough paired data yet",
"emptyDescription": "Log mood and this metric on the same days to see a correlation.",
"weightTitle": "Mood vs. weight",
"bloodPressureTitle": "Mood vs. blood pressure",
"weightAxis": "Weight",
"bloodPressureAxis": "Systolic (mmHg)"
},
"structuredTagsTitle": "Tag breakdown",
"inTargetValue": "{pct}%",
"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.",
"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).",
"weekendUp": "You feel better on weekends (+{delta} vs weekdays).",
"weekendDown": "Your mood runs lower on weekends (-{delta} vs weekdays).",
"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.",
"timeOfDay": "You feel best in the {bucket}, averaging {value}."
},
"timeOfDay": {
"title": "Mood by time of day",
"morning": "Morning",
"afternoon": "Afternoon",
"evening": "Evening",
"night": "Night",
"bestCaption": "You tend to feel best in the {bucket}."
},
"stability": {
"value": "{score}/100",
"bandVerySteady": "Your mood has been very steady",
"bandSteady": "Your mood has been fairly steady",
"bandVariable": "Your mood has been noticeably variable",
"bandVeryVariable": "Your mood has swung a lot lately",
"title": "Stability"
},
"influence": {
"title": "Influence on mood",
"detail": "Averages {withAvg} on the {withDays} days you tagged this vs {withoutAvg} without it.",
"confidenceLow": "Low confidence",
"confidenceMedium": "Medium confidence",
"confidenceHigh": "High confidence"
},
"betterDays": {
"title": "What goes with your better days",
"description": "Tags and metrics that line up with your higher- and lower-mood days, ranked by how strongly they move together."
},
"crosstab": {
"title": "Tags and your health metrics",
"description": "How a health metric differs on the days you tagged each activity, compared with the days you did not.",
"pairLabel": "{tag} · {metric}",
"metricActiveEnergy": "Active energy",
"metricSleepDuration": "Sleep",
"metricNextDayRecovery": "Next-day recovery",
"unitHours": "h",
"unitKcal": "kcal",
"unitScore": "pts",
"detailSameDay": "Averages {withAvg} {unit} on the {withDays} days you tagged this vs {withoutAvg} {unit} without it.",
"detailNextDay": "Averages {withAvg} {unit} the day after the {withDays} days you tagged this vs {withoutAvg} {unit} otherwise."
},
"factorCrosstab": {
"title": "Your rated factors and your vitals",
"description": "How a vital differs on the days you rated each factor low compared with the days you rated it high.",
"pairLabel": "{factor} · {metric}",
"metricSleepDuration": "Sleep",
"metricSteps": "Steps",
"metricRestingHeartRate": "Resting heart rate",
"metricHrv": "Heart-rate variability",
"metricWeight": "Weight",
"metricBloodPressureSys": "Systolic",
"unitHours": "h",
"unitScore": "pts",
"unitSteps": "steps",
"unitBpm": "bpm",
"unitMs": "ms",
"unitKg": "kg",
"unitMmHg": "mmHg",
"detail": "Averages {lowAvg} {unit} on the {lowDays} days you rated {factor} low vs {highAvg} {unit} on the days you rated it high.",
"detailInverse": "Averages {lowAvg} {unit} on your {lowDays} worse {factor} days vs {highAvg} {unit} on your better ones."
},
"discovery": {
"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.",
"empty": "No mood relationships cleared the statistical bar yet. Keep logging.",
"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.",
"outcomeDown": "Higher mood tends to go with lower next-day {factor} in your data.",
"stat": "{n} paired days · r = {r} · q = {q}",
"statLabel": "How this was computed",
"explainerLabel": "How this was computed"
},
"inTargetTitle": "In your range"
},
"derived": {
"coverage": {
"summary": "{present} of {required} inputs · {percent}%",
"ratioLabel": "{present}/{required}",
"historyDays": "Based on {count} days of history",
"missing": "Track these to sharpen this: {list}"
},
"scoreRing": {
"aria": "Score {score} out of 100, {band}",
"ariaProvisional": "Score not available yet — not enough data",
"provisionalCaption": "Not enough data yet",
"band": {
"green": "good",
"yellow": "fair",
"red": "low"
}
},
"provenance": {
"title": "How this is computed",
"trigger": "How this is computed",
"inputsLabel": "Inputs",
"noInputs": "No inputs backed this value yet.",
"methodLabel": "Method",
"window": "From your last {days} days · {source} data",
"asOf": "as of {date}",
"standardLink": "Standard: {name}"
},
"vitals": {
"sectionTitle": "Your vitals",
"sectionSubtitle": "Resting cardiovascular and respiratory signals against your own baseline",
"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",
"typicalRange": "Typical for you: {low}–{high}",
"fitnessYounger": "Cardio fitness of someone ~{years} yr younger",
"fitnessOlder": "Cardio fitness ~{years} yr above your age",
"fitnessTypical": "Cardio fitness typical for your age",
"fitnessNoNorm": "Add your age and sex to frame this",
"vascularBelow": "{years} yr below your age",
"vascularAbove": "{years} yr above your age",
"vascularMatch": "In line with your age",
"vascularNoAge": "Add your date of birth to frame this",
"hrvBand": {
"balanced": "Balanced for you",
"unbalanced": "Above your usual range",
"low": "Below your usual range"
},
"bmiCategory": {
"underweight": "Underweight (WHO)",
"normal": "Normal range (WHO)",
"overweight": "Overweight (WHO)",
"obese": "Obese (WHO)"
},
"sixMinuteBand": {
"green": "{percent}% of predicted for your profile",
"yellow": "{percent}% of predicted for your profile",
"red": "{percent}% of predicted for your profile"
},
"sixMinuteNoBand": "Add your age, height, weight and sex to frame this",
"mobilitySectionTitle": "Mobility & body"
},
"anatomy": {
"outOf": "/100",
"contributorsLabel": "Contributors",
"contributorValue": "{value} · {weight}% weight",
"contributorMissing": "no data",
"disclaimer": "Indicative — not a clinical assessment.",
"insufficient": "Not enough data yet to score this. Keep tracking and it will appear here."
},
"composite": {
"SLEEP_SCORE": {
"title": "Sleep score",
"description": "A transparent sleep-quality score with every sub-score shown.",
"method": "A 0–100 blend of sufficiency (asleep vs your age-based need), efficiency (asleep ÷ in-bed), consistency (how steady your sleep midpoint is), timing (vs your habitual midpoint) and composition (REM + deep share). Sub-scores reweight around any that your data cannot support; nothing is fabricated.",
"sub": {
"sufficiency": "Sufficiency",
"efficiency": "Efficiency",
"consistency": "Consistency",
"timing": "Timing",
"composition": "Composition"
}
},
"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.",
"component": {
"rhr": "Resting heart rate",
"hrv": "HRV (SDNN)",
"sleep": "Sleep",
"respiratory": "Respiratory rate",
"mood": "Mood stability"
},
"caveat": "A wellness proxy, not a recovery or clinical score."
},
"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."
},
"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."
},
"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."
},
"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.",
"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."
},
"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.",
"caveat": "A descriptive wellness proxy, not a training-grade or clinical recovery measure.",
"description": "A nightly recovery proxy from your HRV, resting heart rate and sleep."
},
"STRESS_SCORE": {
"method": "A nightly 0–100 stress proxy from the shape of your intra-day HRV against your baseline. Higher means more physiological load.",
"caveat": "An HRV-derived proxy, NOT an EDA / galvanic-skin stress measurement — your watch has no EDA sensor. Descriptive, not clinical.",
"description": "A nightly stress proxy from the shape of your intra-day HRV."
},
"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.",
"anchorPopulation": "Scored against a general reference while you build training history; once you have enough it switches to your own typical effort.",
"caveat": "A descriptive activity-load proxy, not a clinical or training-grade load measure.",
"description": "A nightly activity-load proxy from your heart-rate-weighted effort, relative to your typical effort."
},
"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."
},
"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."
},
"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."
},
"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."
},
"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."
}
},
"scores": {
"sectionTitle": "Your health scores",
"sectionSubtitle": "Composite recovery, stress and strain read from your connected devices",
"loadError": "Could not load your wellness scores right now.",
"loadingLabel": "Loading your health scores",
"recovery": "Recovery score",
"recoveryCrossLink": "See your wearable's recovery & strain data",
"stress": "Stress",
"strain": "Strain"
},
"coincident": {
"label": "Several vitals off baseline",
"summary": "{count} of your vitals sat outside their personal range today.",
"vitals": "Outside range: {list}",
"cardTitle": "Signals of the day",
"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.",
"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.",
"illnessExplained": "These shifts likely reflect the condition you logged."
},
"trajectory": {
"cardTitle": "Short-horizon projection",
"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.",
"daysNeeded": "About {count} more days of tracking needed before a projection can appear."
}
},
"cardioFitness": {
"title": "Cardio 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",
"description": "VO₂ max readings appear here once Apple Health syncs from your workouts."
}
},
"navCardioFitness": "Cardio Fitness",
"cardioRecovery": {
"title": "Cardio Recovery",
"description": "How far your heart rate drops one minute after peak exercise.",
"chartTitle": "Cardio recovery (bpm)",
"emptyState": {
"title": "No cardio-recovery data yet",
"description": "Cardio-recovery readings appear here once Apple Health syncs from a workout."
}
},
"navCardioRecovery": "Cardio Recovery",
"wristTemperature": {
"title": "Wrist Temperature",
"description": "Your overnight wrist temperature, tracked against your own baseline.",
"chartTitle": "Wrist temperature (°C)",
"emptyState": {
"title": "No wrist-temperature data yet",
"description": "Wrist-temperature readings appear here once Apple Health syncs overnight wear."
}
},
"navWristTemperature": "Wrist Temp",
"falls": {
"title": "Falls",
"description": "Hard falls your Apple Watch detected, counted per day.",
"chartTitle": "Falls per day",
"emptyState": {
"title": "No fall data yet",
"description": "Detected falls appear here once Apple Health syncs. No falls is the goal."
}
},
"navFalls": "Falls",
"sixMinuteWalk": {
"title": "Six-Minute Walk",
"description": "Apple's estimate of how far you could walk in six minutes.",
"chartTitle": "Six-minute walk distance (m)",
"emptyState": {
"title": "No six-minute-walk data yet",
"description": "Six-minute-walk estimates appear here once Apple Health syncs."
}
},
"navSixMinuteWalk": "6-Min Walk",
"stairAscentSpeed": {
"title": "Stair Ascent Speed",
"description": "How fast you climb stairs, measured by your iPhone or Watch.",
"chartTitle": "Stair ascent speed (m/s)",
"emptyState": {
"title": "No stair-ascent-speed data yet",
"description": "Stair-ascent-speed readings appear here once Apple Health syncs."
}
},
"navStairAscentSpeed": "Stair Ascent",
"stairDescentSpeed": {
"title": "Stair Descent Speed",
"description": "How fast you go down stairs, measured by your iPhone or Watch.",
"chartTitle": "Stair descent speed (m/s)",
"emptyState": {
"title": "No stair-descent-speed data yet",
"description": "Stair-descent-speed readings appear here once Apple Health syncs."
}
},
"navStairDescentSpeed": "Stair Descent",
"breathingDisturbances": {
"title": "Breathing Disturbances",
"description": "How often your breathing was disturbed during sleep.",
"chartTitle": "Sleep breathing disturbances",
"emptyState": {
"title": "No breathing-disturbance data yet",
"description": "Sleep-breathing readings appear here once Apple Health syncs from a supported Apple Watch."
}
},
"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.",
"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": {
"irregularRhythm": "Irregular rhythm notification",
"highHeartRate": "High heart rate notification",
"lowHeartRate": "Low heart rate notification",
"walkingSteadiness": "Walking steadiness alert",
"breathingDisturbance": "Breathing disturbance during sleep"
},
"verdict": {
"irregular": "Your device flagged a possible irregular rhythm.",
"notDetected": "Your device did not flag an irregular rhythm.",
"inconclusive": "Your device could not make a reading.",
"low": "Your device flagged low walking steadiness.",
"veryLow": "Your device flagged very low walking steadiness.",
"fired": "Your device flagged this event."
}
},
"trendDescriptor": {
"rising": "Rising over 30 days ({delta}{unit}).",
"falling": "Falling over 30 days ({delta}{unit}).",
"stable": "Stable over the last 30 days.",
"moodImproved": "Mood trended slightly higher over 30 days.",
"moodDeclined": "Mood trended slightly lower over 30 days.",
"moodStable": "Mood held steady over the last 30 days."
},
"target": {
"heading": "Target"
},
"settings": {
"overviewTitle": "Arrange the overview",
"overviewDescription": "Show or hide sections and set their order on the Insights overview."
},
"pillOrder": {
"title": "Sort the navigation pills",
"description": "Drag the pills into the order you want and show or hide them via the eye icon. Hidden detail pages are also removed from the top navigation.",
"dragHandle": "Reorder",
"saveSuccess": "Pill order saved.",
"saveError": "Saving the pill order failed.",
"save": "Save",
"empty": "No navigation pills available yet."
},
"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.",
"deviceScore": {
"learning": "Still learning your baseline — a few more nights will fill in the trend.",
"average": "30-day average {value}",
"unitScore": "score",
"unitMinutes": "min",
"unitBpm": "bpm",
"unitKj": "kJ"
},
"sleepQuality": {
"title": "Sleep quality",
"subtitle": "Nightly scores from your wearable"
},
"recovery": {
"title": "Recovery",
"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.",
"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.",
"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.",
"energyExpenditureKjExplainer": "The energy your body expended over the day, in kilojoules, as your device reports it natively."
}
},
"bodyTempDeviation": {
"title": "Body temperature deviation",
"subtitle": "Overnight delta from your baseline"
},
"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.",
"band": {
"limited": "Limited",
"adequate": "Adequate",
"solid": "Solid",
"strong": "Strong",
"exceptional": "Exceptional"
},
"trend": {
"above": "Above your recent average.",
"steady": "In line with your recent average.",
"below": "Below your recent average."
}
},
"briefing": {
"memory": {
"recall": "Earlier, {text}",
"forward": "Looking ahead: {text}",
"forwardWatch": "Worth keeping an eye on {metric}.",
"forwardHolding": "Everything's holding steady for now."
}
},
"tension": {
"label": "Honest read: {positive} looks good, but {negative} is off — the composite lands {band}.",
"contributor": {
"green": "green",
"yellow": "yellow",
"red": "red"
}
},
"streak": {
"returnLabel": "Your {metric} has been back inside your usual range for {count} days now — whatever that was, it's passed.",
"daysInside": "{count} days inside",
"daysOutside": "{count} days outside"
},
"updatedTodayAt": "Updated today, {time}",
"updatedYesterday": "Updated yesterday",
"updatedOn": "Updated on {date}",
"healthStatus": {
"sectionTitle": "What's changed",
"subtitle": "Signals drifting from your usual range.",
"deviationAbove": "{vital} is above your typical range.",
"deviationBelow": "{vital} is below your typical range.",
"shiftUp": "{vital} has shifted up from your recent normal.",
"shiftDown": "{vital} has shifted down from your recent normal.",
"rangeContext": "Now {value}, usually {low}–{high}.",
"shiftContext": "Around {before} before, {after} since."
},
"breathingScreening": {
"sectionTitle": "Breathing during sleep",
"subtitle": "A screening signal from your sleep data.",
"classificationElevated": "Your device flagged elevated breathing disturbances.",
"classificationNotElevated": "Your device's classification is not elevated.",
"trendUp": "Trending higher than your earlier nights.",
"trendDown": "Trending lower than your earlier nights.",
"trendStable": "Holding steady against your earlier nights.",
"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."
},
"labsChanges": {
"sectionTitle": "Since your last panel",
"subtitle": "How your latest results compare with the panel before.",
"statusInRange": "in range",
"statusBelow": "below range",
"statusAbove": "above range",
"directionFlat": "no change"
},
"navGripStrength": "Grip strength",
"navPainNrs": "Pain",
"navWaistCircumference": "Waist",
"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.",
"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.",
"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?"
},
"pain": {
"title": "Pain (0–10)",
"description": "Patient-reported pain intensity on the 0–10 numeric rating scale, where 0 is no pain and 10 is the worst imaginable. A sustained 2-point change is the signal to watch.",
"chartTitle": "Pain (0–10)",
"emptyState": {
"title": "No pain scores yet",
"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?"
},
"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.",
"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?"
},
"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.",
"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?"
},
"ecg": {
"sectionTitle": "ECG recordings",
"sectionIntro": "Single-lead ECG strips recorded by your device. HealthLog only shows the recording and the result your device produced — it does not read or interpret the waveform.",
"loadError": "Could not load your ECG recordings.",
"backToList": "Back to recordings",
"disclaimer": "This is the result your recording device produced. HealthLog does not read or interpret ECG recordings and does not provide a diagnosis.",
"clinicianNote": "If this result concerns you, discuss this recording with a clinician.",
"resultAttribution": "Recorded result: {result}, as reported by the recording device.",
"result": {
"irregular": "Atrial fibrillation detected",
"notDetected": "No signs of atrial fibrillation",
"inconclusive": "Inconclusive recording",
"none": "No result reported"
},
"meta": {
"recorded": "Recorded",
"duration": "Duration",
"lead": "Lead",
"averageHeartRate": "Average heart rate",
"samplingRate": "Sampling rate",
"leadSingle": "Single lead (Lead I)",
"durationValue": "{seconds} s",
"bpmValue": "{bpm} bpm",
"hzValue": "{hz} Hz",
"unknown": "—"
},
"waveform": {
"ariaLabel": "ECG strip recorded {date}, duration {duration}, average heart rate {heartRate}, recorded result: {result}."
},
"crossLink": {
"title": "ECG recordings",
"recordingsOne": "1 recording on file.",
"recordingsMany": "{count} recordings on file.",
"latestResult": "Latest device result: {result}.",
"cta": "View recordings"
},
"emptyTitle": "No ECG recordings yet",
"emptyDescription": "ECG recordings sync from a compatible single-lead device. Once your device uploads a recording, it appears here.",
"emptyCta": "Connect a device"
},
"intradayPulse": {
"title": "Your day's shape",
"caption": "Your heart rate through the day, averaged in 10-minute steps.",
"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.",
"baseline": "Resting",
"today": "Today",
"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."
}
},
"navEcg": "ECG"
},
"thresholds": {
"defaultLabel": "Default",
"overrideToggleLabel": "Custom range",
"resetAction": "Reset to default",
"resetAllAction": "Reset all to default",
"minLabel": "Min",
"maxLabel": "Max",
"unitSuffix": "({unit})",
"outOfBoundsHint": "Allowed range: {min}–{max} {unit}",
"overrideWarning": "Overriding with values outside guideline ranges may produce unhealthy targets. Only do this on doctor's advice.",
"saveSuccess": "Thresholds updated",
"saveError": "Could not save thresholds",
"resetSuccess": "Reset to default",
"sourceOverride": "User override",
"metricWeight": "Weight",
"metricBpSys": "Blood pressure (systolic)",
"metricBpDia": "Blood pressure (diastolic)",
"metricPulse": "Resting pulse",
"metricBodyFat": "Body fat",
"metricSleep": "Sleep duration",
"metricSteps": "Daily steps",
"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."
},
"onboarding": {
"errorGeneric": "Something went wrong while finishing setup. Please try again.",
"tour": {
"stepOf": "Step {current} of {total}",
"next": "Next",
"back": "Back",
"skip": "Skip tour",
"done": "Got it",
"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."
},
"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."
},
"measurements": {
"title": "Readings & target ranges",
"body": "Measurements shows the history and target range for each metric. Hidden gem: set a target range per value so deviations stand out in colour. These series are the basis for the Coach’s correlations and the doctor report."
},
"medications": {
"title": "Medications & intakes",
"body": "Medications manages schedules, intakes, stock, and titration. Hidden: recurring plans (RRULE/rolling) and low-stock warnings. Your intake rate feeds the adherence pillar on the dashboard and the AI’s context."
},
"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."
},
"illness": {
"title": "Illness journal",
"body": "The illness journal records acute episodes and chronic diagnoses with their flares. Hidden: correlate an episode with your readings, and Rest Mode that pauses reminders. That’s how the Coach understands why values drift for a while."
},
"vorsorge": {
"title": "Checkups",
"body": "Checkups remind you of screenings and vaccinations on their own interval. Tip: “Done” can create a reading or a lab result directly. Due items appear as reminders and in the doctor report."
},
"cycle": {
"title": "Cycle",
"body": "Cycle tracking logs phases and symptoms. Hidden: compare symptoms against mood and sleep. The cycle gives context for swings that would otherwise look unexplained."
},
"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."
},
"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."
},
"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."
},
"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."
},
"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."
},
"achievements": {
"title": "Achievements",
"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."
}
}
},
"shell": {
"back": "Back",
"skip": "Skip",
"next": "Continue",
"step1of4": "Step 1 of 4",
"step2of4": "Step 2 of 4",
"step3of4": "Step 3 of 4",
"step4of4": "Step 4 of 4"
},
"goals": {
"title": "What would you like to track?",
"body": "Pick the areas you care about — we'll surface them first on your dashboard, and they help you decide what to set up next.",
"helpHint": "One to three priorities tend to work best — you can always add more later.",
"options": {
"weightManagement": "Weight management",
"bpTracking": "Blood pressure",
"glucoseTracking": "Glucose",
"sleepImprovement": "Better sleep",
"medicationCompliance": "Medications",
"generalWellness": "General wellness"
}
},
"source": {
"title": "Connect a source",
"body": "Bring in measurements automatically, or stay on manual entry. Nothing here is configured for you — each card just shows where to connect it. Device sources need a free developer app registered on your own account (about 5 minutes); the setup guide on each card walks through it.",
"recommended": "Recommended",
"manual": {
"title": "Manual entry",
"body": "Log readings yourself, whenever it fits. Works on any device, no third-party account required."
},
"withings": {
"title": "Withings",
"body": "Scales, blood-pressure cuffs and trackers from Withings sync automatically once connected.",
"cta": "Connect Withings",
"setupCta": "Set up in Settings",
"setupHint": "Needs your own free Withings developer app first — about 5 minutes, one time."
},
"more": {
"title": "More sources",
"body": "Connect any of these in Settings whenever you're ready — most need a free developer app registered on your own account first.",
"appleHealth": "Apple Health",
"whoop": "WHOOP",
"oura": "Oura",
"polar": "Polar",
"nightscout": "Nightscout",
"fitbit": "Fitbit"
},
"import": "Import existing history"
},
"baseline": {
"title": "A bit about you",
"body": "Four optional fields sharpen target ranges, BMI and reminders. You can adjust any of them later in Settings.",
"displayNameLabel": "Display name",
"displayNamePlaceholder": "How should HealthLog address you?",
"displayNameHint": "Shown on the dashboard greeting and in reports.",
"heightLabel": "Height (cm)",
"genderLabel": "Gender",
"genderNone": "Prefer not to say",
"genderMale": "Male",
"genderFemale": "Female",
"dateOfBirthLabel": "Date of birth",
"dateOfBirthHint": "Used only for age-aware analytics.",
"saveCta": "Save and continue"
},
"done": {
"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.",
"connectCta": "Connect a device",
"logCta": "Log your first measurement",
"importCta": "Import existing history",
"modulesCta": "Choose your modules"
},
"welcomeBack": {
"title": "Welcome back",
"body": "You've already finished onboarding. To adjust anything, head to Settings — everything you set up is editable from there.",
"cta": "Open dashboard"
},
"disclaimer": {
"acknowledge": "I understand: HealthLog is a private tracking tool, not a clinical assessment or diagnosis. If I'm worried I'll talk to my doctor, not this app.",
"learnMore": "Learn more"
},
"welcome": {
"title": "Welcome to HealthLog",
"carouselLabel": "Welcome carousel",
"slideOf": "Slide {current} of {total}",
"prevSlide": "Previous slide",
"nextSlide": "Next slide",
"gotoSlide": "Go to slide {index}",
"cta": "Get started",
"slide1": {
"title": "Track every signal",
"body": "Weight, blood pressure, glucose, sleep, mood — keep your full picture in one log you own."
},
"slide2": {
"title": "Connect your sources",
"body": "Sync with Apple Health and Withings, or add readings by hand. Your data stays on your server."
},
"slide3": {
"title": "See the pattern",
"body": "Daily summaries, trend charts, and a coach that surfaces what changed — all on your own device."
}
},
"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.",
"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."
},
"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.",
"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.",
"ladderTitle": "Three ways to turn it on",
"ladderLocalTitle": "Local model — nothing leaves 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.",
"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."
}
},
"gettingStarted": {
"title": "Getting started",
"subtitle": "Quick wins to get the most out of HealthLog.",
"progress": "{done} of {total} done",
"dismissAll": "Hide checklist",
"dismissTooltip": "Hide this item",
"items": {
"profileTitle": "Set your profile",
"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.",
"measurementCta": "Add measurement",
"medicationTitle": "Add a medication",
"medicationDescription": "Track adherence and get reminders right when you need them.",
"medicationCta": "Add medication",
"dataSourceTitle": "Connect a data source (optional)",
"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.",
"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.",
"insightsCta": "Turn on insights"
}
},
"trendHints": {
"title": "First trend after 5 readings",
"remainingOne": "1 more reading to go.",
"remainingMany": "{count} more readings to go."
},
"settings": {
"researchMode": {
"sectionTitle": "Research Mode",
"subtitle": "Opt-in display of an estimated GLP-1 drug-level curve, derived from EMA-published population pharmacokinetics. Reading-only — never a measurement or medical advice.",
"toggleLabel": "Show the estimated drug-level chart",
"disabledStatus": "Disabled. The drug-level chart is hidden.",
"enabledStaleStatus": "The disclaimer was updated. Re-acknowledge below to bring the chart back.",
"acknowledgedOn": "Acknowledged on {date}.",
"rePromptTitle": "Disclaimer updated",
"rePromptBody": "The Research Mode disclaimer was updated since you last acknowledged it. Re-read and re-confirm to keep the chart visible.",
"rePromptCta": "Re-acknowledge disclaimer",
"disableError": "Could not disable Research Mode. Please try again."
},
"shell": {
"sectionsNav": "Settings sections",
"groups": {
"account": "Account",
"yourData": "Your data",
"display": "Display",
"healthProfile": "Health profile",
"ai": "AI",
"connectivity": "Connectivity",
"system": "System"
}
},
"sections": {
"account": {
"title": "Account",
"description": "Profile, password, passkeys, and your onboarding tour.",
"subtitle": "Your profile, identity, and sign-in details."
},
"integrations": {
"title": "Integrations",
"description": "Connected services, delivery channels, and source priority in one place.",
"subtitle": "Connect and manage your data sources and devices.",
"connectionsHeading": "Connections",
"connectionsDescription": "Connect and manage your data sources and devices.",
"channelsHeading": "Delivery channels",
"channelsDescription": "Where reminders and alerts are delivered.",
"matrixLink": "Per-channel notifications"
},
"notifications": {
"title": "Notifications",
"description": "Every reminder in one place — what gets reminded and when, and where it's delivered.",
"subtitle": "Choose which reminders you receive and where they're delivered.",
"remindersHeading": "Reminders",
"remindersDescription": "What you receive.",
"matrixLink": "Per-channel notifications",
"channelsLink": "Delivery channels"
},
"layout": {
"title": "Appearance",
"description": "Choose how the dashboard, insights, and your tracking modules look and are arranged.",
"backToHub": "Back to Appearance",
"dashboard": {
"title": "Dashboard",
"description": "Tile layout and order."
},
"insights": {
"title": "Insights",
"description": "Overview sections and navigation-pill order."
},
"subtitle": "Personalize how your dashboard, insights, and tracking modules look.",
"medications": {
"title": "Medications",
"description": "List view and manual order."
},
"labs": {
"title": "Labs",
"description": "View, sort, and manual order."
},
"illness": {
"title": "Illness journal",
"description": "List view and episode order."
},
"vorsorge": {
"title": "Checkups",
"description": "List view and reminder order."
},
"mood": {
"title": "Mood tags",
"description": "Groups, tags, and archived tags for the mood picker."
}
},
"dashboard": {
"title": "Dashboard",
"description": "Tile layout and order.",
"subtitle": "Arrange the tiles on your dashboard."
},
"thresholds": {
"title": "Targets",
"description": "Per metric: your own target range for healthy values.",
"subtitle": "Set your personal target ranges per metric."
},
"sources": {
"title": "Source priority",
"description": "Pick which ingest source wins when more than one records the same metric for the same day.",
"integrationsHint": "Connect or disconnect data sources on the Integrations page.",
"integrationsHintLink": "Open integrations",
"cardTitle": "Source priority by metric",
"help": "When several sources deliver the same value on the same day, the top source counts as canonical. The others stay stored for the audit trail.",
"resetDefaults": "Reset to defaults",
"moveUp": "Move up",
"moveDown": "Move down",
"saveSuccess": "Source priority saved.",
"saveError": "Saving the source priority failed.",
"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.",
"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.",
"deviceTypeDefault": "Default device-type ladder",
"resetDeviceTypes": "Reset device-types",
"metrics": {
"steps": "Steps",
"activeEnergy": "Active energy",
"walkingRunningDistance": "Walking + running distance",
"flightsClimbed": "Flights climbed",
"sleep": "Sleep",
"weight": "Weight",
"bloodPressure": "Blood pressure",
"pulse": "Pulse",
"bodyFat": "Body fat",
"bodyTemperature": "Body temperature",
"spo2": "Oxygen saturation",
"hrv": "Heart-rate variability",
"restingHeartRate": "Resting heart rate",
"vo2Max": "VO2 max",
"skinTemperature": "Skin temperature",
"respiratoryRate": "Respiratory rate",
"recovery": "Recovery",
"stress": "Stress",
"sleepDebt": "Sleep debt"
},
"sourceLabels": {
"WITHINGS": "Withings",
"APPLE_HEALTH": "Apple Health",
"MANUAL": "Manual entry",
"IMPORT": "Import",
"WHOOP": "WHOOP",
"FITBIT": "Fitbit",
"COMPUTED": "Computed"
},
"deviceLabels": {
"watch": "Watch",
"band": "Band",
"ring": "Ring",
"phone": "Phone",
"scale": "Scale",
"other": "Other",
"unknown": "Unknown"
},
"subtitle": "Decide which source wins when two report the same metric.",
"nutrients": {
"title": "Synced nutrient intake",
"description": "Daily totals synced from Apple Health over the last {days} days. Read-only — the source app owns the numbers.",
"empty": "No nutrient data has been synced yet.",
"latest": "{amount} {unit} on {date}",
"daysWithData": "{count} of {days} days",
"moduleHint": "Syncing is controlled by the Nutrient intake module.",
"moduleHintLink": "Manage modules"
}
},
"ai": {
"title": "AI provider",
"description": "Provider, model, and API key for the insights — plus your “about me” context.",
"subtitle": "Choose your AI provider and bring your own key."
},
"api": {
"title": "API & Tokens",
"description": "Bearer tokens for your own scripts and apps — log measurements or medication intake from anywhere.",
"subtitle": "Manage API endpoints and access tokens."
},
"advanced": {
"title": "Advanced",
"description": "Opt-in Research Mode toggle plus the account-wide danger zone for wiping every health record.",
"subtitle": "Research mode, data reset, and account deletion."
},
"export": {
"title": "Export & Import",
"description": "Download your data as CSV or a full JSON backup — or import from Apple Health, JSON, or CSV. The doctor report now lives under Health Record.",
"otherOptionsHeading": "Other export options",
"downloadFailed": "Couldn't download the export. Please try again.",
"actions": {
"download": "Download"
},
"filters": {
"since": "From",
"until": "Until"
},
"cards": {
"measurementsCsv": {
"title": "Measurements",
"description": "Weight, blood pressure, pulse, glucose, and every other measurement as comma-separated values."
},
"medicationsCsv": {
"title": "Medications",
"description": "Your medication list with dosage, schedules, and (optionally) the full intake history.",
"includeIntake": "Include intake history"
},
"moodCsv": {
"title": "Mood",
"description": "Daily mood entries with score, tags, and timestamps."
},
"fullBackup": {
"title": "Full backup",
"description": "Every record you own in one JSON file — measurements, medications, mood, cycle, labs, illness episodes, allergies, family history, and workouts. Same shape as the weekly auto-backup.",
"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.",
"stepUpNeeded": "Confirm your second factor, then try again."
},
"cycle": {
"title": "Cycle",
"description": "Cycle and reproductive-health data as a FHIR document — last period, average cycle and period length, current phase."
}
},
"import": {
"heading": "Import",
"description": "Bring data into HealthLog from an Apple Health export, a JSON file, or a CSV. Imports skip rows that already exist, so re-running one is safe.",
"charCount": "{used} / {max} characters",
"appleHealth": {
"title": "Apple Health",
"description": "Upload the export.zip from the Health app on iPhone (Profile → Export All Health Data).",
"dropLabel": "Drop export.zip here",
"dropHint": "or click to choose a file",
"fileInputLabel": "Choose an Apple Health export.zip file",
"choose": "Choose file",
"idempotencyNote": "Re-uploading the same archive merges — it won't create duplicates. Large archives are processed in the background.",
"uploading": "Uploading…",
"uploadFailed": "Upload failed. Please try again.",
"rateLimited": "Too many uploads. Please wait a moment and try again.",
"tooLarge": "That file is too large (limit 1.5 GB).",
"failed": "The import failed.",
"rowsImported": "{count} rows imported so far",
"doneSummary": "Done — {imported} of {read} records imported, {skipped} clinical records skipped.",
"estimateWarning": "Cumulative totals for {count} day(s) were estimated from the largest export source. Native Apple Health statistics remain authoritative.",
"phase": {
"queued": "Queued…",
"unpacking": "Unpacking the archive…",
"parsing": "Reading the export…",
"upserting": "Importing records…"
}
},
"json": {
"title": "JSON file",
"description": "Paste JSON or upload a .json file with measurements and mood entries.",
"pasteLabel": "Paste JSON",
"fileInputLabel": "Choose a JSON file to import",
"schemaHint": "Two arrays: measurements and moodEntries.",
"docsLink": "See the schema and an example.",
"uploadFile": "Upload file",
"downloadExample": "Download example",
"import": "Import",
"invalidJson": "That isn't valid JSON. Check the syntax and try again.",
"invalidPayload": "The data doesn't match the import schema.",
"rateLimited": "Too many imports this hour (limit 5). Please try again later.",
"failed": "The import failed. Please try again.",
"readFailed": "Couldn't read that file.",
"resultSummary": "Imported {measurements} measurements and {moods} mood entries, {skipped} skipped."
},
"csv": {
"title": "CSV file",
"description": "Import measurements from a spreadsheet or meter export. One row per reading.",
"pasteLabel": "Paste CSV",
"fileInputLabel": "Choose a CSV file to import",
"schemaHint": "Columns: type, value, unit, measuredAt (with timezone offset), and optional glucoseContext, notes, externalId.",
"docsLink": "See the column schema and an example.",
"uploadFile": "Upload file",
"downloadExample": "Download example",
"preview": "Preview",
"import": "Import",
"empty": "Add at least one CSV row before importing.",
"rateLimited": "Too many imports this hour (limit 5). Please try again later.",
"tooLarge": "That file is too large (limit 16 MB).",
"invalidPayload": "The CSV could not be parsed. Check the header row and try again.",
"failed": "The import failed. Please try again.",
"readFailed": "Couldn't read that file.",
"previewSummary": "Preview: {inserted} would import, {skipped} skipped.",
"resultSummary": "Imported {inserted} new and updated {updated}, {skipped} skipped.",
"rowError": "Line {line}: {reason}"
}
},
"subtitle": "Export your data or import from a backup."
},
"about": {
"title": "About this app",
"description": "Version, license, links.",
"subtitle": "Version, license, and project links."
},
"sharing": {
"title": "Sharing",
"description": "Create a read-only link to share your health record with a clinician.",
"subtitle": "Share read-only access to your data."
},
"insights": {
"title": "Insights",
"description": "Overview and navigation-pill order.",
"subtitle": "Arrange your overview sections and pill order."
},
"medications": {
"title": "Medications",
"description": "List view, order, and injection sites for your medications.",
"subtitle": "Manage your medication list view and order."
},
"mood": {
"title": "Mood tags",
"description": "Groups, tags, and archived tags for the mood picker.",
"subtitle": "Organize your mood tags, groups, and picker order."
},
"labs": {
"title": "Labs",
"description": "View, sort order, and biomarkers for your labs.",
"subtitle": "Manage the view, sort order, and biomarkers."
},
"illness": {
"title": "Illness journal",
"description": "View and order of your illness episodes.",
"subtitle": "Manage the view and order of episodes."
},
"vorsorge": {
"title": "Checkups",
"description": "View, order, and individual checkup reminders.",
"subtitle": "Manage the view, order, and individual reminders."
},
"modules": {
"title": "Modules",
"saved": "Saved.",
"error": "Couldn't save. Please try again.",
"toggleable": {
"title": "What you track",
"description": "Optional areas. Disabled modules drop out of the navigation, tiles, and insights — your data stays untouched."
},
"manageIn": "Manage in {section}",
"operatorDisabled": "Disabled server-wide",
"subtitle": "Choose which tracking areas HealthLog shows across the app."
},
"gesundheitsakte": {
"title": "Health record",
"description": "Export your full health record as PDF, FHIR R4, or a combined ZIP package.",
"subtitle": "Export a complete, clinician-ready health record."
},
"coach": {
"title": "Coach",
"description": "Enable the Coach, tone and scope, stored memories.",
"subtitle": "Tune the Coach, its proactive nudges, and its memory."
},
"security": {
"title": "Security",
"subtitle": "Two-factor authentication, recovery codes, and passkeys."
},
"privacy": {
"title": "Data & Privacy",
"subtitle": "Your data, retention, encryption, and account security in one place.",
"description": "Export, deletion, retention, encryption status, sessions, and security activity."
},
"mcp": {
"title": "MCP Connector",
"subtitle": "Connect an external assistant to your own health data."
},
"anamnesis": {
"title": "Medical history",
"subtitle": "Manage your allergies and family history.",
"description": "Structured allergies and family history records."
},
"environment": {
"title": "Location & weather",
"subtitle": "Weather, daylight, and location context.",
"disabledHint": "Turn on the Environment module to set a home location and pull in daily weather and daylight.",
"searchPlaceholder": "Search for a city",
"search": "Search",
"searchError": "Could not search for that place.",
"use": "Use",
"select": "Select",
"saveError": "Could not save your change.",
"homeSaved": "Home location saved.",
"travelAdded": "Location period added.",
"travelRemoved": "Location period removed.",
"backfillQueued": "Backfill queued.",
"backfillError": "Could not start the backfill.",
"startDate": "Start date",
"endDate": "End date",
"storedDays": "{count} days of weather stored.",
"home": {
"title": "Home location",
"description": "A coarse, city-level location — never a precise track. Weather and daylight are fetched for this place on days no location period applies, from the date you set it onward.",
"current": "Current: {label}",
"none": "No home location set yet.",
"since": "Weather tracked from {date} onward. Earlier days stay empty until you add a location period."
},
"travel": {
"title": "Location periods",
"description": "Add a place and a date range — a trip, or a stretch of earlier history. The period overrides your home for the days it covers, so weather matches where you actually were. This is how you correct the past.",
"none": "No location periods yet.",
"add": "Add {label}",
"remove": "Remove location period",
"removeConfirmTitle": "Remove this trip?",
"removeConfirmBody": "Readings taken during it stay in your record; only the trip entry goes."
},
"backfill": {
"title": "Backfill past days",
"description": "Fetch and store weather for a past date range so older days join the correlations. The start defaults to your home's effective date; to reach further back, add a location period for that range first.",
"run": "Backfill"
},
"noResults": "No matching places found."
}
},
"profile": "Profile",
"language": "Language",
"languageDescription": "Choose the display language of the application.",
"timeFormat": {
"title": "Hour format",
"description": "Controls whether times render on the 24-hour or the 12-hour (AM/PM) clock.",
"auto": "Automatic (language)",
"h24": "24-hour",
"h12": "12-hour (AM/PM)",
"saved": "Hour format saved.",
"saveError": "Saving the hour format failed."
},
"dateFormat": {
"title": "Date format",
"description": "Controls the order of day, month and year when dates are shown.",
"auto": "Automatic (language)",
"dmy": "DD.MM.YYYY",
"mdy": "MM/DD/YYYY",
"ymd": "YYYY-MM-DD",
"saved": "Date format saved.",
"saveError": "Saving the date format failed."
},
"username": "Username",
"height": "Height (cm)",
"dateOfBirth": "Date of birth",
"dateOfBirthHint": "Used for automatic blood pressure target calculations.",
"gender": "Gender",
"genderNone": "Not specified",
"genderMale": "Male",
"genderFemale": "Female",
"genderHint": "Used for gender-specific target values.",
"timezone": "Timezone",
"timezoneHint": "Used for chart axis labels, reminder times, export timestamps, and Coach context. Stored data is unchanged.",
"timezoneInvalid": "Not a valid IANA timezone.",
"profileSaved": "Profile saved",
"avatar": {
"title": "Profile photo",
"description": "Upload a photo stored on your own server. It appears across the app in place of an external avatar service.",
"upload": "Upload photo",
"replace": "Replace photo",
"remove": "Remove",
"hint": "JPEG, PNG, or WebP. Up to 2 MB and 2048×2048 pixels.",
"uploaded": "Profile photo updated",
"removed": "Profile photo removed",
"invalidType": "Unsupported image type. Use JPEG, PNG, or WebP.",
"tooLarge": "Image exceeds the 2 MB limit.",
"error": "Could not update the profile photo. Please try again."
},
"changePassword": "Change password",
"changePasswordDescription": "Replace your current password with a new one.",
"passwordReset": "Password reset",
"currentPassword": "Current password",
"newPassword": "New password",
"confirmNewPassword": "Confirm new password",
"passwordMismatch": "New passwords do not match",
"passwordUpdated": "Password updated successfully",
"passkeys": "Passkeys",
"registeredPasskeys": "Registered Passkeys",
"passkeysDescription": "Passkeys allow secure login without a password.",
"passkeyName": "Name",
"passkeyDevice": "Device",
"passkeyBackup": "Backup",
"passkeyCreated": "Created",
"passkeyActions": "Actions",
"noPasskeys": "No passkeys registered.",
"addPasskey": "Add passkey",
"passkeyAdded": "Passkey added successfully!",
"passkeyOptionsError": "Could not load passkey options",
"passkeyRegistrationFailed": "Passkey registration failed",
"passkeyRegistrationCancelled": "Passkey registration cancelled",
"passkeyNotSupported": "Your browser or device doesn't support passkeys yet. Try a different browser or device.",
"passkeyAlreadyRegistered": "This device is already registered as a passkey for your account.",
"passkeySecurityBlocked": "Your browser blocked the passkey request for security reasons. Make sure you're on a trusted HTTPS origin and try again.",
"passkeyTimeout": "The passkey prompt timed out. Please try again.",
"passkeyUnknownError": "Passkey registration failed: {message}",
"deletePasskey": "Delete passkey?",
"deletePasskeyDescription": "The passkey will be permanently deleted.",
"singleDevice": "Single device",
"multiDevice": "Multi-device",
"backedUp": "backed up",
"telegram": "Telegram",
"telegramDescription": "Medication reminders via bot.",
"botToken": "Bot Token",
"chatId": "Chat ID",
"enableNotifications": "Enable notifications",
"telegramStep1": "1. Create a bot via @BotFather in Telegram and copy the token.",
"telegramStep2": "2. Send /start to your bot to activate the chat.",
"telegramStep3": "3. Find your Chat ID via @userinfobot or the Bot API.",
"ntfy": "ntfy",
"ntfyDescription": "Notifications via ntfy (self-hosted or ntfy.sh).",
"ntfyEnable": "Enable ntfy",
"ntfyServer": "Server URL",
"ntfyTopic": "Topic",
"ntfyAuthToken": "Auth Token (optional)",
"ntfyAuthTokenHint": "Only needed for private topics with access control.",
"webhook": "Webhook",
"webhookDescription": "POST notifications to any URL — Gotify, Discord, Slack, Matrix, or Home Assistant.",
"webhookEnable": "Enable webhook",
"webhookUrl": "Webhook URL",
"webhookUrlHint": "The full URL to POST to. Must be publicly reachable.",
"webhookHeaderName": "Header name (optional)",
"webhookHeaderValue": "Header value (optional)",
"email": "Email",
"emailDescription": "Receive alerts and reminders by email.",
"emailEnable": "Enable email",
"emailRecipient": "Recipient address",
"webPush": "Browser Push",
"webPushDescription": "Receive notifications directly in your browser, even when HealthLog is not open.",
"webPushNotSupported": "Your browser does not support push notifications.",
"webPushDenied": "Push notifications are blocked. Allow them in your browser settings.",
"webPushNotConfigured": "Web Push is not configured on the server.",
"webPushSubscribe": "Enable push",
"webPushUnsubscribe": "Disable push",
"webPushSubscribed": "Push notifications enabled!",
"webPushUnsubscribed": "Push notifications disabled.",
"webPushSubscribeFailed": "Activation failed",
"webPushActive": "Active",
"kiInsightsDescription": "Optional: Save your OpenAI key for daily, automatic evaluations in Insights.",
"codexConnected": "ChatGPT connected successfully! Insights are now active.",
"codexDisconnected": "ChatGPT connection removed.",
"codexConnectionFailed": "ChatGPT connection failed. Please try again.",
"rawData": "Send raw data",
"rawDataOnDescription": "Aggregated metrics plus anonymized individual points from the last 30 days with time context are sent — never your name, email, or direct account identifiers.",
"rawDataOffDescription": "Only summarized metrics are sent (for example averages, trends, minimum/maximum) — no individual points and no exact time context.",
"rawDataWarning": "Raw mode enabled: the provider receives additional anonymized points from the last 30 days for higher analysis accuracy.",
"regenerateInsights": "Regenerate reports",
"regenerateSuccess": "Reports regenerated successfully",
"regenerateRateLimit": "Please wait — you've hit the hourly limit for analyses.",
"lastGeneratedAt": "Last generated",
"ai": {
"chatgptConnectedBadge": "ChatGPT connected",
"adminAiActiveBadge": "Admin provider active",
"connectionExpiredBadge": "Connection expired",
"connectedSince": "Connected since {when}.",
"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.",
"deviceCodeCopy": "copy",
"deviceCodeWaiting": "Waiting for approval…",
"deviceCodeCancel": "Cancel",
"oauthNotConfigured": "ChatGPT OAuth is not configured on this instance — use your own API key below instead.",
"modelLabel": "Model",
"modelOptionDefault": "— Default —",
"modelOptionCustom": "Custom…",
"customModelLabel": "Custom model name",
"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.",
"savedPreview": "(saved {preview})",
"savedShort": "(saved)",
"saveCta": "Save",
"saved": "Saved",
"saveFailed": "Save failed",
"errorGeneric": "Error",
"providerChain": {
"types": {
"codex": "ChatGPT (Codex)",
"openai": "OpenAI (your key)",
"anthropic": "Anthropic (Claude)",
"local": "Local model",
"admin-openai": "Admin OpenAI"
},
"title": "Fallback chain",
"description": "If the primary provider fails, HealthLog walks the chain in order. Drag the rows to reorder, toggle the switch to disable a provider without removing it.",
"moveUp": "Move up",
"moveDown": "Move down",
"removeFromChain": "Remove from chain",
"addProvider": "Add provider",
"addNoneAvailable": "All providers already in chain",
"saveOrder": "Save chain order",
"saved": "Chain saved",
"saveFailed": "Saving the chain failed",
"resetDefaults": "Reset to defaults",
"resetConfirmTitle": "Reset chain to defaults?",
"resetConfirmBody": "The chain reverts to Codex → OpenAI → Anthropic → Local → Admin OpenAI. Your saved credentials are not touched."
},
"providerCardTitle": "AI provider",
"activeProviderHeading": "Active provider",
"activeProviderBody": "Pick the provider you want to use first. The form below configures only the selected provider; the fallback chain at the bottom decides what happens if it fails.",
"activeProviderLabel": "Primary provider",
"providerConfigTitle": "Provider configuration",
"providerSelect": {
"codex": "ChatGPT account (Codex)",
"openai": "OpenAI (your API key)",
"anthropic": "Anthropic (Claude)",
"local": "Local model (OpenAI-compatible)",
"admin-openai": "Admin-provided OpenAI"
},
"openai": {
"modelSelect": "Model",
"modelOptionCustom": "Custom slug…",
"modelCustomLabel": "Custom model slug",
"modelCustomPlaceholder": "gpt-5",
"baseUrlLabel": "Base URL (advanced)",
"baseUrlPlaceholder": "https://api.openai.com/v1",
"baseUrlHelp": "Override only when using an OpenAI-compatible gateway. Leave blank for OpenAI itself.",
"showAdvanced": "Show advanced",
"hideAdvanced": "Hide advanced",
"apiKey": "API key",
"apiKeyPlaceholder": "sk-…"
},
"codex": {
"statusConnected": "Connected",
"statusDisconnected": "Not connected",
"statusExpired": "Connection expired",
"connectButton": "Connect with ChatGPT",
"disconnectButton": "Disconnect",
"modelSlugLabel": "Model slug",
"modelSlugBody": "Codex uses the model your ChatGPT subscription routes to. The CODEX_MODEL environment variable lets ops override this on the instance.",
"lastInsight": "Last insight: {when}"
},
"adminOpenai": {
"title": "Admin OpenAI",
"body": "Operator-provided OpenAI key, used as the last fallback when no personal provider is configured. Nothing to configure here.",
"notConfigured": "The operator has not configured a shared OpenAI key on this instance."
},
"testProvider": "Test active provider",
"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.",
"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.",
"testReasonUnreachable": "Could not reach the AI provider.",
"coachMemory": {
"title": "What the Coach remembers",
"description": "Durable facts you have told the Coach. It uses these to keep its replies relevant. Remove anything you would rather it forgot.",
"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",
"categoryGoal": "Goals",
"categoryConstraint": "Constraints",
"categoryContext": "Context",
"forget": "Forget",
"forgetAria": "Forget this fact",
"forgetAll": "Forget everything",
"forgetAllConfirmTitle": "Forget everything the Coach remembers?",
"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.",
"loadError": "Could not load what the Coach remembers.",
"forgotToast": "Fact forgotten.",
"forgotError": "Could not forget that fact. Please try again.",
"clearedToast": "Forgot {count} stored facts.",
"clearError": "Could not clear the stored facts. Please try again."
},
"coachReminders": {
"title": "Your reminders",
"description": "Things you asked the Coach to bring back later. Due ones show up here and on the Coach.",
"empty": "No reminders yet. Ask the Coach to remind you about something and it will appear here.",
"loadError": "Could not load your reminders.",
"dueHeading": "Due now",
"allHeading": "Saved",
"duePrefix": "due {when}",
"confirm": "Keep",
"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.",
"status": {
"proposed": "Suggested",
"active": "Saved",
"due": "Due",
"surfaced": "Surfaced",
"done": "Done",
"dismissed": "Dismissed"
},
"deleteConfirmTitle": "Delete this reminder?",
"deleteConfirmBody": "It stops being raised. Anything you have already recorded is untouched.",
"deleteConfirmAction": "Delete"
},
"aboutMe": {
"title": "About me",
"description": "Personal context the Coach and the daily briefing read alongside your data.",
"placeholder": "E.g. shift work, vegetarian diet, knee injury, training for a half marathon…",
"charCount": "{used} / {max} characters",
"clear": "Clear",
"save": "Save",
"savedToast": "About-me note saved.",
"clearedToast": "About-me note cleared.",
"saveError": "Could not save. Please try again.",
"loadError": "The note could not be loaded.",
"hint": "Passed to the Coach and the daily briefing as additional context. Leave empty to send nothing.",
"profileHint": "Age and gender come from your profile and are included automatically.",
"freeTextLabel": "About me (free text)",
"conditionsLabel": "Chronic conditions",
"conditionsPlaceholder": "E.g. hypertension, type 2 diabetes…",
"allergiesLabel": "Allergies & intolerances",
"allergiesPlaceholder": "E.g. lactose intolerance, penicillin allergy…",
"focusLabel": "What should the Coach watch?",
"focusPlaceholder": "E.g. keep an eye on my blood pressure, motivate me to move more…",
"completeness": "{answered} of {total} answered",
"questionsTitle": "The Coach has follow-up questions",
"questionsOpenCoach": "Answer them in the Coach",
"recordsLink": "Allergies, family history and your pre-existing conditions are part of your medical history.",
"recordsLinkCta": "Open medical history"
},
"responseTimeoutHeading": "Response timeout",
"responseTimeoutBody": "How long to wait for the AI to respond before giving up. Raise it for a local or self-hosted model that needs time to load on the first request.",
"responseTimeoutLabel": "Response timeout (seconds)",
"responseTimeoutPlaceholder": "Default (~120)",
"responseTimeoutInvalid": "Enter a number between 10 and 600 seconds.",
"autoRead": {
"title": "Read documents automatically with AI",
"subLabel": "Newly uploaded documents are read and indexed by your configured AI provider without a per-document tap.",
"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. 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 the documents you upload.",
"confirm": "I understand — turn on automatic AI reading",
"cancel": "Cancel"
},
"centralCodex": {
"title": "Use the server's shared AI access",
"subLabel": "Route AI requests through the connection the operator set up for this server, alongside your own providers as a 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 the shared connection",
"cancel": "Cancel"
},
"consent": {
"title": "AI consent",
"activeSince": "Given on {date}. Your health data may be sent to the configured provider for the AI features.",
"withdrawn": "Withdrawn. No health data is sent to an AI provider; the AI features stay switched off.",
"withdraw": "Withdraw consent",
"confirmBody": "The AI features stop working straight away. Nothing already recorded is deleted — use Data & privacy to export or erase your record.",
"confirmWithdraw": "Withdraw",
"regrantHint": "To use the AI features again, switch on automatic document reading or grant consent from the app.",
"error": "The withdrawal could not be saved. Please try again."
}
},
"dashboard": {
"units": {
"title": "Units",
"description": "Choose how distances and speeds are shown across charts and tiles.",
"metric": "Metric",
"imperial": "Imperial",
"saved": "Unit preference saved.",
"saveError": "Could not save your unit preference."
}
},
"withings": "Withings",
"withingsDescription": "Connect your Withings scale and blood-pressure monitor to sync weight, body composition, and blood pressure automatically.",
"withingsCredentials": "API Credentials",
"withingsClientId": "Client ID",
"withingsClientSecret": "Client Secret",
"withingsCredentialsSaved": "Credentials saved",
"withingsCredentialsSavedPlaceholder": "Saved — enter new to replace",
"withingsCredentialsSavedPlaceholderSecret": "Saved — enter new to replace",
"withingsSaveCredentials": "Save",
"configured": "Configured",
"withingsSync": "Sync now",
"withingsFullSync": "Sync all data",
"withingsFullSyncTitle": "Full synchronization?",
"withingsFullSyncDescription": "All available Withings data will be fully synchronized. This may take some time depending on your history.",
"withingsSyncResult": "{count} measurements synchronized",
"withingsFullSyncResult": "{count} measurements fully synchronized",
"withingsSyncFailed": "Sync failed",
"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.",
"replay": "This confirmation link has already been used. Please start the connection again.",
"state": "The response from Withings did not match any open connection request. Please start the connection again.",
"expired": "The connection request expired. Start the connection again and complete the approval within a few minutes.",
"cross_user": "The response belongs to a request from a different account. Please restart the connection from your own account.",
"nocode": "Withings did not return an authorization code. Try again and allow access in the Withings dialog.",
"nocreds": "No Withings API credentials are stored. Save the client ID and client secret first, then connect again.",
"token": "The token exchange with Withings failed. Check the client ID and client secret and try again.",
"generic": "Unknown error while connecting. Please start the connection again."
},
"integrationsSourcesHint": "When several sources report the same metric, the source priority decides which value counts.",
"integrationsSourcesHintLink": "Open source priority",
"withingsSynchronize": "Synchronize",
"withingsDisconnect": "Disconnect",
"withingsDisconnectTitle": "Disconnect Withings?",
"withingsDisconnectDescription": "The connection to Withings will be disconnected. Previously synced data will be preserved.",
"withingsConnect": "Connect with Withings",
"withingsNoCredentials": "Please enter your API credentials above to connect Withings.",
"whoop": "WHOOP",
"whoopDescription": "Connect your WHOOP strap to sync recovery, sleep, strain, and workouts straight into HealthLog.",
"whoopCredentials": "API Credentials",
"whoopClientId": "Client ID",
"whoopClientSecret": "Client Secret",
"whoopCredentialsSaved": "Credentials saved",
"whoopCredentialsSavedPlaceholder": "Saved — enter new to replace",
"whoopCredentialsSavedPlaceholderSecret": "Saved — enter new to replace",
"whoopSaveCredentials": "Save",
"whoopSync": "Sync now",
"whoopFullSync": "Sync all data",
"whoopFullSyncTitle": "Full synchronization?",
"whoopFullSyncDescription": "All available WHOOP history will be fully synchronized. This may take some time depending on your history.",
"whoopSyncResult": "{count} measurements synchronized",
"whoopSyncFailed": "Sync failed",
"whoopSynchronize": "Synchronize",
"whoopDisconnect": "Disconnect",
"whoopDisconnectTitle": "Disconnect WHOOP?",
"whoopDisconnectDescription": "The connection to WHOOP will be disconnected. Previously synced data will be preserved.",
"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.",
"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.",
"state": "The response from WHOOP did not match any open connection request. Please start the connection again.",
"expired": "The connection request expired before it completed. Please start the connection again.",
"cross_user": "The response belongs to a request from a different account. Please restart the connection from your own account.",
"nocode": "WHOOP did not return an authorization code. Try again and allow access in the WHOOP dialog.",
"nocreds": "WHOOP is not configured. Add your WHOOP OAuth credentials above and try again.",
"token": "The token exchange with WHOOP failed. Please start the connection again.",
"generic": "Unknown error while connecting. Please start the connection again."
},
"fitbit": "Fitbit",
"fitbitTag": "Fitbit & Pixel",
"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",
"fitbitSaveCredentials": "Save",
"fitbitSync": "Sync now",
"fitbitFullSync": "Sync all data",
"fitbitFullSyncTitle": "Full synchronization?",
"fitbitFullSyncDescription": "All available Fitbit history will be fully synchronized. This may take some time depending on your history.",
"fitbitSyncResult": "{count} measurements synchronized",
"fitbitSyncFailed": "Sync failed",
"fitbitSynchronize": "Synchronize",
"fitbitDisconnect": "Disconnect",
"fitbitDisconnectTitle": "Disconnect Fitbit?",
"fitbitDisconnectDescription": "The connection to Fitbit will be disconnected. Previously synced data will be preserved.",
"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.",
"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.",
"googleHealthDescriptionSecondary": "You register your own Google Cloud client and bring the credentials here. Stress and readiness are not offered by the API, and Google may ask you to reconnect from time to time. New to the setup? Follow the",
"googleHealthCredentials": "API Credentials",
"googleHealthClientId": "Client ID",
"googleHealthClientSecret": "Client Secret",
"googleHealthCredentialsSaved": "Credentials saved",
"googleHealthCredentialsSavedPlaceholder": "Saved — enter new to replace",
"googleHealthCredentialsSavedPlaceholderSecret": "Saved — enter new to replace",
"googleHealthSaveCredentials": "Save",
"googleHealthSync": "Sync now",
"googleHealthFullSync": "Sync all data",
"googleHealthFullSyncTitle": "Full synchronization?",
"googleHealthFullSyncDescription": "All available Google Health history will be fully synchronized. This may take some time depending on your history.",
"googleHealthSyncResult": "{count} measurements synchronized",
"googleHealthSyncFailed": "Sync failed",
"googleHealthSynchronize": "Synchronize",
"googleHealthDisconnect": "Disconnect",
"googleHealthDisconnectTitle": "Disconnect Google Health?",
"googleHealthDisconnectDescription": "The connection to Google Health will be disconnected. Previously synced data will be preserved.",
"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.",
"googleHealthReconnect": "Reconnect",
"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.",
"state": "The response from Google did not match any open connection request. Please start the connection again.",
"expired": "The connection request expired before it completed. Please start the connection again.",
"cross_user": "The response belongs to a request from a different account. Please restart the connection from your own account.",
"nocode": "Google did not return an authorization code. Try again and allow access in the Google dialog.",
"nocreds": "Google Health is not configured. Add your Google OAuth credentials above and try again.",
"token": "The token exchange with Google failed. Please start the connection again.",
"generic": "Unknown error while connecting. Please start the connection again."
},
"fitbitOauthError": {
"csrf1": "The security check failed because the browser cookie was missing. Please start the connection again in the same browser.",
"state": "The response from Fitbit did not match any open connection request. Please start the connection again.",
"expired": "The connection request expired before it completed. Please start the connection again.",
"cross_user": "The response belongs to a request from a different account. Please restart the connection from your own account.",
"nocode": "Fitbit did not return an authorization code. Try again and allow access in the Fitbit dialog.",
"nocreds": "Fitbit is not configured. Add your Fitbit OAuth credentials above and try again.",
"token": "The token exchange with Fitbit failed. Please start the connection again.",
"generic": "Unknown error while connecting. Please start the connection again."
},
"integrations": {
"withings": {
"reconnect": {
"banner": {
"title": "Activity sync available",
"body": "Your Withings connection was authorised before activity sync was added. Reconnect once to enable steps, active energy, walking + running distance, and floors-climbed ingest from your Withings devices.",
"action": "Reconnect Withings"
}
}
}
},
"integrationPill": {
"connected": "Connected",
"errorReconnect": "Error — reconnect",
"warningServerError": "Connected, server error",
"parkedReconnect": "Paused — reconnect manually",
"notConnected": "Not connected",
"justNow": "just now",
"minutesAgo": "{count} min ago",
"hoursAgo": "{count} h ago",
"daysAgo": "{count} d ago",
"ariaLabel": "Integration status",
"resumeCta": "Reconnect",
"resumeSuccess": "Integration resumed",
"resumeError": "Reconnect failed"
},
"apiTokens": "API Tokens",
"apiTokensDescription": "Review and revoke API tokens for external medication intake. Tokens are issued per medication from the medication's API endpoint toggle.",
"tokenMintMovedDescription": "Tokens are issued per medication. Open a medication and enable its API endpoint to get a token scoped to that medication alone.",
"tokenNamePlaceholder": "Token name (e.g., iPhone Shortcut)",
"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",
"tokenRevokeFailed": "Could not revoke the token. Please try again.",
"tokenRevoke": "Revoke token?",
"tokenRevokeAction": "Revoke token",
"tokenRevokeDescription": "The token will be permanently deactivated. Applications using it will lose access.",
"tokenRevoked": "Revoked",
"tokenExpired": "Expired",
"tokenActive": "Active",
"activeTokensTitle": "Active tokens",
"revokedTokensTitle": "Revoked tokens ({count})",
"tokenTableName": "Name",
"tokenTablePermissions": "Permissions",
"tokenTableStatus": "Status",
"tokenTableCreated": "Created",
"tokenTableLastUsed": "Last used",
"tokenTableActions": "Actions",
"noActiveTokens": "No active tokens available.",
"tokenNeverUsed": "Never",
"apiEndpointsTitle": "API endpoints",
"apiEndpointsDescription": "Overview of currently available external endpoint(s) for token-based ingestion.",
"apiEndpointMethod": "Method",
"apiEndpointPath": "Path",
"apiEndpointAuth": "Authentication",
"apiEndpointExample": "Body example",
"collapse": "Collapse",
"expand": "Expand",
"dangerZone": "Delete All Data",
"dangerZoneTitle": "Danger zone",
"dangerZoneDescription": "Deletes all your health data and integrations. Your user account will be preserved.",
"dangerZoneConfirm": "Delete all data?",
"dangerZoneConfirmDescription": "This will permanently delete all your health data and integrations. Your user account will be preserved.",
"dangerZoneSuccess": "All personal data has been deleted",
"dangerZoneDeleteFailed": "Deletion failed",
"finalDelete": "Delete permanently",
"deleteAccountCardTitle": "Delete account entirely",
"deleteAccountCardDescription": "Deletes your account along with passkeys, audit log, and sessions. This cannot be undone.",
"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.",
"deleteAccountFailed": "Account could not be deleted",
"deleteAccountFinal": "Delete permanently",
"saved": "Saved",
"savingError": "Error saving",
"moodLogTitle": "moodLog",
"moodLogDescription": "Import mood entries.",
"moodLogDeprecated": "Deprecated: mood is now tracked natively in HealthLog with tags and factors. This integration still works but will be removed in a future release.",
"moodLogUrl": "moodLog URL",
"moodLogUrlPlaceholder": "https://mood.example.com",
"moodLogApiKey": "API Key",
"moodLogApiKeyPlaceholder": "ml_...",
"moodLogWebhookSecret": "Webhook Secret",
"moodLogWebhookSecretHelp": "Enter this secret in moodLog as webhook secret",
"moodLogSync": "Sync now",
"moodLogFullSync": "Sync all data",
"moodLogFullSyncConfirm": "Synchronize",
"moodLogFullSyncTitle": "Full sync?",
"moodLogFullSyncDescription": "All available mood data will be fully synchronized.",
"moodLogDisconnect": "Disconnect",
"moodLogDisconnectTitle": "Disconnect moodLog?",
"moodLogDisconnectDescription": "The connection will be removed and all imported mood data will be deleted.",
"moodLogEntries": "Entries",
"moodLogSyncResult": "{count} entries synchronized",
"moodLogSyncFailed": "Sync failed",
"moodLogDisconnected": "moodLog disconnected",
"about": {
"version": "App version",
"gitSha": "Build",
"builtAt": "Built {time}",
"builtAtLabel": "Built",
"license": "License",
"repository": "Source code",
"changelog": "Changelog",
"docs": "Documentation",
"linksHeading": "Sources & docs",
"identityDescription": "Version, license, and build details for this instance.",
"linksDescription": "Source code, changelog, and documentation.",
"newerAvailable": "Newer version: {tag}"
},
"testConnection": {
"test": "Test connection",
"testing": "Testing…",
"ok": "Connected (latency {latency} ms)",
"errors": {
"credentials_rejected": "Credentials rejected — check your token",
"rate_limited": "Rate-limited by the upstream",
"timeout": "Request timed out",
"upstream_error": "Upstream returned an error",
"connection_failed": "Connection failed",
"not_configured": "Not configured",
"url_not_public": "URL is not a public endpoint",
"url_invalid": "URL is invalid",
"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",
"vapid_not_configured": "Web Push not configured (VAPID keys missing)",
"rate_limited_self": "Too many test requests",
"generic": "Test failed"
}
},
"notificationStatus": {
"title": "Delivery status",
"description": "Per-channel state; \"Auto-disabled\" stops retries after permanent errors.",
"emptyDescription": "No channels configured yet. Add a channel below to start tracking its delivery health.",
"stateActive": "Active",
"stateAutoDisabled": "Auto-disabled",
"stateSendingPaused": "Sending paused",
"stateManuallyDisabled": "Disabled",
"lastSuccess": "Last successful send",
"lastFailure": "Last failure",
"consecutiveFailures": "Consecutive failures",
"disabledReason": "Reason",
"nextRetry": "Next retry",
"reEnable": "Re-enable",
"sendTest": "Send test"
},
"identity": {
"description": "Optional details for the health-record export (PDF cover + FHIR export). All fields are optional.",
"fullName": "Full name",
"fullNamePlaceholder": "e.g. Jane Doe",
"insurer": "Health insurer",
"insurerPlaceholder": "e.g. AOK Bayern",
"insuranceNumber": "Insurance number (KVNR)",
"insuranceNumberHint": "10 characters: one letter + nine digits (e.g. A123456780)."
},
"healthRecord": {
"title": "Export health record",
"description": "Generate a complete health record for your doctor — as a PDF, structured (FHIR), or a combined package.",
"format": "Format",
"format_pdf": "PDF",
"format_fhir": "Structured (FHIR)",
"format_package": "Package: PDF + FHIR",
"range": "Period",
"range90": "Last 90 days",
"range180": "Last 6 months",
"range365": "Last 12 months",
"practiceName": "Practice (optional)",
"practiceNamePlaceholder": "e.g. Dr. Smith",
"includedData": "Included data",
"groupVitals": "Vital signs",
"groupCardio": "Heart & fitness",
"groupActivity": "Activity & sleep",
"weight": "Weight",
"bp": "Blood pressure",
"pulse": "Pulse",
"oxygenSaturation": "Oxygen saturation",
"bodyFat": "Body fat",
"bodyComposition": "Body composition",
"restingHeartRate": "Resting heart rate",
"hrv": "Heart rate variability",
"vo2max": "VO₂max",
"steps": "Steps",
"distance": "Distance",
"sleep": "Sleep",
"glucose": "Blood glucose",
"medications": "Medications & adherence",
"mood": "Mood (off by default — sensitive data)",
"bmi": "BMI",
"includeCharts": "Embed trend charts (PDF only)",
"includeAiSummary": "Append AI summary (not clinically validated)",
"fhirNote": "The structured output follows the FHIR R4 standard (ePA-compatible).",
"generate": "Generate",
"error": "Export failed ({code}).",
"labs": "Lab results",
"allergies": "Allergies & intolerances",
"familyHistory": "Family history",
"documentsLink": "Documents for this period"
},
"globalExcludedInjectionSitesLabel": "Globally excluded injection sites",
"globalExcludedInjectionSitesHint": "Sites listed here are never offered for any medication and rejected when logging a dose, even if a medication prefers them.",
"sharing": {
"createTitle": "New share link",
"createDescription": "The link is read-only and time-boxed. The token is shown once on creation — store it then; it cannot be recovered.",
"label": "Label",
"labelPlaceholder": "e.g. Dr. Smith — annual check-up",
"range": "Days of history",
"rangeHint": "How far back the shared window reaches.",
"expiry": "Expires in (days)",
"expiryHint": "At most {max} days.",
"expiryInvalid": "Expiry must be between 1 and {max} days.",
"fhirApi": "Allow scoped FHIR API",
"fhirApiHint": "Let the link serve a read-only FHIR endpoint in addition to the page view.",
"resourceTypes": "FHIR resource types",
"create": "Create link",
"tokenCreated": "Share link created",
"tokenOnce": "Copy this link now — the token is shown only once and cannot be recovered.",
"copy": "Copy link",
"copied": "Copied to clipboard.",
"activeTitle": "Active links",
"noActive": "No active share links.",
"created": "Created",
"expires": "Expires",
"accessCount": "Views",
"revoke": "Revoke",
"revokeDescription": "Revoke this link immediately. Anyone holding it loses access at once. This cannot be undone.",
"statusActive": "Active",
"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.",
"qrLabel": "QR code",
"qrAlt": "QR code containing the share link and passphrase",
"linkLabel": "Link",
"passphraseLabel": "Passphrase",
"passphraseHint": "The recipient needs both the link and this passphrase. The QR code carries both.",
"copyLink": "Copy link",
"copyPassphrase": "Copy passphrase",
"protected": "Passphrase",
"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.",
"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.",
"pickerTitle": "Attach documents",
"pickerDescription": "Search your vault and select documents to share. Up to {max}.",
"pickerSearch": "Search documents",
"pickerEmpty": "No documents found.",
"pickerDone": "Done",
"pickerSelectedCount": "{count} of {max} selected",
"pickerMaxReached": "You've reached the maximum of {max} documents."
},
"genderOther": "Other",
"cycleTracking": {
"title": "Cycle tracking",
"description": "Track your menstrual cycle, predictions, symptoms, and phase insights. On by default for accounts set to female; available to everyone.",
"disclaimer": "Predictions and phases are descriptive estimates from your logged data — not medical advice and not a contraceptive method. They never indicate that it is safe to have unprotected sex. Accuracy improves as you log more cycles. For contraception or any medical decision, consult a healthcare professional.",
"enable": "Enable cycle tracking",
"manage": "Open cycle tracking",
"error": "Couldn't update cycle tracking."
},
"nightscout": "Nightscout",
"nightscoutTag": "CGM",
"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",
"nightscoutToken": "API token",
"nightscoutTokenOptional": "Optional for a public site",
"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.",
"nightscoutPrivateHost": "This site runs on a private network",
"nightscoutPrivateHostHelp": "Enable only if your Nightscout instance is on a LAN, VPN, or Tailscale address. Off for public sites.",
"nightscoutConnect": "Connect",
"nightscoutUpdate": "Save changes",
"nightscoutConnected": "Nightscout connected.",
"nightscoutConnectFailed": "Could not connect to Nightscout.",
"nightscoutDisconnect": "Disconnect",
"nightscoutDisconnectTitle": "Disconnect Nightscout?",
"nightscoutDisconnectDescription": "Future syncs stop. Glucose readings already imported stay in your history.",
"polar": "Polar",
"polarDescription": "Connect your Polar account to sync Nightly Recharge recovery, sleep stages, and daily activity.",
"polarViewData": "View your sleep & recovery",
"polarHelp": "Sign in with Polar to grant access. Data is pulled in the background once an hour.",
"polarCredentials": "API Credentials",
"polarClientId": "Client ID",
"polarClientSecret": "Client Secret",
"polarCredentialsSaved": "Credentials saved",
"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",
"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.",
"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.",
"state": "The response from Polar did not match any open connection request. Please start the connection again.",
"cross_user": "The response belongs to a request from a different account. Please restart the connection from your own account.",
"nocode": "Polar did not return an authorization code. Try again and allow access in the Polar dialog.",
"nocreds": "Polar is not configured on this server. Ask your administrator to add the Polar OAuth credentials.",
"token": "The token exchange with Polar failed. Please start the connection again.",
"rate_limited": "Too many connection attempts. Wait a moment and try again.",
"generic": "Unknown error while connecting. Please start the connection again."
},
"oura": "Oura",
"ouraDescription": "Connect your Oura account to sync readiness, sleep stages, heart-rate variability, and daily activity.",
"ouraViewData": "View your sleep & recovery",
"ouraHelp": "Sign in with Oura to grant access. Data is pulled in the background once an hour.",
"ouraCredentials": "API Credentials",
"ouraClientId": "Client ID",
"ouraClientSecret": "Client Secret",
"ouraCredentialsSaved": "Credentials saved",
"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",
"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.",
"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.",
"state": "The response from Oura did not match any open connection request. Please start the connection again.",
"cross_user": "The response belongs to a request from a different account. Please restart the connection from your own account.",
"nocode": "Oura did not return an authorization code. Try again and allow access in the Oura dialog.",
"nocreds": "Oura is not configured on this server. Ask your administrator to add the Oura OAuth credentials.",
"token": "The token exchange with Oura failed. Please start the connection again.",
"rate_limited": "Too many connection attempts. Wait a moment and try again.",
"generic": "Unknown error while connecting. Please start the connection again."
},
"integrationSetupGuide": "Setup guide",
"coach": {
"activate": {
"title": "Activate Coach",
"description": "Show the Coach button and drawer. On by default — turn it off to hide the Coach everywhere.",
"toggleAria": "Activate the Coach button and drawer",
"savedOn": "Coach activated.",
"savedOff": "Coach hidden.",
"saveError": "Could not save the change. Please try again."
}
},
"withingsDescriptionSecondary": "Readings flow into your dashboard in the background. New to the setup? Follow the",
"whoopDescriptionSecondary": "Readings flow into your dashboard in the background. New to the setup? Follow the",
"fitbitDescriptionSecondary": "Readings flow into your dashboard in the background. New to the setup? Follow the",
"polarDescriptionSecondary": "Readings flow into your dashboard in the background. New to the setup? Follow the",
"ouraDescriptionSecondary": "Readings flow into your dashboard in the background. New to the setup? Follow the",
"nightscoutDescriptionSecondary": "Readings flow into your dashboard in the background. New to the setup? Follow the",
"integrationCredentialsHint": "Where to find these credentials and how to register your own app is covered in the setup guide above.",
"integrationRedirectGuide": {
"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."
},
"security": {
"sessionsTitle": "Active sessions",
"sessionsDescription": "Devices and browsers currently signed in to your account.",
"sessionsLoadError": "Active sessions could not be loaded.",
"sessionsEmpty": "No active sessions.",
"currentSession": "This device",
"lastActive": "Last active {time}",
"unknownLocation": "Unknown location",
"revokeSession": "Sign out",
"revokeError": "Could not complete the request. Please try again.",
"signOutEverywhere": "Sign out everywhere else",
"signOutEverywhereDone": "Signed out {count} other session(s).",
"activityTitle": "Security activity",
"activityDescription": "Recent sign-ins, security changes, and data exports on your account.",
"activityEmpty": "No security activity yet.",
"activityLoadError": "Security activity could not be loaded.",
"action": {
"newDevice": "New-device sign-in",
"loginFailed": "Failed sign-in",
"login": "Sign-in",
"passwordChange": "Password changed",
"mfa": "Two-factor change",
"sessionRevoke": "Session signed out",
"token": "API token change",
"accountDelete": "Account deleted",
"dataClear": "Data reset",
"export": "Data export",
"other": "Security event"
},
"active": "Active",
"inactive": "Inactive",
"stepUpRequired": "For your security, sign in again to change your second factor.",
"useRecoveryCode": "Use a recovery code instead",
"useAuthenticator": "Use your authenticator app instead",
"totp": {
"title": "Authenticator app",
"description": "Use a time-based code from an authenticator app as your second factor.",
"setUp": "Set up",
"step1": "Scan the QR code with your authenticator app, or enter the secret manually.",
"step2": "Enter the 6-digit code the app shows to confirm.",
"qrAlt": "QR code for authenticator app setup",
"qrUnavailable": "QR code unavailable",
"manualEntry": "Or enter this secret manually",
"enterCode": "Enter the 6-digit code",
"verify": "Verify",
"setupFailed": "Could not start setup. Please try again.",
"invalidCode": "That code is not valid. Please try again.",
"disable": "Disable",
"disableTitle": "Disable two-factor authentication",
"disableConfirm": "Enter a current code to turn off your second factor. This also deletes your recovery codes.",
"currentCode": "Current code",
"disableFailed": "Could not disable the second factor."
},
"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.",
"download": "Download",
"remainingOne": "{count} recovery code remaining.",
"remainingOther": "{count} recovery codes remaining.",
"regenerate": "Regenerate codes",
"regenFailed": "Could not regenerate recovery codes.",
"savedIt": "I've saved them",
"regenerateTitle": "Regenerate recovery codes?",
"regenerateConfirm": "This replaces your current recovery codes. Your existing codes will stop working immediately, and a new set is shown only once."
},
"keys": {
"title": "Security keys",
"description": "Register a hardware or platform security key as a second factor.",
"empty": "No security keys registered yet.",
"add": "Add security key",
"addFailed": "Could not register the security key.",
"rename": "Rename",
"renameFailed": "Could not rename the security key.",
"remove": "Remove security key",
"removeFailed": "Could not remove the security key.",
"removeConfirm": "This security key will no longer work as a second factor.",
"lastUsed": "Last used {date}",
"neverUsed": "Never used",
"added": "added {date}",
"nameLabel": "Security key name"
},
"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."
},
"trustedDevices": {
"title": "Trusted devices",
"description": "Browsers you chose to trust skip the second factor for 30 days. The password is still required. Revoke any you don't recognize.",
"loadError": "Could not load trusted devices.",
"revokeError": "Could not revoke the device. Please try again.",
"revoke": "Revoke",
"revokeAll": "Forget all devices",
"revokeAllDone": "Forgot {count} trusted device(s).",
"unnamed": "Unknown device",
"current": "This device",
"expires": "Trusted until {date}",
"revokeConfirmTitle": "Stop trusting this device?",
"revokeConfirmBody": "It will ask for your second factor again the next time you sign in from it.",
"revokeAllConfirmTitle": "Stop trusting every device?",
"revokeAllConfirmBody": "Every device will ask for your second factor again the next time you sign in from it, including this one."
},
"revokeSessionConfirmTitle": "Sign this device out?",
"revokeSessionConfirmBody": "{device} will need to sign in again. Nothing recorded on it is affected.",
"signOutEverywhereConfirmTitle": "Sign out every other device?",
"signOutEverywhereConfirmBody": "Every device except this one will need to sign in again. This device stays signed in. Nothing you have recorded is affected."
},
"privacy": {
"intro": {
"title": "Your data stays yours",
"body": "HealthLog is self-hosted. This page brings together how your data is protected, how long it is kept, how to get it out, and how to delete it."
},
"encryption": {
"title": "Encrypted at rest",
"description": "Sensitive fields are encrypted in the database.",
"summary": "Your sensitive data is encrypted at rest with {algorithm} across {columns} fields in {models} record types.",
"statement": "Your sensitive data is encrypted at rest with AES-256-GCM."
},
"stored": {
"title": "What's stored",
"description": "The categories of data this account holds.",
"measurements": "Measurements (weight, blood pressure, pulse, glucose, sleep, body composition)",
"medications": "Medications and intake history",
"moodLabs": "Mood entries and lab results",
"coach": "Coach conversations",
"integrations": "Integration tokens (encrypted)",
"security": "Account and security activity (sessions, sign-in log)"
},
"retention": {
"title": "Retention",
"description": "How long time-bound records are kept before automatic cleanup.",
"coach": "Coach conversations: kept {days} days",
"audit": "Security activity log: kept {days} days",
"delivery": "Notification delivery log: kept {days} days",
"unavailable": "Retention details are unavailable right now."
},
"export": {
"title": "Download my data",
"description": "Export your records as CSV or JSON, optionally passphrase-encrypted, or generate a full health record.",
"openExport": "Export & backup",
"openHealthRecord": "Health record"
},
"delete": {
"title": "Delete or reset",
"description": "Remove your account entirely, or wipe your health records while keeping the account.",
"backupLag": "Deletion removes your data immediately. Encrypted off-host backups still contain it until they roll off the operator's backup retention window.",
"openAdvanced": "Delete or reset"
},
"posture": {
"title": "Privacy posture",
"description": "Control how much your data is shared with AI features and opt-in research.",
"openAi": "AI privacy mode",
"openResearch": "Research mode"
}
},
"mcp": {
"enableTitle": "Remote MCP endpoint",
"enableDescription": "Let an MCP-capable assistant (Claude.ai, ChatGPT) read your health data over a scoped token. Off by default.",
"enabled": "Enabled",
"disabled": "Disabled",
"enableToggleLabel": "Enable the MCP endpoint",
"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 read-only token to connect an assistant. The token is shown once.",
"scopeNote": "Tokens are scoped to health:read — read-only access to your own records. They 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.",
"connectionsTitle": "Connected assistants",
"connectionsDescription": "Assistants you authorized through the sign-in flow. Revoking a connection ends its access immediately, including its ability to refresh.",
"noConnections": "No connected assistants.",
"connectionConnected": "Connected",
"connectionLastUsed": "Last used",
"connectionNeverUsed": "Never used",
"connectionRevoke": "Disconnect",
"connectionRevokeDescription": "This ends the assistant's access immediately and stops it from renewing. It will need to be re-authorized to reconnect.",
"connectionRevokeFailed": "Could not disconnect the assistant."
},
"strava": "Strava",
"stravaDescription": "Connect your Strava account to sync your activities into your workout history.",
"stravaDescriptionSecondary": "Activities flow into your dashboard in the background. New to the setup? Follow the",
"stravaViewData": "View your workouts",
"stravaCredentials": "API Credentials",
"stravaClientId": "Client ID",
"stravaClientSecret": "Client Secret",
"stravaCredentialsSaved": "Credentials saved",
"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",
"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.",
"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.",
"state": "The response from Strava did not match any open connection request. Please start the connection again.",
"cross_user": "The response belongs to a request from a different account. Please restart the connection from your own account.",
"nocode": "Strava did not return an authorization code. Try again and allow access in the Strava dialog.",
"nocreds": "Strava is not configured on this server. Ask your administrator to add the Strava API credentials.",
"token": "The token exchange with Strava failed. Please start the connection again.",
"rate_limited": "Too many connection attempts. Wait a moment and try again.",
"generic": "Unknown error while connecting. Please start the connection again."
},
"appleHealth": {
"title": "Apple Health",
"description": "Live sync comes from the HealthLog iOS app. It is not a web or OAuth connection.",
"status": {
"checking": "Checking Apple Health data…",
"dataReceived": "Apple Health data received",
"setup": "Set up in iOS app",
"unavailable": "Apple Health status unavailable"
},
"lastDataLabel": "Last Apple Health data:",
"setupTitle": "Turn on live sync",
"permissionStep": "In the HealthLog iOS app, open Settings → Apple Health and allow the health categories you want to share.",
"backgroundStep": "Keep Background App Refresh enabled. The app syncs new data automatically in the foreground and when iOS grants background time.",
"importNote": "Need older history or cannot use the iOS app? The Apple Health XML/ZIP upload is a one-shot fallback and does not enable live sync.",
"importAction": "Open one-shot import"
},
"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.",
"docsLink": "Read the guide"
},
"glucoseReference": {
"title": "Glucose reference band",
"description": "Which band your blood-glucose readings are judged against.",
"enable": "Use the diabetes goal band",
"explainer": "Off, readings are judged against the general non-diabetic reference band. On, they are judged against the tighter glycaemic goal band from the ADA Standards of Care, and the Coach grounds its glucose remarks on that band instead. Your own target overrides below still take precedence.",
"disclaimer": "This selects a reference band. It is not a diagnosis, it is never inferred from a reading, and the app takes no clinical action on it. Which targets apply to you is a question for your clinician.",
"error": "Could not save the setting."
}
},
"admin": {
"title": "Administration",
"subtitle": "System status, users, and settings",
"settingsSaveError": "Failed to save settings",
"systemStatus": "System Status",
"systemStatusDescription": "Runtime state of this instance: database, worker, and record counts.",
"database": "Database",
"databaseConnected": "Connected",
"databaseError": "Error",
"startedAt": "Started",
"users": "Users",
"measurementsCount": "Measurements",
"activeTokens": "Active API Tokens",
"activeSessions": "Active Sessions",
"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.",
"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.",
"loadError": "Failed to load host metrics. Try refreshing the page."
},
"aiServerKey": {
"title": "AI server key",
"description": "An operator-wide provider key every account can fall back to when no personal key is configured.",
"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.",
"statusConfigured": "Configured",
"statusNotConfigured": "Not configured",
"keyLabel": "API key",
"keyPlaceholder": "sk-...",
"keyPlaceholderSet": "Stored ({preview}) — enter a new key to replace it",
"modelLabel": "Model",
"baseUrlLabel": "Base URL",
"save": "Save",
"remove": "Remove key",
"saved": "AI server key settings saved",
"error": "Saving the AI server key failed"
},
"aiQuality": {
"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.",
"windowLabel": "Last {days} days",
"generatedAtLabel": "Generated",
"colSeverity": "Severity",
"colMetric": "Metric",
"colProvider": "Provider",
"colPromptVersion": "Prompt",
"colHelpful": "Helpful",
"colNotHelpful": "Not helpful",
"colHelpfulRate": "Helpful rate"
},
"coachFeedback": {
"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.",
"windowLabel": "Last {days} days",
"generatedAtLabel": "Generated",
"colPromptVersion": "Prompt version",
"colTone": "Tone",
"colVerbosity": "Verbosity",
"colHelpful": "Helpful",
"colNotHelpful": "Not helpful",
"colN": "n",
"colHelpfulRate": "Helpful rate"
},
"workerStatus": "Job Worker",
"workerRunning": "Running",
"workerStopped": "Stopped",
"lastReminderCheck": "Last Reminder Check",
"appSettings": "Application Settings",
"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.",
"defaultLanguage": "Default language",
"defaultLanguageDescription": "Used for new users and as fallback.",
"defaultUserTimezone": "Default timezone for new accounts",
"defaultUserTimezoneDescription": "Used for new accounts that don't carry a browser-detected zone. Does not affect existing users.",
"defaultUserTimezoneFallback": "Europe/Berlin (default)",
"servicesGlobal": "Services (global)",
"servicesGlobalDescription": "Disabled services are not available to any user.",
"telegramGlobal": "Allow Telegram notifications.",
"ntfyGlobal": "Allow ntfy notifications.",
"webPushGlobal": "Allow browser push notifications.",
"moodLogGlobal": "Allow mood-log reminders.",
"integrationWebPush": "Web Push",
"offlineGeoLabel": "Geo data",
"offlineGeoEnabled": "Offline (GeoLite2)",
"offlineGeoFallback": "Online ({host}) — set MAXMIND_LICENSE_KEY in CI",
"apiGlobal": "Allow API endpoints and API tokens.",
"umamiTitle": "Umami",
"umamiDescription": "Web analytics with Umami",
"glitchtipTitle": "GlitchTip",
"glitchtipDescription": "Error tracking with GlitchTip",
"webPushVapidTitle": "Web Push VAPID",
"umamiEnabled": "Enable Umami tracking.",
"umamiScriptUrl": "Umami script URL",
"umamiScriptUrlPlaceholder": "https://analytics.example.com/script.js",
"umamiWebsiteId": "Umami website ID",
"umamiWebsiteIdPlaceholder": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
"glitchtipEnabled": "Enable GlitchTip error tracking.",
"glitchtipDsn": "GlitchTip DSN",
"glitchtipDsnPlaceholder": "https://<public-key>@glitchtip.example.com/<project-id>",
"glitchtipEnvironment": "GlitchTip environment",
"glitchtipEnvironmentPlaceholder": "production",
"webPushVapidDescription": "Configure VAPID keys and subject here so browser push works without environment variables.",
"webPushVapidPublicKey": "VAPID public key",
"webPushVapidPublicKeyPlaceholder": "BElx... (Base64URL)",
"webPushVapidPrivateKey": "VAPID private key",
"webPushVapidPrivateKeyPlaceholder": "Optional: enter a new private key",
"webPushVapidSubject": "VAPID subject",
"webPushVapidSubjectPlaceholder": "mailto:you@example.com",
"webPushVapidGenerate": "Generate keys",
"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?",
"webPushVapidGenerateConfirmTitle": "Regenerate VAPID keys?",
"webPushVapidRegenerate": "Regenerate",
"configured": "Configured",
"monitoringTestSuccess": "Test event sent",
"monitoringTestFailed": "Monitoring test failed",
"assistant": {
"title": "Assistant Surfaces",
"description": "Each toggle hides a model-driven surface app-wide without removing the provider configuration. The master kills every sub-flag at once.",
"master": {
"title": "Assistant enabled",
"description": "Master switch for every model-driven surface. When off, every sub-flag below is forced off."
},
"coach": {
"title": "Coach",
"description": "Chat drawer, launcher button, and the mobile FAB on every Insights page."
},
"briefing": {
"title": "Daily Briefing",
"description": "Briefing card, hero strip narration, recommendations grid, and the regenerate action."
},
"insightStatus": {
"title": "Status cards",
"description": "Per-metric status cards on every /insights sub-page."
},
"correlations": {
"title": "Correlations",
"description": "Correlation tile narration on the Insights overview."
},
"healthScoreExplainer": {
"title": "Health-Score explainer",
"description": "The ? glyph next to the Health-Score delta line. The delta digit stays visible regardless."
}
},
"modules": {
"title": "Module availability",
"description": "Turn a module off for the whole server. A module disabled here is off for every account regardless of personal preference. Core domains (weight, blood pressure, pulse, medications) are always on and cannot be disabled.",
"saveError": "Could not update module availability."
},
"invites": {
"title": "Invites",
"description": "Registration invite links — they work even while registration is closed. The link is shown only once.",
"adminOnlyHint": "Only admins can create and revoke invites.",
"create": "Create invite",
"createTitle": "Create invite",
"createDescription": "The link admits a signup even while registration is closed.",
"ttlLegend": "Valid for",
"createDays": "{days} days",
"maxUsesLabel": "Maximum uses",
"maxUsesHint": "How many signups this link admits (1–50).",
"createConfirm": "Create invite",
"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.",
"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.",
"copyError": "Copy failed.",
"qrAlt": "QR code for the invite link",
"loadError": "Could not load the invites.",
"emptyTitle": "No invites yet",
"emptyDescription": "Create an invite link to admit someone while registration is closed.",
"colStatus": "Status",
"colCreated": "Created",
"colExpires": "Expires",
"colUses": "Uses",
"colRedeemedBy": "Redeemed by",
"colActions": "Actions",
"byCreator": "by {by}",
"expiresInDaysOne": "in 1 day",
"expiresInDaysOther": "in {count} days",
"statusActive": "Active",
"statusExpired": "Expired",
"statusExhausted": "Used up",
"statusRevoked": "Revoked",
"redeemerDeleted": "deleted account",
"redeemedByMore": "{username} + {count} more",
"redemptionsTitle": "{count} redemptions",
"revoke": "Revoke",
"revokeAria": "Revoke invite",
"revokeConfirmTitle": "Revoke this invite?",
"revokeConfirmBody": "The invite link becomes invalid immediately. Accounts already registered through it remain, and the redemption history stays visible.",
"revokeConfirmAction": "Revoke",
"cancel": "Cancel",
"revokedToast": "Invite revoked.",
"revokeError": "Could not revoke the invite."
},
"userManagement": "User Management",
"userManagementDescription": "Manage accounts: roles, password resets, and forced logouts.",
"userName": "Name",
"userEmail": "Email",
"userRole": "Role",
"userPasskeys": "Passkeys",
"userCreated": "Created",
"userActions": "Actions",
"editUser": "Edit user",
"editUserTitle": "Edit user: {name}",
"demoteToUser": "Demote to user",
"promoteToAdmin": "Promote to admin",
"toUser": "Make user",
"toAdmin": "Make admin",
"ownRoleUnchangeable": "Cannot change own role",
"resetPassword": "Reset password",
"resetPasswordTitle": "Reset password: {name}",
"newPassword": "New password",
"newPasswordPlaceholder": "At least 12 characters",
"passwordReset": "Password has been reset",
"reset": "Reset",
"loadingUsers": "Loading users…",
"apiTokens": "API Tokens",
"apiTokensDescription": "All active and revoked API tokens across all accounts.",
"tokenUser": "User",
"tokenName": "Name",
"tokenPermissions": "Permissions",
"tokenPermissionAll": "All",
"tokenPermissionAllTooltip": "Wildcard permission — this token can call every API route.",
"tokenStatus": "Status",
"tokenLastUsed": "Last used",
"tokenCreated": "Created",
"tokenNeverUsed": "Never",
"tokensEmptyTitle": "No API tokens yet",
"tokensEmptyDescription": "Tokens are issued when a native client signs in or via Settings → Account.",
"loginOverview": "Login Overview",
"loginOverviewDescription": "Sign-in and auth events across all accounts, filterable and exportable as CSV.",
"allAuthEvents": "All auth events",
"failedOnly": "Failed only",
"loginEmptyDescription": "Sign-ins, sign-outs, and passkey changes will show up here.",
"loginEmptyFailedTitle": "No failed sign-in attempts",
"loginEmptyFailedDescription": "That's the safe state. Switch to all events to see successful sign-ins.",
"loginEmptyResetFilter": "Show all events",
"showingEntries": "Showing {count} of {total} auth entries",
"status": "Status",
"action": "Action",
"ip": "IP",
"location": "Location",
"timestamp": "Time",
"provider": "Provider",
"providerPassword": "Password",
"providerPasskey": "Passkey",
"providerApiToken": "API token",
"providerWithings": "Withings",
"providerUnknown": "Unknown",
"outcome": "Outcome",
"outcomeSuccess": "Success",
"outcomeFailed": "Failed",
"auditDetails": "Details",
"deleteAllData": "Delete all data globally",
"deleteAllDescription": "Deletes all measurement, medication, integration, and log data for all users. User accounts will be preserved.",
"deleteAllConfirm": "Really delete all data?",
"deleteAllConfirmDescription": "This will permanently delete all measurements, medications, intake events, API tokens, Withings connections, open authentication challenges, notification channels (Telegram, ntfy, Web Push), push subscriptions, and queued Telegram message deletions for all users. User accounts, the audit log, and submitted feedback are preserved so the wipe itself remains traceable and bug reports stay triageable.",
"deleteButton": "Delete all data",
"deleteAllPromptLabel": "Type {token} to continue",
"finalDelete": "Delete permanently",
"deletedResult": "Deleted: {measurements} measurements, {medications} medications, {intakeEvents} intakes, {apiTokens} API tokens, {withingsConnections} Withings connections, {authChallenges} auth challenges, {notificationChannels} notification channels, {pushSubscriptions} push subscriptions, {telegramScheduledDeletions} queued Telegram deletions. Feedback rows preserved.",
"authRegister": "Registration",
"authLogin": "Login",
"authLoginPasskey": "Passkey login",
"authLoginPassword": "Password login",
"authLoginFailed": "Failed",
"authLogout": "Logout",
"authPasskeyRegister": "Passkey added",
"authPasskeyDelete": "Passkey deleted",
"authTokenAutoissueNative": "Native client token issued",
"authTokenRefresh": "Token refreshed",
"authTokenRevoke": "Token revoked",
"medicationReminders": "Medication Reminders",
"medicationRemindersDescription": "Thresholds for reminder badge color transitions on medication cards.",
"notificationHealth": {
"title": "Notification health",
"description": "Delivery results across all users over the last 24 hours.",
"empty": "No notifications sent in this window.",
"ok": "OK",
"error": "Failed",
"skipped": "Skipped",
"autoDisabled": "Auto-disabled channels"
},
"reminderLateMinutes": "Late threshold (minutes)",
"reminderLateMinutesDescription": "Minutes after window end until the badge changes from yellow to orange.",
"reminderMissedMinutes": "Missed threshold (minutes)",
"reminderMissedMinutesDescription": "Minutes after window end until the intake is considered missed.",
"notificationTestSend": "Send test",
"notificationTestSuccess": "Test notification sent",
"notificationTestFailed": "Failed to send test notification",
"reminderCheckRun": "Run reminder check",
"reminderCheckSuccess": "Reminder check completed",
"reminderCheckFailed": "Failed to run reminder check",
"reminderCheckResults": "Results",
"reminderCheckNotifOn": "Notifications on",
"reminderCheckNotifOff": "Notifications off",
"reminderCheckEventsToday": "Events today",
"reminderCheckNotifSent": "Sent",
"shell": {
"overview": "Overview",
"sectionsNav": "Admin sections"
},
"overview": {
"welcomeTitle": "Welcome, {name}",
"welcomeSubtitle": "You are signed in as administrator. Pick a section to manage HealthLog.",
"snapshotTitle": "System snapshot",
"snapshotVersion": "Version",
"snapshotDatabase": "Database",
"snapshotWorker": "Worker",
"snapshotStarted": "Started",
"snapshotBuildSha": "Build SHA",
"snapshotBuiltAt": "Built at",
"snapshotOfflineGeo": "Geo data",
"snapshotOfflineGeoOn": "Offline (GeoLite2)",
"snapshotOfflineGeoOff": "Online ({host})",
"versionTileTitle": "Version",
"versionTileVersion": "Running version",
"versionTileBuildSha": "Build SHA",
"versionTileBuiltAt": "Built at",
"versionTileUpdateAvailable": "Update available: {tag}",
"versionTileUpToDate": "Up to date",
"snapshotLoadError": "Failed to load system snapshot.",
"snapshotLoading": "Loading snapshot…",
"auditTitle": "Recent activity",
"auditEmpty": "No recent audit entries.",
"auditLoadError": "Failed to load recent activity.",
"auditLoading": "Loading activity…",
"auditViewAll": "View all"
},
"section": {
"system-status": {
"title": "System Status",
"subtitle": "Worker, database, and integration health at a glance."
},
"general": {
"title": "General",
"subtitle": "Registration, default language, and other app-wide toggles."
},
"services": {
"title": "Services",
"subtitle": "Enable or disable notification channels and integrations system-wide."
},
"integrations": {
"title": "Integrations",
"subtitle": "Configure Umami, GlitchTip, Web Push, and bug reports."
},
"coach": {
"title": "Coach",
"subtitle": "Assistant surfaces, server key, and the Coach and Insights feedback-quality tables in one place."
},
"reminders": {
"title": "Reminders",
"subtitle": "Tune medication reminder thresholds and run a manual check."
},
"users": {
"title": "Users",
"subtitle": "Manage user accounts, roles, and active sessions.",
"filter": {
"all": "All",
"admin": "Admins",
"user": "Users"
},
"forceLogout": "Force logout",
"forceLogoutConfirmTitle": "Force logout {name}?",
"forceLogoutConfirmBody": "All active sessions for this user will be revoked. They will need to sign in again on every device.",
"forceLogoutSuccess": "Logged {name} out of {count} session(s)",
"forceLogoutFailed": "Failed to force logout",
"cannotLogoutSelf": "Cannot force-logout yourself",
"emptyTitle": "No users in this view",
"emptyDescription": "There are no users matching the current filter.",
"emptyResetFilter": "Show all users"
},
"invites": {
"title": "Invites",
"subtitle": "Mint, track, and revoke registration invite links."
},
"api-tokens": {
"title": "API Tokens",
"subtitle": "Active bearer tokens issued to native clients and integrations."
},
"login-overview": {
"title": "Login Overview",
"subtitle": "Audit trail of authentication and admin events."
},
"auditLog": {
"filterActor": "Actor (user id or username)",
"filterAction": "Action",
"filterActionAll": "All actions",
"filterTarget": "Target (id or path)",
"filterDate": "Date range",
"range24h": "Last 24 hours",
"range7d": "Last 7 days",
"range30d": "Last 30 days",
"rangeAll": "All time",
"perPage": "Per page",
"prev": "Previous",
"next": "Next",
"pageOf": "Page {page} of {total}",
"export": "Export CSV",
"empty": "No audit entries match the current filters."
},
"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. Buffer is volatile and capped at 500 entries.",
"filterTraceId": "Trace ID",
"filterAction": "Action contains…",
"filterLevel": "Level",
"levelAll": "All levels",
"filterRange": "Time window",
"range15m": "Last 15 minutes",
"range1h": "Last hour",
"range6h": "Last 6 hours",
"rangeAll": "Whole buffer",
"colLevel": "Level",
"colTimestamp": "Timestamp",
"colAction": "Action",
"colDuration": "Duration",
"colTraceId": "Trace",
"viewDetails": "View details for {action} at {timestamp}",
"showing": "Showing {count} of up to {bufferMax} buffered events",
"empty": "Buffer is empty",
"emptyDescription": "No events match the current filters yet. Hit refresh after triggering some traffic.",
"refresh": "Refresh",
"eventDetails": "Event details",
"closeDetails": "Close details"
},
"backups": {
"title": "Backups",
"subtitle": "Weekly per-user data snapshots stored in PostgreSQL.",
"description": "Each user gets one rolling snapshot per backup type. Sizes show the encrypted blob — payloads are not downloadable from this page.",
"runNow": "Backup now",
"runEnqueued": "Backup job enqueued",
"runFailed": "Failed to enqueue backup",
"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.",
"colUser": "User",
"colType": "Type",
"typeWeeklyAuto": "Weekly (auto)",
"typeManual": "Manual",
"colSize": "Size",
"colCreatedAt": "Last snapshot",
"colActions": "Actions",
"retentionLabel": "Retention: {days} days",
"download": "Download",
"downloadAria": "Download backup for {username}",
"downloadFailed": "Download failed",
"downloadStarted": "Download started",
"uploadTitle": "Upload backup",
"uploadDescription": "Validate a backup file and store it as a manual snapshot. Restoring is a separate step.",
"uploadButton": "Upload file",
"uploadHelp": "JSON file matching the current backup schema. Max 10 MB.",
"uploadSuccess": "Backup uploaded ({count} records)",
"uploadFailed": "Upload failed",
"restore": "Restore",
"restoreAria": "Restore from backup for {username}",
"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. If included in the snapshot, instance-wide settings overwrite the configuration for the entire installation.",
"restorePromptLabel": "Type RESTORE to continue",
"restoreConfirm": "Restore now",
"restoreInProgress": "Restoring…",
"restoreSuccess": "Restore complete",
"restoreFailed": "Restore failed",
"docsLink": "Documentation"
},
"danger-zone": {
"title": "Danger Zone",
"subtitle": "Destructive system-wide operations."
},
"about": {
"title": "About",
"subtitle": "Version, license, and update status."
},
"module-availability": {
"title": "Modules",
"subtitle": "Turn modules on or off for every account on this server."
},
"encryption": {
"title": "Encryption",
"subtitle": "Encryption coverage and key-rotation status for data at rest.",
"loading": "Loading encryption status…",
"loadError": "Failed to load encryption status.",
"coverageTitle": "Coverage",
"coverageDescription": "How many encrypted rows sit under each key id. Only key ids and counts are shown — never key material.",
"activeKeyId": "Active key id",
"configuredKeys": "Configured keys",
"totalRows": "Encrypted rows",
"staleRows": "Rows not on the active key",
"safeToDropLegacy": "Safe to drop the legacy key",
"rotationIncomplete": "{count} rows still need rotation",
"rotationTitle": "Key rotation",
"rotationDescription": "Re-encrypt every encrypted column to the active key. The command-line tool stays the canonical path; this trigger is a convenience.",
"rotationState": "State",
"lastRun": "Last run: scanned {scanned}, rotated {rotated}, errors {errors}.",
"rotateNow": "Rotate now",
"rotateConfirmTitle": "Re-encrypt the whole record?",
"rotateConfirmDescription": "Re-encrypts every encrypted column to the active key. It never adds or drops a key and is safe to re-run. This can take a while on large accounts.",
"cancel": "Cancel",
"rotateConfirm": "Start rotation",
"rotateEnqueued": "Rotation started.",
"rotateFailed": "Could not start the rotation.",
"stepUpNeeded": "A fresh second factor is required. Confirm your second factor, or use the command-line tool if you have no second factor enrolled.",
"cliNote": "A second factor is required to use this button. Operators without one rotate with scripts/rotate-encryption-key.ts.",
"columnsTitle": "Per-column coverage",
"columnsDescription": "Each encrypted column with its row counts on the active key versus older keys.",
"colColumn": "Column",
"colTotal": "Total",
"colActive": "On active key",
"colStale": "Stale",
"state": {
"idle": "Idle",
"running": "Running",
"completed": "Completed",
"failed": "Failed"
}
}
},
"carrier": "Carrier",
"mfaRequired": "Require a second factor",
"mfaRequiredDescription": "Every account without an active second factor is sent to enrollment after sign-in. This prompts web users to enroll — it does not block direct API or native (Bearer) access for accounts not yet enrolled.",
"mfaEnforcedOn": "MFA on",
"mfaEnforcedOff": "MFA off",
"mfaEnforcedOnHint": "A second factor is required for this user. Click to stop requiring it.",
"mfaEnforcedOffHint": "Require a second factor for this user.",
"copyIp": "Copy IP address",
"ipCopied": "IP address copied",
"copyFailed": "Could not copy.",
"documentMaxFile": "Document upload limit",
"documentMaxFileDescription": "Per-file size cap for the document vault (1–100 MB).",
"documentQuota": "Document storage quota",
"documentQuotaDescription": "Default per-account document storage (0.1–1024 GB).",
"userDocumentQuota": "Document quota override",
"userDocumentQuotaDefault": "Default",
"userDocumentQuotaHint": "Leave empty to use the instance default.",
"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.",
"statusConnected": "Connected",
"statusDisconnected": "Not connected",
"statusExpired": "Expired",
"connectButton": "Connect a ChatGPT account",
"disconnectButton": "Disconnect",
"connectedSince": "Connected since {when}",
"connected": "Shared AI connection linked",
"disconnected": "Shared AI connection removed",
"error": "Something went wrong — please try again"
}
},
"achievements": {
"title": "Achievements",
"subtitle": "Earn achievements by tracking your health and taking your meds on time.",
"loginRequired": "Please sign in to view achievements.",
"points": "Points",
"unlocked": "Unlocked",
"nextGoal": "Next goal",
"allCompleted": "All achievements unlocked!",
"completed": "Completed",
"goalReached": "Goal reached",
"remainingUnlocks": "{count} still unlockable",
"noneUnlockedYet": "No achievements unlocked yet.",
"pointsValue": "{points} points",
"metricCount": "{count}",
"metricDays": "{count} days",
"metricPercent": "{count}%",
"badges": {
"intakeTotal1": {
"title": "First intake",
"description": "Record your first taken medication event."
},
"intakeTotal10": {
"title": "Intake starter",
"description": "Record 10 taken medication events."
},
"intakeTotal50": {
"title": "Intake routine",
"description": "Record 50 taken medication events."
},
"intakeTotal150": {
"title": "Intake expert",
"description": "Record 150 taken medication events."
},
"intakeTotal300": {
"title": "Intake legend",
"description": "Record 300 taken medication events."
},
"overIntake1": {
"title": "Double take",
"description": "Take medication at least once more than planned."
},
"skippedIntake1": {
"title": "Stepped back",
"description": "Skip at least one planned intake."
},
"passkeyCreated1": {
"title": "Passkey set up",
"description": "Create your first passkey."
},
"passkeyLogin1": {
"title": "Passkey login",
"description": "Sign in at least once with a passkey."
},
"passwordLogin1": {
"title": "Old school",
"description": "Sign in at least once with username and password."
},
"loginStreak7": {
"title": "Login streak 7d",
"description": "Sign in on 7 consecutive days."
},
"loginStreak30": {
"title": "Login streak 30d",
"description": "Sign in on 30 consecutive days."
},
"onTimePerfect1": {
"title": "On-time 1d",
"description": "Take all medications on time for 1 day."
},
"compliance801": {
"title": "80% adherence · 1d",
"description": "Reach at least 80% 30-day adherence for 1 day."
},
"bmiGreen1": {
"title": "BMI green · 1d",
"description": "Keep your BMI in the normal range for 1 day."
},
"bpGreen1": {
"title": "BP green · 1d",
"description": "Keep your blood pressure in the normal range for 1 day."
},
"pulseGreen1": {
"title": "Pulse green · 1d",
"description": "Keep your resting pulse in the normal range for 1 day."
},
"onTimePerfect7": {
"title": "On-time 7d",
"description": "Take all medications on time for 7 consecutive days."
},
"compliance807": {
"title": "80% adherence · 7d",
"description": "Reach at least 80% 30-day adherence for 7 consecutive days."
},
"bmiGreen7": {
"title": "BMI green · 7d",
"description": "Keep your BMI in the normal range for 7 consecutive days."
},
"bpGreen7": {
"title": "BP green · 7d",
"description": "Keep your blood pressure in the normal range for 7 consecutive days."
},
"pulseGreen7": {
"title": "Pulse green · 7d",
"description": "Keep your resting pulse in the normal range for 7 consecutive days."
},
"onTimePerfect30": {
"title": "On-time 30d",
"description": "Take all medications on time for 30 consecutive days."
},
"compliance8030": {
"title": "80% adherence · 30d",
"description": "Reach at least 80% 30-day adherence for 30 consecutive days."
},
"bmiGreen30": {
"title": "BMI green · 30d",
"description": "Keep your BMI in the normal range for 30 consecutive days."
},
"bpGreen30": {
"title": "BP green · 30d",
"description": "Keep your blood pressure in the normal range for 30 consecutive days."
},
"pulseGreen30": {
"title": "Pulse green · 30d",
"description": "Keep your resting pulse in the normal range for 30 consecutive days."
},
"onTimePerfect180": {
"title": "On-time 180d",
"description": "Take all medications on time for 180 consecutive days."
},
"compliance80180": {
"title": "80% adherence · 180d",
"description": "Reach at least 80% 30-day adherence for 180 consecutive days."
},
"bmiGreen180": {
"title": "BMI green · 180d",
"description": "Keep your BMI in the normal range for 180 consecutive days."
},
"bpGreen180": {
"title": "BP green · 180d",
"description": "Keep your blood pressure in the normal range for 180 consecutive days."
},
"pulseGreen180": {
"title": "Pulse green · 180d",
"description": "Keep your resting pulse in the normal range for 180 consecutive days."
},
"onTimePerfect360": {
"title": "On-time 360d",
"description": "Take all medications on time for 360 consecutive days."
},
"compliance80360": {
"title": "80% adherence · 360d",
"description": "Reach at least 80% 30-day adherence for 360 consecutive days."
},
"bmiGreen360": {
"title": "BMI green · 360d",
"description": "Keep your BMI in the normal range for 360 consecutive days."
},
"bpGreen360": {
"title": "BP green · 360d",
"description": "Keep your blood pressure in the normal range for 360 consecutive days."
},
"pulseGreen360": {
"title": "Pulse green · 360d",
"description": "Keep your resting pulse in the normal range for 360 consecutive days."
},
"moodFirst": {
"title": "First mood",
"description": "Log your first mood entry."
},
"moodStreak7": {
"title": "Mood diarist 7d",
"description": "Log a mood entry on 7 consecutive days."
},
"moodStreak30": {
"title": "Mood diarist 30d",
"description": "Log a mood entry on 30 consecutive days."
},
"moodUp7": {
"title": "Brighter week",
"description": "Your 7-day mood average improved by at least 1.0 point compared to the previous week."
},
"weightFirst": {
"title": "First weigh-in",
"description": "Record your first weight measurement."
},
"weight50": {
"title": "Fifty weigh-ins",
"description": "Record 50 weight measurements."
},
"weight200": {
"title": "200 weigh-ins",
"description": "Record 200 weight measurements."
},
"bpFirst": {
"title": "First reading",
"description": "Record your first blood-pressure measurement."
},
"bp50": {
"title": "Fifty BP readings",
"description": "Record 50 blood-pressure measurements."
},
"bp200": {
"title": "200 BP readings",
"description": "Record 200 blood-pressure measurements."
},
"pulseFirst": {
"title": "First pulse",
"description": "Record your first pulse measurement."
},
"consistentMonth": {
"title": "Consistent month",
"description": "Log entries on at least 25 distinct days within a single calendar month."
},
"entryStreak7": {
"title": "Tracker streak 7d",
"description": "Log at least one entry on 7 consecutive days."
},
"entryStreak30": {
"title": "Tracker streak 30d",
"description": "Log at least one entry on 30 consecutive days."
},
"weekendWarrior": {
"title": "Weekend tracker",
"description": "Log entries on 4 consecutive Saturday + Sunday weekend pairs."
},
"hiddenNightOwl": {
"title": "Night owl",
"description": "Logged an entry between 02:00 and 04:00 in the morning."
},
"hiddenEarlyBird": {
"title": "Early bird",
"description": "Logged an entry between 04:00 and 06:00 in the morning."
},
"hiddenLeapDay": {
"title": "Leap-day legend",
"description": "Logged an entry on February 29."
},
"hiddenDoctorPdf": {
"title": "House call",
"description": "Exported your first doctor-report PDF."
},
"hiddenLocaleFlip": {
"title": "Polyglot",
"description": "Switched the app language at least once."
},
"missFree7": {
"title": "No dose missed · 7d",
"description": "7 consecutive days without a missed dose."
},
"missFree30": {
"title": "No dose missed · 30d",
"description": "30 consecutive days without a missed dose."
},
"missFree90": {
"title": "No dose missed · 90d",
"description": "90 consecutive days without a missed dose."
},
"measurementWeeks4": {
"title": "Measuring routine",
"description": "4 consecutive weeks with measurements on at least 5 days each."
},
"selfContextComplete": {
"title": "Self-report maintained",
"description": "All four self-report fields filled in — the Coach knows your context."
},
"sleepLog7": {
"title": "Sleep log · 7d",
"description": "Sleep data recorded on 7 consecutive days."
}
},
"nextProgressLabel": "Progress to unlock",
"completedOn": "Completed on {date}",
"locked": "Locked",
"criterionHint": "{current} / {target}",
"progressPercent": "{percent}%",
"categories": {
"medication": "Medication",
"vitals": "Vitals",
"mood": "Mood",
"security": "Account & security",
"engagement": "Engagement",
"hidden": "Hidden"
},
"hiddenCard": {
"title": "Hidden achievement",
"description": "Keep tracking — you might just stumble across it.",
"ariaLabel": "Hidden locked achievement"
},
"hiddenUnlockToast": {
"title": "You unlocked a hidden achievement!"
},
"dashboardCard": {
"title": "Recent unlocks",
"viewAll": "View all",
"empty": "No achievements yet — keep logging to unlock your first."
}
},
"notifications": {
"title": "Notifications",
"eventColumn": "Event",
"subtitle": "Choose which notifications you want to receive through which channel.",
"loadError": "Notification preferences could not be loaded.",
"noChannels": "Configure a notification channel in Settings → Integrations first.",
"goToSettings": "Go to channel settings",
"channelDisabled": "Disabled",
"admin": {
"deployFailedTitle": "Deployment failed: {application}",
"deployFailedBody": "An error occurred while deploying {application} (#{deployment}): {error}. View logs: {logsUrl}",
"testNotificationTitle": "HealthLog test notification",
"testNotificationBody": "This test notification was triggered from the admin panel. If you can see it, the channel is working.",
"reminderCheckMissedTitle": "Reminder missed: {medication}",
"reminderCheckMissedBody": "{medication} ({dose}) was not logged in the {window} window.",
"reminderCheckOverdueTitle": "Dose overdue: {medication}",
"reminderCheckOverdueBody": "{medication} ({dose}) in the {window} window is {minutes} minutes overdue.",
"offlineGeoUnavailableTitle": "Offline geolocation databases not loaded",
"offlineGeoUnavailableBody": "HealthLog is resolving login locations through the online ipwho.is fallback. To enable the offline GeoLite2-City + GeoLite2-ASN databases, set MAXMIND_LICENSE_KEY in GitHub Actions secrets at {secretsUrl} and redeploy. Until then the carrier column on the login overview stays empty.",
"tlsPinChangedTitle": "TLS leaf certificate changed: {host}",
"tlsPinChangedBody": "The TLS leaf served by {host} now has SPKI pin {servedPin}, which is not in the known pin set. Pinned clients (the native app) will fail to connect once the old pin is gone. Re-extract the new leaf pin, add it to TLS_LEAF_SPKI_PINS and the native client's pin set, and ship a build before this certificate expires on {validTo}. See docs/ops/tls-cert-pin.md."
},
"user": {
"telegramTestBody": "HealthLog: connection successful. Telegram notifications are active."
},
"moodReminder": {
"title": "Daily mood reminder",
"description": "A gentle nudge at your chosen time when you haven't logged a mood for the day. Routes only through channels you've already configured (Telegram, ntfy, Web Push, Apple Push) and stays silent once you've logged today.",
"toggleAria": "Toggle daily mood reminder",
"statusOn": "Active at your chosen time",
"statusOff": "Off",
"enabledToast": "Mood reminder enabled.",
"disabledToast": "Mood reminder disabled.",
"saveError": "Save failed. Please try again.",
"hourLabel": "Reminder time",
"hourAria": "Mood reminder hour",
"hourSavedToast": "Reminder time updated."
},
"coachNudge": {
"title": "Proactive Coach",
"description": "Reaches out when your data suggests a look at the Coach — for example low medication adherence or an elevated weekly blood-pressure average. Topics and frequency are adjustable.",
"toggleAria": "Toggle proactive Coach nudges",
"statusOn": "Active",
"statusOff": "Off",
"groupsLabel": "Topics",
"groupMedication": "Medication",
"groupMedicationDesc": "Patchy intakes over the past week.",
"groupVitals": "Vitals",
"groupVitalsDesc": "Blood pressure, recovery, weight trend, sleep.",
"groupRoutine": "Routine",
"groupRoutineDesc": "Abrupt tracking stops and self-context check-ups.",
"frequencyLabel": "Frequency",
"frequencyWeekly": "At most once a week",
"frequencyBiweekly": "At most every two weeks",
"frequencyAria": "Select nudge frequency",
"enabledToast": "Proactive Coach nudges enabled.",
"disabledToast": "Proactive Coach nudges disabled.",
"saveError": "Could not save. Please try again later.",
"suggestionsLabel": "Example suggestions",
"suggestionsDesc": "Show the occasional ready-made example question on the Coach screen.",
"suggestionsAria": "Toggle example Coach suggestions",
"aiComposedLabel": "Let the Coach phrase the nudge",
"aiComposedDesc": "When a provider is available, the proactive nudge is written by the model instead of the fixed template. Off by default.",
"aiComposedAria": "Toggle AI-composed proactive nudge"
},
"lowStock": {
"title": "Low-stock alert",
"description": "Checks your tracked medication supplies once a day and notifies you when one covers fewer days than this threshold. One notification per shortage; it re-arms after a refill.",
"toggleAria": "Toggle low-stock alerts",
"statusOn": "Active",
"statusOff": "Off",
"daysLabel": "Notify below (days)",
"daysAria": "Select the low-stock threshold in days",
"leadLabel": "Reorder lead time (days)",
"leadAria": "Reorder lead time in days",
"leadHelp": "The alert fires this many days plus one dose-interval earlier so a refill arrives before your last dose. A single medication can override this on its supply tab.",
"leadSavedToast": "Reorder lead time saved.",
"savedToast": "Low-stock threshold saved.",
"enabledToast": "Low-stock alerts enabled.",
"disabledToast": "Low-stock alerts disabled.",
"saveError": "Could not save. Please try again.",
"medicationsLink": "Go to your medications"
},
"eventMedicationReminder": "Medication reminder",
"eventMedicationReminderDesc": "Sent at each scheduled dose time.",
"eventMeasurementAnomaly": "Unusual measurement",
"eventMeasurementAnomalyDesc": "Sent when a reading is well outside your usual range.",
"eventComplianceLow": "Low adherence",
"eventComplianceLowDesc": "Sent when your adherence over the last few days drops below 80 %.",
"eventWithingsSyncFailed": "Withings sync failed",
"eventWithingsSyncFailedDesc": "Sent when Withings synchronisation fails multiple attempts in a row.",
"eventSystemAlert": "System notice",
"eventSystemAlertDesc": "General messages from the HealthLog server, e.g. maintenance windows or account notes.",
"eventPersonalRecord": "Personal record",
"eventPersonalRecordDesc": "Sent when a reading beats your previous best.",
"eventMoodReminder": "Mood reminder",
"eventMoodReminderDesc": "Daily nudge to log your current mood.",
"eventCyclePeriodSoon": "Period coming up",
"eventCyclePeriodSoonDesc": "Sent a couple of days before your predicted next period.",
"eventCyclePeriodConfirm": "Did your period start?",
"eventCyclePeriodConfirmDesc": "A gentle check-in on or after the predicted start while no period is logged.",
"eventCycleFertileSoon": "Fertile window coming up",
"eventCycleFertileSoonDesc": "Sent a few days before your estimated fertile window when your goal is trying to conceive.",
"eventMedicationLowStock": "Medication stock low",
"eventMedicationLowStockDesc": "When a tracked medication supply covers fewer days than your low-stock threshold",
"eventCoachNudge": "Coach nudge",
"eventCoachNudgeDesc": "Occasional prompt from your Coach when your recent trends warrant a check-in.",
"eventMeasurementReminder": "Measurement reminder",
"eventMeasurementReminderDesc": "Sent when a tracked measurement is due.",
"eventMedicationIntakeSync": "Medication intake sync",
"eventMedicationIntakeSyncDesc": "Cross-device update when a dose is logged, taken or skipped.",
"eventDailyBriefing": "Daily briefing",
"eventDailyBriefingDesc": "One calm morning summary of your day's read. Off until you turn it on.",
"security": {
"newDeviceTitle": "New sign-in to your account",
"newDeviceBody": "A new sign-in from {device} ({location}). If this wasn't you, change your password immediately.",
"unknownLocation": "unknown location"
},
"loginRequired": "Please sign in to manage notifications.",
"someChannelsGloballyDisabled": "One or more channels are turned off in Settings and won’t receive notifications.",
"reminderSettingsLink": "Reminder settings",
"channelsLink": "Channels"
},
"i18n": {
"maintainershipBanner": {
"notice": "This locale is machine-translated including the Coach's safety-critical instructions. Automated drift-guard runs in CI; please report any Coach regressions on GitHub.",
"cta": "Report on GitHub",
"dismiss": "Dismiss"
}
},
"targets": {
"bmi": "BMI",
"average30d": "30-day average:",
"consistency": {
"ariaLabel": "Last 7 days, in-range status per day",
"daysInRange": "{count} of {total} in range",
"daysLogged": "{count} of {total} logged",
"dotInRange": "in range",
"dotNearRange": "near range",
"dotOutOfRange": "out of range",
"dotNotLogged": "not logged",
"relativeDay": {
"today": "today",
"yesterday": "yesterday",
"twoDaysAgo": "2 days ago",
"threeDaysAgo": "3 days ago",
"fourDaysAgo": "4 days ago",
"fiveDaysAgo": "5 days ago",
"sixDaysAgo": "6 days ago"
}
},
"edit": {
"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",
"maxLabel": "Max",
"systolicMin": "Systolic min",
"systolicMax": "Systolic max",
"diastolicMin": "Diastolic min",
"diastolicMax": "Diastolic max",
"boundsHint": "Allowed range: {min}–{max} {unit}",
"resetToDefault": "Reset to default",
"saveSuccess": "Target range updated",
"saveError": "Could not save the target range",
"resetSuccess": "Target range reset to default",
"validationOrder": "The minimum must be lower than the maximum.",
"validationBounds": "Enter values within the allowed range shown below."
},
"currentValue": "Current: {value} {unit}",
"targetRangeValue": "Target: {min}–{max} {unit}",
"sourceLabel": "Source: {source}",
"inTarget": "Within target range",
"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",
"status": {
"underweight": "Underweight",
"normal": "Normal",
"overweight": "Overweight",
"obesityGrade1": "Obesity Grade I",
"obesityGrade2": "Obesity Grade II",
"obesityGrade3": "Obesity Grade III",
"optimal": "Optimal",
"highNormal": "High-normal",
"hypertensionGrade1": "Hypertension Grade 1",
"hypertensionGrade2": "Hypertension Grade 2",
"hypertensionGrade3": "Hypertension Grade 3",
"belowTypicalRange": "Below typical range",
"elevated": "Elevated",
"aboveTypicalRange": "Above typical range",
"significantlyLow": "Significantly low",
"slightlyLow": "Slightly low",
"onTarget": "On target",
"slightlyElevated": "Slightly elevated",
"significantlyElevated": "Significantly elevated",
"farTooShort": "Far too short",
"tooShort": "Too short",
"slightlyLong": "Slightly long",
"farTooLong": "Far too long",
"belowEssential": "Below essential",
"essential": "Essential",
"athletic": "Athletic",
"fitness": "Fitness",
"acceptable": "Acceptable",
"obese": "Obese",
"veryLow": "Very low",
"lowActive": "Low active",
"moderatelyActive": "Moderately active",
"active": "Active",
"veryActive": "Very active",
"good": "Good",
"moderate": "Moderate",
"low": "Low",
"high": "High",
"veryGood": "Very good",
"veryStable": "Very stable",
"stable": "Stable",
"fluctuating": "Fluctuating"
}
},
"passwordStrength": {
"veryWeak": "Very weak",
"weak": "Weak",
"acceptable": "Acceptable",
"strong": "Strong",
"veryStrong": "Very strong",
"tooShort": "Too short",
"characters": "characters",
"minLength": "At least {count} characters required."
},
"telegram": {
"errorInvalidAction": "Invalid action.",
"errorMedicationNotFound": "Medication not found.",
"errorMedicationInactive": "Medication not found or inactive.",
"errorUnknownAction": "Unknown action.",
"snoozeOneHour": "1 hour",
"snoozeThreeHours": "3 hours",
"snoozedFor": "{name} snoozed for {duration}.",
"skipped": "{name} skipped.",
"alreadyRecorded": "{name} was already recorded.",
"recordedAsTaken": "{name} recorded as taken.",
"confirmed": "{name} confirmed.",
"genericConfirmed": "Confirmed.",
"cancelled": "Cancelled.",
"moodLogged": "Logged: {score}/5",
"moodNotePrompt": "Add a short note (optional).",
"moodNoteSaved": "Note saved.",
"moodNoteExpired": "That prompt has expired.",
"remindLater": "Reminder postponed for {duration}.",
"measurementDone": "Marked as done.",
"measurementNotFound": "Reminder not found.",
"buttonMoodNote": "Note…",
"buttonLater": "Later",
"buttonDone": "Done",
"noActiveMedications": "No active medications found.",
"whichMedication": "<b>Which medication did you take?</b>",
"cancelButton": "Cancel",
"askMedicationName": "Please specify a medication, e.g. <b>taken Ramipril</b>.",
"medicationNotFoundExact": "Medication not found. Please send the name exactly as in HealthLog.",
"helpHeader": "<b>Available commands:</b>",
"helpBody": "/help — show this help\n/add — record an intake\n/start — start the bot\n\n<b>Text commands:</b>\ntaken &lt;name&gt; — confirm an intake\n\n<b>Buttons in reminders:</b>\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.",
"measureValueInvalid": "Reply with a number to log a reading.",
"measureValueOutOfRange": "That value is outside the plausible range.",
"measureValueExpired": "That prompt has expired."
},
"medicationReminders": {
"phaseGreenTitle": "🟢 Reminder: {medName}",
"phaseGreenMessage": "🟢 Reminder:\n<b>{medName}</b> ({doseInfo}, {timeWindow})\nWindow closes in {minutes} min.",
"phaseYellowTitle": "🟡 Due soon: {medName}",
"phaseYellowMessage": "🟡 Due soon:\n<b>{medName}</b> ({doseInfo}, {timeWindow})\n{minutes} min left.",
"phaseOrangeTitle": "🟠 Overdue: {medName}",
"phaseOrangeMessage": "🟠 Overdue:\n<b>{medName}</b> ({doseInfo}, {timeWindow})\nOverdue by {minutes} min.",
"phaseRedTitle": "🔴 Missed: {medName}",
"phaseRedMessage": "🔴 Missed:\n<b>{medName}</b> ({doseInfo}, {timeWindow})\nMarked as missed.",
"buttonTaken": "Taken",
"buttonConfirm": "✓ Confirm",
"buttonSnoozeOneHour": "🕐 1h",
"buttonSnoozeThreeHours": "🕐 3h",
"buttonSkip": "⏭ Skip"
},
"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}."
},
"moodReminders": {
"dailyTitle": "Log your mood",
"dailyBody": "How are you feeling today?"
},
"coachNudges": {
"greetingMorning": "Good morning",
"greetingMorningNamed": "Good morning, {name}",
"greetingHey": "Hey there",
"greetingHeyNamed": "Hey {name}",
"complianceBody": "Your medication routine slipped a little this week. If you like, we can look at what would make it easier to keep up.",
"bpBody": "Your blood pressure has been running a touch above your usual range this week. Whenever you're ready, I'm happy to look at it with you.",
"scoreBody": "Your recovery has been easing off over the last few days. If you're curious what's behind it, I'm here to talk it through.",
"selfContextBody": "It's been a while since your self-description was updated. When you have a moment, refreshing it helps me understand you better.",
"weightBody": "Your weight has drifted a little from your target range lately. If you'd like, we can take stock together, calmly.",
"sleepDebtBody": "Several of your nights came up short this week. If you want, we can look for a pattern together.",
"measurementGapBody": "Your log has been quiet for about a week. Whenever it suits you, a quick check-in helps you pick things back up.",
"focusNote": "It also ties into what you said you wanted to keep an eye on.",
"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?"
},
"clinicianView": {
"title": "Shared health record",
"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.",
"vitals": "Vital signs",
"labs": "Lab values",
"medications": "Medications & adherence",
"bmi": "Body mass index (BMI)",
"statSummary": "latest {latest} (avg {avg}, range {min}–{max})",
"adherence": "{rate} adherence",
"noAdherence": "—",
"glucose": {
"FASTING": "Glucose (fasting)",
"POSTPRANDIAL": "Glucose (postprandial)",
"RANDOM": "Glucose (random)",
"BEDTIME": "Glucose (bedtime)"
},
"wellness": {
"title": "Wellness scores",
"disclaimer": "Descriptive scores (0–100) computed from tracked signals. These are not a clinical assessment and not a diagnosis.",
"recovery": "Recovery score",
"stress": "Stress score",
"strain": "Strain score",
"score": "Wellness score"
},
"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.",
"label": "Passphrase",
"error": "That passphrase is not correct.",
"submit": "Unlock"
},
"loadError": {
"title": "This shared view could not be loaded",
"description": "Something went wrong while opening this shared health record. The link may have expired, or there was a temporary problem. Try again, or ask the person who shared it for a new link.",
"retry": "Try again"
},
"documents": {
"title": "Documents",
"untitled": "Untitled document",
"download": "Download",
"attachmentHint": "This file downloads to your device (no in-page preview).",
"exifNote": "Camera metadata (EXIF/GPS) has been removed from shared JPEG, PNG and WebP images."
}
},
"cycle": {
"symptomCategory": {
"physical": "Physical",
"emotional": "Emotional",
"digestive": "Digestive",
"custom": "Custom"
},
"symptom": {
"cramps": "Cramps",
"headache": "Headache",
"bloating": "Bloating",
"acne": "Acne",
"breastTenderness": "Breast tenderness",
"fatigue": "Fatigue",
"backPain": "Back pain",
"insomnia": "Insomnia",
"libidoHigh": "High libido",
"libidoLow": "Low libido",
"moodSwings": "Mood swings",
"foodCravings": "Food cravings",
"nausea": "Nausea",
"diarrhea": "Diarrhea",
"constipation": "Constipation",
"custom": {
"add": "Add symptom",
"label": "Name",
"labelPlaceholder": "e.g. Dizziness",
"icon": "Icon",
"limitReached": "Custom symptom limit reached.",
"remove": "Remove {label}",
"fallbackLabel": "Custom symptom"
}
},
"prediction": {
"disclaimer": "Predictions are estimates from your logged data, not medical advice or contraception. Accuracy improves as you log more cycles."
},
"insights": {
"headline": {
"title": "Your cycle and your body",
"restingHeartRate": "Your resting heart rate runs about {delta} {unit} {dir} in your luteal phase than your follicular phase.",
"heartRateVariability": "Your heart-rate variability runs about {delta} {unit} {dir} in your luteal phase than your follicular phase.",
"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."
},
"crosstab": {
"description": "How each measurement compares between your luteal and follicular phases, on your own data.",
"pairLabel": "{metric} · luteal vs follicular",
"detail": "Luteal {lutealAvg} {unit} ({lutealDays} days) vs follicular {follicularAvg} {unit} ({follicularDays} days).",
"metricRestingHeartRate": "Resting heart rate",
"metricHrv": "Heart-rate variability",
"metricSleepDuration": "Sleep duration",
"metricSteps": "Steps",
"metricWeight": "Weight",
"metricBasalBodyTemp": "Basal body temperature",
"metricWristTemperature": "Overnight wrist temperature",
"metricSkinTemperature": "Skin temperature",
"metricBloodGlucose": "Blood glucose",
"metricMood": "Mood",
"unitHours": "h",
"unitSteps": "steps",
"unitBpm": "bpm",
"unitMs": "ms",
"unitKg": "kg",
"unitCelsius": "°C",
"unitGlucose": "mg/dL",
"unitMood": "pts",
"confidenceLow": "Low confidence",
"confidenceMedium": "Medium confidence",
"confidenceHigh": "High confidence"
},
"title": "Cycle insights",
"symptomPatternsTitle": "Symptom patterns by phase",
"symptomPatternsEmpty": "Log symptoms across a cycle to see which phase they cluster in.",
"symptomMostlyIn": "Mostly in {phase} ({count}/{total} days)"
},
"phaseEducation": {
"title": "What's happening now",
"whatsHappening": {
"MENSTRUAL": "Your period is the start of a new cycle, as the uterine lining sheds. Energy and mood often feel lower in these first days.",
"FOLLICULAR": "After your period, oestrogen gradually rises as the body prepares an egg. Many people notice steadier energy through this stretch.",
"OVULATORY": "Around mid-cycle an egg is released and fertility peaks for a short window. This phase is the briefest of the four.",
"LUTEAL": "After ovulation, progesterone rises and the body settles in. In the days before your next period some people notice premenstrual changes."
},
"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.",
"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."
},
"commonHere": "You often notice this here",
"stillLearning": "Still learning your cycle. Keep logging and this fills in with patterns from your own days."
},
"insightsSummary": {
"title": "Your cycle",
"currentDay": "Day {day} of your cycle",
"noActiveCycle": "No active cycle yet",
"viewDetails": "View cycle insights"
},
"wellnessRing": {
"label": "Cycle"
},
"disclaimer": "These predictions are descriptive estimates from your logged data, not a contraceptive method and not medical advice. They never indicate that it is safe to have unprotected sex. For contraception or any medical decision, consult a healthcare professional.",
"title": "Your cycle",
"subtitle": "Log your period and symptoms, see what comes next.",
"tabs": {
"calendar": "Calendar",
"predictions": "Predictions",
"insights": "Insights",
"settings": "Settings"
},
"logToday": "Log today",
"startedPeriod": "Started my period today",
"endedPeriod": "Ended my period today",
"phase": {
"MENSTRUAL": "Menstrual",
"FOLLICULAR": "Follicular",
"OVULATORY": "Ovulatory",
"LUTEAL": "Luteal",
"none": "No phase",
"label": "Phase"
},
"flow": {
"NONE": "None",
"SPOTTING": "Spotting",
"LIGHT": "Light",
"MEDIUM": "Medium",
"HEAVY": "Heavy",
"label": "Flow"
},
"ovulationTest": {
"NEGATIVE": "Negative",
"POSITIVE_LH_SURGE": "LH surge",
"ESTROGEN_SURGE": "Estrogen surge",
"INDETERMINATE": "Indeterminate",
"label": "Ovulation test"
},
"mucus": {
"DRY": "Dry",
"STICKY": "Sticky",
"CREAMY": "Creamy",
"WATERY": "Watery",
"EGG_WHITE": "Egg white",
"label": "Cervical mucus"
},
"cervixPosition": {
"LOW": "Low",
"HIGH": "High"
},
"cervixFirmness": {
"FIRM": "Firm",
"SOFT": "Soft"
},
"cervixOpening": {
"CLOSED": "Closed",
"OPEN": "Open"
},
"goal": {
"GENERAL_HEALTH": "General health",
"AVOID_PREGNANCY": "Avoiding pregnancy",
"TRYING_TO_CONCEIVE": "Trying to conceive",
"PERIMENOPAUSE": "Perimenopause",
"OFF": "Tracking off",
"label": "What are you tracking for?",
"description": "This shapes the language and which predictions you see. Fertile-window guidance shows only when you are trying to conceive."
},
"ring": {
"dayOfCycle": "Day {day}",
"dayUnknown": "—",
"ariaPhase": "Cycle day {day}, {phase} phase",
"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.",
"logPeriodCta": "Log period"
},
"calendar": {
"legendPeriod": "Logged period",
"legendPredicted": "Predicted period",
"legendFertile": "Fertile window",
"legendOvulation": "Ovulation",
"legendSymptoms": "Symptoms logged",
"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.",
"legendSymptom": "Symptoms",
"legendOvulationConfirmed": "Confirmed ovulation",
"flowSpotting": "spotting",
"flowLight": "light",
"flowMedium": "medium",
"flowHeavy": "heavy"
},
"predictions": {
"title": "What comes next",
"nextPeriod": "Next period",
"nextPeriodWindow": "{low} – {high}",
"fertileWindow": "Fertile window",
"ovulation": "Estimated ovulation",
"confidenceHigh": "High",
"confidenceMedium": "Medium",
"confidenceLow": "Low",
"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.",
"none": "No prediction yet. Log a period to get started.",
"ovulationConfirmed": "Ovulation (confirmed)"
},
"history": {
"title": "Your cycles",
"avgLength": "Average length",
"variability": "Variability",
"avgPeriodLength": "Average period",
"regularity": "Regularity",
"regularityREGULAR": "Regular",
"regularityIRREGULAR": "Irregular",
"regularityLEARNING": "Learning",
"days": "{count} days",
"daysPlusMinus": "± {count} days",
"none": "No cycles recorded yet.",
"recentCycles": "Recent cycles",
"ongoing": "ongoing",
"periodDays": "period {count} d",
"ovulationChip": "Ovulation",
"chartTitle": "Cycle length over time",
"chartCaption": "Each bar is one cycle: the rose base is your period, the rest is the cycle length.",
"chartAria": "Cycle-length chart of your last {count} cycles, averaging {avg} days, classified as {regularity}.",
"legendPeriodSegment": "Period days",
"legendRestSegment": "Rest of cycle"
},
"sheet": {
"title": "Log your day",
"description": "Capture today's flow, symptoms, and notes.",
"flow": "Flow",
"symptoms": "Symptoms",
"temperature": "Basal body temperature",
"temperaturePlaceholder": "°C",
"temperatureDisturbed": "Mark reading as disturbed",
"temperatureDisturbedHint": "Fever, illness, alcohol or a late measurement — excluded from the temperature evaluation.",
"ovulationTest": "Ovulation test",
"mucus": "Cervical mucus",
"cervix": "Cervix",
"cervixPosition": "Position",
"cervixFirmness": "Firmness",
"cervixOpening": "Opening",
"intercourse": "Intercourse",
"protected": "Protected",
"intermenstrualBleeding": "Spotting between periods",
"pregnancyTest": "Pregnancy test",
"progesteroneTest": "Progesterone test",
"contraceptive": "Contraceptive",
"severity": "Severity",
"severityLevel": "Severity {level} of 4",
"delete": "Delete",
"note": "Note",
"notePlaceholder": "Anything you want to remember about today…",
"save": "Save",
"saving": "Saving…",
"cancel": "Cancel",
"saveError": "Could not save. Try again.",
"temperatureSection": "Temperature & ovulation",
"intimacySection": "Intimacy & contraception",
"testsSection": "Tests",
"phaseDayHeader": "Day {day} · {phase}",
"bbtHint": "Take it first thing in the morning, before getting up."
},
"testResult": {
"POSITIVE": "Positive",
"NEGATIVE": "Negative",
"INDETERMINATE": "Unclear"
},
"settings": {
"title": "Cycle settings",
"typicalCycleLength": "Typical cycle length (days)",
"typicalPeriodLength": "Typical period length (days)",
"lutealPhaseLength": "Luteal phase length (days)",
"priorsDescription": "These priors help your predictions before you have logged many cycles. Leave blank to use the defaults.",
"rawChartMode": "Raw chart mode",
"rawChartModeDescription": "Show only your logged data with no predictions or interpretation.",
"secondarySymptomLabel": "Secondary fertility sign",
"secondarySymptomDescription": "The second sign paired with your temperature for the symptothermal double-check. Most people track cervical mucus; switch to cervix observation if you prefer.",
"secondarySymptomCitation": "Read about the method (study)",
"secondarySymptom": {
"MUCUS": "Cervical mucus",
"CERVIX": "Cervix observation"
},
"prediction": "Predictions",
"predictionDescription": "Forecast your next period and, when relevant, your fertile window.",
"encryption": "Encrypt sensitive entries",
"encryptionDescription": "Encrypt intent-revealing fields (pregnancy tests, contraception, intercourse) at rest, on top of the always-encrypted notes.",
"discreet": "Discreet notifications",
"discreetDescription": "Hide cycle details from notification text on your lock screen.",
"saved": "Settings saved",
"saveError": "Could not save. Try again.",
"save": "Save",
"reminders": "Reminders",
"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."
},
"contraceptive": {
"NONE": "None",
"UNSPECIFIED": "Other",
"IMPLANT": "Implant",
"INJECTION": "Injection",
"IUD": "IUD",
"INTRAVAGINAL_RING": "Ring",
"ORAL": "Pill",
"PATCH": "Patch",
"EMERGENCY": "Emergency"
},
"loadError": "Couldn't load your cycle data.",
"saveError": "Couldn't save your cycle entry.",
"deleteError": "Couldn't delete the entry.",
"bbt": {
"title": "Basal body temperature",
"caption": "Your morning temperature across this cycle. A sustained rise of about 0.2 °C follows ovulation.",
"empty": "No temperature readings yet",
"emptyHint": "Log your basal body temperature each morning to see your cycle's temperature shift.",
"ovulationEstimate": "Est. ovulation",
"tooltipTemp": "{temp} °C",
"ovulationConfirmed": "Confirmed ovulation"
},
"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.",
"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.",
"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.",
"progesteroneTestLabel": "What is a progesterone test?",
"intercourse": "Whether sexual intercourse took place on this day.",
"intercourseLabel": "What does intercourse track?",
"protected": "Whether contraception was used during intercourse.",
"protectedLabel": "What does protected mean?"
}
},
"cycleReminders": {
"periodSoonTitle": "Period likely soon",
"periodSoonBody": "Your next period is predicted in about two days.",
"periodConfirmTitle": "Did your period start?",
"periodConfirmBody": "Your period was predicted around now. Log it to keep predictions accurate.",
"fertileSoonTitle": "Fertile window coming up",
"fertileSoonBody": "Your estimated fertile window is predicted to start in about two days. This is an estimate, not a medical or contraceptive guarantee.",
"discreetTitle": "HealthLog reminder",
"discreetBody": "You have a reminder in HealthLog."
},
"dataList": {
"allSources": "All sources",
"dateFrom": "From",
"dateTo": "To",
"dateRange": "Date range",
"valueRange": "Value",
"valueMin": "Min",
"valueMax": "Max",
"typeLabel": "Type",
"sourceLabel": "Source",
"resetFilters": "Reset",
"clearFilter": "Clear filter: {label}",
"selectAll": "Select all on this page",
"selectRow": "Select row",
"selected": "{count} selected",
"deleteN": "Delete ({count})",
"clearSelection": "Clear selection",
"selectionBarLabel": "Selection actions"
},
"measurementReminders": {
"sectionTitle": "Checkups",
"sectionDescription": "Reminders for what to measure or check, when, and where.",
"addButton": "Add reminder",
"markDone": "Done",
"delete": "Delete",
"deleteConfirmTitle": "Delete reminder?",
"deleteConfirmDescription": "This checkup reminder will be permanently deleted.",
"disabledBadge": "Off",
"nextDue": {
"none": "Not scheduled",
"today": "Due today",
"tomorrow": "Due tomorrow",
"inDays": "In {days} days"
},
"overdueByDays": "Overdue by {days} days",
"cadence": {
"everyNDays": "Every {days} days",
"custom": "Custom schedule",
"customInterval": "Custom (every N days)",
"rruleOption": "Custom rule (RRULE)"
},
"location": {
"prefix": "At: {location}"
},
"types": {
"WEIGHT": "Weight",
"BLOOD_PRESSURE_SYS": "Blood pressure",
"PULSE": "Pulse",
"BLOOD_GLUCOSE": "Blood glucose",
"OXYGEN_SATURATION": "Oxygen saturation",
"BODY_FAT": "Body fat",
"BODY_TEMPERATURE": "Body temperature",
"FAT_MASS": "Fat mass",
"FAT_FREE_MASS": "Fat-free mass",
"MUSCLE_MASS": "Muscle mass",
"LEAN_BODY_MASS": "Lean body mass",
"BONE_MASS": "Bone mass",
"TOTAL_BODY_WATER": "Body water",
"VISCERAL_FAT": "Visceral fat",
"BODY_MASS_INDEX": "Body mass index (BMI)",
"WAIST_CIRCUMFERENCE": "Waist circumference",
"PHQ9_SCORE": "PHQ-9 · mood",
"GAD7_SCORE": "GAD-7 · worry",
"WHO5_SCORE": "WHO-5 · wellbeing",
"SCI_SCORE": "SCI · sleep"
},
"typeGroups": {
"vitals": "Vitals",
"bodyComposition": "Body composition",
"mentalWellbeing": "Mental wellbeing"
},
"empty": {
"title": "No reminders yet",
"description": "Add a reminder to measure your blood pressure on a cadence, or to schedule an annual blood panel."
},
"form": {
"label": "Label",
"labelPlaceholder": "e.g. Measure blood pressure",
"kind": "Type",
"kindType": "Linked to a measurement",
"kindFreeText": "Free-text check",
"measurementType": "Measurement",
"cadence": "Repeat",
"notifyHour": "Remind at",
"location": "Where (optional)",
"locationPlaceholder": "e.g. GP, Lab",
"save": "Save",
"createTitle": "New reminder",
"editTitle": "Edit reminder",
"customInterval": "Repeat every (days)",
"rrule": "Recurrence rule (RRULE)",
"rruleHint": "RFC-5545, e.g. FREQ=YEARLY for an annual check.",
"firstDue": "First due (optional)"
},
"pushTitle": "Checkup reminder",
"pushBody": "Time for: {label}",
"pushLocation": "(at {location})",
"edit": "Edit",
"originCoach": "Coach",
"until": "Until {date}",
"selfPlanned": "Self-planned",
"captureValue": "Log value",
"measureNow": "Measure now",
"startCheckIn": "Start check-in",
"nextDueLabel": "Next due:",
"lastDoneLabel": "Last done:",
"customize": "Customize checkups",
"adherence": {
"label": "Within interval",
"onTrack": "On track",
"due": "Due now"
},
"capture": {
"title": "Log measurement",
"description": "Enter the reading; the reminder is marked done."
},
"manage": {
"title": "Manage reminders",
"description": "Enable or disable individual reminders.",
"empty": "No reminders to customize yet."
},
"dashboard": {
"empty": "No upcoming checkup reminders.",
"openLink": "Open checkups"
},
"showMeasurements": "Show measurements",
"loadError": "Could not load your reminders."
},
"moduleList": {
"viewToggleLabel": "View",
"viewCards": "Card view",
"viewList": "List view",
"viewHeading": "View",
"viewDescription": "Choose whether entries show as cards or as a compact list.",
"reorder": {
"heading": "Order",
"description": "Drag the entries to set the order they appear in.",
"empty": "No entries to reorder yet."
}
},
"labs": {
"title": "Lab results",
"subtitle": "Bloodwork and biomarker readings",
"addResult": "Add value",
"addDescription": "Record a biomarker reading from a lab report.",
"addFirst": "Add your first result",
"emptyTitle": "No lab results yet",
"emptyDescription": "Record bloodwork like HbA1c, LDL or ferritin to track it over time and share it with your doctor.",
"referenceLabel": "Reference",
"readingsCount": "{count} readings",
"deleteConfirmTitle": "Delete lab result?",
"deleteConfirmDescription": "This lab result will be deleted. You can undo this for a short moment afterwards.",
"deletedToast": "Result deleted",
"deleteError": "Could not delete the result",
"loadError": "Could not load lab results",
"customize": "Customize labs",
"localOcr": {
"heading": "Read scans on this device",
"description": "Lets you scan a lab report even when your AI provider can't read images: the photo is read on your device and only the extracted text is sent to your provider. Less accurate — review every value before saving."
},
"sort": {
"heading": "Sort order",
"label": "Order of values",
"recentDesc": "Most recent reading first",
"recentAsc": "Oldest reading first",
"alphaAsc": "Name (A–Z)",
"alphaDesc": "Name (Z–A)",
"manual": "Sort manually",
"hint": "With manual sorting you can drag the biomarkers below into your own order."
},
"range": {
"inRange": "In range",
"below": "Below range",
"above": "Above range"
},
"form": {
"value": "Value",
"takenAt": "Sample date",
"note": "Note",
"notePlaceholder": "Optional context for this result",
"requiredError": "Enter a value.",
"save": "Save",
"saveAndAddAnother": "Save & add another",
"savedToast": "Result saved",
"saveError": "Could not save the result",
"biomarker": "Biomarker",
"biomarkerPlaceholder": "Pick a biomarker",
"defineNew": "+ Define new biomarker",
"noBiomarkersHint": "Define a biomarker first to record a value against it.",
"pickBiomarkerError": "Pick a biomarker first.",
"resultType": "Result type",
"numeric": "Numeric",
"qualitative": "Qualitative",
"qualitativeResult": "Result",
"qualitativePlaceholder": "e.g. negative",
"qualNegative": "negative",
"qualPositive": "positive",
"qualBorderline": "borderline"
},
"backToLabs": "Back to lab results",
"hasNote": "Note",
"editTitle": "Edit reading",
"editDescription": "Correct the value, date or note of this reading.",
"editedToast": "Reading updated",
"editError": "Could not update the reading",
"editTimestampError": "Enter a valid date.",
"editReading": "Edit reading",
"deleteReading": "Delete reading",
"restoredToast": "Reading restored",
"restoreError": "Could not restore the reading",
"detail": {
"emptyTitle": "No readings yet",
"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",
"valuesDescription": "Every reading for this biomarker. Edit or remove an entry directly.",
"backToMarker": "Back to {marker}",
"latestResult": "Latest result"
},
"chart": {
"empty": "No readings in this period.",
"valueLabel": "Value",
"range": {
"30": "30d",
"90": "90d",
"365": "1y",
"all": "All"
}
},
"biomarker": {
"manageTitle": "Biomarkers",
"managerDescription": "Define a marker once — its unit and range are reused for every reading.",
"define": "Define",
"defineFirst": "Define your first biomarker",
"defineTitle": "Define biomarker",
"defineDescription": "Set the name, unit and reference range once. You pick the marker when adding a value.",
"editTitle": "Edit biomarker",
"edit": "Edit",
"delete": "Delete",
"deletedToast": "Biomarker deleted",
"deleteError": "Could not delete the biomarker",
"deleteConfirmTitle": "Delete biomarker?",
"deleteConfirmDescription": "The biomarker and all of its recorded values are permanently deleted. This cannot be undone.",
"emptyTitle": "No biomarkers yet",
"emptyDescription": "Define markers like LDL or HbA1c to record values against them.",
"loadError": "Could not load biomarkers",
"noRange": "No reference range",
"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.",
"name": "Name",
"namePlaceholder": "e.g. LDL cholesterol",
"unit": "Unit",
"unitPlaceholder": "e.g. mg/dL",
"panel": "Panel",
"panelPlaceholder": "e.g. Lipids",
"lowerBound": "Reference low",
"upperBound": "Reference high",
"lowerPlaceholder": "Lower bound",
"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).",
"requiredError": "Name and unit are required.",
"rangeOrderError": "The lower bound must not exceed the upper bound.",
"save": "Save biomarker",
"savedToast": "Biomarker saved",
"updatedToast": "Biomarker updated",
"saveError": "Could not save the biomarker"
},
"hide": "Hide",
"unhide": "Restore",
"hiddenToast": "Biomarker hidden",
"unhiddenToast": "Biomarker restored",
"hideError": "Could not update the biomarker",
"allHidden": "Every biomarker is hidden.",
"hiddenSection": "Hidden"
},
"catalog": {
"total-cholesterol": "Total cholesterol",
"ldl": "LDL cholesterol",
"hdl": "HDL cholesterol",
"triglycerides": "Triglycerides",
"fasting-glucose": "Fasting glucose",
"hba1c": "HbA1c",
"tsh": "TSH",
"ft3": "Free T3",
"ft4": "Free T4",
"ferritin": "Ferritin",
"transferrin-saturation": "Transferrin saturation",
"vitamin-d": "Vitamin D (25-OH)",
"vitamin-b12": "Vitamin B12",
"folate": "Folate",
"hs-crp": "hs-CRP",
"creatinine": "Creatinine",
"egfr": "eGFR",
"alt": "ALT",
"ast": "AST",
"ggt": "GGT",
"sodium": "Sodium",
"potassium": "Potassium",
"hemoglobin": "Haemoglobin",
"hematocrit": "Haematocrit",
"wbc": "White blood cells",
"platelets": "Platelets",
"panel": {
"lipids": "Lipids",
"glucose": "Glucose metabolism",
"thyroid": "Thyroid",
"iron": "Iron",
"vitamins": "Vitamins",
"inflammation": "Inflammation",
"renal": "Kidney",
"liver": "Liver",
"electrolytes": "Electrolytes",
"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.",
"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.",
"fasting-glucose": "Fasting glucose is the concentration of sugar in the blood measured after an overnight fast, reflecting how the body holds its baseline blood-sugar level without recent food. Glucose is the body's primary immediate fuel, and insulin normally keeps it within a narrow range. A fasting measurement removes the effect of recent meals, making it a standard screen for how glucose regulation is functioning. It is one of the markers used to assess metabolic health over time.",
"hba1c": "HbA1c is the share of haemoglobin in red blood cells that has become bound to glucose, which accumulates in proportion to average blood-sugar exposure. Because red cells live for about three months, it reflects average glucose over the preceding two to three months rather than a single moment. This makes it a stable, meal-independent view of glucose control. Its accuracy can be affected by conditions that change red-cell lifespan.",
"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.",
"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.",
"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.",
"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.",
"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."
},
"apob": "Apolipoprotein B (ApoB)",
"lp-a": "Lipoprotein(a)",
"fasting-insulin": "Fasting insulin",
"omega-3-index": "Omega-3 index"
},
"noteLoadFailed": "Note could not be loaded; it will be kept unchanged when you save.",
"showingLatestOf": "Showing the latest {shown} of {total} readings",
"ocr": {
"scanButton": "Scan a report",
"addScan": "Scan a document",
"addManual": "Add a value manually",
"uploadHint": "Upload a photo or PDF of a lab report",
"acceptWithPdf": "JPEG, PNG, WebP, or PDF",
"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.",
"rangeFromScan": "Reference range taken from the scan",
"rangeVerify": "Verify the reference range",
"reviewTitle": "Review before saving",
"reviewHint": "Check each reading, then save the ones you want to keep.",
"foundCount": "{count} readings found",
"confirmRow": "Include this reading",
"analyteLabel": "Test name",
"resultLabel": "Result",
"valueLabel": "Value",
"unitLabel": "Unit",
"dateLabel": "Date",
"refLowLabel": "Reference low",
"refHighLabel": "Reference high",
"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",
"saveSelected": "Save {count} selected",
"discardAll": "Discard all",
"savedToast": "{count} lab results saved",
"noRows": "No readings could be found in this report.",
"nothingToSave": "Select at least one reading to save.",
"saveFailed": "Couldn't save the readings. Please try again.",
"providerUnsupported": "Your AI provider can't read images. Configure a vision-capable model.",
"consentRequired": "AI processing consent is required to scan a report.",
"rateLimited": "Too many scans. Try again later.",
"budgetExceeded": "Your AI usage budget for today is reached.",
"fileTooLarge": "File is too large (max 12 MB).",
"fileType": "Upload a JPEG, PNG, WebP, or PDF.",
"extractFailed": "Couldn't read the report. Try a clearer photo.",
"pdfNeedsAnthropic": "PDF scanning needs a Claude vision provider; upload a photo instead."
},
"loadMoreReadings": "Load more readings",
"documentsLink": "Lab report documents",
"notLinkedYet": "Not linked to a biomarker yet"
},
"modules": {
"cycle": {
"label": "Cycle",
"description": "Track period, phases, and predictions."
},
"mood": {
"label": "Mood",
"description": "Log daily mood and tags."
},
"sleep": {
"label": "Sleep",
"description": "Sleep duration, stages, and timeline."
},
"glucose": {
"label": "Glucose",
"description": "Blood-glucose readings and trends."
},
"workouts": {
"label": "Workouts",
"description": "Training sessions and activity."
},
"recovery": {
"label": "Recovery",
"description": "Recovery and strain metrics from your devices."
},
"labs": {
"label": "Lab results",
"description": "Capture lab results and keep their history."
},
"achievements": {
"label": "Achievements",
"description": "Badges and streaks for your routine."
},
"coach": {
"label": "Coach",
"description": "AI chat grounded in your own data."
},
"insights": {
"label": "Insights",
"description": "AI analysis, briefing, and correlations."
},
"doctorReport": {
"label": "Doctor report",
"description": "PDF and FHIR export for your practice."
},
"medications": {
"label": "Medications",
"description": "Schedules, intakes, and adherence."
},
"illness": {
"label": "Illness journal",
"description": "Track illness and condition episodes with a daily symptom timeline."
},
"mcp": {
"label": "External assistant access (MCP)",
"description": "Let an MCP-capable assistant read your health data over a scoped token. Off by default."
},
"environment": {
"label": "Environment",
"description": "Pull in daily weather and daylight for your location to correlate with mood, sleep, and vitals. Off by default."
},
"inboundDocuments": {
"label": "Documents",
"description": "Keep every medical letter, report, and scan in one encrypted, searchable place — linked to your conditions. Off by default."
},
"mentalHealth": {
"label": "Mental wellbeing",
"description": "Opt-in PHQ-9 and GAD-7 screeners beside mood tracking. Off by default; answers are encrypted and kept out of the AI Coach."
},
"nutrients": {
"label": "Nutrient intake",
"description": "Store daily micronutrient totals (vitamins, minerals, water, caffeine) synced from Apple Health. Off by default."
}
},
"illness": {
"title": "Illness journal",
"subtitle": "A retrospective log of your illness and condition episodes.",
"settings": {
"viewDescription": "Choose whether episodes show as cards or as a compact list.",
"orderDescription": "Drag your episodes into the order you want to see them in."
},
"customize": "Customize illness journal",
"newEpisode": "New episode",
"logDay": "Log a day",
"markRecovered": "Mark recovered",
"deletedToast": "Episode deleted",
"restoreError": "Could not restore the episode",
"onsetOn": "Started {date}",
"recoveredOn": "recovered {date}",
"status": {
"active": "Active",
"ongoing": "Ongoing",
"recovered": "Recovered"
},
"empty": {
"title": "No episodes yet",
"body": "Start an episode to keep a daily symptom timeline and look back on how it unfolded."
},
"type": {
"INFECTION": "Infection",
"ALLERGY": "Allergy",
"INJURY": "Injury",
"MENTAL_HEALTH": "Mental health",
"AUTOIMMUNE": "Autoimmune",
"CHRONIC": "Chronic",
"OTHER": "Other"
},
"lifecycle": {
"ACUTE": "Acute",
"CHRONIC_ONGOING": "Chronic / ongoing",
"RECURRING": "Recurring",
"FLARE": "Flare"
},
"new": {
"title": "New episode",
"description": "Record an illness or condition. You can log daily symptoms afterwards.",
"label": "Name",
"labelPlaceholder": "e.g. Common cold",
"type": "Type",
"lifecycle": "Course",
"onset": "Started on",
"note": "Note",
"notePlaceholder": "Anything worth remembering (encrypted).",
"saveError": "Could not save the episode. Please try again.",
"parent": "Part of",
"parentNone": "Not linked",
"resolved": "Ended on",
"resolvedHelp": "Leave empty while the episode is still ongoing.",
"markOngoing": "Still ongoing"
},
"sheet": {
"title": "Log {date}",
"description": "Record today's symptoms, how you function, and any fever.",
"symptoms": "Symptoms",
"functionalImpact": "How you function",
"fever": "Temperature",
"note": "Note",
"noteSet": "Set",
"notePlaceholder": "How the day felt (encrypted).",
"severityFor": "Severity for {symptom}",
"saveError": "Could not save the day. Please try again.",
"day": "Day"
},
"impact": {
"0": "Fully functional",
"1": "Slightly limited",
"2": "Mostly resting",
"3": "Bedbound"
},
"symptom": {
"runnyNose": "Runny nose",
"stuffyNose": "Stuffy nose",
"sneezing": "Sneezing",
"soreThroat": "Sore throat",
"cough": "Cough",
"headache": "Headache",
"bodyAches": "Body aches",
"fatigue": "Fatigue"
},
"correlation": {
"title": "How it unfolded",
"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",
"nadirBody": "How far each tracked signal strayed from your typical range.",
"recoveryGapTitle": "Recovery gap",
"recoveryGapLag": "Your numbers settled {days} days after you felt better.",
"recoveryGapLead": "Your numbers settled {days} days before you marked recovery.",
"recoveryGapLagSymptom": "You felt better {days} days before your logged symptoms eased.",
"recoveryGapLeadSymptom": "Your logged symptoms eased {days} days before you marked recovery.",
"recoveryGapSame": "Your numbers settled the same day you felt better.",
"sleepContextMore": "During this episode you slept noticeably more than usual (about {hours}h/night).",
"sleepContextLess": "During this episode you slept noticeably less than usual (about {hours}h/night).",
"redFlagTitle": "Worth a closer look",
"redFlagSpo2": "Your oxygen saturation stayed low for several days. If this recurs, seek medical care.",
"redFlagFever": "You ran a sustained fever. If this recurs, seek medical care.",
"direction": {
"above": "above your usual",
"below": "below your usual"
},
"settled": "Nothing notable stood out from your usual range during this episode."
},
"insights": {
"title": "Your illness history",
"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.",
"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"
},
"section": {
"active": "Active",
"resolved": "Resolved"
},
"flares": {
"countOne": "1 flare",
"countOther": "{count} flares"
},
"timeline": {
"title": "Day timeline",
"error": "Could not load the timeline.",
"severity": "Severity {severity}",
"noSymptoms": "No symptoms logged.",
"impact": "How you functioned: {impact}",
"fever": "Temperature: {value} °C",
"empty": "No days logged yet."
},
"loadError": "Could not load this episode.",
"backToList": "Back to journal",
"detail": {
"note": "Note"
},
"edit": {
"title": "Edit episode",
"description": "Update this episode's details."
},
"menu": {
"label": "Episode actions"
},
"deleteConfirm": {
"title": "Delete this episode?",
"body": "“{label}” and all its day-logs will be removed. You can undo this for a short moment afterwards."
},
"vital": {
"RESTING_HEART_RATE": "Resting heart rate",
"HEART_RATE_VARIABILITY": "Heart-rate variability",
"RECOVERY_SCORE": "Recovery",
"OXYGEN_SATURATION": "Oxygen saturation",
"BODY_TEMPERATURE": "Body temperature",
"RESPIRATORY_RATE": "Respiratory rate",
"BLOOD_PRESSURE_SYS": "Systolic blood pressure",
"BLOOD_PRESSURE_DIA": "Diastolic blood pressure",
"PULSE": "Pulse",
"WEIGHT": "Weight",
"FUNCTIONAL_IMPACT": "Functional impact"
},
"listLoadError": "Could not load your episodes."
},
"coach": {
"reminderSuggestion": {
"title": "Set a reminder?",
"accept": "Set reminder",
"dismiss": "Not now",
"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",
"cadence": {
"weightDaily": "Weigh yourself daily, around the same time",
"bp722": "Measure your blood pressure twice a day for a week",
"glucoseStructured": "Test your glucose on a structured daily schedule"
}
},
"suggestedAction": {
"apply": "Add",
"dismiss": "Not now",
"applied": "Added",
"dismissed": "Dismissed",
"failed": "Couldn't add that — please try again",
"checkup": {
"title": "Add a check-up reminder?"
},
"note": {
"title": "Save a reminder?"
},
"interval": {
"yearly": "Every year",
"halfYearly": "Every six months",
"quarterly": "Every three months",
"monthly": "Every month"
}
},
"settings": {
"reminderSuggestionsLabel": "Cadence suggestions",
"reminderSuggestionsDescription": "Let the Coach offer an occasional, evidence-based reminder to measure a metric more regularly."
},
"plans": {
"title": "Plans",
"pageDescription": "If-then plans agreed in your Coach conversations. Confirm a proposal to make it part of the Coach's memory.",
"proposalTitle": "Plan proposal",
"ifThen": "If {cue}, then {action}.",
"targetPrefix": "Target: {target}",
"reviewPrefix": "Check-in: {when}",
"accept": "Accept plan",
"decline": "Decline",
"accepted": "Plan accepted — the Coach will keep it in mind.",
"declined": "Proposal declined.",
"failed": "That didn't work — please try again.",
"markMet": "Goal met",
"abandon": "End plan",
"remove": "Remove",
"empty": "No plans yet. When you commit to a concrete if-then intention in a conversation, the Coach proposes it here for confirmation.",
"groupProposed": "Suggestions",
"groupActive": "Active",
"groupPast": "Completed",
"status": {
"proposed": "Proposed",
"active": "Active",
"met": "Met",
"abandoned": "Ended",
"review_due": "Check-in due",
"reviewed": "Reviewed"
}
},
"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.",
"conversationPoisoned": "An earlier message in this conversation contains wording that overrides my instructions. Please start a new conversation."
}
},
"safety": {
"floor": {
"bpHighTitle": "Very high blood pressure",
"bpHighDoctor": "Two recent readings were {systolic}/{diastolic} mmHg or higher. Rest, re-check in a few minutes, and contact your doctor as soon as possible if it stays this high.",
"bpHighEmergency": "Two recent readings were {systolic}/{diastolic} mmHg or higher and you noted symptoms. If you have chest pain, breathlessness, weakness, or vision or speech changes, call emergency services now.",
"bpLowTitle": "Low blood pressure",
"bpLowDoctor": "Two recent readings had a systolic below {systolic} mmHg. If you feel dizzy or faint, sit or lie down, and contact your doctor if it continues.",
"bpLowEmergency": "Two recent readings had a systolic below {systolic} mmHg and you noted symptoms. If you feel faint, confused, or have cold clammy skin, call emergency services now.",
"glucoseLowTitle": "Low blood sugar",
"glucoseLowDoctor": "Two recent readings were below {threshold} {unit} ({value} {unit}). Take fast-acting carbohydrate, re-check in 15 minutes, and contact your doctor if lows continue.",
"glucoseLowEmergency": "Two recent readings were below {threshold} {unit} ({value} {unit}) and you noted symptoms. Treat now with fast-acting sugar; if you cannot, or you feel very unwell, call emergency services.",
"glucoseLowSevereTitle": "Very low blood sugar",
"glucoseLowSevereDoctor": "Two recent readings were below {threshold} {unit} ({value} {unit}). Treat immediately with fast-acting carbohydrate, re-check in 15 minutes, and contact your doctor.",
"glucoseLowSevereEmergency": "Two recent readings were below {threshold} {unit} ({value} {unit}) and you noted symptoms. Treat now; if you cannot keep food down or feel very unwell, call emergency services.",
"glucoseHighTitle": "Very high blood sugar",
"glucoseHighDoctor": "Two recent readings were {value} {unit} or higher. Re-check, hydrate, and contact your doctor as soon as possible if it stays this high.",
"glucoseHighEmergency": "Two recent readings were {value} {unit} or higher and you noted symptoms. If you have vomiting, fast breathing, or confusion, call emergency services now."
}
},
"version": {
"updateAvailable": {
"title": "A new version is available",
"reload": "Reload",
"dismiss": "Dismiss"
}
},
"mentalHealth": {
"pageTitle": "Mental wellbeing",
"pageDescription": "Validated, opt-in self-checks — PHQ-9 (mood), GAD-7 (worry), WHO-5 (well-being) and SCI (sleep) — that sit beside your mood tracking. The value is the trend over time, not any single number.",
"moodLink": "View your mood history",
"attributionLabel": "Attribution",
"attributionShow": "Source and licence for {instrument}",
"choosePrompt": "Choose a check-in",
"start": "Start",
"back": "Back",
"submit": "See my result",
"submitting": "Saving…",
"saved": "Saved",
"error": "Something went wrong. Please try again.",
"instrument": {
"phq9": "PHQ-9 · mood",
"gad7": "GAD-7 · worry",
"who5": "WHO-5 · well-being",
"sci": "SCI · sleep"
},
"instrumentSub": {
"phq9": "Depression screen, 9 questions",
"gad7": "Anxiety screen, 7 questions",
"who5": "Well-being check, 5 questions",
"sci": "Sleep check, 8 questions"
},
"options": {
"0": "Not at all",
"1": "Several days",
"2": "More than half the days",
"3": "Nearly every day"
},
"functionalTitle": "If you checked off any problems, how difficult have these made it to do your work, take care of things at home, or get along with other people?",
"functional": {
"0": "Not difficult at all",
"1": "Somewhat difficult",
"2": "Very difficult",
"3": "Extremely difficult"
},
"functionalOptionalHint": "Optional — you can submit without answering this question.",
"result": {
"title": "Your result",
"totalLabel": "Total score",
"bandLabel": "Range for this screen",
"takeAnother": "Take another check-in"
},
"band": {
"PHQ9": {
"minimal": "None / minimal",
"mild": "Mild",
"moderate": "Moderate",
"modSevere": "Moderately severe",
"severe": "Severe"
},
"GAD7": {
"minimal": "None / minimal",
"mild": "Mild",
"moderate": "Moderate",
"severe": "Severe"
},
"WHO5": {
"low": "Lower well-being",
"good": "Good well-being"
},
"SCI": {
"belowThreshold": "Possible insomnia range",
"aboveThreshold": "No insomnia indication"
}
},
"history": {
"title": "Your history",
"empty": "No check-ins yet. Your trend will appear here once you complete one.",
"flaggedBadge": "Support shown",
"chartTitle": "Score trend",
"totalLabel": "Score",
"bandLabel": "Category"
},
"crisis": {
"title": "You don't have to face this alone",
"intro": "You indicated thoughts of being better off dead or of hurting yourself. Support is available right now, and reaching out is a sign of strength.",
"ifDanger": "If you are in immediate danger, call {emergency} now.",
"resourcesTitle": "People who can help"
},
"items": {
"phq9": {
"1": "Little interest or pleasure in doing things",
"2": "Feeling down, depressed, or hopeless",
"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",
"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",
"9": "Thoughts that you would be better off dead, or of hurting yourself in some way"
},
"gad7": {
"1": "Feeling nervous, anxious, or on edge",
"2": "Not being able to stop or control worrying",
"3": "Worrying too much about different things",
"4": "Trouble relaxing",
"5": "Being so restless that it is hard to sit still",
"6": "Becoming easily annoyed or irritable",
"7": "Feeling afraid as if something awful might happen"
},
"who5": {
"1": "I have felt cheerful and in good spirits",
"2": "I have felt calm and relaxed",
"3": "I have felt active and vigorous",
"4": "I woke up feeling fresh and rested",
"5": "My daily life has been filled with things that interest me"
},
"sci": {
"1": "… how long does it take you to fall asleep?",
"2": "… if you then wake up during the night … how long are you awake for in total? (add all the wakenings up)",
"3": "… how many nights a week do you have a problem with your sleep?",
"4": "… how would you rate your sleep quality?",
"5": "… affected your mood, energy, or relationships?",
"6": "… affected your concentration, productivity, or ability to stay awake?",
"7": "… troubled you in general?",
"8": "… how long have you had a problem with your sleep?"
}
},
"crisisResource": {
"telefonSeelsorge": {
"name": "TelefonSeelsorge (24/7, free, confidential)"
},
"nummerGegenKummer": {
"name": "Nummer gegen Kummer (for young people)"
},
"telefonSeelsorgeAt": {
"name": "Telefonseelsorge Österreich (24/7, free, confidential)"
},
"dargeboteneHand": {
"name": "Die Dargebotene Hand (24/7, free, confidential)"
},
"krisenchat": {
"name": "krisenchat (24/7 chat, young people)"
},
"findahelpline": {
"name": "Find a helpline (worldwide directory)"
},
"euEmotionalSupport": {
"name": "Emotional-support helpline"
},
"lifeline988": {
"name": "988 Suicide & Crisis Lifeline"
},
"crisisTextLine": {
"name": "Crisis Text Line"
}
},
"instrumentDescription": {
"phq9": "9-question depression screen. Answer for the last two weeks.",
"gad7": "7-question anxiety screen. Answer for the last two weeks.",
"who5": "5-question well-being check. Answer for the last two weeks; higher numbers mean better well-being.",
"sci": "8-question sleep check. Most questions ask about the past month; higher scores mean better sleep."
},
"progress": "{current} / {total}",
"next": "Next",
"lastResult": "Last test",
"lastScore": "Last result",
"noResultYet": "No check-in yet",
"backToList": "Overview",
"followUpHint": {
"phq9": "Your score is in a range where talking to a health professional may help. This is a gentle suggestion, not a diagnosis.",
"gad7": "Your score is in a range where talking to a health professional may help. This is a gentle suggestion, not a diagnosis.",
"who5": "A well-being score of 50 or below can be worth a closer look. If you like, the PHQ-9 check-in on this page looks at mood in more depth. This is a gentle suggestion, not a diagnosis.",
"sci": "In the study behind this questionnaire, scores of 16 or below were associated with probable insomnia. If poor sleep keeps troubling you, talking to a health professional may help. This is not a diagnosis."
},
"validatedInEnglishNote": "This questionnaire is validated in English; the questions are shown in the original English wording.",
"who5Options": {
"0": "At no time",
"1": "Some of the time",
"2": "Less than half of the time",
"3": "More than half of the time",
"4": "Most of the time",
"5": "All of the time"
},
"sciOptions": {
"duration": {
"0": "≥ 61 min",
"1": "46–60 min",
"2": "31–45 min",
"3": "16–30 min",
"4": "0–15 min"
},
"nights": {
"0": "5–7",
"1": "4",
"2": "3",
"3": "2",
"4": "0–1"
},
"quality": {
"0": "Very poor",
"1": "Poor",
"2": "Average",
"3": "Good",
"4": "Very good"
},
"impact": {
"0": "Very much",
"1": "Much",
"2": "Somewhat",
"3": "A little",
"4": "Not at all"
},
"problemDuration": {
"0": "> 1 year",
"1": "7–12 months",
"2": "3–6 months",
"3": "1–2 months",
"4": "I don't have a problem / < 1 month"
}
},
"stems": {
"who5": {
"period": "Over the last two weeks …"
},
"sci": {
"night": "Thinking about a typical night in the last month …",
"impact": "Thinking about the past month, to what extent has poor sleep …",
"finally": "Finally …"
}
},
"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."
},
"records": {
"disclaimer": "These are your own records, not a medical diagnosis. HealthLog does not diagnose, treat, or interpret them.",
"allergies": {
"cardTitle": "Allergies & intolerances",
"cardDescription": "Substances you react to, with the reaction and how severe it is.",
"description": "Record an allergy or intolerance.",
"add": "Add allergy",
"addFirst": "Add your first allergy",
"addTitle": "Add allergy",
"editTitle": "Edit allergy",
"formDescription": "The substance is stored as plain text; the reaction and note are encrypted.",
"emptyTitle": "No allergies recorded",
"emptyDescription": "Add substances you react to and their reactions.",
"loadError": "Couldn't load your allergies.",
"deletedToast": "Allergy deleted",
"deleteError": "Couldn't delete the allergy.",
"deleteConfirmTitle": "Delete this allergy?",
"deleteConfirmDescription": "This removes the record. It can't be undone.",
"category": {
"FOOD": "Food",
"MEDICATION": "Medication",
"ENVIRONMENT": "Environment",
"BIOLOGIC": "Biologic",
"OTHER": "Other"
},
"type": {
"ALLERGY": "Allergy",
"INTOLERANCE": "Intolerance"
},
"severity": {
"NONE": "Not assessed",
"MILD": "Mild",
"MODERATE": "Moderate",
"SEVERE": "Severe"
},
"status": {
"ACTIVE": "Active",
"INACTIVE": "Inactive",
"RESOLVED": "Resolved"
},
"form": {
"substance": "Substance",
"substancePlaceholder": "e.g. Penicillin, Peanuts",
"category": "Category",
"type": "Type",
"severity": "Severity",
"status": "Status",
"onset": "First noticed",
"reaction": "Reaction",
"reactionPlaceholder": "e.g. hives, swelling, anaphylaxis",
"note": "Note",
"notePlaceholder": "Anything else worth remembering",
"requiredError": "Enter the substance.",
"savedToast": "Allergy saved",
"updatedToast": "Allergy updated",
"saveError": "Couldn't save the allergy."
}
},
"family": {
"cardTitle": "Family history",
"cardDescription": "Conditions in your relatives, one entry per condition.",
"description": "Record a condition in a relative.",
"add": "Add entry",
"addFirst": "Add your first entry",
"addTitle": "Add family history",
"editTitle": "Edit family history",
"formDescription": "The relationship and condition are stored as plain text; the note is encrypted.",
"emptyTitle": "No family history recorded",
"emptyDescription": "Add conditions that run in your family.",
"loadError": "Couldn't load your family history.",
"deletedToast": "Entry deleted",
"deleteError": "Couldn't delete the entry.",
"deleteConfirmTitle": "Delete this entry?",
"deleteConfirmDescription": "This removes the record. It can't be undone.",
"ageAtOnsetShort": "Age {age}",
"relationship": {
"MOTHER": "Mother",
"FATHER": "Father",
"SISTER": "Sister",
"BROTHER": "Brother",
"DAUGHTER": "Daughter",
"SON": "Son",
"GRANDMOTHER_MATERNAL": "Grandmother (maternal)",
"GRANDFATHER_MATERNAL": "Grandfather (maternal)",
"GRANDMOTHER_PATERNAL": "Grandmother (paternal)",
"GRANDFATHER_PATERNAL": "Grandfather (paternal)",
"AUNT": "Aunt",
"UNCLE": "Uncle",
"COUSIN": "Cousin",
"HALF_SIBLING": "Half-sibling",
"OTHER": "Other relative"
},
"form": {
"relationship": "Relative",
"condition": "Condition",
"conditionPlaceholder": "e.g. Type 2 diabetes, Breast cancer",
"ageAtOnset": "Age at onset",
"ageAtOnsetPlaceholder": "e.g. 55",
"note": "Note",
"notePlaceholder": "Anything else worth remembering",
"requiredError": "Enter the condition.",
"ageError": "Enter an age between 0 and 120.",
"savedToast": "Entry saved",
"updatedToast": "Entry updated",
"saveError": "Couldn't save the entry."
}
},
"conditions": {
"cardTitle": "Pre-existing conditions",
"cardDescription": "Chronic conditions and what the Coach watches.",
"conditionsLabel": "Chronic conditions",
"focusLabel": "What the Coach watches",
"loadError": "Couldn't load your conditions.",
"savedToast": "Conditions saved.",
"saveError": "Could not save. Please try again."
}
},
"environment": {
"fields": {
"tempMean": "Daily temperature",
"tempMin": "Overnight low",
"sunshine": "Sunshine",
"daylight": "Daylight",
"precip": "Precipitation",
"pressureMean": "Barometric pressure",
"pressureDelta": "Pressure swing"
}
},
"documents": {
"title": "Documents",
"subtitle": "Every letter, report, and scan in one searchable place — encrypted at rest.",
"pageUpload": "Upload",
"kind": {
"DOCTOR_REPORT": "Doctor report",
"DISCHARGE_LETTER": "Discharge letter",
"OTHER": "Other",
"LAB_RESULT": "Lab result",
"IMAGING": "Imaging",
"PRESCRIPTION": "Prescription",
"REFERRAL": "Referral",
"INSURANCE": "Insurance",
"VACCINATION": "Vaccination"
},
"filter": {
"searchLabel": "Search documents",
"searchPlaceholder": "Search title or filename…",
"typeGroup": "Document type",
"conditionGroup": "Condition",
"yearGroup": "Year",
"clear": "Clear filters",
"typeAll": "All types",
"typeCount": "{count} types",
"conditionAll": "All conditions",
"yearAll": "All years"
},
"card": {
"untitled": "Untitled document",
"selectLabel": "Select {title}",
"openLabel": "Open {title}",
"attachmentBadge": "Download only",
"uploading": "Uploading…",
"dismissFailed": "Dismiss failed upload",
"processing": "Processing…",
"ready": "Ready"
},
"error": {
"fileTooLarge": "This file is larger than the {maxSize} limit.",
"quotaExceeded": "Storage is full — {used} of {quota} used.",
"unsupportedType": "This file type is not supported.",
"purged": "This document was permanently removed and cannot be restored.",
"duplicateExists": "An identical document is already stored.",
"rateLimited": "Too many uploads right now — try again in a few minutes.",
"generic": "Upload failed. Please try again."
},
"toast": {
"duplicate": "Already stored — highlighting the existing document.",
"deleted": "Document deleted.",
"restoreFailed": "Couldn't restore the document."
},
"timeline": {
"loadingMore": "Loading more…",
"listLabel": "Documents timeline"
},
"upload": {
"browse": "Choose files",
"quotaAlmostFull": "Storage almost full",
"quotaUsed": "{used} of {quota} used",
"queuedAnnouncement": "{count} file(s) added to the upload queue"
},
"selection": {
"count": "{count} selected",
"clear": "Clear selection"
},
"list": {
"loadError": "Couldn't load your documents."
},
"empty": {
"title": "Your document vault is empty",
"description": "Store doctor letters, lab reports, imaging, prescriptions, and vaccination records — encrypted, and searchable by type, condition, and year.",
"action": "Upload a first document",
"noMatchesTitle": "No matching documents",
"noMatchesDescription": "Nothing matches the current search and filters."
},
"detail": {
"title": "Document details",
"summary": {
"title": "Summary",
"pending": "The summary is being prepared.",
"none": "No summary has been generated for this document yet.",
"withheld": "A summary was generated but did not pass the safety check, so it is not shown. You can try again, or read the document itself.",
"unavailable": "No summary could be generated for this document.",
"generate": "Generate summary",
"regenerate": "Generate again",
"generating": "Generating…"
},
"loadError": "Couldn't load this document.",
"saveError": "Couldn't save the change.",
"deleteError": "Couldn't delete the document.",
"download": "Download",
"delete": "Delete",
"titleLabel": "Title",
"titlePlaceholder": "Add a title",
"kindLabel": "Type",
"dateLabel": "Document date",
"conditionsLabel": "Linked conditions",
"linkCondition": "Link",
"noConditions": "Not linked to a condition",
"previewUnavailable": "No inline preview for this file type",
"uploadedMeta": "Added {date} · {size}",
"share": "Share",
"labValuesLink": "View {count} lab values"
},
"dropOverlay": {
"title": "Drop files to upload",
"hint": "They are stored encrypted in your document vault"
},
"bulk": {
"barLabel": "Actions for selected documents",
"setKind": "Change type",
"linkCondition": "Link condition",
"delete": "Delete",
"updated": "{count} document(s) updated",
"deleted": "{count} document(s) deleted",
"restored": "{count} document(s) restored",
"partialFailure": "{failed} of {total} could not be updated",
"failed": "The action could not be completed",
"share": "Share",
"shareTooMany": "A share link can hold at most {max} documents. Deselect some and try again."
},
"episodeCard": {
"title": "Documents",
"link": "Link",
"upload": "Upload",
"viewAll": "Show all",
"emptyLine": "No documents linked to this condition yet.",
"loadError": "Could not load the linked documents"
},
"linkPicker": {
"title": "Link documents",
"description": "Pick documents from your vault that belong to this condition.",
"searchPlaceholder": "Search by title or filename",
"empty": "No documents found."
},
"assist": {
"suggest": "Suggest details",
"suggesting": "Reading…",
"suggestedTitle": "Suggested title",
"suggestedKind": "Suggested type",
"suggestedDate": "Suggested date",
"apply": "Apply",
"useTitle": "Use title",
"applied": "Applied",
"dismiss": "Dismiss",
"empty": "Nothing could be read from this document.",
"unavailableBody": "Set up an AI provider to suggest a title, type, and date.",
"unavailableLocalOcr": "Turn on local OCR in the AI settings to read images on this device.",
"unavailableAction": "Open AI settings",
"errorGeneric": "Couldn't read the document. Try again.",
"errorOcr": "Couldn't read text from this image.",
"errorRateLimited": "Too many AI requests — try again in a few minutes.",
"errorBudget": "Your AI budget for today is used up.",
"errorPdfNeedsVision": "Scanning PDFs needs a Claude vision provider.",
"errorFileType": "This file type can't be read.",
"errorLocalOcrDisabled": "Turn on local OCR in the AI settings first.",
"errorProvider": "No AI provider is set up for this.",
"errorTextImageOnly": "Local OCR reads images only — not this file."
},
"summary": {
"summarise": "Summarise",
"showText": "Show extracted text",
"summaryTitle": "Summary",
"textTitle": "Extracted text",
"close": "Hide"
},
"ai": {
"readDone": "The AI read your document.",
"read": "Read with AI",
"reread": "Read again",
"reading": "Reading…"
},
"contentIndex": {
"indexPrompt": "Make document contents searchable.",
"indexAll": "Index all for search",
"indexAllPending": "Starting…",
"indexAllQueued": "Indexing {count} document(s) in the background.",
"indexAllNothing": "Everything is already indexed.",
"indexAllError": "Couldn't start indexing."
},
"share": {
"title": "Share this document",
"multiTitle": "Share these documents",
"multiLabel": "{count} documents",
"description": "Create a read-only clinician link with this document attached. The link and its passphrase appear once."
},
"chat": {
"title": "Chat about this document",
"openAria": "Ask the Coach about this document",
"openButton": "Ask the Coach"
}
},
"selfDescription": {
"dataPosture": "HealthLog is self-hosted: your health data stays on your own instance, encrypted at rest. AI features use a provider key you bring or a local model, so nothing leaves your instance beyond the provider you configure, and there is no third-party analytics on your health data."
},
"customMetrics": {
"sectionTitle": "Custom metrics",
"sectionSubtitle": "Measurements you define and track yourself.",
"add": "Add custom metric",
"addValue": "Add value",
"defineTitle": "Define a custom metric",
"defineDescription": "Name the measurement, set its unit, and optionally a target range.",
"editTitle": "Edit custom metric",
"edit": "Edit",
"delete": "Delete",
"deleteConfirmTitle": "Delete this custom metric?",
"deleteConfirmDescription": "The metric is removed from your list. Its logged values are kept.",
"deletedToast": "Custom metric deleted",
"deleteError": "Could not delete the custom metric",
"showAllValues": "Show all values",
"emptyDescription": "Define your own measurements to track and chart them.",
"noValuesYet": "No values yet",
"loadError": "Could not load custom metrics",
"loadMore": "Load more values",
"showingLatestOf": "Showing the latest {shown} of {total}",
"backToMeasurements": "Back to measurements",
"form": {
"name": "Name",
"namePlaceholder": "e.g. Morning grip strength",
"unit": "Unit",
"unitPlaceholder": "e.g. kg",
"decimals": "Decimal places",
"decimalsPlaceholder": "e.g. 1",
"targetLow": "Target low",
"targetLowPlaceholder": "Lower bound",
"targetHigh": "Target high",
"targetHighPlaceholder": "Upper bound",
"description": "Description",
"descriptionPlaceholder": "What this measures (optional)",
"targetHint": "The target range is optional and is drawn as a band on the chart.",
"requiredError": "Name and unit are required",
"rangeOrderError": "Target low must not exceed target high",
"save": "Save",
"savedToast": "Custom metric saved",
"updatedToast": "Custom metric updated",
"saveError": "Could not save the custom metric"
},
"entry": {
"value": "Value",
"measuredAt": "Date",
"note": "Note",
"addDescription": "Log a value for this metric.",
"edit": "Edit value",
"editTitle": "Edit value",
"editDescription": "Update the value, date, or note.",
"delete": "Delete value",
"deleteConfirmTitle": "Delete this value?",
"deleteConfirmDescription": "This value is removed permanently.",
"valueError": "Enter a numeric value",
"timestampError": "Enter a valid date",
"savedToast": "Value logged",
"saveError": "Could not log the value",
"editedToast": "Value updated",
"editError": "Could not update the value",
"deletedToast": "Value deleted",
"deleteError": "Could not delete the value"
},
"chart": {
"empty": "No values in this range",
"valueLabel": "Value",
"range": {
"30": "30d",
"90": "90d",
"365": "1y",
"all": "All"
}
},
"detail": {
"title": "Custom metric",
"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",
"valuesDescription": "Every logged value for this metric.",
"backToMetric": "Back to {metric}"
}
},
"nutrients": {
"names": {
"vitamin_a": "Vitamin A",
"thiamin": "Thiamin (B1)",
"riboflavin": "Riboflavin (B2)",
"niacin": "Niacin (B3)",
"pantothenic_acid": "Pantothenic acid (B5)",
"vitamin_b6": "Vitamin B6",
"biotin": "Biotin (B7)",
"folate": "Folate (B9)",
"vitamin_b12": "Vitamin B12",
"vitamin_c": "Vitamin C",
"vitamin_d": "Vitamin D",
"vitamin_e": "Vitamin E",
"vitamin_k": "Vitamin K",
"calcium": "Calcium",
"iron": "Iron",
"magnesium": "Magnesium",
"phosphorus": "Phosphorus",
"zinc": "Zinc",
"copper": "Copper",
"manganese": "Manganese",
"selenium": "Selenium",
"chromium": "Chromium",
"molybdenum": "Molybdenum",
"iodine": "Iodine",
"water": "Water",
"caffeine": "Caffeine"
},
"page": {
"title": "Nutrient intake",
"description": "Hydration and vitamin/mineral intake synced from your phone's health app, plus manual water entries.",
"moduleOffTitle": "Nutrient intake is off",
"moduleOffDescription": "Turn on the nutrients module to see hydration and vitamin/mineral intake here. Synced intake becomes part of the record the Coach can read.",
"moduleOffCta": "Turn on nutrients",
"emptyTitle": "No nutrient data yet",
"emptyDescription": "Data arrives from your phone's health app sync or a manual water entry."
},
"hydration": {
"referenceMeta": "Reference intake {value} {unit}/day · EFSA",
"quickAddTitle": "Add water",
"quickAddCustomLabel": "Custom amount (mL)",
"quickAddCustomPlaceholder": "250",
"quickAddSubmit": "Add",
"quickAddError": "Couldn't save that — try again.",
"quickAddSuccess": "{amount} mL water added.",
"editTotal": "Edit today's total"
},
"caffeine": {
"ceilingMeta": "Safe-level ceiling {value} {unit}/day · EFSA"
},
"micronutrients": {
"title": "Vitamins & minerals",
"rowMeta": "{days} of {window} days · ref {value} {unit} (EFSA)",
"rowMetaNoRef": "{days} of {window} days",
"footer": "{tracked} of {total} tracked micronutrients have data in this window.",
"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."
},
"daily": {
"line": {
"score": "Your health score today is {score}.",
"allClear": "Nothing needs your attention today."
},
"push": {
"title": "Your morning briefing",
"bodyProvisional": "{line} · Last night's sleep isn't in yet."
},
"item": {
"doseWindow": {
"title": "Medication due",
"body": "A dose is due soon.",
"bodyNamed": "{name} is due soon.",
"overdueTitle": "Medication overdue",
"overdueBody": "A dose is past due.",
"overdueBodyNamed": "{name} is past due."
},
"preventiveCare": {
"title": "Check-up due",
"body": "{label} is due.",
"bodyMany": "{count} check-ups are due."
},
"syncIssue": {
"title": "Sync needs attention",
"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.",
"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."
}
},
"ecgNewRecording": {
"title": "New ECG recording",
"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",
"notDetected": "no irregular rhythm",
"inconclusive": "an inconclusive result"
}
}
},
"action": {
"logDose": "Log dose",
"reconnect": "Reconnect",
"viewCheckups": "View check-ups",
"checkinKeep": "Keep it",
"checkinAdjust": "Adjust",
"checkinLetGo": "Let it go",
"viewMilestone": "View",
"viewPulse": "View pulse",
"viewEcg": "View recording"
},
"today": {
"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.",
"justIn": "Just in",
"justInAt": "Just in · {time}",
"worthALook": "Worth a look",
"allClear": "Nothing needs your attention today.",
"ringLink": "Open {metric} details"
},
"milestone": {
"metric": {
"restingHeartRate": "resting heart rate",
"heartRateVariability": "heart-rate variability",
"respiratoryRate": "respiratory rate",
"weight": "weight",
"generic": "this metric"
},
"record": {
"title": "A new {metric} best",
"body": "A personal best for your {metric} today — quietly noted, nothing to do."
},
"returnToBaseline": {
"title": "Back in range: {metric}",
"body": "Your {metric} has settled back inside your usual range. Whatever that was, it has passed."
},
"sustainedInRange": {
"week1": {
"title": "A week in range",
"body": "Your {metric} has held inside your usual range for a week now. Nice and steady."
},
"week2": {
"title": "Two weeks in range",
"body": "Your {metric} has stayed in your usual range for two weeks. Calm and steady."
},
"week3": {
"title": "Three weeks in range",
"body": "Three weeks of your {metric} sitting in your usual range. A real stretch of steadiness."
},
"week4": {
"title": "A month in range",
"body": "A full month with your {metric} in your usual range. Beautifully steady."
}
}
}
}
}