Feature: Adding Locale Middleware

This commit is contained in:
2026-08-05 23:58:53 +03:00
parent 4c00369005
commit 93469d033f
4 changed files with 192 additions and 0 deletions
@@ -0,0 +1,18 @@
<?php
namespace Modules\Core\Localization;
use Lunar\Models\Contracts\Language as LanguageContract;
class LanguageCacheObserver
{
public function saved(LanguageContract $language): void
{
LocaleMiddleware::forgetLanguagesCache();
}
public function deleted(LanguageContract $language): void
{
LocaleMiddleware::forgetLanguagesCache();
}
}
+78
View File
@@ -0,0 +1,78 @@
<?php
namespace Modules\Core\Localization;
use Closure;
use Illuminate\Http\Request;
use Illuminate\Support\Collection;
use Illuminate\Support\Facades\App;
use Illuminate\Support\Facades\Cache;
use Lunar\Models\Language;
use Symfony\Component\HttpFoundation\Response;
class LocaleMiddleware
{
private const CACHE_KEY = 'core.localization.languages';
public function handle(Request $request, Closure $next): Response
{
$languages = $this->availableLanguages();
if ($languages->isEmpty()) {
return $next($request);
}
$segment = (string) $request->segment(1);
$language = $languages->firstWhere('code', $segment);
if (! $language) {
return $this->redirectToLocalizedUrl($request, $languages);
}
App::setLocale($language->code);
$request->attributes->set('locale', $language->code);
$request->attributes->set('language', $language);
return $next($request);
}
public static function forgetLanguagesCache(): void
{
Cache::forget(self::CACHE_KEY);
}
private function redirectToLocalizedUrl(Request $request, Collection $languages): Response
{
$locale = $this->negotiateLocale($request, $languages);
$path = trim($request->getPathInfo(), '/');
$target = '/'.$locale.($path !== '' ? '/'.$path : '');
$query = $request->getQueryString();
if ($query) {
$target .= '?'.$query;
}
return redirect($target);
}
private function negotiateLocale(Request $request, Collection $languages): string
{
$preferred = $request->getPreferredLanguage($languages->pluck('code')->all());
if ($preferred) {
return $preferred;
}
return $languages->firstWhere('default', true)?->code
?? $languages->first()->code;
}
private function availableLanguages(): Collection
{
return Cache::rememberForever(
self::CACHE_KEY,
fn () => Language::query()->get(['id', 'code', 'name', 'default']),
);
}
}
+6
View File
@@ -4,12 +4,15 @@ namespace Modules\Core\Providers;
use Illuminate\Support\Facades\Blade;
use Illuminate\Support\ServiceProvider;
use Lunar\Models\Language;
use Modules\Core\Command\AnonymizeCommand;
use Modules\Core\Command\ExportCleanupCommand;
use Modules\Core\Command\ExportCommand;
use Modules\Core\Command\ImportCommand;
use Modules\Core\Command\InstallLunarCommand;
use Modules\Core\Command\MigrateImportCommand;
use Modules\Core\Localization\LanguageCacheObserver;
use Modules\Core\Localization\LocaleMiddleware;
class CoreServiceProvider extends ServiceProvider
{
@@ -24,6 +27,9 @@ class CoreServiceProvider extends ServiceProvider
Blade::anonymousComponentPath(__DIR__ . '/../../resources/views', 'core');
$this->loadMigrationsFrom(__DIR__ . '/../../database/migrations');
$this->app['router']->aliasMiddleware('locale', LocaleMiddleware::class);
Language::observe(LanguageCacheObserver::class);
$this->publishes([
__DIR__ . '/../../config/core.php' => config_path('core.php'),
__DIR__ . '/../../config/scout.php' => config_path('scout.php'),