Files
landing-api/app/Http/Middleware/SetLocale.php
Josep Piguillem 3897113313 Initial commit: Pireon Admin — headless admin panel and public API
Laravel 13 + Filament 5 admin panel and REST API for a non-profit developer
collective, backed by the Pireon OAuth identity server. The public site is a
separate, server-rendered application consuming /api/public/v1.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-19 17:55:27 +02:00

94 lines
2.9 KiB
PHP

<?php
declare(strict_types=1);
namespace App\Http\Middleware;
use Carbon\Carbon;
use Carbon\CarbonImmutable;
use Closure;
use Illuminate\Http\Request;
use Symfony\Component\HttpFoundation\Response;
/**
* Resolves the locale for the request and applies it to the framework, to
* Carbon, and to translatable model attributes.
*
* Precedence, most specific first:
*
* 1. ?lang=xx — an explicit, single-request override (API friendly)
* 2. session — what the signed-in visitor picked in the switcher
* 3. users.locale — their stored preference
* 4. Accept-Language — what their client asked for
* 5. locales.default
*/
class SetLocale
{
public function handle(Request $request, Closure $next): Response
{
$locale = $this->resolve($request);
app()->setLocale($locale);
// Dates rendered in the panel and serialised by the API follow suit.
CarbonImmutable::setLocale($locale);
Carbon::setLocale($locale);
// Translatable attributes read this locale, and fall back to
// locales.fallback when a record has no translation for it.
app()->setFallbackLocale((string) config('locales.fallback'));
$response = $next($request);
// Lets caches and clients see which language they actually received.
$response->headers->set('Content-Language', $locale);
return $response;
}
protected function resolve(Request $request): string
{
$supported = array_keys(config('locales.supported'));
$candidates = [
$request->query(config('locales.query_parameter')),
// The API stack is stateless, so there is no session to consult.
// hasSession() is the safe check — session() throws when unset.
$request->hasSession()
? $request->session()->get(config('locales.session_key'))
: null,
$request->user()?->locale,
$this->fromAcceptLanguage($request, $supported),
config('locales.default'),
];
foreach ($candidates as $candidate) {
if (is_string($candidate) && in_array($candidate, $supported, true)) {
return $candidate;
}
}
return (string) config('locales.default');
}
/**
* Pick the best supported locale from the Accept-Language header, honouring
* its quality values. "ca-ES" matches the "ca" we support.
*
* @param array<int, string> $supported
*/
protected function fromAcceptLanguage(Request $request, array $supported): ?string
{
foreach ($request->getLanguages() as $language) {
$base = strtolower(str_replace('_', '-', $language));
$base = explode('-', $base)[0];
if (in_array($base, $supported, true)) {
return $base;
}
}
return null;
}
}