diff --git a/src/CoreBundle/EventSubscriber/LocaleSubscriber.php b/src/CoreBundle/EventSubscriber/LocaleSubscriber.php index 7922a393d1e..79ed6f71d90 100644 --- a/src/CoreBundle/EventSubscriber/LocaleSubscriber.php +++ b/src/CoreBundle/EventSubscriber/LocaleSubscriber.php @@ -9,6 +9,7 @@ use Chamilo\CoreBundle\Entity\Course; use Chamilo\CoreBundle\Settings\SettingsManager; use Chamilo\CourseBundle\Settings\SettingsCourseManager; +use Doctrine\ORM\EntityManagerInterface; use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface; use Symfony\Component\EventDispatcher\EventSubscriberInterface; use Symfony\Component\HttpFoundation\Request; @@ -24,95 +25,119 @@ public function __construct( private string $defaultLocale, private SettingsManager $settingsManager, private ParameterBagInterface $parameterBag, - private SettingsCourseManager $courseSettingsManager + private SettingsCourseManager $courseSettingsManager, + private EntityManagerInterface $em, ) {} public function onKernelRequest(RequestEvent $event): void { $request = $event->getRequest(); + // Skip if not installed or no session is available $installed = $this->parameterBag->has('installed') && 1 === (int) $this->parameterBag->get('installed'); if (!$installed || !$request->hasSession()) { return; } - $sessionHandler = $request->getSession(); + $session = $request->getSession(); - // Override locale if forced via ?_locale=xx - if ($attrLocale = $request->query->get('_locale')) { - $sessionHandler->set('_selected_locale', $attrLocale); + // Honor explicit override via ?_locale=xx (persist for later requests) + if ($queryLocale = $request->query->get('_locale')) { + $session->set('_selected_locale', $queryLocale); } - // Determine locale based on priority logic + // Resolve locale and apply $locale = $this->getCurrentLanguage($request); - - // Apply locale to request and session $request->setLocale($locale); - $sessionHandler->set('_locale', $locale); + $session->set('_locale', $locale); } public function getCurrentLanguage(Request $request): string { - $sessionHandler = $request->getSession(); + $session = $request->getSession(); $localeList = []; - // 1. Platform default locale + // 1) Platform default if ($platformLocale = $this->settingsManager->getSetting('language.platform_language')) { $localeList['platform_lang'] = $platformLocale; } - // 2. User profile locale from session - if ($userLocale = $sessionHandler->get('_locale_user')) { + // 2) User profile (from session) + if ($userLocale = $session->get('_locale_user')) { $localeList['user_profil_lang'] = $userLocale; } - // 3. Course locale or user locale if course allows user language - $course = $sessionHandler->get('course'); + // 3) Course language, or user language if course allows it + // First try: course already in session + $course = $session->get('course'); + + // Fallback: resolve course from request if not in session yet + if (!$course instanceof Course) { + // Accept both numeric id (?cid=123) and code (?cid=ABC) as well as legacy ?cidReq=CODE + $cid = $request->query->get('cid'); + $cidReq = $request->query->get('cidReq'); + + if ($cid) { + if (ctype_digit((string) $cid)) { + $course = $this->em->getRepository(Course::class)->find((int) $cid); + } else { + $course = $this->em->getRepository(Course::class)->findOneBy(['code' => (string) $cid]); + } + } + + if (!$course && $cidReq) { + $course = $this->em->getRepository(Course::class)->findOneBy(['code' => (string) $cidReq]); + } + } + if ($course instanceof Course) { - $userLocale = $localeList['user_profil_lang'] ?? null; + $userLocale = $localeList['user_profil_lang'] ?? null; $courseLocale = $course->getCourseLanguage(); + // The per-course setting decides whether to use user language $this->courseSettingsManager->setCourse($course); - if ('1' === $this->courseSettingsManager->getCourseSettingValue('show_course_in_user_language') && $userLocale) { + $allowUser = $this->courseSettingsManager->getCourseSettingValue('show_course_in_user_language') === '1'; + + if ($allowUser && $userLocale) { $localeList['course_lang'] = $userLocale; } elseif ($courseLocale) { $localeList['course_lang'] = $courseLocale; } } - // 4. Locale selected manually via URL - if ($localeFromUrl = $sessionHandler->get('_selected_locale')) { - $localeList['user_selected_lang'] = $localeFromUrl; + // 4) Explicit selection via URL (?_locale=xx) saved earlier in session + if ($selected = $session->get('_selected_locale')) { + $localeList['user_selected_lang'] = $selected; } - // 5. Resolve locale based on configured language priorities + // 5) Honor configured priorities language_priority_1..4 foreach ([ - 'language_priority_1', - 'language_priority_2', - 'language_priority_3', - 'language_priority_4', - ] as $settingKey) { + 'language_priority_1', + 'language_priority_2', + 'language_priority_3', + 'language_priority_4', + ] as $settingKey) { $priority = $this->settingsManager->getSetting("language.$settingKey"); if (!empty($priority) && !empty($localeList[$priority])) { return $localeList[$priority]; } } - // 6. Fallback order if priorities are not defined + // 6) Fallback order when priorities are absent foreach (['platform_lang', 'user_profil_lang', 'course_lang', 'user_selected_lang'] as $key) { if (!empty($localeList[$key])) { return $localeList[$key]; } } - // 7. Final fallback to system default + // 7) Final fallback to system default return $this->defaultLocale; } public static function getSubscribedEvents(): array { return [ - // must be registered before the default Locale listener + // Must run before Symfony's default Locale listener KernelEvents::REQUEST => [['onKernelRequest', 20]], ]; }