EasyAdminBundle icon indicating copy to clipboard operation
EasyAdminBundle copied to clipboard

Language switch doesn't work with pretty URLs on CRUD controllers

Open speller opened this issue 10 months ago • 4 comments

Describe the bug After switching to pretty URLs, I can't switch locale in CRUD controllers anymore.

To Reproduce Package version: 4.24.4 PHP version: 8.4

Locale configuration in config/packages/translation.yaml:

framework:
  default_locale: ru
  enabled_locales: ['en', 'ru']

Dashboard controller:

    public function configureDashboard(): Dashboard
    {
        return Dashboard::new()
            ->setLocales(['en', 'ru'])
        ;
    }
  1. I'm on the page http://localhost:7000/ru/admin/dashboard/customer (Ru locale)
  2. The locale switcher shows two languages - English and Russian
  3. The En locale link is: http://localhost:7000/ru/admin/dashboard/customer?_locale=en
  4. When I click on the English link, nothing changes, I still see the Russian language page.
  5. If I edit the URL manually to switch to the /en/ URL prefix, I get the No route found for "GET http://localhost:7000/en/admin/dashboard/customer" error.

This issue doesn't happen on the Dashboard http://localhost:7000/ru/admin/dashboard - the link to the English version is correct: http://localhost:7000/en/admin/dashboard and on custom routes (non-CRUD controllers).

speller avatar Feb 25 '25 13:02 speller

For custom controllers, I can see the following entries in the generated routes file in the cache:

...
    'admin_profile.en' => [[], ['_controller' => 'App\\Controller\\Admin\\ProfileController', '_locale' => 'en', '_canonical_route' => 'admin_profile'], [], [['text', '/en/admin/profile']], [], [], []],
    'admin_profile.ru' => [[], ['_controller' => 'App\\Controller\\Admin\\ProfileController', '_locale' => 'ru', '_canonical_route' => 'admin_profile'], [], [['text', '/ru/admin/profile']], [], [], []],
...
    'admin_profile' => [[], ['_controller' => 'App\\Controller\\Admin\\ProfileController'], ['_locale' => 'en|ru'], [['text', '/admin/profile']], [], [], []],

But for CRUD controllers, I can see only this kind of entries:

    'admin_dashboard_customer_index' => [[], ['_locale' => 'ru', '_controller' => 'App\\Controller\\Admin\\CustomerCrudController::index', 'routeCreatedByEasyAdmin' => true, 'dashboardControllerFqcn' => 'App\\Controller\\Admin\\DashboardController', 'crudControllerFqcn' => 'App\\Controller\\Admin\\CustomerCrudController', 'crudAction' => 'index'], ['_locale' => 'en|ru'], [['text', '/ru/admin/dashboard/customer']], [], [], []],

speller avatar Feb 25 '25 13:02 speller

I think the issue is a regression after #6754. The \EasyCorp\Bundle\EasyAdminBundle\Router\AdminRouteGenerator::generateAdminRoutes() method now adds the _locale parameter to the generated CRUD controller routes. This leads to the issue in the \Symfony\Component\Routing\Loader\Configurator\Traits\PrefixTrait::addPrefix() method that is postprocessing routes returned by the EasyAdmin generator where it checks for the _locale parameter presence and if present, it doesn't generate localized URLs:

    final protected function addPrefix(RouteCollection $routes, string|array $prefix, bool $trailingSlashOnRoot): void
    {
        ...
            foreach ($routes->all() as $name => $route) {
                if (null === $locale = $route->getDefault('_locale')) { // Prefixed locale routes are generated inside this IF block
                    $priority = $routes->getPriority($name) ?? 0;
                    $routes->remove($name);
                    foreach ($prefix as $locale => $localePrefix) {
                        $localizedRoute = clone $route;
                        $localizedRoute->setDefault('_locale', $locale);
                        $localizedRoute->setRequirement('_locale', preg_quote($locale));
                        $localizedRoute->setDefault('_canonical_route', $name);
                        $localizedRoute->setPath($localePrefix.(!$trailingSlashOnRoot && '/' === $route->getPath() ? '' : $route->getPath()));
                        $routes->add($name.'.'.$locale, $localizedRoute, $priority);
                    }
         ...

The following patch solves the issue for me until a proper fix is introduced:

--- a/src/Router/AdminRouteGenerator.php
+++ b/src/Router/AdminRouteGenerator.php
@@ -169,7 +169,6 @@
                     }

                     $defaults = [
-                        '_locale' => $this->defaultLocale,
                         '_controller' => $crudControllerFqcn.'::'.$actionName,
                         EA::ROUTE_CREATED_BY_EASYADMIN => true,
                         EA::DASHBOARD_CONTROLLER_FQCN => $dashboardFqcn,

speller avatar Feb 25 '25 14:02 speller

I also have the same issue when adding the locale prefixes to admin routes, and the patch @speller fixes it for me too.

andersonamuller avatar Mar 05 '25 22:03 andersonamuller

I just implemented the pretty URLs, and the dashboard index was correctly using the browser's language, but opening a CRUD Controller would switch it to the fallback language. @speller's patch fixes it, thanks!

Naroh091 avatar Mar 18 '25 21:03 Naroh091