Çok dilli bir Laravel sitesini mcamara/laravel-localization ve spatie/laravel-responsecache ile yönetiyorsanız, yanıt önbelleğiniz yanlış bölgeleri ziyaretçilere sunuyor olabilir. İşte İngilizce bir sitemizin sürekli olarak Çince içerik sunmasına neden olan bir hatayı nasıl çözdüğümüz hakkında anlatım.
Problem: Laravel Çok Dilli Site Önbelleği Yanlış Dile Yapıştı
Problem: Laravel Çok Dilli Site Önbelleği Yanlış Dile Yapıştı
Her gün yaklaşık bir kez, üretim aşamasındaki Laravel 12 sitemiz tüm ziyaretçilere Çince içerik sunmaya başladı. Anasayfa, blog yazıları, hizmet sayfaları – her şey İngilizce yerine Basitleştirilmiş Çince olarak görüntüleniyordu. Tek çözüm, yanıt önbelleğini manuel olarak temizlemekti:
php artisan responsecache:clear
İçerik İngilizceye geri dönerdi… ta ki bir gün sonra tekrar Çinceye dökülene kadar.
Çok Dilli Laravel Yığınımız
Çok Dilli Laravel Yığınımız
- Laravel 12 ile birlikte URL’yi önceden belirlenmiş
mcamara/laravel-localizationkullanarak (/en/blog,/zh/blog,/de/blog) -
spatie/laravel-responsecacheile tam sayfa HTML önbelleği (7 günlük TTL)DefaultHasherkullanarak - Altı desteklenen dil dağarcığı,
zh(Basitleştirilmiş Çince) dahil olmak üzere -
hideDefaultLocaleInURLfalseolarak ayarlanmış – tüm URL’lerde açık bir dil öneki bulunmaktadır
Temel Sebep: Neden spatie/laravel-responsecache Yerel Ayarları Göz Ardı Ediyor
Temel Sebep: Neden
spatie/laravel-responsecache Yerel Ayarları Göz Ardı EdiyorYanıt önbelleği, render edilen HTML’i istek URL’sinin bir hash’i ile anahtarlıyor. URL’lerimiz dil öneklerini içerdiğinden (/en/blog ve /zh/blog gibi), her dil için kendi önbellek girişi alması gerekir. Peki, Çince içerik İngilizce sayfalara nasıl sızıyordu?
Üzerimize üç şey birleşiyordu.
1. useAcceptLanguageHeader URL Yerel Ayarını Yönlendirme Çözümlemesi Sırasında Aşar
1.
useAcceptLanguageHeader URL Yerel Ayarını Yönlendirme Çözümlemesi Sırasında Aşarconfig/laravellocalization.php içinde bu ayar var:
'useAcceptLanguageHeader' => true,
Bu, mcamara/laravel-localization‘ya “Eğer URL’den yerel ayarı belirleyemezsen, tarayıcının Accept-Language başlığını kontrol et” demektir.
Özellikle makul görünüyor. Ancak LaravelLocalization::setLocale(), her istekte yönlendirme çözümlemesi esnasında çalışır. URL segmenti tanınan bir yerel ayar içermediğinde (örneğin, / istemi), bir yedek olarak getCurrentLocale() çağrılır:
public function getCurrentLocale()
{
if ($this->currentLocale) {
return $this->currentLocale;
}
if ($this->useAcceptLanguageHeader() && !$this->app->runningInConsole()) {
$negotiator = new LanguageNegotiator(...);
return $negotiator->negotiateLanguage();
}
return $this->configRepository->get('app.locale');
}
Bir Çince bot (Baidu, Sogou, vb.) kök URL / ile Accept-Language: zh isteğinde bulunduğunda, müzakereci zh döner ve app()->setLocale('zh') bir yan etkiolarak yönlendirme çözümlemesi sırasında çağırılır. Sayfa Çince olarak render edilir, önbelleğe alınır ve sonraki ziyaretçiler bu URL'ye girdiklerinde Çince içerik görmeye devam ederler, ta ki önbellek süresi dolana ya da temizlenene kadar.
2. Spatie’nin DefaultHasher Önbellek Anahtarında Yereli Dahil Etmez
2. Spatie’nin
DefaultHasher Önbellek Anahtarında Yereli Dahil EtmezSpatie’nin laravel-responsecache‘deki DefaultHasher, önbellek anahtarlarını şu şekilde oluşturur:
return 'responsecache-' . hash('xxh128',
"{$request->getHost()}-{$request->getPathInfo()}-{$request->getMethod()}/{$suffix}"
);
Aktif yerel ayar yalnızca üstü kapalı olarak URL yolunda bulunur. Eğer herhangi bir kenar durumu app()->getLocale()‘in render sırasında yanlış bir yerel ayar döndürmesine neden olursa, yanlış HTML “doğru” URL’nin anahtarı altında önbelleğe alınır. Derinlemesine bir savunma yoktur – DefaultHasher URL yolunun ve aktif yerel ayarın her zaman uyuştuğunu varsayar.
3. Synchronous Artisan::call() Model Gözlemcilerinde Yerel Durumu Değiştirir
3. Synchronous
Artisan::call() Model Gözlemcilerinde Yerel Durumu DeğiştirirBizim ClearResponseCacheObserver her model güncellemelerinde şunu yapıyordu:
protected function refreshSite(Model $model): void {
ResponseCache::clear(); // Tüm önbelleği sil
Artisan::call('generate-sitemap'); // Synchronous çalışıyor!
$this->submitToIndexNow($model); // Arama motorlarına bildirim
}
Sitemap komutu dahili olarak LaravelLocalization::setLocale('en') çağrısını yapar, uygulama yerel ayarını bir aktif web isteği sırasında değiştirir. Ardından submitToIndexNow, arama motorlarına (Çinli olanlar dahil) tüm yerel URL’ler hakkında bilgi verir ve botları birkaç saniye içinde taramaya gelmeye iter – o sırada yanıt önbelleği silinmiş olduğu için.
Çözüm: Laravel Yanıt Önbelleğini Yerel Ayara Duyarlı Hale Getirmek İçin Üç Değişiklik
Çözüm: Laravel Yanıt Önbelleğini Yerel Ayara Duyarlı Hale Getirmek İçin Üç Değişiklik
Çözüm 1: spatie/laravel-responsecache için Özel Yerel Ayara Duyarlı Hashler
Çözüm 1:
spatie/laravel-responsecache için Özel Yerel Ayara Duyarlı HashlerÖncelikle DefaultHasher‘ı genişleten özel bir hashler oluşturduk ve her önbellek anahtarına app()->getLocale()‘yi açıkça dahil ettik:
declare(strict_types=1);
namespace App\Http\CacheProfiles;
use Illuminate\Http\Request;
use Spatie\ResponseCache\Hasher\DefaultHasher;
class LocaleAwareHasher extends DefaultHasher {
public function getHashFor(Request $request): string {
$cacheNameSuffix = $this->getCacheNameSuffix($request);
$locale = app()->getLocale();
return 'responsecache-' . hash('xxh128',
"{$request->getHost()}-{$this->getNormalizedRequestUri($request)}-{$request->getMethod()}-{$locale}/{$cacheNameSuffix}"
);
}
}
Bunu config/responsecache.php içinde kaydedin:
'hasher' => \App\Http\CacheProfiles\LocaleAwareHasher::class,
Artık URL /en/blog olmasına rağmen app()->getLocale() bir şekilde zh dönerse ayrı önbellek girişleri oluşur, birinin diğerinin üzerine yazması yerine. Bu, yerel önbellek kirlenmesini yapısal olarak imkansız kılar.
Çözüm 2: useAcceptLanguageHeaderi mcamara/laravel-localization içinde devre dışı bırakın
Çözüm 2:
useAcceptLanguageHeaderi mcamara/laravel-localization içinde devre dışı bırakın// config/laravellocalization.php
'useAcceptLanguageHeader' => false,
Tüm URL’lerimiz açık dil önekleri içerdiğinden (/en/, /zh/, vb.), Accept-Language başlığı kontrolüne ihtiyaç yoktur. Bu devre dışı bırakıldığında, önek içermeyen istekler varsayılan uygulama yerel ayarına (en) geri döner, botların başlıklarından müzakere etmez.
Bu, temel tetikleyici oldu. Bir konfigürasyon satırı, Çince botların Accept-Language başlığı aracılığıyla yanıt önbelleğini zehirlemesine izin veren.
Çözüm 3: Sitemap Oluşturmayı Kuyruk İşine Taşıyın
Çözüm 3: Sitemap Oluşturmayı Kuyruk İşine Taşıyın
Model gözlemcisindeki senkron Artisan::call('generate-sitemap')‘ı kuyruğa alınacak bir iş ile değiştirdik:
class GenerateSitemapJob implements ShouldQueue {
public function handle(): void {
Artisan::call('generate-sitemap');
}
}
// Gözlemcide:
protected function refreshSite(Model $model): void {
ResponseCache::clear();
GenerateSitemapJob::dispatch(); // İzole kuyruk işçisinde çalışır
$this->submitToIndexNow($model);
}
Sitemap komutundaki LaravelLocalization::setLocale('en') çağrısı artık izole bir kuyruk işçi işleminde gerçekleşiyor.
Laravel Uygulamanızın Etkilenip Etkilenmediğini Nasıl Kontrol Edersiniz
Laravel Uygulamanızın Etkilenip Etkilenmediğini Nasıl Kontrol Edersiniz
Aşağıdaki koşullar altında bu yanıt önbelleği yerel ayarı hatasına karşı hassas olabilirsiniz:
useAcceptLanguageHeadertrueolarak ayarlanmışsaconfig/laravellocalization.phpiçindeDefaultHasher(varsayılan) kullanıyorsanızconfig/responsecache.phpiçinde- Hata hemen görünür hale getiren Latin olmayan diller (Çince, Arapça vb.) etkinse
spatie/laravel-responsecacheilemcamara/laravel-localization‘yı birlikte kullanıyorsanız
Unutmayın: Dağıtım Sonrası Yanıt Önbelleğini Temizleyin
Unutmayın: Dağıtım Sonrası Yanıt Önbelleğini Temizleyin
Yeni LocaleAwareHasher ile önbellek anahtar formatı değiştiği için, dağıttıktan sonar mevcut yanıt önbelleğini temizlemelisiniz:
php artisan responsecache:clear
Kaynak: Orijinal Makale
- Problem: Laravel Çok Dilli Site Önbelleği Yanlış Dile Yapıştı
- Çok Dilli Laravel Yığınımız
- Temel Sebep: Neden spatie/laravel-responsecache Yerel Ayarları Göz Ardı Ediyor
- 1. useAcceptLanguageHeader URL Yerel Ayarını Yönlendirme Çözümlemesi Sırasında Aşar
- 2. Spatie’nin DefaultHasher Önbellek Anahtarında Yereli Dahil Etmez
- 3. Synchronous Artisan::call() Model Gözlemcilerinde Yerel Durumu Değiştirir
- Çözüm: Laravel Yanıt Önbelleğini Yerel Ayara Duyarlı Hale Getirmek İçin Üç Değişiklik
- Çözüm 1: spatie/laravel-responsecache için Özel Yerel Ayara Duyarlı Hashler
- Çözüm 2: useAcceptLanguageHeaderi mcamara/laravel-localization içinde devre dışı bırakın
- Çözüm 3: Sitemap Oluşturmayı Kuyruk İşine Taşıyın
- Laravel Uygulamanızın Etkilenip Etkilenmediğini Nasıl Kontrol Edersiniz
- Unutmayın: Dağıtım Sonrası Yanıt Önbelleğini Temizleyin


