diff --git a/config/services.php b/config/services.php index ee66e56f8c..fdff843efc 100644 --- a/config/services.php +++ b/config/services.php @@ -246,8 +246,7 @@ ->arg(2, service('cache.easyadmin')) ->arg(3, service('filesystem')) ->arg(4, '%kernel.build_dir%') - ->arg(5, '%kernel.default_locale%') - ->arg(6, tagged_iterator(EasyAdminExtension::TAG_ADMIN_ROUTE_CONTROLLER)) + ->arg(5, tagged_iterator(EasyAdminExtension::TAG_ADMIN_ROUTE_CONTROLLER)) ->set(AdminRouteLoader::class) ->arg(0, service(AdminRouteGenerator::class)) diff --git a/src/Router/AdminRouteGenerator.php b/src/Router/AdminRouteGenerator.php index 043e3e7d9d..36b6b89609 100644 --- a/src/Router/AdminRouteGenerator.php +++ b/src/Router/AdminRouteGenerator.php @@ -85,7 +85,6 @@ public function __construct( private readonly CacheItemPoolInterface $cache, private readonly Filesystem $filesystem, private readonly string $buildDir, - private readonly string $defaultLocale, private readonly iterable $adminRouteControllers = [], ) { } @@ -210,7 +209,6 @@ private function generateAdminRoutes(): array } $defaults = [ - '_locale' => $this->defaultLocale, '_controller' => $crudControllerFqcn.'::'.$actionRouteConfig['actionName'], EA::ROUTE_CREATED_BY_EASYADMIN => true, EA::DASHBOARD_CONTROLLER_FQCN => $dashboardFqcn, diff --git a/tests/Functional/AdminRoute/AdminRouteTest.php b/tests/Functional/AdminRoute/AdminRouteTest.php index ee94c7baa3..b1cfb9e6d7 100644 --- a/tests/Functional/AdminRoute/AdminRouteTest.php +++ b/tests/Functional/AdminRoute/AdminRouteTest.php @@ -605,6 +605,24 @@ public function testLegacyAttributesRoutesAreAccessible(): void $this->assertSame('Legacy export action', $client->getResponse()->getContent()); } + public function testCrudRoutesDoNotSetLocaleDefault(): void + { + $client = static::createClient(); + $router = $client->getContainer()->get('router'); + + // CRUD routes should NOT have '_locale' in defaults (regression test for #6842) + $crudRoute = $router->getRouteCollection()->get('admin_built_in_action_list'); + $this->assertNotNull($crudRoute); + $this->assertArrayNotHasKey('_locale', $crudRoute->getDefaults(), + 'CRUD routes must not set _locale in defaults, otherwise i18n prefix routing breaks'); + + // but routes with explicit '_locale' via #[AdminRoute] options should still have it + $invokableRoute = $router->getRouteCollection()->get('admin_custom_invokable'); + $this->assertNotNull($invokableRoute); + $this->assertSame('en', $invokableRoute->getDefault('_locale'), + 'Routes with explicit _locale in #[AdminRoute] options should keep it'); + } + public function testLegacyLinkToCrudMenuItemStillWorks(): void { $menuItem = MenuItem::linkToCrud('Products', 'fas fa-box', Product::class); diff --git a/tests/Functional/AdminRoute/I18nAdminRouteTest.php b/tests/Functional/AdminRoute/I18nAdminRouteTest.php new file mode 100644 index 0000000000..dd4f0f6c82 --- /dev/null +++ b/tests/Functional/AdminRoute/I18nAdminRouteTest.php @@ -0,0 +1,104 @@ +markTestSkipped('AdminRoute attributes require Symfony 5.4.1 or higher'); + } + + parent::setUp(); + + $client = static::createClient(); + + $buildDir = $client->getKernel()->getContainer()->getParameter('kernel.build_dir'); + $filesystem = new Filesystem(); + $filesystem->touch($buildDir.'/easyadmin_pretty_urls_enabled'); + + self::ensureKernelShutdown(); + } + + protected function tearDown(): void + { + $filesystem = new Filesystem(); + $cacheDir = sys_get_temp_dir().'/com.github.easycorp.easyadmin/tests/admin_route_i18n/var/test/cache'; + $filesystem->remove($cacheDir.'/easyadmin_pretty_urls_enabled'); + + parent::tearDown(); + } + + public function testDashboardRoutesHaveLocaleVariants(): void + { + $client = static::createClient(); + $router = $client->getContainer()->get('router'); + $routes = $router->getRouteCollection(); + + foreach (['admin', 'second_admin'] as $dashboard) { + foreach (self::LOCALES as $locale) { + $routeName = $dashboard.'.'.$locale; + $route = $routes->get($routeName); + + $this->assertNotNull($route, sprintf('Route "%s" should exist', $routeName)); + $this->assertSame($locale, $route->getDefault('_locale'), + sprintf('Route "%s" should have _locale default set to "%s"', $routeName, $locale)); + + $expectedPrefix = '/'.$locale.'/'; + $this->assertStringStartsWith($expectedPrefix, $route->getPath(), + sprintf('Route "%s" path should start with "%s"', $routeName, $expectedPrefix)); + } + } + } + + public function testCrudRoutesHaveLocaleVariants(): void + { + $client = static::createClient(); + $router = $client->getContainer()->get('router'); + $routes = $router->getRouteCollection(); + + $baseRouteName = 'admin_built_in_action_list'; + + foreach (self::LOCALES as $locale) { + $routeName = $baseRouteName.'.'.$locale; + $route = $routes->get($routeName); + + $this->assertNotNull($route, sprintf('Route "%s" should exist', $routeName)); + $this->assertSame($locale, $route->getDefault('_locale'), + sprintf('Route "%s" should have _locale default set to "%s"', $routeName, $locale)); + + $expectedPath = '/'.$locale.'/admin/built-in-action/index'; + $this->assertSame($expectedPath, $route->getPath(), + sprintf('Route "%s" should have path "%s"', $routeName, $expectedPath)); + } + } + + public function testLocaleRoutesAreAccessible(): void + { + $client = static::createClient(); + + foreach (self::LOCALES as $locale) { + $client->request('GET', '/'.$locale.'/admin/foo/list'); + + $this->assertResponseIsSuccessful( + sprintf('Request to "/%s/admin/foo/list" should be successful', $locale) + ); + $this->assertSame('Foo List', $client->getResponse()->getContent()); + } + } +} diff --git a/tests/Functional/Apps/AdminRouteApp/config/i18n_routes.php b/tests/Functional/Apps/AdminRouteApp/config/i18n_routes.php new file mode 100644 index 0000000000..7804b0b0d7 --- /dev/null +++ b/tests/Functional/Apps/AdminRouteApp/config/i18n_routes.php @@ -0,0 +1,8 @@ +import('.', 'easyadmin.routes') + ->prefix(['en' => '/en', 'ja' => '/ja', 'es' => '/es']); +}; diff --git a/tests/Functional/Apps/AdminRouteApp/src/I18nKernel.php b/tests/Functional/Apps/AdminRouteApp/src/I18nKernel.php new file mode 100644 index 0000000000..d2129cb6b4 --- /dev/null +++ b/tests/Functional/Apps/AdminRouteApp/src/I18nKernel.php @@ -0,0 +1,23 @@ +environment.'/cache'; + } + + public function getLogDir(): string + { + return sys_get_temp_dir().'/com.github.easycorp.easyadmin/tests/admin_route_i18n/var/'.$this->environment.'/log'; + } + + protected function configureRoutes(RoutingConfigurator $routes): void + { + $routes->import($this->getProjectDir().'/config/i18n_routes.php'); + } +} diff --git a/tests/Unit/Router/AdminRouteGeneratorTest.php b/tests/Unit/Router/AdminRouteGeneratorTest.php index f7b73d5a0d..a63e0cfa27 100644 --- a/tests/Unit/Router/AdminRouteGeneratorTest.php +++ b/tests/Unit/Router/AdminRouteGeneratorTest.php @@ -64,7 +64,6 @@ public function testFindRoute(?string $dashboardControllerFqcn, ?string $crudCon $cacheMock, new Filesystem(), self::$kernel->getBuildDir(), - 'en', ); $routeName = $adminRouteGenerator->findRouteName($dashboardControllerFqcn, $crudControllerFqcn, $action);