diff --git a/ftl/core/statistics.ftl b/ftl/core/statistics.ftl index e6c7c5811..54fd053c2 100644 --- a/ftl/core/statistics.ftl +++ b/ftl/core/statistics.ftl @@ -106,6 +106,7 @@ statistics-true-retention-week = Last week statistics-true-retention-month = Last month statistics-true-retention-year = Last year statistics-true-retention-all-time = All time +statistics-true-retention-not-applicable = N/A statistics-range-all-time = all statistics-range-1-year-history = last 12 months statistics-range-all-history = all history diff --git a/ts/lib/tslib/i18n/utils.ts b/ts/lib/tslib/i18n/utils.ts index 7dd00d5a7..d13e6c2c3 100644 --- a/ts/lib/tslib/i18n/utils.ts +++ b/ts/lib/tslib/i18n/utils.ts @@ -55,6 +55,10 @@ export function localizedNumber(n: number, precision = 2): string { return rounded.toLocaleString(langs); } +export function createLocaleNumberFormat(options?: Intl.NumberFormatOptions): Intl.NumberFormat { + return new Intl.NumberFormat(langs, options); +} + export function localeCompare( first: string, second: string, diff --git a/ts/routes/graphs/true-retention.ts b/ts/routes/graphs/true-retention.ts index 8aacc376c..4ad2fc464 100644 --- a/ts/routes/graphs/true-retention.ts +++ b/ts/routes/graphs/true-retention.ts @@ -1,7 +1,7 @@ // Copyright: Ankitects Pty Ltd and contributors // License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html import * as tr from "@generated/ftl"; -import { localizedNumber } from "@tslib/i18n"; +import { createLocaleNumberFormat } from "@tslib/i18n"; import { assertUnreachable } from "@tslib/typing"; import { RevlogRange } from "./graph-helpers"; @@ -106,12 +106,17 @@ export function calculateRetentionPercentageString( passed: number, failed: number, ): string { - let percentage = 0; const total = passed + failed; - if (total !== 0) { - percentage = (passed / total) * 100; + if (total === 0) { + return tr.statisticsTrueRetentionNotApplicable(); } - return localizedNumber(percentage, 1) + "%"; + const numberFormat = createLocaleNumberFormat({ + minimumFractionDigits: 1, + maximumFractionDigits: 1, + style: "percent", + }); + + return numberFormat.format(passed / total); }