fix(import): pluralise the note on records HealthLog wrote itself

The note had one form per locale, so a single left-out record read as a
plural. It now resolves One, Few and Other through tCount like the other
counted strings, with the singular in every locale and the Polish few form.
This commit is contained in:
Marc-André Bombeck committed 2026-10-04 14:34:42 +02:00
1 parent 4dabc83513
commit 67e8e7c4f2
9 files changed
+106 -19

No files matched your search

@@ -0,0 +1,62 @@
/**
* The note under a finished Apple Health import that says how many records
* were left out because HealthLog wrote them into Apple Health itself.
*
* The count is often 1, and a single string rendered "1 Einträge". The note
* reads the plural tier of the active locale, so each locale's own singular
* (and the Polish few form) reaches the screen.
*/
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 type { MessageBundle } from "@/lib/i18n/load-locale";
import { locales, type Locale } from "@/lib/i18n/config";
import { AppleHealthOwnRecordsNote } from "../apple-health-import-card";
function bundle(locale: Locale): MessageBundle {
return JSON.parse(
readFileSync(join(process.cwd(), "messages", `${locale}.json`), "utf8"),
) as MessageBundle;
}
function render(locale: Locale, count: number): string {
return renderToStaticMarkup(
<I18nProvider initialLocale={locale} initialMessages={bundle(locale)}>
<AppleHealthOwnRecordsNote count={count} />
</I18nProvider>,
)
.replace(/<[^>]+>/g, "")
.trim();
}
describe("<AppleHealthOwnRecordsNote>", () => {
it("uses the singular for one record", () => {
expect(render("de", 1)).toMatch(/^1 Eintrag,/);
expect(render("en", 1)).toMatch(/^1 record that/);
expect(render("es", 1)).toContain("1 registro que");
expect(render("fr", 1)).toMatch(/^1 enregistrement que/);
expect(render("it", 1)).toMatch(/^1 registrazione che/);
expect(render("pl", 1)).toContain("1 wpis,");
});
it("uses the plural for several, and the Polish few form for 2 to 4", () => {
expect(render("de", 5)).toMatch(/^5 Einträge,/);
expect(render("en", 5)).toMatch(/^5 records that/);
expect(render("pl", 3)).toContain("3 wpisy,");
expect(render("pl", 5)).toContain("5 wpisów,");
});
it("renders a sentence with the count in every locale", () => {
for (const locale of locales) {
for (const count of [1, 2, 5]) {
const text = render(locale, count);
expect(text, `${locale} ${count}`).toContain(String(count));
expect(text, `${locale} ${count}`).not.toContain("writtenByHealthLog");
}
}
});
});
@@ -32,7 +32,11 @@ interface JobStatus {
clinical?: { skipped?: number };
cumulativeEstimates?: { days?: number; rows?: number };
/** Records HealthLog wrote into Apple Health itself, left out here. */
writtenByHealthLog?: { byMarker?: number; matchedManual?: number };
writtenByHealthLog?: {
byMarker?: number;
byExternalId?: number;
matchedManual?: number;
};
/** HK types deferred by design — read but not (yet) imported. */
deferred?: Record<string, number>;
/** Per-key drop counters — plain HK types are unsupported-by-design,
@@ -249,6 +253,22 @@ export function AppleHealthSkipLines({
);
}
/** How many records the import left out because HealthLog wrote them. */
export function AppleHealthOwnRecordsNote({ count }: { count: number }) {
const { tCount } = useTranslations();
return (
<p
data-testid="import-apple-health-own-skipped"
className="text-muted-foreground text-sm"
>
{tCount(
"settings.sections.export.import.appleHealth.writtenByHealthLog",
count,
)}
</p>
);
}
export function AppleHealthImportCard() {
const { t } = useTranslations();
const fileInputRef = useRef<HTMLInputElement>(null);
@@ -346,6 +366,7 @@ export function AppleHealthImportCard() {
const isDone = status?.status === "done";
const ownRecordsSkipped =
(status?.result?.writtenByHealthLog?.byMarker ?? 0) +
(status?.result?.writtenByHealthLog?.byExternalId ?? 0) +
(status?.result?.writtenByHealthLog?.matchedManual ?? 0);
const isFailed = status?.status === "failed";
const busy = uploading || isRunning;
@@ -498,17 +519,7 @@ export function AppleHealthImportCard() {
</p>
)}
{isDone && ownRecordsSkipped > 0 && (
<p
data-testid="import-apple-health-own-skipped"
className="text-muted-foreground text-sm"
>
{t(
"settings.sections.export.import.appleHealth.writtenByHealthLog",
{
count: ownRecordsSkipped,
},
)}
</p>
<AppleHealthOwnRecordsNote count={ownRecordsSkipped} />
)}
{isDone && (status?.result?.cumulativeEstimates?.days ?? 0) > 0 && (
<AppleHealthEstimateWarning