Gereksinimler ve Ön Hazırlık
Çok dilli bir yapı kurmadan önce sisteminizin belirli standartlara sahip olması gerekir. Laravel 11 veya üzeri bir sürüm kullanmanız, güncel güvenlik yamalarından ve performans iyileştirmelerinden yararlanmanızı sağlar. Ayrıca Composer paket yöneticisinin yüklü olduğundan emin olun.
- Laravel Framework: 11.x veya daha güncel sürüm.
- PHP Sürümü: 8.2 veya üzeri.
- Veritabanı: MySQL veya PostgreSQL.
- Temel Bilgi: Eloquent ORM ve Middleware yapısı hakkında ön bilgi.
Veritabanı Mimarisi: Translatable Pattern
Çok dilli içerik yönetimi için en yaygın ve yönetilebilir yöntem "Translatable" (çevrilebilir) modelidir. Bu yöntemde, ana içerik tablosu ile çeviri tablosunu birbirinden ayırırız. Böylece ana tablonun yapısını değiştirmeden yeni diller ekleyebiliriz.
Öncelikle içeriklerin tutulacağı "posts" tablosunu ve çevirilerin tutulacağı "post_translations" tablosunu oluşturalım. Aşağıdaki migration örneği, veritabanı ilişkisini nasıl kuracağımızı gösterir:
// Veritabanı migration dosyası örneği
Schema::create('posts', function (Blueprint $table) {
$table->id();
$table->string('slug')->unique();
$table->boolean('is_published')->default(true);
$table->timestamps();
});
Schema::create('post_translations', function (Blueprint $table) {
$table->id();
$table->foreignId('post_id')->constrained()->onDelete('cascade');
$table->string('locale')->index(); // 'tr', 'en', 'de' gibi
$table->string('title');
$table->text('content');
$table->unique(['post_id', 'locale']);
});
Bu yapıda post_id ve locale sütunlarının birleşimi benzersiz (unique) olmalıdır. Bu, bir gönderinin belirli bir dilde yalnızca bir kez çevirisinin olmasını garanti eder ve veri bütünlüğünü korur.
Eloquent İlişkileri ve Veri Erişimi
Veritabanı yapısını kurduktan sonra, Laravel'in Eloquent ORM özelliklerini kullanarak bu iki tabloyu birbirine bağlamamız gerekir. Model içerisinde hasMany ilişkisi kurarak çevirilere kolayca erişebiliriz.
// Post.php modeli içerisinde ilişki tanımlama
public function translations()
{
return $this->hasMany(PostTranslation::class);
}
// Belirli bir dildeki içeriği getiren yardımcı yöntem
public function translate($locale = null)
{
return $this->translations()->where('locale', $locale ?? app()->getLocale())->first();
}
Bu yöntem, Controller içerisinde $post->translate('tr')->title şeklinde temiz bir sözdizimi ile verilere erişmenizi sağlar. Eğer belirtilen dilde çeviri yoksa, null döneceği için uygulama mantığınızda "fallback" (varsayılan dil) kontrolü yapmayı unutmayın.
Middleware ile Dil Yönetimi
Kullanıcının hangi dilde içerik göreceğini belirlemek için bir Middleware kullanmak en profesyonel yaklaşımdır. Bu katman, gelen isteğin (request) URL yapısını kontrol eder ve uygulamayı ilgili dile ayarlar.
// SetLocale.php middleware örneği
public function handle(Request $request, Closure $next)
{
$locale = $request->segment(1);
if (in_array($locale, ['tr', 'en', 'de'])) {
app()->setLocale($locale);
} else {
app()->setLocale(config('app.fallback_locale'));
}
return $next($request);
}
Bu middleware, URL'nin ilk segmentini kontrol eder. Örneğin site.com/tr/hakkimizda adresine gidildiğinde tr dilini aktif eder. Bu, SEO açısından da oldukça faydalıdır çünkü her dilin kendine ait bir URL yapısı olur.
Çok Dilli İçerik Yönetim Modelleri Karşılaştırması
| Yöntem | Avantaj | Dezavantaj |
|---|---|---|
| Ayrı Tablolar | Veri bütünlüğü yüksek, esnek. | Karmaşık sorgular gerektirir. |
| JSON Sütunları | Hızlı geliştirme, tek tablo. | Büyük verilerde sorgu performansı düşük. |
| Sabit Dosyalar | Çok hızlı, veritabanı yükü yok. | Dinamik içerik için uygun değil. |
Güvenlik ve Performans İpuçları
Kritik Güvenlik Uyarısı: Çok dilli yapılarda URL üzerinden alınan dil parametrelerini mutlaka valide edin. "Directory Traversal" veya "SQL Injection" risklerine karşı, sadece izin verilen dillerin (whitelist) sisteme girmesine izin verin. Asla kullanıcıdan gelen dil bilgisini doğrudan veritabanı sorgusuna veya dosya yoluna eklemeyin.
Performans tarafında ise, her çeviri sorgusunda veritabanını yormamak için with('translations') kullanarak "Eager Loading" yöntemini tercih edin. Bu, N+1 sorgu problemini engelleyerek uygulamanızın yanıt süresini ciddi oranda düşürecektir.
Sıkça Sorulan Sorular
Laravel'de varsayılan dil nasıl değiştirilir?
config/app.php dosyası içerisindeki locale anahtarını güncelleyerek varsayılan dili değiştirebilirsiniz. Ayrıca fallback_locale ayarını da aynı dosyadan yönetebilirsiniz.
URL'lerde dil parametresi zorunlu mudur?
Zorunlu değildir ancak SEO ve kullanıcı deneyimi için önerilir. Alternatif olarak kullanıcı tercihlerini Session veya Cookie üzerinde tutabilirsiniz.
Arama motorları çok dilli yapıyı nasıl algılar?
Google gibi arama motorları, hreflang etiketlerini kullanmanızı önerir. HTML head kısmına her dil için alternatif linkler ekleyerek arama motorlarına bildirim yapmalısınız.
Veritabanı sorgularında çeviri yoksa ne yapmalıyım?
Uygulamanızda bir "fallback" mekanizması kurmalısınız. Eğer seçilen dilde içerik yoksa, config('app.fallback_locale') değerini kullanarak varsayılan dildeki içeriği getiren bir mantık kurun.
Çeviri tabloları çok büyürse ne olur?
Çeviri tablolarına locale sütunu üzerinde indeks eklediğinizden emin olun. Bu, sorgu hızını büyük ölçüde artıracaktır.
Çok Dilli Uygulamalarda Test Stratejileri
Çok dilli bir yapı kurduğunuzda, uygulamanızın farklı dillerde doğru çalışıp çalışmadığını doğrulamak için birim testleri (unit tests) ve özellik testleri (feature tests) yazmanız kritik öneme sahiptir. Özellikle middleware katmanının dil parametresini doğru algıladığından ve veritabanı sorgularının ilgili çeviriyi getirdiğinden emin olmalısınız.
Aşağıdaki örnek, bir içeriğin farklı dillerdeki yanıtlarını test etmek için kullanılan bir Laravel test metodunu göstermektedir:
public function test_it_can_fetch_content_in_different_languages()
{
$post = Post::factory()->create();
$post->setTranslation('title', 'en', 'Hello World');
$post->setTranslation('title', 'tr', 'Merhaba Dünya');
$this->get('/en/posts/' . $post->id)
->assertSee('Hello World');
$this->get('/tr/posts/' . $post->id)
->assertSee('Merhaba Dünya');
}
İleri Seviye İpucu: Çeviri Önbellekleme (Caching)
Veritabanı üzerinde her istekte çeviri tablolarına gitmek, özellikle trafik arttığında sorgu yükünü artırabilir. Laravel'in Cache mekanizmasını kullanarak çevirileri belleğe almak, uygulamanızın tepki süresini milisaniyelere indirebilir. Çeviri modellerinizde saved veya deleted olaylarını (model events) dinleyerek önbelleği otomatik olarak temizleyebilirsiniz.
Önbellekleme stratejisi için basit bir uygulama örneği:
public function getTranslatedTitleAttribute()
{
return Cache::remember("post_{$this->id}_title_" . app()->getLocale(), 3600, function () {
return $this->translations()->where('locale', app()->getLocale())->first()->title;
});
}
Deployment Sürecinde Dikkat Edilmesi Gerekenler
- Dil Dosyalarının Senkronizasyonu: Deployment sırasında
langdizinindeki dosyaların tüm sunucularda güncel olduğundan emin olun. - Veritabanı Migration: Yeni bir dil eklediğinizde, mevcut tabloları etkilemeyecek şekilde
ALTER TABLEişlemlerini planlayın. - CDN ve Varlıklar: Eğer çeviriye bağlı olarak farklı görseller (örneğin metin içeren banner'lar) kullanıyorsanız, bunları CDN üzerinde dil klasörlerine göre ayırarak yönetin.
Not: Çok dilli yapılarda "Fallback" (yedek dil) mekanizmasını mutlaka yapılandırın. Kullanıcı talep ettiği dilde bir içerik bulamadığında, sistemin boş dönmek yerine varsayılan dildeki içeriği göstermesi kullanıcı deneyimi açısından hayati önem taşır.
Sonuç
Laravel ile çok dilli içerik yönetimi, doğru planlama yapıldığında oldukça sürdürülebilir ve ölçeklenebilir bir süreçtir. Bu rehberde öğrendiğiniz veritabanı ilişkileri, middleware yönetimi ve performans odaklı yaklaşımlar, projenizi profesyonel bir seviyeye taşıyacaktır. Bir sonraki adım olarak, içeriklerinizi yönetebileceğiniz bir "Admin Panel" arayüzü geliştirmeyi ve çevirileri kolaylaştırmak için paketleri (örneğin spatie/laravel-translatable) incelemeyi düşünebilirsiniz.
Sorumluluk Reddi: Bu makalede yer alan kod örnekleri eğitim amaçlıdır. Üretim ortamına almadan önce tüm girdileri sanitize etmeyi ve Laravel'in sunduğu CSRF koruması gibi güvenlik katmanlarını aktif tutmayı unutmayınız.


Yorumlar (0)
Yorum Yaz