mirror of
https://github.com/MBombeck/HealthLog.git
synced 2026-11-12 22:26:13 +00:00
1 parent
313d8491de
commit
51e2d68a88
9 files changed
+108
-7
No files matched your search
+7
-1
@@ -798,7 +798,13 @@
|
||||
"unitRatio": "Verhältnis",
|
||||
"unitRating": "Stufe",
|
||||
"typeWho5Score": "WHO-5-Wert",
|
||||
"typeSciScore": "SCI-Wert"
|
||||
"typeSciScore": "SCI-Wert",
|
||||
"durationReadAs": "Gelesen als {duration}",
|
||||
"durationHoursMinutes": "{hours} Std. {minutes} Min.",
|
||||
"durationHoursOnly": "{hours} Std.",
|
||||
"durationMinutesOnly": "{minutes} Min.",
|
||||
"durationInvalid": "Gib eine Dauer ein, zum Beispiel 7,5, 7:30 oder 7h 30m.",
|
||||
"durationTooLong": "Ein Eintrag kann nicht länger als 24 Stunden sein."
|
||||
},
|
||||
"metricCatalog": {
|
||||
"title": "Was HealthLog erfassen kann",
|
||||
|
||||
+7
-1
@@ -798,7 +798,13 @@
|
||||
"unitRatio": "ratio",
|
||||
"unitRating": "rating",
|
||||
"typeWho5Score": "WHO-5 score",
|
||||
"typeSciScore": "SCI score"
|
||||
"typeSciScore": "SCI score",
|
||||
"durationReadAs": "Read as {duration}",
|
||||
"durationHoursMinutes": "{hours} h {minutes} min",
|
||||
"durationHoursOnly": "{hours} h",
|
||||
"durationMinutesOnly": "{minutes} min",
|
||||
"durationInvalid": "Enter a duration like 7.5, 7:30 or 7h 30m.",
|
||||
"durationTooLong": "One entry can't be longer than 24 hours."
|
||||
},
|
||||
"metricCatalog": {
|
||||
"title": "What HealthLog can track",
|
||||
|
||||
+7
-1
@@ -798,7 +798,13 @@
|
||||
"unitRatio": "ratio",
|
||||
"unitRating": "nivel",
|
||||
"typeWho5Score": "Puntuación WHO-5",
|
||||
"typeSciScore": "Puntuación SCI"
|
||||
"typeSciScore": "Puntuación SCI",
|
||||
"durationReadAs": "Se lee como {duration}",
|
||||
"durationHoursMinutes": "{hours} h {minutes} min",
|
||||
"durationHoursOnly": "{hours} h",
|
||||
"durationMinutesOnly": "{minutes} min",
|
||||
"durationInvalid": "Escribe una duración como 7,5, 7:30 o 7h 30m.",
|
||||
"durationTooLong": "Una entrada no puede durar más de 24 horas."
|
||||
},
|
||||
"metricCatalog": {
|
||||
"title": "Lo que HealthLog puede registrar",
|
||||
|
||||
+7
-1
@@ -798,7 +798,13 @@
|
||||
"unitRatio": "ratio",
|
||||
"unitRating": "niveau",
|
||||
"typeWho5Score": "Score WHO-5",
|
||||
"typeSciScore": "Score SCI"
|
||||
"typeSciScore": "Score SCI",
|
||||
"durationReadAs": "Compris comme {duration}",
|
||||
"durationHoursMinutes": "{hours} h {minutes} min",
|
||||
"durationHoursOnly": "{hours} h",
|
||||
"durationMinutesOnly": "{minutes} min",
|
||||
"durationInvalid": "Saisis une durée comme 7,5, 7:30 ou 7h 30m.",
|
||||
"durationTooLong": "Une saisie ne peut pas dépasser 24 heures."
|
||||
},
|
||||
"metricCatalog": {
|
||||
"title": "Ce que HealthLog peut suivre",
|
||||
|
||||
+7
-1
@@ -798,7 +798,13 @@
|
||||
"unitRatio": "rapporto",
|
||||
"unitRating": "livello",
|
||||
"typeWho5Score": "Punteggio WHO-5",
|
||||
"typeSciScore": "Punteggio SCI"
|
||||
"typeSciScore": "Punteggio SCI",
|
||||
"durationReadAs": "Letto come {duration}",
|
||||
"durationHoursMinutes": "{hours} h {minutes} min",
|
||||
"durationHoursOnly": "{hours} h",
|
||||
"durationMinutesOnly": "{minutes} min",
|
||||
"durationInvalid": "Inserisci una durata come 7,5, 7:30 o 7h 30m.",
|
||||
"durationTooLong": "Una voce non può superare le 24 ore."
|
||||
},
|
||||
"metricCatalog": {
|
||||
"title": "Cosa può monitorare HealthLog",
|
||||
|
||||
+7
-1
@@ -798,7 +798,13 @@
|
||||
"unitRatio": "비율",
|
||||
"unitRating": "단계",
|
||||
"typeWho5Score": "WHO-5 점수",
|
||||
"typeSciScore": "SCI 점수"
|
||||
"typeSciScore": "SCI 점수",
|
||||
"durationReadAs": "{duration}(으)로 읽었어요",
|
||||
"durationHoursMinutes": "{hours}시간 {minutes}분",
|
||||
"durationHoursOnly": "{hours}시간",
|
||||
"durationMinutesOnly": "{minutes}분",
|
||||
"durationInvalid": "7.5, 7:30, 7h 30m처럼 시간을 입력해 주세요.",
|
||||
"durationTooLong": "한 번에 24시간보다 길게 입력할 수 없어요."
|
||||
},
|
||||
"metricCatalog": {
|
||||
"title": "HealthLog가 기록할 수 있는 것",
|
||||
|
||||
+7
-1
@@ -798,7 +798,13 @@
|
||||
"unitRatio": "stosunek",
|
||||
"unitRating": "poziom",
|
||||
"typeWho5Score": "Wynik WHO-5",
|
||||
"typeSciScore": "Wynik SCI"
|
||||
"typeSciScore": "Wynik SCI",
|
||||
"durationReadAs": "Odczytano jako {duration}",
|
||||
"durationHoursMinutes": "{hours} godz. {minutes} min",
|
||||
"durationHoursOnly": "{hours} godz.",
|
||||
"durationMinutesOnly": "{minutes} min",
|
||||
"durationInvalid": "Wpisz czas trwania, np. 7,5, 7:30 lub 7h 30m.",
|
||||
"durationTooLong": "Jeden wpis nie może przekraczać 24 godzin."
|
||||
},
|
||||
"metricCatalog": {
|
||||
"title": "Co HealthLog potrafi śledzić",
|
||||
|
||||
@@ -99,6 +99,8 @@ const LEGIT_IDENTICAL = new Set<string>([
|
||||
"labs.catalog.hs-crp",
|
||||
"measurements.typeHrvRmssd",
|
||||
"measurements.typeVo2Max",
|
||||
// "{hours} h {minutes} min": the SI symbols for hour and minute.
|
||||
"measurements.durationHoursMinutes",
|
||||
"settings.sections.sources.metrics.vo2Max",
|
||||
// Brand / product / proper nouns.
|
||||
"settings.googleHealth",
|
||||
|
||||
@@ -0,0 +1,57 @@
|
||||
import { readFileSync } from "node:fs";
|
||||
import { join } from "node:path";
|
||||
import { describe, expect, it } from "vitest";
|
||||
import { renderToStaticMarkup } from "react-dom/server";
|
||||
|
||||
import { I18nProvider } from "@/lib/i18n/context";
|
||||
import { parseDurationEntry } from "@/lib/measurements/parse-duration";
|
||||
import { DurationReadAs } from "../duration-read-as";
|
||||
|
||||
/**
|
||||
* The hint under a duration field says how the entry was read, so "7.5",
|
||||
* "7:30" and "7h30" can each be checked before saving.
|
||||
*/
|
||||
function render(minutes: number, locale: "en" | "de" | "ko" = "en") {
|
||||
return renderToStaticMarkup(
|
||||
<I18nProvider initialLocale={locale}>
|
||||
<DurationReadAs minutes={minutes} />
|
||||
</I18nProvider>,
|
||||
);
|
||||
}
|
||||
|
||||
function readAs(raw: string): string {
|
||||
const read = parseDurationEntry(raw, "h");
|
||||
if (!read.ok) throw new Error(`refused ${raw}`);
|
||||
return render(read.minutes);
|
||||
}
|
||||
|
||||
describe("<DurationReadAs>", () => {
|
||||
it.each(["7.5", "7,5", "7:30", "7h30", "7 h 30 min"])(
|
||||
"shows %j as seven and a half hours",
|
||||
(raw) => {
|
||||
expect(readAs(raw)).toContain("Read as 7 h 30 min");
|
||||
},
|
||||
);
|
||||
|
||||
it("leaves out a zero part", () => {
|
||||
expect(render(480)).toContain("Read as 8 h<");
|
||||
expect(render(45)).toContain("Read as 45 min");
|
||||
});
|
||||
|
||||
it("speaks the reader's language", () => {
|
||||
expect(render(450, "de")).toContain("7 Std. 30 Min.");
|
||||
expect(render(450, "ko")).toContain("7시간 30분");
|
||||
});
|
||||
|
||||
it("is wired under the measurement form's value field", () => {
|
||||
const form = readFileSync(
|
||||
join(process.cwd(), "src/components/measurements/measurement-form.tsx"),
|
||||
"utf8",
|
||||
);
|
||||
expect(form).toMatch(
|
||||
/hint=\{\s*durationRead\?\.ok === true \? \(\s*<DurationReadAs minutes=\{durationRead\.minutes\} \/>/,
|
||||
);
|
||||
// A refused entry is an inline field error, never a toast.
|
||||
expect(form).toMatch(/setValueError\(\s*t\(/);
|
||||
});
|
||||
});
|
||||
Reference in new issue
Block a user