diff --git a/src/lib/pluralize.ts b/src/lib/pluralize.ts
new file mode 100644
index 000000000..f2672ead5
--- /dev/null
+++ b/src/lib/pluralize.ts
@@ -0,0 +1,16 @@
+export const pluralRules = {
+ file: "files",
+ insertion: "insertions",
+ deletion: "deletions",
+ commit: "commits",
+ issue: "issues",
+ contributor: "contributors",
+ patch: "patches",
+} as const;
+
+export function pluralize(
+ singular: keyof typeof pluralRules,
+ count: number,
+): string {
+ return count === 1 ? singular : pluralRules[singular];
+}
diff --git a/src/views/projects/Header.svelte b/src/views/projects/Header.svelte
index ce13920b7..9ae47fa36 100644
--- a/src/views/projects/Header.svelte
+++ b/src/views/projects/Header.svelte
@@ -10,6 +10,7 @@
import PeerSelector from "@app/views/projects/PeerSelector.svelte";
import { closeFocused } from "@app/components/Floating.svelte";
import { config } from "@app/lib/config";
+ import { pluralize } from "@app/lib/pluralize";
export let activeRoute: ProjectRoute;
export let project: Project;
@@ -120,7 +121,7 @@
active={activeRoute.params.view.resource === "history"}
on:click={() => toggleContent("history", true)}>
{tree.stats.commits}
- commit(s)
+ {pluralize("commit", tree.stats.commits)}
toggleContent("issues", false)}>
{project.issues.open ?? 0}
- issue(s)
+ {pluralize("issue", project.issues.open)}
toggleContent("patches", false)}>
{project.patches.open ?? 0}
- patch(es)
+ {pluralize("patch", project.patches.open)}
{tree.stats.contributors}
- contributor(s)
+ {pluralize("contributor", tree.stats.contributors)}
diff --git a/src/views/projects/SourceBrowser/Changeset.svelte b/src/views/projects/SourceBrowser/Changeset.svelte
index bfca4a5c1..760a1edc6 100644
--- a/src/views/projects/SourceBrowser/Changeset.svelte
+++ b/src/views/projects/SourceBrowser/Changeset.svelte
@@ -1,6 +1,8 @@