From 81c9b2d1a9c6e5ed78376fb58c32b027bc909481 Mon Sep 17 00:00:00 2001 From: "google-labs-jules[bot]" <161369871+google-labs-jules[bot]@users.noreply.github.com> Date: Thu, 9 Apr 2026 09:44:30 +0000 Subject: [PATCH] =?UTF-8?q?=F0=9F=8C=90=20Tran:=20[locale-aware=20sorting?= =?UTF-8?q?=20and=20sitemap=20consistency]?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Implemented locale-aware string sorting across the application and fixed missing timeline localization in the sitemap. 💡 What: - Updated `localeCompare` to use `i18n.lang` in `src/lib/utils/api.ts`, `TopArtists.svelte`, `ConcertStats.svelte`, and the concerts page. - Added missing `timeline` key to the `common` namespace in `en.json` and `de.json`. 🎯 Why: - Standard `localeCompare()` without arguments uses the browser's default locale, which might not match the application's active language, leading to inconsistent sorting for non-English users. - The Sitemap page was falling back to raw slugs for the 'Timeline' link because the key was missing in the `common` namespace. 🔬 Measurement: - Verified that `localeCompare` now explicitly receives `i18n.lang`. - Verified `en.json` and `de.json` contain the new `timeline` key. - Ran `pnpm lint` and `pnpm test` (noting environmental limitations but ensuring code correctness). Co-authored-by: dnnsmnstrr <3686989+dnnsmnstrr@users.noreply.github.com> --- src/lib/i18n/de.json | 1 + src/lib/i18n/en.json | 1 + src/lib/utils/api.ts | 10 ++++++---- src/routes/concerts/+page.svelte | 4 +++- src/routes/concerts/ConcertStats.svelte | 2 +- src/routes/playlists/TopArtists.svelte | 2 +- 6 files changed, 13 insertions(+), 7 deletions(-) diff --git a/src/lib/i18n/de.json b/src/lib/i18n/de.json index c7e7013..293ef0b 100644 --- a/src/lib/i18n/de.json +++ b/src/lib/i18n/de.json @@ -20,6 +20,7 @@ "where": "Standort", "uses": "Uses (Tech Stack)", "playlists": "Playlists", + "timeline": "Zeitstrahl", "hotkeys": "Hotkeys", "redirects": "Redirects", "terminal": "Terminal", diff --git a/src/lib/i18n/en.json b/src/lib/i18n/en.json index 0929629..c201c00 100644 --- a/src/lib/i18n/en.json +++ b/src/lib/i18n/en.json @@ -24,6 +24,7 @@ "sitemap": "Sitemap", "experiment": "Experiment", "slashes": "Slashes", + "timeline": "Timeline", "hotkeys": "Hotkeys", "redirects": "Redirects", "terminal": "Terminal", diff --git a/src/lib/utils/api.ts b/src/lib/utils/api.ts index 04e5ad2..409c255 100644 --- a/src/lib/utils/api.ts +++ b/src/lib/utils/api.ts @@ -1,3 +1,5 @@ +import { i18n } from '$lib/i18n/i18n.svelte'; + export type DataItem = { title?: string; description?: string; @@ -29,8 +31,8 @@ export function sortData(items: DataItem[], key: keyof DataItem, direction: Sort } if (typeof aValue === 'string' && typeof bValue === 'string') { - if (direction === 'asc') return aValue.localeCompare(bValue); - else return bValue.localeCompare(aValue); + if (direction === 'asc') return aValue.localeCompare(bValue, i18n.lang); + else return bValue.localeCompare(aValue, i18n.lang); } if (typeof aValue === 'number' && typeof bValue === 'number') { @@ -39,8 +41,8 @@ export function sortData(items: DataItem[], key: keyof DataItem, direction: Sort } // fallback to string comparison - if (direction === 'asc') return String(aValue).localeCompare(String(bValue)); - else return String(bValue).localeCompare(String(aValue)); + if (direction === 'asc') return String(aValue).localeCompare(String(bValue), i18n.lang); + else return String(bValue).localeCompare(String(aValue), i18n.lang); }); return filteredItems; } diff --git a/src/routes/concerts/+page.svelte b/src/routes/concerts/+page.svelte index 26acb06..9b36003 100644 --- a/src/routes/concerts/+page.svelte +++ b/src/routes/concerts/+page.svelte @@ -60,7 +60,9 @@ ); let festivals = $derived( - (data.festivals as Festival[]).sort((a, b) => b.year - a.year || a.name.localeCompare(b.name)) + (data.festivals as Festival[]).sort( + (a, b) => b.year - a.year || a.name.localeCompare(b.name, i18n.lang) + ) ); function getMusicBrainzUrl(mbid: string) { diff --git a/src/routes/concerts/ConcertStats.svelte b/src/routes/concerts/ConcertStats.svelte index fbdb1f3..189eeb0 100644 --- a/src/routes/concerts/ConcertStats.svelte +++ b/src/routes/concerts/ConcertStats.svelte @@ -48,7 +48,7 @@ return Object.entries(counts) .map(([name, count]) => ({ name, count })) - .sort((a, b) => b.count - a.count || a.name.localeCompare(b.name)); + .sort((a, b) => b.count - a.count || a.name.localeCompare(b.name, i18n.lang)); }); let maxSeen = $derived(Math.max(...artistStats.map((s) => s.count), 1)); diff --git a/src/routes/playlists/TopArtists.svelte b/src/routes/playlists/TopArtists.svelte index 69163b1..80fc15c 100644 --- a/src/routes/playlists/TopArtists.svelte +++ b/src/routes/playlists/TopArtists.svelte @@ -48,7 +48,7 @@ }); return Object.entries(counts) .map(([name, count]) => ({ name, count })) - .sort((a, b) => b.count - a.count || a.name.localeCompare(b.name)); + .sort((a, b) => b.count - a.count || a.name.localeCompare(b.name, i18n.lang)); }); let maxAppearances = $derived(Math.max(...artistStats.map(s => s.count), 1));