This content is not yet available in 🇺🇸 English. Showing the 🇹🇷 Türkçe version.
next-intl ile Çok Dilli Next.js: Routing, Mesajlar ve SEO
Bu rehberde ne öğreneceksiniz?
Bu yazı bir haber özeti değil; adım adım uygulayabileceğiniz bir öğretici makale (tutorial) formatındadır. Her bölümün sonunda pratik çıkarımlar ve üretim ortamında karşılaşacağınız senaryolar yer alır.
- [locale] segment yapısını kurmak
- Sunucu ve istemci bileşenlerinde çeviri kullanmak
- Tarih ve relativeTime için useNow pattern
- hreflang ve metadata çevirisi
Ön koşullar
Rehberi verimli takip etmek için aşağıdaki bilgilere aşina olmanız önerilir. Eksik hissettiğiniz konularda ilgili bölümde ek kaynak ipuçları bulacaksınız.
- App Router
- Temel SEO (hreflang, canonical)
Güncellik ve teknoloji yığını
Makale 2026 itibarıyla güncellenmiştir. Örnekler ve API referansları şu yığınla uyumludur: Next.js 16, next-intl 4.x, App Router [locale] segment. Eski sürüm dokümantasyonu ile karıştırmamak için major versiyon farklarını özellikle belirttik.
Framework sürümleri hızla değişir; kalıcı olan prensipler (güvenlik, katman ayrımı, ölçüm) bu rehberin omurgasını oluşturur.
Locale routing ve middleware
Kullanıcı dilini URL'den, cookie'den veya Accept-Language'den türetin; tek kaynak seçin.
middleware.ts ile /tr/blog ve /en/blog yönlendirmesi standarttır. Default locale için prefix politikası (always / as-needed) SEO'yu etkiler.
// middleware.ts
import createMiddleware from "next-intl/middleware";
import { routing } from "./i18n/routing";
export default createMiddleware(routing);
export const config = { matcher: ["/((?!api|_next|.*\..*).*)"] };
Locale routing ve middleware — Uygulama adımları
Aşağıdaki adımları sırayla uygulayın. Her adım tamamlandığında bir sonrakine geçin; özellikle güvenlik ve veri bütünlüğü adımlarını atlamayın.
Adım adım uygulama
Aşağıdaki sırayı takip edin. Her adımı tamamlamadan bir sonrakine geçmeyin; özellikle güvenlik ve veri katmanı adımları atlanmamalıdır.
- next-intl middleware oluşturun
- app/[locale]/layout.tsx ile provider sarmalayın
- Geçersiz locale için notFound()
// middleware.ts
import createMiddleware from "next-intl/middleware";
import { routing } from "./i18n/routing";
export default createMiddleware(routing);
export const config = { matcher: ["/((?!api|_next|.*\..*).*)"] };
Mesaj dosyaları ve namespace
messages/tr.json ve messages/en.json paralel anahtar yapısında olmalı.
Blog, Nav, Auth gibi namespace'ler merge conflict'i azaltır. Eksik anahtar için build-time kontrol (strict mode) önerilir.
Mesaj dosyaları ve namespace — Ek örnek
İkinci örnek, edge case veya alternatif yaklaşımı gösterir.
// BlogCard.tsx — relativeTime
"use client";
import { useNow, useFormatter } from "next-intl";
export function BlogCard({ date }: { date: Date }) {
const now = useNow({ updateInterval: 60_000 });
const format = useFormatter();
return <time>{format.relativeTime(date, now)}</time>;
}
SEO: alternate links ve canonical
Aynı içeriğin iki dilde duplicate content sayılmaması için hreflang şart.
Production ortamında next-intl ile ilgili en sık görülen sorun, geliştirme ortamındaki varsayımların (küçük veri seti, tek kullanıcı, sıcak cache) canlı trafikte çökmemesidir. Bu yüzden her değişiklikten önce yük testi veya en azından p95 latency ölçümü yapın.
Structured logging (request id, route, süre, kullanıcı id’si — PII olmadan) ve hata oranı alarmları, sorunları kullanıcı şikayetinden önce yakalamanızı sağlar. Log’da stack trace tutun; kullanıcıya generic mesaj gösterin.
Dokümantasyonu kod ile birlikte güncelleyin: README, ADR (Architecture Decision Record) veya ekip wiki’sinde “neden bu kararı aldık?” sorusunun cevabı gelecekteki sizin en büyük yardımcınızdır.
Derinlemesine: Senaryo çalışması
Gerçek bir ekip senaryosu: Cuma akşamı deploy sonrası hata oranı yükseldi. Aşağıdaki kontrol listesi ile kök nedeni daraltın.
Son deploy diff'ine bakın: şema migration, env değişikliği, feature flag açılışı.
Trace id ile tek bir başarısız isteği uçtan uca izleyin (edge → server → DB).
Gerekirse kill switch veya önceki imaja rollback; veri migration geri alınamazsa kod rollback yeterli olmayabilir.
Adım adım uygulama
Aşağıdaki sırayı takip edin. Her adımı tamamlamadan bir sonrakine geçmeyin; özellikle güvenlik ve veri katmanı adımları atlanmamalıdır.
- Metrik panosunda hata oranı ve p95 latency
- Log'da son 15 dakika exception grupları
- Son başarılı deploy tag'ine dönüş kararı
Production checklist
Canlıya çıkmadan önce bu maddeleri review edin.
Production ortamında üretim ortamı ile ilgili en sık görülen sorun, geliştirme ortamındaki varsayımların (küçük veri seti, tek kullanıcı, sıcak cache) canlı trafikte çökmemesidir. Bu yüzden her değişiklikten önce yük testi veya en azından p95 latency ölçümü yapın.
Structured logging (request id, route, süre, kullanıcı id’si — PII olmadan) ve hata oranı alarmları, sorunları kullanıcı şikayetinden önce yakalamanızı sağlar. Log’da stack trace tutun; kullanıcıya generic mesaj gösterin.
Dokümantasyonu kod ile birlikte güncelleyin: README, ADR (Architecture Decision Record) veya ekip wiki’sinde “neden bu kararı aldık?” sorusunun cevabı gelecekteki sizin en büyük yardımcınızdır.
- Rate limit ve timeout tanımlı
- Secret'lar secret manager'da
- Health check ve readiness probe çalışıyor
- Alarm eşikleri tanımlı (5xx, latency)
Sık yapılan hatalar
Aşağıdaki tuzaklar eğitim ortamlarında nadiren, production'da ise pahalıya mal olur. Code review checklist'inize eklemenizi öneririz.
- Client'ta hard-coded Türkçe string bırakmak
- relativeTime için useNow kullanmamak (ENVIRONMENT_FALLBACK)
- Locale prefix tutarsızlığı
Pratik alıştırmalar
Okumak yeterli değildir; öğrenmeyi pekiştirmek için küçük bir side-project veya mevcut kod tabanınızda şu görevleri uygulayın:
- Yeni bir sayfa için tr/en mesaj ekleyin
- generateMetadata ile locale başlık üretin
Özet ve sonraki adımlar
Bu rehberdeki prensipleri tek seferde tüm projeye uygulamaya çalışmayın. Önce tek bir route veya modül seçin, ölçün, sonra yaygınlaştırın.
- RTL dil desteği
- Çeviri CMS entegrasyonu