diff --git a/src/lib/components/layout/main/card/BlueskyPostCard.svelte b/src/lib/components/layout/main/card/BlueskyPostCard.svelte
index 13d8f06..eee26b9 100644
--- a/src/lib/components/layout/main/card/BlueskyPostCard.svelte
+++ b/src/lib/components/layout/main/card/BlueskyPostCard.svelte
@@ -3,6 +3,7 @@
import { Card } from '$lib/components/ui';
import { fetchLatestBlueskyPost, type BlueskyPost } from '$lib/services/atproto';
import { formatRelativeTime } from '$lib/utils/formatDate';
+ import { formatCompactNumber } from '$lib/utils/formatNumber';
import { Heart, Repeat2, MessageCircle, ExternalLink, X } from '@lucide/svelte';
let post: BlueskyPost | null = null;
@@ -10,6 +11,9 @@
let error: string | null = null;
let lightboxImage: { url: string; alt: string } | null = null;
+ // Detect system locale, fallback to en-GB
+ const locale = typeof navigator !== 'undefined' ? navigator.language || 'en-GB' : 'en-GB';
+
onMount(async () => {
try {
post = await fetchLatestBlueskyPost();
@@ -20,16 +24,7 @@
}
});
- function formatNumber(num?: number): string {
- if (!num) return '0';
- if (num >= 1_000_000) return `${(num / 1_000_000).toFixed(1)}M`;
- if (num >= 1_000) return `${(num / 1_000).toFixed(1)}K`;
- return num.toString();
- }
-
function getPostUrl(uri: string): string {
- // Convert AT URI to bsky.app URL
- // Format: at://did:plc:xxx/app.bsky.feed.post/rkey
const parts = uri.split('/');
const did = parts[2];
const rkey = parts[4];
@@ -50,13 +45,8 @@
document.body.style.overflow = '';
}
- // Render rich text with facets (links, mentions, hashtags)
function renderRichText(text: string, facets?: any[]): string {
- if (!facets || facets.length === 0) {
- return escapeHtml(text);
- }
-
- // Sort facets by byteStart to process them in order
+ if (!facets || facets.length === 0) return escapeHtml(text);
const sortedFacets = [...facets].sort((a, b) => a.index.byteStart - b.index.byteStart);
let result = '';
@@ -64,10 +54,7 @@
for (const facet of sortedFacets) {
const { byteStart, byteEnd } = facet.index;
-
- // Add text before this facet
result += escapeHtml(text.slice(lastIndex, byteStart));
-
const facetText = text.slice(byteStart, byteEnd);
const feature = facet.features?.[0];
@@ -88,9 +75,7 @@
lastIndex = byteEnd;
}
- // Add remaining text after last facet
result += escapeHtml(text.slice(lastIndex));
-
return result;
}
@@ -284,7 +269,7 @@
{/if}
-
+
{#if depth === 0 || (depth === 1 && !postData.quotedPost)}
{#if postData.replyCount !== undefined}
@@ -293,21 +278,21 @@
class="h-{isQuoted ? '3' : '4'} w-{isQuoted ? '3' : '4'}"
aria-hidden="true"
/>
- {formatNumber(postData.replyCount)}
+ {formatCompactNumber(postData.replyCount, locale)}
{/if}
{#if postData.repostCount !== undefined}
- {formatNumber(postData.repostCount)}
+ {formatCompactNumber(postData.repostCount, locale)}
{/if}
{#if postData.likeCount !== undefined}
- {formatNumber(postData.likeCount)}
+ {formatCompactNumber(postData.likeCount, locale)}
{/if}
diff --git a/src/lib/components/layout/main/card/ProfileCard.svelte b/src/lib/components/layout/main/card/ProfileCard.svelte
index e0d22de..5d8bae6 100644
--- a/src/lib/components/layout/main/card/ProfileCard.svelte
+++ b/src/lib/components/layout/main/card/ProfileCard.svelte
@@ -3,6 +3,7 @@
import { Card } from '$lib/components/ui';
import { fetchProfile, type ProfileData } from '$lib/services/atproto';
import LinkCard from './LinkCard.svelte';
+ import { formatCompactNumber } from '$lib/utils/formatNumber';
let profile: ProfileData | null = null;
let loading = true;
@@ -10,6 +11,9 @@
let imageLoaded = false;
let bannerLoaded = false;
+ // Detect system locale, fallback to en-GB
+ const locale = typeof navigator !== 'undefined' ? navigator.language || 'en-GB' : 'en-GB';
+
onMount(async () => {
try {
profile = await fetchProfile();
@@ -19,13 +23,6 @@
loading = false;
}
});
-
- function formatNumber(num?: number): string {
- if (!num) return '0';
- if (num >= 1_000_000) return `${(num / 1_000_000).toFixed(1)}M`;
- if (num >= 1_000) return `${(num / 1_000).toFixed(1)}K`;
- return num.toString();
- }
@@ -118,21 +115,21 @@
- {formatNumber(safeProfile.postsCount)}
+
+ {formatCompactNumber(safeProfile.postsCount, locale)}
+
Posts
- {formatNumber(safeProfile.followersCount)}
+
+ {formatCompactNumber(safeProfile.followersCount, locale)}
+
Followers
- {formatNumber(safeProfile.followsCount)}
+
+ {formatCompactNumber(safeProfile.followsCount, locale)}
+
Following
diff --git a/src/lib/utils/formatNumber.ts b/src/lib/utils/formatNumber.ts
index ce64a69..4383463 100644
--- a/src/lib/utils/formatNumber.ts
+++ b/src/lib/utils/formatNumber.ts
@@ -3,24 +3,42 @@
*/
/**
- * Formats large numbers into compact human-readable format
+ * Determines the effective locale, preferring system locale with fallback to 'en-GB'.
+ */
+function getLocale(locale?: string): string {
+ return (
+ locale ||
+ (typeof navigator !== 'undefined' && navigator.language) ||
+ 'en-GB'
+ );
+}
+
+/**
+ * Formats large numbers into a compact, human-readable format.
+ * Automatically adapts to the given or system locale.
* @param num - The number to format
+ * @param locale - Optional locale string (defaults to system or 'en-GB')
* @returns Formatted string (e.g., "1.2K", "3.4M")
*/
-export function formatCompactNumber(num?: number): string {
- if (!num) return '0';
- if (num >= 1_000_000) return `${(num / 1_000_000).toFixed(1)}M`;
- if (num >= 1_000) return `${(num / 1_000).toFixed(1)}K`;
- return num.toString();
+export function formatCompactNumber(num?: number, locale?: string): string {
+ if (num === undefined || num === null) return '0';
+ const effectiveLocale = getLocale(locale);
+
+ return new Intl.NumberFormat(effectiveLocale, {
+ notation: 'compact',
+ compactDisplay: 'short',
+ maximumFractionDigits: 1
+ }).format(num);
}
/**
- * Formats a number with thousand separators
+ * Formats a number with thousand separators.
+ * Automatically adapts to the given or system locale.
* @param num - The number to format
- * @param locale - The locale to use (default: system locale)
+ * @param locale - Optional locale string (defaults to system or 'en-GB')
* @returns Formatted string (e.g., "1,234,567")
*/
export function formatNumber(num: number, locale?: string): string {
- const userLocale = locale || (typeof navigator !== 'undefined' ? navigator.language : 'en-GB');
- return new Intl.NumberFormat(userLocale).format(num);
-}
+ const effectiveLocale = getLocale(locale);
+ return new Intl.NumberFormat(effectiveLocale).format(num);
+}
\ No newline at end of file