Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
83 changes: 54 additions & 29 deletions src/CoreBundle/EventSubscriber/LocaleSubscriber.php
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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]],
];
}
Expand Down
Loading