82 lines
2.6 KiB
PHP
82 lines
2.6 KiB
PHP
<?php
|
|
|
|
namespace App\Http\Middleware;
|
|
|
|
use Closure;
|
|
use Illuminate\Http\Request;
|
|
use Illuminate\Support\Facades\Cookie;
|
|
|
|
class SetLocale
|
|
{
|
|
/** @var array<string> */
|
|
private array $available = [
|
|
'en','de','es','pt_BR','tr','pl',
|
|
// prepared, not yet enabled in UI
|
|
'fr','it','ru','uk','vi','id','zh_CN','ja','ko','sv','no','fi','nl',
|
|
];
|
|
|
|
public function handle(Request $request, Closure $next)
|
|
{
|
|
$locale = $this->resolveLocale($request);
|
|
|
|
// Apply
|
|
app()->setLocale($locale);
|
|
|
|
// Persist for guests as well (1 year)
|
|
$request->session()->put('locale', $locale);
|
|
Cookie::queue(cookie('locale', $locale, 60 * 24 * 365));
|
|
|
|
// If logged in and preference changed, consider persisting upstream (no local DB writes)
|
|
if ($user = $request->user()) {
|
|
if (($user->preferred_locale ?? null) !== $locale) {
|
|
// Defer persistence to external API; keep request-scoped preference only.
|
|
// Optionally, emit an event or queue a task to sync.
|
|
}
|
|
}
|
|
|
|
return $next($request);
|
|
}
|
|
|
|
private function resolveLocale(Request $request): string
|
|
{
|
|
// 1) explicit query param ?lang=xx
|
|
$q = $request->query('lang');
|
|
if ($q && $this->isAllowed($q)) return $this->normalize($q);
|
|
|
|
// 2) user preference
|
|
$u = $request->user();
|
|
if ($u && $this->isAllowed($u->preferred_locale ?? null)) return $this->normalize($u->preferred_locale);
|
|
|
|
// 3) session
|
|
$s = $request->session()->get('locale');
|
|
if ($this->isAllowed($s)) return $this->normalize((string) $s);
|
|
|
|
// 4) cookie
|
|
$c = $request->cookie('locale');
|
|
if ($this->isAllowed($c)) return $this->normalize((string) $c);
|
|
|
|
// 5) Accept-Language best effort
|
|
$preferred = $request->getPreferredLanguage($this->available);
|
|
if ($this->isAllowed($preferred)) return $this->normalize((string) $preferred);
|
|
|
|
// 6) fallback
|
|
return config('app.locale', 'en');
|
|
}
|
|
|
|
private function isAllowed($code): bool
|
|
{
|
|
if (!$code) return false;
|
|
$norm = $this->normalize((string) $code);
|
|
return in_array($norm, $this->available, true);
|
|
}
|
|
|
|
private function normalize(string $code): string
|
|
{
|
|
// Normalize e.g. pt-br → pt_BR, zh-cn → zh_CN; others lower-case
|
|
$code = str_replace([' ', '-'], ['','_'], trim($code));
|
|
if (strtolower($code) === 'pt_br') return 'pt_BR';
|
|
if (strtolower($code) === 'zh_cn') return 'zh_CN';
|
|
return strtolower($code);
|
|
}
|
|
}
|