Nginx Üzerinde Subdomain ile Laravel'de Çoklu Dil Yönetimi

PHP
Laravel'de çoklu dil yönetimini birçok farklı yaklaşım ile ele alabilirsiniz. Bu tamamen geliştiricinin tercihine kalmış durumda olup, herhangi bir yöntemin diğerinden daha üstün olması gibi bir durum söz konusu değildir. Örneğin bir controller yöntemi aracılığıyla dili değiştirip, bu tercihi session bazlı belirleyebilir, uygulamayı da session'da tuttuğunuz o değere göre çalıştırabilirsiniz, ya da sadece dil parametresini url'ye ekleyip (siteniz.com/page/about?lang=en ve siteniz.com/page/about?lang=tr) query string üzerinden parse_str vb. bir fonksiyon kullanarak dil değerini url'den çekebilir veya routeları oluştururken, her zaman ilk olarak dil parametresini elde ederek, uygulamayı hangi dilde çalıştıracağınızı belirtebilir (siteniz.com/tr/page/about ve siteniz.com/en/page/about), bir başka tercih olarak da bu yazıda bahsedeceğim subdomain aracılığıyla uygulamanızı yönetebilirsiniz (tr.siteniz.com/page/about ve en.siteniz.com/page/about).

Öncelikle belirtmek isterim ki, yine bu yöntemi nasıl yapacağınız size kalmış ama ben daha basit olduğunu düşündüğüm için, middleware ile göstereceğim. Middleware'in ne olduğunu tekrar hatırlatacak olursam, uygulamanız çalışırken, gelen istekleri filtreleyen ya da istekleri cevaba dönüştürmeden önce bazı düzenlemeler yapan ara bileşen olduğunu söyleyebilirim. Burada biz de, uygulamaya gelen her isteğe cevap vermeden önce, uygulamanın dilini subdomain'deki değere göre düzenleyeceğiz. Middleware'i oluşturmak için alttaki komutu kullanabilirsiniz.
$ php artisan make:middleware SetLocale
Devamında da app/Http/Kernel.php içerisinde $middleware dizisine bu middleware'i eklemelisiniz.
protected $middleware = [
\Illuminate\Foundation\Http\Middleware\CheckForMaintenanceMode::class,
\Illuminate\Foundation\Http\Middleware\ConvertEmptyStringsToNull::class,
\Illuminate\Foundation\Http\Middleware\ValidatePostSize::class,
\App\Http\Middleware\TrimStrings::class,
\App\Http\Middleware\SetLocale::class
];
Devamında app/Http/Middleware/SetLocale.php dosyasında dili nasıl değiştirmesi gerektiği mantığını oluşturduğumuzda, işin Laravel kısmı tamamlanmış olacak. Alttaki kod parçasına yorumlar ekledim, muhtemelen her şey yeteri kadar açık gelecektir, ancak şuna dikkat etmeniz önemli, languages parametresi içindeki locale değerlerinin, tr_TR.UTF-8 vb. gibi, sisteminizde yüklü olması lazım, $ sudo locale-gen tr_TR.UTF-8 ile eksik olanları oluşturabilirsiniz.

namespace App\Http\Middleware;

use App;
use Carbon\Carbon;
use Closure;

class SetLocale
{
/**
* Dil ekleyeceğinizde bu değeri değiştirmelisiniz.
* Örneğin İspanyolca eklemek için 'es' => 'es_ES.UTF-8' anahtar değer ikilisini ekleyebilirsiniz.
*
* $languages = ['en' => 'en_US.UTF-8', 'es' => 'es_ES.UTF-8', 'tr' => 'tr_TR.UTF-8'];
*
* @var array
*/
protected $languages = ['en' => 'en_US.UTF-8', 'tr' => 'tr_TR.UTF-8'];

/**
* İstek yapılan adresin en.siteniz.com olduğunu varsayalım.
*
* @param \Illuminate\Http\Request $request
* @param \Closure $next
* @return mixed
*/
public function handle($request, Closure $next)
{
$urlPieces = explode('.', $request->getHost()); // urlPieces değişkenine ['en', 'siteniz', 'com'] dizisini atar.
$language = $urlPieces[0]; // language değişkenine en değerini atar
if (array_key_exists($language, $this->languages)) { // en değeri en, tr değerlerinden birisi mi diye kontrol edilir
App::setLocale($language); // Uygulamanın bölgesel ayarlarını düzenler, trans vb. fonksiyon çağırdınızda en dizininde arama yapar
Carbon::setLocale($language); // Carbon'un formatLocalized yöntemi ile işlem yapıldığında İngilizce çıktı üretmesini sağlar
setlocale(LC_ALL, $this->languages[$language]); // Sistemin bölgesel ayarlarını Amerika'ya göre ayarlar
}
return $next($request);
}
}
Ayrıca unutmamanız gerekir ki, eğer subdomain haricinde direkt olarak siteniz.com'a istek gelirse, sistem config/app.php içerisindeki locale anahtarına atanan dil ile çalışacaktır. Laravel kısmında yapacaklarımız bu kadar, işin nginx kısmında da sadece eklediğiniz her dil için subdomaini eklemeniz lazım.

Türkçe'nin anadil olduğunu ve İngilizce için subdomain oluşturacağımızı varsayalım. Nginx kısmında dikkat etmeniz gereken tek şey, hem siteniz.com hem de en.siteniz.com adreslerinin aynı root'a sahip olacak olması. Eğer her subdomain için ayrı error ve access log'u tutmayacaksanız, ayrı bloklarda herhangi ekstra bir ayarlama yapmanıza da gerek yok.
server {
server_name en.siteniz.com siteniz.com;
root /var/www/siteniz.com/current/public;
...
}
Her yeni dil eklediğinizde, middleware'inizin languages parametresini düzenleyip, nginx bloğuna da o subdomaini eklemeniz lazım. Bunun dışında herhangi bir değişikliğe ihtiyacınız yok.

En başta örnek verdiğim about sayfalarını veritabanına ihtiyaç duymadan, language dosyaları ile gerçeklemeye çalışırsanız eğer, resources/lang/en/application.php ve resources/lang/tr/application.php dosyalarını sırasıyla alttaki gibi düzenlediğinizi varsayalım.
// resources/lang/en/application.php
return [
'about' => 'About'
];
// resources/lang/tr/application.php
return [
'about' => 'Hakkında'
];
Alttaki şekilde de route tanımladığınızı düşünelim.
Route::get('page/about', function () {
    return trans('application.about');
});
en.siteniz.com/page/about About çıktısını, siteniz.com/page/about sayfası ise Hakkında çıktısını döndürecektir.