diff --git a/src/CoreBundle/EventSubscriber/LocaleSubscriber.php b/src/CoreBundle/EventSubscriber/LocaleSubscriber.php index 6ee15cc9740..2b2a74faa26 100644 --- a/src/CoreBundle/EventSubscriber/LocaleSubscriber.php +++ b/src/CoreBundle/EventSubscriber/LocaleSubscriber.php @@ -8,6 +8,7 @@ use Chamilo\CoreBundle\Entity\Course; use Chamilo\CoreBundle\Settings\SettingsManager; +use Chamilo\CourseBundle\Settings\SettingsCourseManager; use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface; use Symfony\Component\EventDispatcher\EventSubscriberInterface; use Symfony\Component\HttpFoundation\Request; @@ -15,50 +16,38 @@ use Symfony\Component\HttpKernel\KernelEvents; /** - * Checks the portal listener depending of different settings: - * platform, user, course. + * Handles locale selection based on platform, user, and course settings. */ class LocaleSubscriber implements EventSubscriberInterface { - protected string $defaultLocale; - protected ParameterBagInterface $parameterBag; - protected SettingsManager $settingsManager; - - public function __construct(string $defaultLocale, SettingsManager $settingsManager, ParameterBagInterface $parameterBag) - { - $this->defaultLocale = $defaultLocale; - $this->settingsManager = $settingsManager; - $this->parameterBag = $parameterBag; + public function __construct( + private string $defaultLocale, + private SettingsManager $settingsManager, + private ParameterBagInterface $parameterBag, + private SettingsCourseManager $courseSettingsManager + ) { } public function onKernelRequest(RequestEvent $event): void { $request = $event->getRequest(); - /*if (!$request->hasPreviousSession()) { - return; - }*/ - - $installed = false; - if ($this->parameterBag->has('installed')) { - $installed = 1 === (int) $this->parameterBag->get('installed'); - } - - if (!$installed) { - return; - } - if (!$request->hasSession()) { + $installed = $this->parameterBag->has('installed') && 1 === (int) $this->parameterBag->get('installed'); + if (!$installed || !$request->hasSession()) { return; } $sessionHandler = $request->getSession(); + // Override locale if forced via ?_locale=xx if ($attrLocale = $request->query->get('_locale')) { $sessionHandler->set('_selected_locale', $attrLocale); } + // Determine locale based on priority logic $locale = $this->getCurrentLanguage($request); - // if no explicit locale has been set on this request, use one from the session + + // Apply locale to request and session $request->setLocale($locale); $sessionHandler->set('_locale', $locale); } @@ -68,73 +57,57 @@ public function getCurrentLanguage(Request $request): string $sessionHandler = $request->getSession(); $localeList = []; - // 1. Check platform locale; + // 1. Platform default locale if ($platformLocale = $this->settingsManager->getSetting('language.platform_language')) { $localeList['platform_lang'] = $platformLocale; } - // 2. Check user locale - // _locale_user is set when user logins the system check UserLocaleListener + // 2. User profile locale from session if ($userLocale = $sessionHandler->get('_locale_user')) { $localeList['user_profil_lang'] = $userLocale; } - // 3. Check course locale - if ($request->query->getInt('cid') - || $request->request->getInt('cid') - || $request->attributes->getInt('cid') - ) { - /** @var Course|null $course */ - // 3. Check course locale - if ($course = $sessionHandler->get('course')) { - if ($courseLocale = $course->getCourseLanguage()) { - $localeList['course_lang'] = $courseLocale; - } + // 3. Course locale or user locale if course allows user language + $course = $sessionHandler->get('course'); + if ($course instanceof Course) { + $userLocale = $localeList['user_profil_lang'] ?? null; + $courseLocale = $course->getCourseLanguage(); + + $this->courseSettingsManager->setCourse($course); + if ($this->courseSettingsManager->getCourseSettingValue('show_course_in_user_language') === '1' && $userLocale) { + $localeList['course_lang'] = $userLocale; + } elseif ($courseLocale) { + $localeList['course_lang'] = $courseLocale; } } - // 4. force locale if it was selected from the URL + // 4. Locale selected manually via URL if ($localeFromUrl = $sessionHandler->get('_selected_locale')) { $localeList['user_selected_lang'] = $localeFromUrl; } - $priorityList = [ - 'language_priority_1', - 'language_priority_2', - 'language_priority_3', - 'language_priority_4', - ]; - - $locale = ''; - foreach ($priorityList as $setting) { - $priority = $this->settingsManager->getSetting(\sprintf('language.%s', $setting)); + // 5. Resolve locale based on configured language priorities + foreach ([ + '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])) { - $locale = $localeList[$priority]; - - break; + return $localeList[$priority]; } } - if (empty($locale)) { - // Use default order - $priorityList = [ - 'platform_lang', - 'user_profil_lang', - 'course_lang', - 'user_selected_lang', - ]; - foreach ($priorityList as $setting) { - if (!empty($localeList[$setting])) { - $locale = $localeList[$setting]; - } + // 6. Fallback order if priorities are not defined + foreach (['platform_lang', 'user_profil_lang', 'course_lang', 'user_selected_lang'] as $key) { + if (!empty($localeList[$key])) { + return $localeList[$key]; } } - if (empty($locale)) { - $locale = $this->defaultLocale; - } - - return $locale; + // 7. Final fallback to system default + return $this->defaultLocale; } public static function getSubscribedEvents(): array diff --git a/webpack.config.js b/webpack.config.js index 228ddd5a281..b4b31faf4b0 100755 --- a/webpack.config.js +++ b/webpack.config.js @@ -136,6 +136,52 @@ Encore.copyFiles({ to: "libs/select2/js/[name].[ext]", }) -const config = Encore.getWebpackConfig() +const fs = require("fs") +const path = require("path") +class CopyUnhashedAssetsPlugin { + apply(compiler) { + compiler.hooks.afterEmit.tap("CopyUnhashedAssetsPlugin", (compilation) => { + const buildPath = path.resolve(__dirname, "public/build") + + // === COPY legacy_document.js without hash === + const legacyDocumentFile = fs.readdirSync(buildPath).find((f) => + f.match(/^legacy_document\.[a-f0-9]+\.js$/) + ) + if (legacyDocumentFile) { + fs.copyFileSync( + path.join(buildPath, legacyDocumentFile), + path.join(buildPath, "legacy_document.js") + ) + } + + // === COPY runtime.js without hash === + const runtimeFile = fs.readdirSync(buildPath).find((f) => + f.match(/^runtime\.[a-f0-9]+\.js$/) + ) + if (runtimeFile) { + fs.copyFileSync( + path.join(buildPath, runtimeFile), + path.join(buildPath, "runtime.js") + ) + } + // === COPY document.css without hash === + const cssPath = path.join(buildPath, "css") + if (fs.existsSync(cssPath)) { + const documentCssFile = fs.readdirSync(cssPath).find((f) => + f.match(/^document\.[a-f0-9]+\.css$/) + ) + if (documentCssFile) { + fs.copyFileSync( + path.join(cssPath, documentCssFile), + path.join(cssPath, "document.css") + ) + } + } + }) + } +} + +Encore.addPlugin(new CopyUnhashedAssetsPlugin()) +const config = Encore.getWebpackConfig() module.exports = config