From 454a363117a7a66eb6f1b0250dbaba5b96296cff Mon Sep 17 00:00:00 2001 From: krzysztofrewak Date: Fri, 5 Jan 2024 14:40:12 +0100 Subject: [PATCH] #198 - i18n routing --- app/Console/Kernel.php | 2 +- app/Exceptions/Handler.php | 2 +- app/Http/Controllers/ContactController.php | 16 + app/Http/Controllers/Controller.php | 2 +- app/Http/Controllers/FallbackController.php | 47 +++ app/Http/Controllers/HomeController.php | 16 + app/Http/Kernel.php | 24 +- app/Http/Middleware/Authenticate.php | 2 +- app/Http/Middleware/EncryptCookies.php | 12 - app/Http/Middleware/HandleInertiaRequests.php | 18 - app/Http/Middleware/Localize.php | 21 ++ .../PreventRequestsDuringMaintenance.php | 13 - .../Middleware/RedirectIfAuthenticated.php | 4 +- app/Http/Middleware/TrimStrings.php | 2 +- app/Http/Middleware/TrustHosts.php | 2 +- app/Http/Middleware/TrustProxies.php | 2 +- app/Http/Middleware/ValidateSignature.php | 12 - app/Http/Middleware/VerifyCsrfToken.php | 12 - app/Models/User.php | 2 +- app/Providers/AppServiceProvider.php | 2 +- app/Providers/EventServiceProvider.php | 2 +- app/Providers/RouteServiceProvider.php | 11 +- bootstrap/app.php | 6 +- composer.json | 6 +- composer.lock | 347 +++++++++++++++++- config/app.php | 8 +- config/auth.php | 2 +- config/localized-routes.php | 47 +++ config/sanctum.php | 4 +- database/factories/UserFactory.php | 2 +- environment/dev/app/Dockerfile | 2 +- lang/pl/routes.php | 7 + public/favicon.ico | 0 public/logo.png | Bin 0 -> 6821 bytes resources/js/Layout/Navigation.vue | 10 + resources/js/Pages/Contact.vue | 13 + resources/js/Pages/Home.vue | 13 + resources/js/Pages/Welcome.vue | 286 --------------- resources/views/app.blade.php | 26 +- routes/web.php | 13 +- tests/Feature/ExampleTest.php | 17 - .../Feature/LocalisedRoutingFallbackTest.php | 28 ++ tests/Feature/LocalisedRoutingTest.php | 34 ++ 43 files changed, 679 insertions(+), 418 deletions(-) create mode 100644 app/Http/Controllers/ContactController.php create mode 100644 app/Http/Controllers/FallbackController.php create mode 100644 app/Http/Controllers/HomeController.php delete mode 100644 app/Http/Middleware/EncryptCookies.php delete mode 100644 app/Http/Middleware/HandleInertiaRequests.php create mode 100644 app/Http/Middleware/Localize.php delete mode 100644 app/Http/Middleware/PreventRequestsDuringMaintenance.php delete mode 100644 app/Http/Middleware/ValidateSignature.php delete mode 100644 app/Http/Middleware/VerifyCsrfToken.php create mode 100644 config/localized-routes.php create mode 100644 lang/pl/routes.php delete mode 100644 public/favicon.ico create mode 100644 public/logo.png create mode 100644 resources/js/Layout/Navigation.vue create mode 100644 resources/js/Pages/Contact.vue create mode 100644 resources/js/Pages/Home.vue delete mode 100644 resources/js/Pages/Welcome.vue delete mode 100644 tests/Feature/ExampleTest.php create mode 100644 tests/Feature/LocalisedRoutingFallbackTest.php create mode 100644 tests/Feature/LocalisedRoutingTest.php diff --git a/app/Console/Kernel.php b/app/Console/Kernel.php index 45bd3bbc..43240e02 100644 --- a/app/Console/Kernel.php +++ b/app/Console/Kernel.php @@ -2,7 +2,7 @@ declare(strict_types=1); -namespace BlumilkWebsite\Console; +namespace Blumilk\Website\Console; use Illuminate\Console\Scheduling\Schedule; use Illuminate\Foundation\Console\Kernel as ConsoleKernel; diff --git a/app/Exceptions/Handler.php b/app/Exceptions/Handler.php index 36065e50..51de315c 100644 --- a/app/Exceptions/Handler.php +++ b/app/Exceptions/Handler.php @@ -2,7 +2,7 @@ declare(strict_types=1); -namespace BlumilkWebsite\Exceptions; +namespace Blumilk\Website\Exceptions; use Illuminate\Foundation\Exceptions\Handler as ExceptionHandler; diff --git a/app/Http/Controllers/ContactController.php b/app/Http/Controllers/ContactController.php new file mode 100644 index 00000000..9bae09e1 --- /dev/null +++ b/app/Http/Controllers/ContactController.php @@ -0,0 +1,16 @@ +render("Contact"); + } +} diff --git a/app/Http/Controllers/Controller.php b/app/Http/Controllers/Controller.php index 6aef5e56..551eadab 100644 --- a/app/Http/Controllers/Controller.php +++ b/app/Http/Controllers/Controller.php @@ -2,7 +2,7 @@ declare(strict_types=1); -namespace BlumilkWebsite\Http\Controllers; +namespace Blumilk\Website\Http\Controllers; use Illuminate\Foundation\Auth\Access\AuthorizesRequests; use Illuminate\Foundation\Validation\ValidatesRequests; diff --git a/app/Http/Controllers/FallbackController.php b/app/Http/Controllers/FallbackController.php new file mode 100644 index 00000000..157f576a --- /dev/null +++ b/app/Http/Controllers/FallbackController.php @@ -0,0 +1,47 @@ +shouldRedirect()) { + return false; + } + + $localizedUrl = Route::localizedUrl(); + $route = $this->findRouteByUrl($localizedUrl); + + if ($route->isFallback) { + return false; + } + + return Redirect::to($route->uri(), $this->getRedirectStatusCode()) + ->header("Cache-Control", "no-store, no-cache, must-revalidate"); + } + + protected function findRouteByUrl(string $url): \Illuminate\Routing\Route + { + $parts = explode("/", $url); + $path = implode("/", array_splice($parts, 4)); + $url = $this->translator->uri($path); + + $domain = implode("/", array_splice($parts, -4)); + + return Route::getRoutes()->match(Request::create($domain . "/" . $url)); + } +} diff --git a/app/Http/Controllers/HomeController.php b/app/Http/Controllers/HomeController.php new file mode 100644 index 00000000..ce7eb266 --- /dev/null +++ b/app/Http/Controllers/HomeController.php @@ -0,0 +1,16 @@ +render("Home"); + } +} diff --git a/app/Http/Kernel.php b/app/Http/Kernel.php index d3132f79..edd5b618 100644 --- a/app/Http/Kernel.php +++ b/app/Http/Kernel.php @@ -2,36 +2,39 @@ declare(strict_types=1); -namespace BlumilkWebsite\Http; +namespace Blumilk\Website\Http; -use BlumilkWebsite\Http\Middleware\Authenticate; -use BlumilkWebsite\Http\Middleware\EncryptCookies; -use BlumilkWebsite\Http\Middleware\HandleInertiaRequests; -use BlumilkWebsite\Http\Middleware\PreventRequestsDuringMaintenance; -use BlumilkWebsite\Http\Middleware\RedirectIfAuthenticated; -use BlumilkWebsite\Http\Middleware\TrimStrings; -use BlumilkWebsite\Http\Middleware\TrustProxies; -use BlumilkWebsite\Http\Middleware\ValidateSignature; -use BlumilkWebsite\Http\Middleware\VerifyCsrfToken; +use Blumilk\Website\Http\Middleware\Authenticate; +use Blumilk\Website\Http\Middleware\Localize; +use Blumilk\Website\Http\Middleware\RedirectIfAuthenticated; +use Blumilk\Website\Http\Middleware\TrimStrings; +use Blumilk\Website\Http\Middleware\TrustProxies; +use CodeZero\LocalizedRoutes\Middleware\SetLocale; use Illuminate\Auth\Middleware\AuthenticateWithBasicAuth; use Illuminate\Auth\Middleware\Authorize; use Illuminate\Auth\Middleware\EnsureEmailIsVerified; use Illuminate\Auth\Middleware\RequirePassword; use Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse; +use Illuminate\Cookie\Middleware\EncryptCookies; use Illuminate\Foundation\Http\Kernel as HttpKernel; use Illuminate\Foundation\Http\Middleware\ConvertEmptyStringsToNull; +use Illuminate\Foundation\Http\Middleware\PreventRequestsDuringMaintenance; use Illuminate\Foundation\Http\Middleware\ValidatePostSize; +use Illuminate\Foundation\Http\Middleware\VerifyCsrfToken; use Illuminate\Http\Middleware\HandleCors; use Illuminate\Http\Middleware\SetCacheHeaders; use Illuminate\Routing\Middleware\SubstituteBindings; use Illuminate\Routing\Middleware\ThrottleRequests; +use Illuminate\Routing\Middleware\ValidateSignature; use Illuminate\Session\Middleware\AuthenticateSession; use Illuminate\Session\Middleware\StartSession; use Illuminate\View\Middleware\ShareErrorsFromSession; +use Inertia\Middleware as HandleInertiaRequests; class Kernel extends HttpKernel { protected $middleware = [ + Localize::class, TrustProxies::class, HandleCors::class, PreventRequestsDuringMaintenance::class, @@ -46,6 +49,7 @@ class Kernel extends HttpKernel StartSession::class, ShareErrorsFromSession::class, VerifyCsrfToken::class, + SetLocale::class, SubstituteBindings::class, HandleInertiaRequests::class, ], diff --git a/app/Http/Middleware/Authenticate.php b/app/Http/Middleware/Authenticate.php index 1124767c..e08cf789 100644 --- a/app/Http/Middleware/Authenticate.php +++ b/app/Http/Middleware/Authenticate.php @@ -2,7 +2,7 @@ declare(strict_types=1); -namespace BlumilkWebsite\Http\Middleware; +namespace Blumilk\Website\Http\Middleware; use Illuminate\Auth\Middleware\Authenticate as Middleware; use Illuminate\Http\Request; diff --git a/app/Http/Middleware/EncryptCookies.php b/app/Http/Middleware/EncryptCookies.php deleted file mode 100644 index 5d8f4eb4..00000000 --- a/app/Http/Middleware/EncryptCookies.php +++ /dev/null @@ -1,12 +0,0 @@ -header("Accept-Language"), "pl")) { + app()->setLocale("pl"); + } + + return $next($request); + } +} diff --git a/app/Http/Middleware/PreventRequestsDuringMaintenance.php b/app/Http/Middleware/PreventRequestsDuringMaintenance.php deleted file mode 100644 index 7a0ec8c3..00000000 --- a/app/Http/Middleware/PreventRequestsDuringMaintenance.php +++ /dev/null @@ -1,13 +0,0 @@ -prefix("api") ->group(base_path("routes/api.php")); - Route::middleware("web") - ->group(base_path("routes/web.php")); + Route::localized(function (): void { + Route::middleware("web") + ->group(base_path("routes/web.php")); + }); + + Route::fallback(FallbackController::class); }); } } diff --git a/bootstrap/app.php b/bootstrap/app.php index a34893be..008284e0 100644 --- a/bootstrap/app.php +++ b/bootstrap/app.php @@ -2,9 +2,9 @@ declare(strict_types=1); -use BlumilkWebsite\Console\Kernel as ConsoleKernel; -use BlumilkWebsite\Exceptions\Handler; -use BlumilkWebsite\Http\Kernel as HttpKernel; +use Blumilk\Website\Console\Kernel as ConsoleKernel; +use Blumilk\Website\Exceptions\Handler; +use Blumilk\Website\Http\Kernel as HttpKernel; use Illuminate\Contracts\Console\Kernel as ConsoleKernelContract; use Illuminate\Contracts\Debug\ExceptionHandler; use Illuminate\Contracts\Http\Kernel as HttpKernelContract; diff --git a/composer.json b/composer.json index 68bc4a82..14b75a41 100644 --- a/composer.json +++ b/composer.json @@ -7,6 +7,7 @@ "require": { "php": "^8.2", "ext-pdo": "*", + "codezero/laravel-localized-routes": "^3.1", "guzzlehttp/guzzle": "^7.8.0", "inertiajs/inertia-laravel": "^0.6.11", "laravel/framework": "^10.32.1", @@ -24,7 +25,7 @@ }, "autoload": { "psr-4": { - "BlumilkWebsite\\": "app/", + "Blumilk\\Website\\": "app/", "Database\\Factories\\": "database/factories/", "Database\\Seeders\\": "database/seeders/" } @@ -66,7 +67,8 @@ "preferred-install": "dist", "sort-packages": true, "allow-plugins": { - "php-http/discovery": true + "php-http/discovery": true, + "codezero/composer-preload-files": true } }, "minimum-stability": "stable", diff --git a/composer.lock b/composer.lock index be11bdec..8fd66fdb 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "398810ea5ea540a05776ca8ad1c485f2", + "content-hash": "d2ee22e0186e116f54ea76abef028d54", "packages": [ { "name": "brick/math", @@ -130,6 +130,351 @@ ], "time": "2023-12-11T17:09:12+00:00" }, + { + "name": "codezero/browser-locale", + "version": "3.3.0", + "source": { + "type": "git", + "url": "https://github.com/codezero-be/browser-locale.git", + "reference": "5dc1b89c8dcaece285b2ebb69ebdc783144e4cab" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/codezero-be/browser-locale/zipball/5dc1b89c8dcaece285b2ebb69ebdc783144e4cab", + "reference": "5dc1b89c8dcaece285b2ebb69ebdc783144e4cab", + "shasum": "" + }, + "require": { + "php": "^7.0|^8.0" + }, + "require-dev": { + "illuminate/support": "^5.5|^6.0|^7.0|^8.0|^9.0|^10.0", + "mockery/mockery": "^1.3.3", + "phpunit/phpunit": "^6.0|^7.0|^8.0|^9.0" + }, + "type": "library", + "extra": { + "laravel": { + "providers": [ + "CodeZero\\BrowserLocale\\Laravel\\BrowserLocaleServiceProvider" + ] + } + }, + "autoload": { + "psr-4": { + "CodeZero\\BrowserLocale\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Ivan Vermeyen", + "email": "ivan@codezero.be" + } + ], + "description": "Get the most preferred locales from your visitor's browser.", + "keywords": [ + "browser", + "country", + "detect", + "language", + "locale", + "php", + "website" + ], + "support": { + "issues": "https://github.com/codezero-be/browser-locale/issues", + "source": "https://github.com/codezero-be/browser-locale/tree/3.3.0" + }, + "funding": [ + { + "url": "https://paypal.me/ivanvermeyen", + "type": "custom" + }, + { + "url": "https://ko-fi.com/ivanvermeyen", + "type": "ko_fi" + } + ], + "time": "2023-02-03T13:33:21+00:00" + }, + { + "name": "codezero/composer-preload-files", + "version": "1.0.2", + "source": { + "type": "git", + "url": "https://github.com/codezero-be/composer-preload-files.git", + "reference": "83246aa68c08ed7c2b1dbcb451b4faf65aa658d9" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/codezero-be/composer-preload-files/zipball/83246aa68c08ed7c2b1dbcb451b4faf65aa658d9", + "reference": "83246aa68c08ed7c2b1dbcb451b4faf65aa658d9", + "shasum": "" + }, + "require": { + "composer-plugin-api": "^2.0", + "php": ">= 7.0" + }, + "require-dev": { + "composer/composer": "^2.0" + }, + "type": "composer-plugin", + "extra": { + "class": "CodeZero\\ComposerPreloadFiles\\Plugin" + }, + "autoload": { + "psr-4": { + "CodeZero\\ComposerPreloadFiles\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Ivan Vermeyen", + "email": "ivan@codezero.be" + } + ], + "description": "Composer plugin to autoload files before vendor files.", + "keywords": [ + "autoload", + "composer", + "files", + "helpers", + "include", + "load", + "plugin", + "require" + ], + "support": { + "issues": "https://github.com/codezero-be/composer-preload-files/issues", + "source": "https://github.com/codezero-be/composer-preload-files/tree/1.0.2" + }, + "time": "2023-05-24T15:46:41+00:00" + }, + { + "name": "codezero/laravel-localized-routes", + "version": "3.1.5", + "source": { + "type": "git", + "url": "https://github.com/codezero-be/laravel-localized-routes.git", + "reference": "0ebb3acd58b4b635ec9d6d20de9a1770da0c9ced" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/codezero-be/laravel-localized-routes/zipball/0ebb3acd58b4b635ec9d6d20de9a1770da0c9ced", + "reference": "0ebb3acd58b4b635ec9d6d20de9a1770da0c9ced", + "shasum": "" + }, + "require": { + "codezero/browser-locale": "^3.0", + "codezero/composer-preload-files": "^1.0", + "codezero/laravel-uri-translator": "^1.0", + "codezero/php-url-builder": "^1.0", + "illuminate/support": "^7.0|^8.0|^9.0|^10.0", + "php": "^7.2.5|^8.0" + }, + "require-dev": { + "mockery/mockery": "^1.3.3", + "orchestra/testbench": "^5.0|^6.0|^7.0|^8.0", + "phpunit/phpunit": "^8.0|^9.0" + }, + "type": "library", + "extra": { + "laravel": { + "providers": [ + "CodeZero\\LocalizedRoutes\\LocalizedRoutesServiceProvider" + ], + "aliases": { + "LocaleConfig": "CodeZero\\LocalizedRoutes\\Facades\\LocaleConfig" + } + }, + "preload-files": [ + "src/helpers.php" + ] + }, + "autoload": { + "psr-4": { + "CodeZero\\LocalizedRoutes\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Ivan Vermeyen", + "email": "ivan@codezero.be" + } + ], + "description": "A convenient way to set up, manage and use localized routes in a Laravel app.", + "keywords": [ + "country", + "language", + "laravel", + "locale", + "localization", + "php", + "routes", + "routing", + "translation" + ], + "support": { + "issues": "https://github.com/codezero-be/laravel-localized-routes/issues", + "source": "https://github.com/codezero-be/laravel-localized-routes/tree/3.1.5" + }, + "funding": [ + { + "url": "https://paypal.me/ivanvermeyen", + "type": "custom" + }, + { + "url": "https://ko-fi.com/ivanvermeyen", + "type": "ko_fi" + } + ], + "time": "2023-06-01T20:21:52+00:00" + }, + { + "name": "codezero/laravel-uri-translator", + "version": "1.0.0", + "source": { + "type": "git", + "url": "https://github.com/codezero-be/laravel-uri-translator.git", + "reference": "30e630dc89908e4075c650d8858d1630764b9540" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/codezero-be/laravel-uri-translator/zipball/30e630dc89908e4075c650d8858d1630764b9540", + "reference": "30e630dc89908e4075c650d8858d1630764b9540", + "shasum": "" + }, + "require": { + "illuminate/support": "^7.0|^8.0|^9.0|^10.0", + "php": "^7.2.5|^8.0" + }, + "require-dev": { + "orchestra/testbench": "^5.0|^6.0|^7.0|^8.0", + "phpunit/phpunit": "^8.0|^9.0" + }, + "type": "library", + "extra": { + "laravel": { + "providers": [ + "CodeZero\\UriTranslator\\UriTranslatorServiceProvider" + ] + } + }, + "autoload": { + "psr-4": { + "CodeZero\\UriTranslator\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Ivan Vermeyen", + "email": "ivan@codezero.be" + } + ], + "description": "Translate a URI or individual slugs.", + "keywords": [ + "country", + "language", + "laravel", + "locale", + "localization", + "php", + "slugs", + "uri", + "url" + ], + "support": { + "issues": "https://github.com/codezero-be/laravel-uri-translator/issues", + "source": "https://github.com/codezero-be/laravel-uri-translator/tree/1.0.0" + }, + "funding": [ + { + "url": "https://paypal.me/ivanvermeyen", + "type": "custom" + }, + { + "url": "https://ko-fi.com/ivanvermeyen", + "type": "ko_fi" + } + ], + "time": "2023-03-14T15:01:53+00:00" + }, + { + "name": "codezero/php-url-builder", + "version": "1.0.0", + "source": { + "type": "git", + "url": "https://github.com/codezero-be/php-url-builder.git", + "reference": "c30a21c503158c26dd4ab5cfdf64b2eb90fa9f78" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/codezero-be/php-url-builder/zipball/c30a21c503158c26dd4ab5cfdf64b2eb90fa9f78", + "reference": "c30a21c503158c26dd4ab5cfdf64b2eb90fa9f78", + "shasum": "" + }, + "require": { + "php": ">=7.2" + }, + "require-dev": { + "phpunit/phpunit": "^8.0|^9.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "CodeZero\\UrlBuilder\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Ivan Vermeyen", + "email": "ivan@codezero.be" + } + ], + "description": "Parse, manipulate and rebuild a URL.", + "keywords": [ + "builder", + "parse", + "query", + "uri", + "url" + ], + "support": { + "issues": "https://github.com/codezero-be/php-url-builder/issues", + "source": "https://github.com/codezero-be/php-url-builder/tree/1.0.0" + }, + "funding": [ + { + "url": "https://paypal.me/ivanvermeyen", + "type": "custom" + }, + { + "url": "https://ko-fi.com/ivanvermeyen", + "type": "ko_fi" + } + ], + "time": "2023-03-31T17:50:16+00:00" + }, { "name": "dflydev/dot-access-data", "version": "v3.0.2", diff --git a/config/app.php b/config/app.php index aacd3050..54b30cfc 100644 --- a/config/app.php +++ b/config/app.php @@ -2,9 +2,9 @@ declare(strict_types=1); -use BlumilkWebsite\Providers\AppServiceProvider; -use BlumilkWebsite\Providers\EventServiceProvider; -use BlumilkWebsite\Providers\RouteServiceProvider; +use Blumilk\Website\Providers\AppServiceProvider; +use Blumilk\Website\Providers\EventServiceProvider; +use Blumilk\Website\Providers\RouteServiceProvider; use Illuminate\Support\Facades\Facade; use Illuminate\Support\ServiceProvider; @@ -15,7 +15,7 @@ ])->toArray(); return [ - "name" => env("APP_NAME", "Laravel"), + "name" => "Blumilk software development", "env" => env("APP_ENV", "production"), "debug" => (bool)env("APP_DEBUG", false), "url" => env("APP_URL", "http://localhost"), diff --git a/config/auth.php b/config/auth.php index 7c58a286..7c4c12c9 100644 --- a/config/auth.php +++ b/config/auth.php @@ -2,7 +2,7 @@ declare(strict_types=1); -use BlumilkWebsite\Models\User; +use Blumilk\Website\Models\User; return [ "defaults" => [ diff --git a/config/localized-routes.php b/config/localized-routes.php new file mode 100644 index 00000000..4f0f2906 --- /dev/null +++ b/config/localized-routes.php @@ -0,0 +1,47 @@ + ["en", "pl"], + "fallback_locale" => "en", + "omitted_locale" => null, + "redirect_to_localized_urls" => true, + "redirect_status_code" => 301, + "404_view" => "errors.404", + "route_action" => "locale", + "user_attribute" => "locale", + "session_key" => "locale", + "cookie_name" => "locale", + "cookie_minutes" => 60 * 24 * 365, + "detectors" => [ + RouteActionDetector::class, + UrlDetector::class, + OmittedLocaleDetector::class, + UserDetector::class, + SessionDetector::class, + CookieDetector::class, + BrowserDetector::class, + AppDetector::class, + ], + "trusted_detectors" => [ + RouteActionDetector::class, + ], + "stores" => [ + SessionStore::class, + CookieStore::class, + AppStore::class, + ], +]; diff --git a/config/sanctum.php b/config/sanctum.php index 7e51295a..df13425b 100644 --- a/config/sanctum.php +++ b/config/sanctum.php @@ -2,8 +2,8 @@ declare(strict_types=1); -use BlumilkWebsite\Http\Middleware\EncryptCookies; -use BlumilkWebsite\Http\Middleware\VerifyCsrfToken; +use Blumilk\Website\Http\Middleware\EncryptCookies; +use Blumilk\Website\Http\Middleware\VerifyCsrfToken; use Laravel\Sanctum\Sanctum; return [ diff --git a/database/factories/UserFactory.php b/database/factories/UserFactory.php index 2ee4f682..2dc45536 100644 --- a/database/factories/UserFactory.php +++ b/database/factories/UserFactory.php @@ -4,7 +4,7 @@ namespace Database\Factories; -use BlumilkWebsite\Models\User; +use Blumilk\Website\Models\User; use Illuminate\Database\Eloquent\Factories\Factory; use Illuminate\Support\Str; diff --git a/environment/dev/app/Dockerfile b/environment/dev/app/Dockerfile index 10d43dff..775f9fda 100644 --- a/environment/dev/app/Dockerfile +++ b/environment/dev/app/Dockerfile @@ -5,7 +5,7 @@ FROM composer/composer:2.6.5-bin as composer-bin FROM node:21.1.0-bullseye-slim as node # For other versions check: https://hub.docker.com/_/php/tags?page=1&name=fpm-bullseye -FROM php:8.2.12-fpm-bullseye +FROM php:8.3.1-fpm-bullseye COPY --from=composer-bin ./composer /usr/bin/composer diff --git a/lang/pl/routes.php b/lang/pl/routes.php new file mode 100644 index 00000000..0c66ce1e --- /dev/null +++ b/lang/pl/routes.php @@ -0,0 +1,7 @@ + "kontakt", +]; diff --git a/public/favicon.ico b/public/favicon.ico deleted file mode 100644 index e69de29b..00000000 diff --git a/public/logo.png b/public/logo.png new file mode 100644 index 0000000000000000000000000000000000000000..c6124b409d86ae91383ccae99ea4ccab8a06108c GIT binary patch literal 6821 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 T67{D2hN38^DqHr-^y9w(#OBGM literal 0 HcmV?d00001 diff --git a/resources/js/Layout/Navigation.vue b/resources/js/Layout/Navigation.vue new file mode 100644 index 00000000..5c4440b8 --- /dev/null +++ b/resources/js/Layout/Navigation.vue @@ -0,0 +1,10 @@ + + + diff --git a/resources/js/Pages/Contact.vue b/resources/js/Pages/Contact.vue new file mode 100644 index 00000000..27f3ec12 --- /dev/null +++ b/resources/js/Pages/Contact.vue @@ -0,0 +1,13 @@ + + + diff --git a/resources/js/Pages/Home.vue b/resources/js/Pages/Home.vue new file mode 100644 index 00000000..c926189b --- /dev/null +++ b/resources/js/Pages/Home.vue @@ -0,0 +1,13 @@ + + + diff --git a/resources/js/Pages/Welcome.vue b/resources/js/Pages/Welcome.vue deleted file mode 100644 index 4ebcef1a..00000000 --- a/resources/js/Pages/Welcome.vue +++ /dev/null @@ -1,286 +0,0 @@ - - - - - diff --git a/resources/views/app.blade.php b/resources/views/app.blade.php index 9911d029..0d2fb68d 100644 --- a/resources/views/app.blade.php +++ b/resources/views/app.blade.php @@ -1,12 +1,28 @@ - + - - - @vite('resources/js/app.ts') + + + + + @vite("resources/js/app.ts") @inertiaHead -@inertia + @if (Route::isLocalized() || Route::isFallback()) +
    + @foreach(LocaleConfig::getLocales() as $locale) + @if ( ! App::isLocale($locale)) +
  • + + + +
  • + @endif + @endforeach +
+ @endif + + @inertia diff --git a/routes/web.php b/routes/web.php index 2301789d..120a2949 100644 --- a/routes/web.php +++ b/routes/web.php @@ -2,7 +2,14 @@ declare(strict_types=1); -use Illuminate\Support\Facades\Route; -use Inertia\Response; +use Blumilk\Website\Http\Controllers\ContactController; +use Blumilk\Website\Http\Controllers\HomeController; +use Illuminate\Routing\Router; +use Illuminate\Translation\Translator; -Route::get("/", fn(): Response => inertia("Welcome")); +/** @var Router $router */ +$router = app(Router::class); +$lang = app(Translator::class); + +$router->get("/", HomeController::class)->name("home"); +$router->get($lang->uri("contact"), ContactController::class)->name("contact"); diff --git a/tests/Feature/ExampleTest.php b/tests/Feature/ExampleTest.php deleted file mode 100644 index 55a42c3a..00000000 --- a/tests/Feature/ExampleTest.php +++ /dev/null @@ -1,17 +0,0 @@ -get("/"); - - $response->assertStatus(200); - } -} diff --git a/tests/Feature/LocalisedRoutingFallbackTest.php b/tests/Feature/LocalisedRoutingFallbackTest.php new file mode 100644 index 00000000..54e03a9a --- /dev/null +++ b/tests/Feature/LocalisedRoutingFallbackTest.php @@ -0,0 +1,28 @@ +get("/contact"); + $response->assertStatus(301)->assertRedirect("/en/contact"); + } + + public function testFallbackLocaleForPolishRedirect(): void + { + $response = $this->get("/contact", ["Accept-Language" => "pl"]); + $response->assertStatus(301)->assertRedirect("/pl/kontakt"); + } + + public function testFallbackLocaleForNotSupportedLanguageRedirect(): void + { + $response = $this->get("/contact", ["Accept-Language" => "kz"]); + $response->assertStatus(301)->assertRedirect("/en/contact"); + } +} diff --git a/tests/Feature/LocalisedRoutingTest.php b/tests/Feature/LocalisedRoutingTest.php new file mode 100644 index 00000000..bf9ac616 --- /dev/null +++ b/tests/Feature/LocalisedRoutingTest.php @@ -0,0 +1,34 @@ +get("/en/contact"); + $response->assertStatus(200); + } + + public function testExistingLocalisedRoute(): void + { + $response = $this->get("/pl/kontakt"); + $response->assertStatus(200); + } + + public function testNonExistingRoute(): void + { + $response = $this->get("/en/kontakt"); + $response->assertStatus(404); + } + + public function testNonExistingLocalisedRoute(): void + { + $response = $this->get("/pl/contact"); + $response->assertStatus(404); + } +}