Musa Yılmaz
·2 dk okuma

Admin Panelinden Yönetilen Çok Dilli SEO Landing Sayfaları Kurmak

nextjsseodjangoi18n

Bir havalimanı transfer sitesinde "İstanbul Havalimanı - Taksim Transfer" gibi onlarca konum bazlı sayfaya, hem de 15 farklı dilde ihtiyacımız vardı. Bunu her dil için elle yazılmış statik sayfalarla yönetmek sürdürülemezdi — yeni bir lokasyon eklemek demek, geliştiriciye ihtiyaç duymak demekti.

Veri odaklı sayfa üretimi

Çözüm, sayfa içeriğini kod yerine veritabanında tutmaktı. Django admin üzerinden bir "Lokasyon" ve "Transfer Rotası" modeli tanımladık; her rota kaydı başlık, açıklama, fiyat aralığı gibi alanları 15 dilde tutuyor. Next.js tarafında ise tek bir dinamik route bu veriyi çekip sayfayı üretiyor:

// app/[locale]/transfer/[slug]/page.tsx
export async function generateStaticParams() {
  const routes = await fetchAllTransferRoutes();
  return routes.flatMap((route) =>
    locales.map((locale) => ({ locale, slug: route.slug }))
  );
}
 
export default async function TransferPage({ params }) {
  const { locale, slug } = await params;
  const route = await fetchTransferRoute(slug, locale);
  return <TransferLandingTemplate route={route} />;
}

Yeni bir lokasyon eklemek artık admin panelinde birkaç alan doldurmaktan ibaret; deploy gerekmiyor.

ISR ile anında güncelleme

Sayfalar generateStaticParams ile build zamanında statik üretiliyor, ama admin panelinden bir içerik güncellendiğinde bunu beklemek istemedik. Django tarafında bir kayıt kaydedildiğinde Next.js'in revalidate endpoint'ine bir webhook atıyoruz:

# Django signal
@receiver(post_save, sender=TransferRoute)
def revalidate_page(sender, instance, **kwargs):
    requests.post(
        f"{NEXTJS_URL}/api/revalidate",
        json={"path": f"/transfer/{instance.slug}"},
        headers={"Authorization": f"Bearer {REVALIDATE_SECRET}"},
    )

Bu sayede sayfa hem statik üretimin performans avantajını koruyor hem de içerik değişikliği saniyeler içinde canlıya yansıyor.

Arapça için RTL desteği

15 dilden biri Arapça olduğu için sadece metin çevirisi yetmiyor, sayfa yönünün de (RTL) değişmesi gerekiyor. next-intl ile locale'e göre dir attribute'unu otomatik ayarladık:

<html lang={locale} dir={locale === "ar" ? "rtl" : "ltr"}>

Tailwind'de de rtl: varyantını kullanarak margin/padding gibi yön bağımlı stilleri tersine çevirdik.

Sonuç

Bu yapı sayesinde firma, yeni bir şehir veya rota eklemek istediğinde bana veya başka bir geliştiriciye ihtiyaç duymuyor — admin panelinden birkaç alan dolduruyor, sayfa saniyeler içinde 15 dilde SEO'ya uygun şekilde yayında oluyor.