Lumina'nın kurumsal sitesini Türkçe ve İngilizce iki dilde yayına almaya karar verdiğimizde, "sadece çeviri yeter" sandık. Pratikte iki dilli bir Next.js 16 sitesinin SEO sağlığını korumak; routing, metadata, sitemap, canonical ve UX kararları zinciri demekti. Bu yazıda kurduğumuz sistemi özetliyoruz.
1. Routing: as-needed prefix
next-intl'de üç prefix modu var: always,as-needed ve never. Türkçe'yi varsayılan dilimiz seçtik (ana hedef pazar) ve as-needed moduna geçtik. Sonuç:
/ve/hakkimizdadoğrudan Türkçe/enve/en/hakkimizdaİngilizce- Slug'lar her iki dilde aynı (
/hakkimizda)
Slug'ları İngilizce'ye lokalize etmedik (/en/about gibi). next-intl'in pathnames özelliği bunu destekliyor ama bizim için ek karmaşa: aynı içerik için iki ayrı kanonik path olmak zorunda kalıyor. İlk sürümde basit tutmayı seçtik; ileride bunu yeniden değerlendirebiliriz.
2. Hreflang: arama motorlarına dil ailelerini söylemek
Her sayfada her iki dil için hreflangtag'leri olmalı:
<link rel="alternate" hreflang="tr" href="/hakkimizda" /> <link rel="alternate" hreflang="en" href="/en/hakkimizda" /> <link rel="alternate" hreflang="x-default" href="/hakkimizda" />
Next.js 16'ın metadata API'sı bunu kolaylaştırıyor: alternates.languagesfield'ı. Biz bunu bir helper'la sarmalayıp tüm sayfalardan tutarlı şekilde kullanıyoruz.
3. Sitemap: dinamik ve dil farkındalı
app/sitemap.tsdosyası tüm rotaları üretirken her rota için iki entry oluşturmalı (TR ve EN). Aksi halde Google İngilizce sayfaları "görünmez" sanır:
for (const route of ROUTES) {
for (const locale of locales) {
entries.push({
url: `${siteUrl}${getPath(route, locale)}`,
lastModified: new Date(),
alternates: {
languages: { tr: `...`, en: `...` }
}
});
}
}4. Locale switcher UX
Kullanıcı dil değiştirdiğinde aynı içerik sayfasının diğer dilini görmeli — anasayfaya değil. usePathnameile mevcut path'i alıp router.replace(pathname, {locale})ile değiştiriyoruz. next-intl'in typed navigation helper'ları bu işlemi tip güvenli yapıyor.
5. Apple-grade içerik standardı
SEO sadece teknik bir disiplin değil. Apple App Store Developer Program enrollment red gerekçemiz "minimal content"tı — bu, sayfa sayısı kadar her sayfanın doluluğu da önemli demek. Lumina sitesinde 21 unique route × 2 dil = 42 sayfa hedefliyoruz. Her sayfa, varolan bir şirketten beklenen seviyede içerik taşıyor:
- Şirket künyesi (sicil, vergi, adres) footer'da görünür
- Engineering blog: gerçek teknik içerik
- Yasal sayfalar: gerçek hukuki metinler, jenerik şablon değil
- İletişim formu: çalışıyor, test ediliyor (Apple test eder!)
6. Lighthouse'ı build pipeline'a bağlamak
Build sonrası her route için Lighthouse koşmak yerine; kritik sayfaları (anasayfa, hakkımızda, ürünler) belirleyip Lighthouse CI ile her PR'da kontrol ediyoruz. Performans bütçesi:
- LCP < 2.0s on mobile 4G
- CLS < 0.05
- INP < 150ms
- Initial JS < 200KB
Sonuç
Çok dilli SEO; Next.js 16, next-intl ve Vercel'in ortak sistemiyle çözülmüş bir problem. Kritik nokta, dilsel UX'in ve içerik kalitesinin teknik altyapı kadar önemli olduğu. Apple'ın "minimal content" reddi bize bunu net bir şekilde hatırlattı: arama motorları kadar insan da, sitenin dolu olduğunu görmek istiyor.