Skip to content

Commit 4149584

Browse files
MaxDatenclaude
andcommitted
feat(i18n): localize OG preview image for maxdaten.de
Pass locale as query parameter to the OG image route so the server resolves translated text (headline, subheadline, badge, brand) via the existing i18n system. German shares on social media now show German copy and the maxdaten.de brand instead of hardcoded English. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent 75c06c3 commit 4149584

File tree

5 files changed

+39
-10
lines changed

5 files changed

+39
-10
lines changed

src/routes/+layout.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,10 @@ export const prerender = true;
1313

1414
export const load = ({ url }) => {
1515
const locale: Locale = getLocaleFromPath(url.pathname);
16-
const ogImageUrl = new URL(`/og.jpg?v=${version}`, url.origin).href;
16+
const ogImageUrl = new URL(
17+
`/og.jpg?locale=${locale}&v=${version}`,
18+
url.origin
19+
).href;
1720

1821
const description = t(locale, 'meta.description');
1922
const title = t(locale, 'meta.title');

src/routes/og.jpg/+server.ts

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,15 +3,21 @@ import { error } from '@sveltejs/kit';
33
import type { RequestHandler } from './$types';
44
import { generateOgImage } from '$lib/server/og-generation';
55
import { loadProfileImageUrl } from './profile-image';
6+
import { t, type Locale } from '$lib/i18n';
67

78
export const prerender = false;
89

910
export const GET: RequestHandler = async ({ url }) => {
1011
try {
12+
const locale = (url.searchParams.get('locale') as Locale) || 'en';
1113
const avatarUrl = await loadProfileImageUrl(url);
1214

1315
return await generateOgImage(ProfileOgCard, {
14-
badge: 'Available for 2026',
16+
badge: t(locale, 'hero.badge'),
17+
headline: t(locale, 'hero.headline'),
18+
headlineAccent: t(locale, 'hero.headlineAccent'),
19+
sub: t(locale, 'hero.subheadline'),
20+
brand: locale === 'de' ? 'maxdaten.de' : 'maxdaten.io',
1521
avatarUrl,
1622
});
1723
} catch (err) {

src/routes/og.jpg/ProfileOgCard.svelte

Lines changed: 17 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,21 @@
33
<script lang="ts">
44
type Props = {
55
badge?: string;
6+
headline?: string;
7+
headlineAccent?: string;
8+
sub?: string;
9+
brand?: string;
610
avatarUrl?: string;
711
};
812
9-
let { badge = 'Available for 2026', avatarUrl }: Props = $props();
13+
let {
14+
badge = 'Available for 2026',
15+
headline = 'Products that ship',
16+
headlineAccent = 'Systems that scale',
17+
sub = 'Full-stack product engineering with knowledge transfer built in — 15+ years from startup to 100M+ requests/day.',
18+
brand = 'maxdaten.io',
19+
avatarUrl,
20+
}: Props = $props();
1021
</script>
1122

1223
<div class="wrapper">
@@ -17,25 +28,24 @@
1728
<div class="container">
1829
<!-- Left Text Column -->
1930
<div class="og_textbox">
20-
<div class="brand">maxdaten.io</div>
31+
<div class="brand">{brand}</div>
2132
<div class="badge">{badge}</div>
2233
<h1>
23-
<span class="line">Products that ship.</span>
34+
<span class="line">{headline}.</span>
2435
<span class="line"
25-
><span class="highlight">Systems that scale</span>.</span
36+
><span class="highlight">{headlineAccent}</span>.</span
2637
>
2738
</h1>
2839
<p class="sub">
29-
Full-stack product engineering with knowledge transfer built in
30-
— 15+ years from startup to 100M+ requests/day.
40+
{sub}
3141
</p>
3242
</div>
3343

3444
<!-- Right Card - Extends beyond frame edge -->
3545
<div class="card-wrapper">
3646
<div class="card">
3747
<div class="card-header">
38-
<span>MAXDATEN.IO</span>
48+
<span>{brand.toUpperCase()}</span>
3949
</div>
4050
{#if avatarUrl}
4151
<img src={avatarUrl} alt="Avatar" class="avatar" />

src/routes/og.jpg/preview/+page.svelte

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@
2424
</div>
2525

2626
<div class="og-preview-card">
27-
<ProfileOgCard badge="Available for 2026" avatarUrl={data.avatarUrl} />
27+
<ProfileOgCard {...data.ogProps} avatarUrl={data.avatarUrl} />
2828
</div>
2929

3030
<div class="og-preview-info">

src/routes/og.jpg/preview/+page.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,17 +2,27 @@ import { error } from '@sveltejs/kit';
22
import type { PageLoad } from './$types';
33
import { authors } from '$lib/data/authors';
44
import { loadProfileImageUrl } from '../profile-image';
5+
import { t, type Locale } from '$lib/i18n';
56

67
export const prerender = 'auto';
78

89
export const load: PageLoad = async ({ url }) => {
910
try {
11+
const locale = (url.searchParams.get('locale') as Locale) || 'en';
1012
const author = authors.jloos;
1113
const avatarUrl = await loadProfileImageUrl(url);
1214

1315
return {
1416
author,
1517
avatarUrl,
18+
locale,
19+
ogProps: {
20+
badge: t(locale, 'hero.badge'),
21+
headline: t(locale, 'hero.headline'),
22+
headlineAccent: t(locale, 'hero.headlineAccent'),
23+
sub: t(locale, 'hero.subheadline'),
24+
brand: locale === 'de' ? 'maxdaten.de' : 'maxdaten.io',
25+
},
1626
};
1727
} catch (err) {
1828
console.error('Failed to load data for profile OG preview', err);

0 commit comments

Comments
 (0)