diff --git a/composer.json b/composer.json
index 1759a76..80a1fba 100644
--- a/composer.json
+++ b/composer.json
@@ -33,7 +33,7 @@
"illuminate/http": "^10.0 || ^11.0",
"illuminate/routing": "^10.0 || ^11.0",
"illuminate/support": "^10.0 || ^11.0",
- "laravel-lang/config": "^1.5",
+ "laravel-lang/config": "^1.6",
"laravel-lang/locales": "^2.8"
},
"require-dev": {
diff --git a/phpunit.xml b/phpunit.xml
index 2829ec8..7c7083b 100644
--- a/phpunit.xml
+++ b/phpunit.xml
@@ -20,5 +20,8 @@
+
+
+
diff --git a/src/Middlewares/LocalizationByModel.php b/src/Middlewares/LocalizationByModel.php
new file mode 100644
index 0000000..f9831b8
--- /dev/null
+++ b/src/Middlewares/LocalizationByModel.php
@@ -0,0 +1,48 @@
+has($user = $this->user($request))) {
+ return $user->getAttribute($this->attribute());
+ }
+
+ return null;
+ }
+
+ protected function has(?Model $user): bool
+ {
+ return $user && $this->hasAttribute($user);
+ }
+
+ protected function user(Request $request): ?Model
+ {
+ return $request->user($this->guard);
+ }
+
+ protected function attribute(): string
+ {
+ return $this->names()->column;
+ }
+
+ protected function hasAttribute(Model $user): bool
+ {
+ if (method_exists($user, 'hasAttribute')) {
+ return $user->hasAttribute($this->attribute());
+ }
+
+ return array_key_exists($this->attribute(), $user->getAttributes());
+ }
+}
diff --git a/src/Services/Route.php b/src/Services/Route.php
index 0eed673..27a8815 100644
--- a/src/Services/Route.php
+++ b/src/Services/Route.php
@@ -10,6 +10,7 @@
use LaravelLang\Routes\Helpers\Route as RouteName;
use LaravelLang\Routes\Middlewares\LocalizationByCookie;
use LaravelLang\Routes\Middlewares\LocalizationByHeader;
+use LaravelLang\Routes\Middlewares\LocalizationByModel;
use LaravelLang\Routes\Middlewares\LocalizationByParameterPrefix;
use LaravelLang\Routes\Middlewares\LocalizationBySession;
@@ -23,6 +24,7 @@ public function group(Closure $callback): void
LocalizationByCookie::class,
LocalizationByHeader::class,
LocalizationBySession::class,
+ LocalizationByModel::class,
])->group($callback);
BaseRoute::prefix('{' . $this->names()->parameter . '}')
@@ -32,6 +34,7 @@ public function group(Closure $callback): void
LocalizationByCookie::class,
LocalizationByHeader::class,
LocalizationBySession::class,
+ LocalizationByModel::class,
])->group($callback);
}
}
diff --git a/tests/Concerns/Routes.php b/tests/Concerns/Routes.php
index d553cd2..c1a7542 100644
--- a/tests/Concerns/Routes.php
+++ b/tests/Concerns/Routes.php
@@ -8,6 +8,7 @@
use LaravelLang\Routes\Facades\LocalizationRoute;
use LaravelLang\Routes\Middlewares\LocalizationByCookie;
use LaravelLang\Routes\Middlewares\LocalizationByHeader;
+use LaravelLang\Routes\Middlewares\LocalizationByModel;
use LaravelLang\Routes\Middlewares\LocalizationByParameter;
use LaravelLang\Routes\Middlewares\LocalizationByParameterWithRedirect;
use LaravelLang\Routes\Middlewares\LocalizationBySession;
@@ -53,6 +54,16 @@ public function setUpRoutes(): void
->get('session/{foo}', $this->jsonResponse())
->name('via.session');
+ app('router')
+ ->middleware(LocalizationByModel::class)
+ ->get('model/default/{foo}', $this->jsonResponse())
+ ->name('via.model.default');
+
+ app('router')
+ ->middleware(LocalizationByModel::class . ':foo')
+ ->get('model/guard/{foo}', $this->jsonResponse())
+ ->name('via.model.guard');
+
app('router')
->middleware([
LocalizationByParameter::class,
@@ -60,6 +71,7 @@ public function setUpRoutes(): void
LocalizationByHeader::class,
LocalizationByCookie::class,
LocalizationBySession::class,
+ LocalizationByModel::class,
])
->get('clean/{foo}', $this->jsonResponse())
->name('clean');
diff --git a/tests/Feature/Middlewares/ModelAuthorizedGuardTest.php b/tests/Feature/Middlewares/ModelAuthorizedGuardTest.php
new file mode 100644
index 0000000..8762ae8
--- /dev/null
+++ b/tests/Feature/Middlewares/ModelAuthorizedGuardTest.php
@@ -0,0 +1,68 @@
+assertSuccessful()
+ ->assertJsonPath($foo, LocaleValue::TranslationFrench);
+
+ assertEventNotDispatched();
+});
+
+test('aliased locale', function (string $locale) {
+ actingAs(fakeUser($locale));
+
+ $foo = 'test';
+
+ getJson(route('via.model.guard', compact('foo', 'locale')))
+ ->assertSuccessful()
+ ->assertJsonPath($foo, LocaleValue::TranslationGerman);
+
+ assertEventDispatched();
+})->with('aliased-locales');
+
+test('empty locale', function (int|string|null $locale) {
+ actingAs(fakeUser($locale));
+
+ $foo = 'test';
+
+ getJson(route('via.model.guard', compact('foo', 'locale')))
+ ->assertSuccessful()
+ ->assertJsonPath($foo, LocaleValue::TranslationFrench);
+
+ assertEventNotDispatched();
+})->with('empty-locales');
+
+test('uninstalled locale', function (string $locale) {
+ actingAs(fakeUser($locale));
+
+ $foo = 'test';
+
+ getJson(route('via.model.guard', compact('foo', 'locale')))
+ ->assertSuccessful()
+ ->assertJsonPath($foo, LocaleValue::TranslationFrench);
+
+ assertEventDispatched();
+})->with('uninstalled-locales');
+
+test('unknown locale', function (int|string $locale) {
+ actingAs(fakeUser($locale));
+
+ $foo = 'test';
+
+ getJson(route('via.model.guard', compact('foo', 'locale')))
+ ->assertSuccessful()
+ ->assertJsonPath($foo, LocaleValue::TranslationFrench);
+
+ assertEventDispatched();
+})->with('unknown-locales');
diff --git a/tests/Feature/Middlewares/ModelAuthorizedTest.php b/tests/Feature/Middlewares/ModelAuthorizedTest.php
new file mode 100644
index 0000000..a072455
--- /dev/null
+++ b/tests/Feature/Middlewares/ModelAuthorizedTest.php
@@ -0,0 +1,68 @@
+assertSuccessful()
+ ->assertJsonPath($foo, LocaleValue::TranslationFrench);
+
+ assertEventNotDispatched();
+});
+
+test('aliased locale', function (string $locale) {
+ actingAs(fakeUser($locale));
+
+ $foo = 'test';
+
+ getJson(route('via.model.default', compact('foo', 'locale')))
+ ->assertSuccessful()
+ ->assertJsonPath($foo, LocaleValue::TranslationGerman);
+
+ assertEventDispatched();
+})->with('aliased-locales');
+
+test('empty locale', function (int|string|null $locale) {
+ actingAs(fakeUser($locale));
+
+ $foo = 'test';
+
+ getJson(route('via.model.default', compact('foo', 'locale')))
+ ->assertSuccessful()
+ ->assertJsonPath($foo, LocaleValue::TranslationFrench);
+
+ assertEventNotDispatched();
+})->with('empty-locales');
+
+test('uninstalled locale', function (string $locale) {
+ actingAs(fakeUser($locale));
+
+ $foo = 'test';
+
+ getJson(route('via.model.default', compact('foo', 'locale')))
+ ->assertSuccessful()
+ ->assertJsonPath($foo, LocaleValue::TranslationFrench);
+
+ assertEventDispatched();
+})->with('uninstalled-locales');
+
+test('unknown locale', function (int|string $locale) {
+ actingAs(fakeUser($locale));
+
+ $foo = 'test';
+
+ getJson(route('via.model.default', compact('foo', 'locale')))
+ ->assertSuccessful()
+ ->assertJsonPath($foo, LocaleValue::TranslationFrench);
+
+ assertEventDispatched();
+})->with('unknown-locales');
diff --git a/tests/Feature/Middlewares/ModelUnauthorized.php b/tests/Feature/Middlewares/ModelUnauthorized.php
new file mode 100644
index 0000000..935e29b
--- /dev/null
+++ b/tests/Feature/Middlewares/ModelUnauthorized.php
@@ -0,0 +1,27 @@
+assertSuccessful()
+ ->assertJsonPath($foo, LocaleValue::TranslationFrench);
+
+ assertEventNotDispatched();
+});
+
+test('without guard', function () {
+ $foo = 'test';
+
+ getJson(route('via.model.default', compact('foo')))
+ ->assertSuccessful()
+ ->assertJsonPath($foo, LocaleValue::TranslationFrench);
+
+ assertEventNotDispatched();
+});
diff --git a/tests/Fixtures/Models/User.php b/tests/Fixtures/Models/User.php
new file mode 100644
index 0000000..e1887c6
--- /dev/null
+++ b/tests/Fixtures/Models/User.php
@@ -0,0 +1,14 @@
+ $locale,
+ ]);
+}
diff --git a/tests/Pest.php b/tests/Pest.php
index 31aebee..aaa1e8f 100644
--- a/tests/Pest.php
+++ b/tests/Pest.php
@@ -1,7 +1,8 @@
beforeEach(fn () => Event::fake())
->in('Feature', 'Unit');
diff --git a/tests/TestCase.php b/tests/TestCase.php
index 1a407f4..bf0a85d 100644
--- a/tests/TestCase.php
+++ b/tests/TestCase.php
@@ -32,8 +32,18 @@ protected function defineEnvironment($app): void
$config->set('app.locale', LocaleValue::LocaleMain);
+ $config->set('auth.guards.foo', [
+ 'driver' => 'session',
+ 'provider' => 'users',
+ ]);
+
$config->set(Name::Shared() . '.aliases', [
LocaleValue::LocaleAliasParent => LocaleValue::LocaleAlias,
]);
}
+
+ protected function defineDatabaseMigrations(): void
+ {
+ $this->loadMigrationsFrom(__DIR__ . '/database/migrations');
+ }
}
diff --git a/tests/database/migrations/2024_06_20_000000_create_users_table.php b/tests/database/migrations/2024_06_20_000000_create_users_table.php
new file mode 100644
index 0000000..2c4a7cf
--- /dev/null
+++ b/tests/database/migrations/2024_06_20_000000_create_users_table.php
@@ -0,0 +1,25 @@
+id();
+
+ $table->string('locale')->nullable();
+
+ $table->timestamps();
+ });
+ }
+
+ public function down(): void
+ {
+ Schema::dropIfExists('users');
+ }
+};