mainRecordType === 'pages') { return $this->processPageLocalization($instructions->mode, $instructions->recordUid, $instructions->targetLanguageId, $instructions->additionalData); } // Handle single record localization for other record types return $this->processSingleRecordLocalization($instructions->mode, $instructions->mainRecordType, $instructions->recordUid, $instructions->targetLanguageId); } /** * Process single record localization (non-page records) */ protected function processSingleRecordLocalization( LocalizationMode $mode, string $type, int $uid, int $targetLanguage ): LocalizationResult { // Validate that the record exists $record = BackendUtility::getRecord($type, $uid); if (!$record) { return LocalizationResult::error( [ sprintf( $this->getLanguageService()->sL('backend.wizards.localization:error.recordNotFound'), $uid, $type ), ] ); } // Check if translation already exists $existingTranslation = $this->localizationRepository->getRecordTranslation($type, $uid, $targetLanguage); if ($existingTranslation !== null) { // Translation already exists, return success with no-op finisher return LocalizationResult::success( new NoopLocalizationFinisher() ); } $cmd = [ $type => [ $uid => [ $mode->getDataHandlerCommand() => $targetLanguage, ], ], ]; $dataHandler = GeneralUtility::makeInstance(DataHandler::class); $dataHandler->start([], $cmd); $dataHandler->process_cmdmap(); if ($dataHandler->errorLog !== []) { return LocalizationResult::error($dataHandler->errorLog); } // Get the newly created record UID from DataHandler's copy mapping $newUid = $dataHandler->copyMappingArray_merged[$type][$uid] ?? null; // If no UID was found in copy mapping, try to find the translated record if ($newUid === null) { $translation = $this->localizationRepository->getRecordTranslation($type, $uid, $targetLanguage); $newUid = $translation?->getUid(); } // Generate redirect finisher or use reload finisher as fallback $redirectUrl = $newUid !== null ? $this->generateRedirectUrl($type, $newUid, $targetLanguage) : null; return LocalizationResult::success( $redirectUrl !== null ? new RedirectLocalizationFinisher($redirectUrl) : new ReloadLocalizationFinisher() ); } /** * Process page localization including selected content elements */ protected function processPageLocalization( LocalizationMode $mode, int $pageUid, int $targetLanguage, array $additionalData ): LocalizationResult { // Get selected content elements from additionalData $selectedContent = $additionalData['selectedRecordUids'] ?? []; $cmd = []; // Step 1: Check if page translation already exists $pageTranslation = $this->localizationRepository->getPageTranslations($pageUid, [$targetLanguage], $this->getBackendUser()->workspace); if ($pageTranslation === []) { // Page translation doesn't exist - create it // Always use 'localize' command for pages (even for copy mode) // as we need to create a proper page translation/overlay $cmd['pages'] = [ $pageUid => [ 'localize' => $targetLanguage, ], ]; } // Step 2: Add selected content elements to the command if (!empty($selectedContent)) { $cmd['tt_content'] = []; foreach ($selectedContent as $contentUid) { $cmd['tt_content'][(int)$contentUid] = [ $mode->getDataHandlerCommand() => $targetLanguage, ]; } } // If no commands were built (page already exists, no content selected), // still return success with a no-op finisher if (empty($cmd)) { // Use no-op finisher to indicate nothing was done, but offer to reload return LocalizationResult::success( new NoopLocalizationFinisher() ); } $dataHandler = GeneralUtility::makeInstance(DataHandler::class); $dataHandler->start([], $cmd); $dataHandler->process_cmdmap(); if ($dataHandler->errorLog !== []) { return LocalizationResult::error($dataHandler->errorLog); } // Generate redirect finisher to the page layout in the target language or use reload finisher as fallback $redirectUrl = $this->generateRedirectUrl('pages', $pageUid, $targetLanguage); return LocalizationResult::success( $redirectUrl !== null ? new RedirectLocalizationFinisher($redirectUrl) : new ReloadLocalizationFinisher() ); } /** * Generate redirect URL based on record type */ protected function generateRedirectUrl(string $type, int $uid, int $targetLanguage): ?string { if ($type === 'pages') { // Redirect to page layout module with the target language return (string)$this->uriBuilder->buildUriFromRoute('web_layout', [ 'id' => $uid, 'languages' => [$targetLanguage], ]); } // For other record types, redirect to the edit form of the translated record $record = BackendUtility::getRecord($type, $uid); if ($record && isset($record['pid'])) { $returnUrl = null; if ($type === 'sys_file_metadata') { // Get the file from the metadata record and build return URL to filelist module try { $file = $this->resourceFactory->getFileObject((int)$record['file']); $parentFolder = $file->getParentFolder(); $returnUrl = (string)$this->uriBuilder->buildUriFromRoute( 'media_management', ['id' => $parentFolder->getCombinedIdentifier()] ); } catch (\Exception) { // File not found or inaccessible, fall back to default return URL } } if ($returnUrl === null) { $returnUrl = (string)$this->uriBuilder->buildUriFromRoute( 'web_layout', [ 'id' => $record['pid'], 'languages' => [$targetLanguage], ] ); } // Redirect to edit form for the newly created record return (string)$this->uriBuilder->buildUriFromRoute('record_edit', [ 'edit' => [ $type => [ $uid => 'edit', ], ], 'returnUrl' => $returnUrl, ]); } return null; } protected function getLanguageService(): LanguageService { return $GLOBALS['LANG']; } protected function getBackendUser(): BackendUserAuthentication { return $GLOBALS['BE_USER']; } }