diff --git a/Build/Sources/Core13/localization.js b/Build/Sources/Core13/localization.js
deleted file mode 100644
index 8ed6f31e..00000000
--- a/Build/Sources/Core13/localization.js
+++ /dev/null
@@ -1,13 +0,0 @@
-/*
- * This file is part of the TYPO3 CMS project.
- *
- * It is free software; you can redistribute it and/or modify it under
- * the terms of the GNU General Public License, either version 2
- * of the License, or any later version.
- *
- * For the full copyright and license information, please read the
- * LICENSE.txt file that was distributed with this source code.
- *
- * The TYPO3 project - inspiring people to share!
- */
-import DocumentService from"@typo3/core/document-service.js";import $ from"jquery";import{SeverityEnum}from"@typo3/backend/enum/severity.js";import AjaxRequest from"@typo3/core/ajax/ajax-request.js";import Icons from"@typo3/backend/icons.js";import Modal from"@typo3/backend/modal.js";import MultiStepWizard from"@typo3/backend/multi-step-wizard.js";import"@typo3/backend/element/icon-element.js";import{MarkupIdentifiers}from"@typo3/backend/enum/icon-types.js";class Localization{constructor(){this.triggerButton=".t3js-localize",DocumentService.ready().then((()=>{this.initialize()}))}async initialize(){const e=await Icons.getIcon("actions-localize",Icons.sizes.large),t=await Icons.getIcon("actions-edit-copy",Icons.sizes.large),a=await Icons.getIcon("actions-localize-deepl",Icons.sizes.large,null,null,MarkupIdentifiers.inline);$(this.triggerButton).removeClass("disabled"),$(document).on("click",this.triggerButton,(async l=>{l.preventDefault();const o=$(l.currentTarget),n=[],i=[];if(0===o.data("allowTranslate")&&0===o.data("allowCopy"))return void Modal.confirm(TYPO3.lang["window.localization.mixed_mode.title"],TYPO3.lang["window.localization.mixed_mode.message"],SeverityEnum.warning,[{text:TYPO3?.lang?.["button.ok"]||"OK",btnClass:"btn-warning",name:"ok",trigger:(e,t)=>t.hideModal()}]);const c=await(await this.loadAvailableLanguages(parseInt(o.data("pageId"),10),parseInt(o.data("languageId"),10))).resolve();if(o.data("allowTranslate")&&(n.push('
"),MultiStepWizard.getComponent().on("change",".t3js-language-option",(e=>{MultiStepWizard.set("sourceLanguage",$(e.currentTarget).val()),MultiStepWizard.unlockNextStep()}));const a=$("",{class:"row"});for(const e of c){const t="language"+e.uid,l=$("",{type:"radio",name:"language",id:t,value:e.uid,class:"btn-check t3js-language-option"}),o=$("",{class:"btn btn-default btn-block",for:t}).text(" "+e.title).prepend(e.flagIcon);a.append($("",{class:"col-sm-4"}).append(l).append(o))}e.empty().append(a)})),MultiStepWizard.addSlide("localize-summary",TYPO3.lang["localize.view.summary"],"",SeverityEnum.notice,TYPO3.lang["localize.wizard.step.selectRecords"],(async(e,t)=>{e.empty().html('
');
- });
- this.getSummary(
- parseInt($triggerButton.data('pageId'), 10),
- parseInt($triggerButton.data('languageId'), 10),
- ).then(async (response: AjaxResponse): Promise => {
- const result: SummaryRecord = await response.resolve();
- $slide.empty();
- this.records = [];
-
- const columns = result.columns.columns;
- const columnList = result.columns.columnList;
-
- columnList.forEach((colPos: number): void => {
- if (typeof result.records[colPos] === 'undefined') {
- return;
- }
-
- const column = columns[colPos];
- const $row = $('', { class: 'row' });
-
- result.records[colPos].forEach((record: SummaryColPosRecord): void => {
- const label = ' (' + record.uid + ') ' + record.title;
- this.records.push(record.uid);
-
- $row.append(
- $('', { class: 'col-sm-6' }).append(
- $('', { class: 'input-group' }).append(
- $('', { class: 'input-group-addon' }).append(
- $('', {
- type: 'checkbox',
- class: 't3js-localization-toggle-record',
- id: 'record-uid-' + record.uid,
- checked: 'checked',
- 'data-uid': record.uid,
- 'aria-label': label,
- }),
- ),
- $('', {
- class: 'form-control',
- for: 'record-uid-' + record.uid,
- })
- .text(label)
- .prepend(record.icon),
- ),
- ),
- );
- });
-
- $slide.append(
- $('', {
- class: 'localization-fieldset',
- }).append(
- $('')
- .text(column)
- .prepend(
- $('', {
- class: 't3js-localization-toggle-column',
- type: 'checkbox',
- checked: 'checked',
- }),
- ),
- $row,
- ),
- );
- });
-
- Wizard.unlockNextStep();
-
- Wizard.getComponent()
- .on('change', '.t3js-localization-toggle-record', (cmpEvt: JQueryEventObject): void => {
- const $me = $(cmpEvt.currentTarget);
- const uid = $me.data('uid');
- const $parent = $me.closest('fieldset');
- const $columnCheckbox = $parent.find('.t3js-localization-toggle-column');
-
- if ($me.is(':checked')) {
- this.records.push(uid);
- } else {
- const index = this.records.indexOf(uid);
- if (index > -1) {
- this.records.splice(index, 1);
- }
- }
-
- const $allChildren = $parent.find('.t3js-localization-toggle-record');
- const $checkedChildren = $parent.find('.t3js-localization-toggle-record:checked');
-
- $columnCheckbox.prop('checked', $checkedChildren.length > 0);
- $columnCheckbox.prop(
- 'indeterminate',
- $checkedChildren.length > 0 && $checkedChildren.length < $allChildren.length,
- );
-
- if (this.records.length > 0) {
- Wizard.unlockNextStep();
- } else {
- Wizard.lockNextStep();
- }
- })
- .on('change', '.t3js-localization-toggle-column', (toggleEvt: JQueryEventObject): void => {
- const $me = $(toggleEvt.currentTarget);
- const $children = $me.closest('fieldset').find('.t3js-localization-toggle-record');
-
- $children.prop('checked', $me.is(':checked'));
- $children.trigger('change');
- });
- });
- },
- );
-
- Wizard.addFinalProcessingSlide((): void => {
- this.localizeRecords(
- parseInt($triggerButton.data('pageId'), 10),
- parseInt($triggerButton.data('languageId'), 10),
- this.records,
- ).then((): void => {
- Wizard.dismiss();
- document.location.reload();
- });
- }).then((): void => {
- Wizard.show();
-
- Wizard.getComponent().on('click', '.t3js-localization-option', (optionEvt: JQueryEventObject): void => {
- const $me = $(optionEvt.currentTarget);
- const $radio = $me.find('input[type="radio"]');
-
- if ($me.data('helptext')) {
- const $container = $(optionEvt.delegateTarget);
- $container.find('.t3js-localization-option').removeClass('active');
- $container.find('.t3js-helptext').addClass('text-body-secondary');
- $me.addClass('active');
- $container.find($me.data('helptext')).removeClass('text-body-secondary');
- }
- this.loadAvailableLanguages(
- parseInt($triggerButton.data('pageId'), 10),
- parseInt($triggerButton.data('languageId'), 10),
- ).then(async (response: AjaxResponse): Promise => {
- const result: Array = await response.resolve();
-
- if (result.length === 1) {
- this.sourceLanguage = result[0].uid;
- } else {
- // This seems pretty ugly solution to find the right language uid but its done the same way in the core... line 211-213
- // If we have more then 1 language we need to find the first radio button and check its value to get the source language
- this.sourceLanguage = $radio.prev().val() as number;
-
- }
-
- if ($radio.length > 0) {
- if (
- $radio.val() == 'localizedeepl' ||
- $radio.val() == 'localizedeeplauto'
- ) {
- this.deeplSettings().then(async (response) => {
- const result: AjaxControllerResponse = await response.resolve();
-
- if (result.status === false) {
- Wizard.lockNextStep()
-
- let divDeepl: HTMLElement = $radio.val() == 'localizedeepl'
- ? window.parent.document.querySelector('#deeplText .alert')
- : window.parent.document.querySelector('#deeplTextAuto .alert');
-
- divDeepl.hidden = false;
- }
- })
- }
-
- }
- });
-
- this.localizationMode = $radio.val().toString();
- Wizard.unlockNextStep()
- });
- });
- });
- });
- });
- });
- }
-
- /**
- * Load available languages from page
- *
- * @param {number} pageId
- * @param {number} languageId
- * @returns {Promise}
- */
- private loadAvailableLanguages(pageId: number, languageId: number): Promise {
- return new AjaxRequest(TYPO3.settings.ajaxUrls.page_languages)
- .withQueryArguments({
- pageId: pageId,
- languageId: languageId,
- })
- .get();
- }
-
- /**
- * Get summary for record processing
- *
- * @param {number} pageId
- * @param {number} languageId
- * @returns {Promise}
- */
- private getSummary(pageId: number, languageId: number): Promise {
- return new AjaxRequest(TYPO3.settings.ajaxUrls.records_localize_summary)
- .withQueryArguments({
- pageId: pageId,
- destLanguageId: languageId,
- languageId: this.sourceLanguage,
- })
- .get();
- }
-
- /**
- * Localize records
- *
- * @param {number} pageId
- * @param {number} languageId
- * @param {Array} uidList
- * @returns {Promise}
- */
- private localizeRecords(pageId: number, languageId: number, uidList: Array): Promise {
- return new AjaxRequest(TYPO3.settings.ajaxUrls.records_localize)
- .withQueryArguments({
- pageId: pageId,
- srcLanguageId: this.sourceLanguage,
- destLanguageId: languageId,
- action: this.localizationMode,
- uidList: uidList,
- })
- .get();
- }
-
- /**
- * Returns status of deepl configuration, is not set Deepl Button are disabled
- */
- private deeplSettings(): Promise {
- return new AjaxRequest(TYPO3.settings.ajaxUrls.deepl_check_configuration).get();
- }
-}
-
-export default new Localization();
diff --git a/Build/phpstan/Core12/phpstan-baseline.neon b/Build/phpstan/Core12/phpstan-baseline.neon
index 638332f2..1a1104fa 100644
--- a/Build/phpstan/Core12/phpstan-baseline.neon
+++ b/Build/phpstan/Core12/phpstan-baseline.neon
@@ -35,21 +35,6 @@ parameters:
count: 1
path: ../../../Classes/Override/Core12/DatabaseRecordListWithGridelements.php
- -
- message: "#^Method WebVision\\\\Deepltranslate\\\\Core\\\\Override\\\\LocalizationController\\:\\:process\\(\\) has parameter \\$params with no value type specified in iterable type array\\.$#"
- count: 1
- path: ../../../Classes/Override/LocalizationController.php
-
- -
- message: "#^Unsafe access to private constant WebVision\\\\Deepltranslate\\\\Core\\\\Override\\\\LocalizationController\\:\\:ACTION_LOCALIZEDEEPL through static\\:\\:\\.$#"
- count: 3
- path: ../../../Classes/Override/LocalizationController.php
-
- -
- message: "#^Unsafe access to private constant WebVision\\\\Deepltranslate\\\\Core\\\\Override\\\\LocalizationController\\:\\:ACTION_LOCALIZEDEEPL_AUTO through static\\:\\:\\.$#"
- count: 3
- path: ../../../Classes/Override/LocalizationController.php
-
-
message: "#^Call to method write\\(\\) on an unknown class TYPO3\\\\CMS\\\\Core\\\\Configuration\\\\SiteWriter\\.$#"
count: 1
diff --git a/Build/phpstan/Core13/phpstan-baseline.neon b/Build/phpstan/Core13/phpstan-baseline.neon
index 149333db..8f5f68ba 100644
--- a/Build/phpstan/Core13/phpstan-baseline.neon
+++ b/Build/phpstan/Core13/phpstan-baseline.neon
@@ -40,21 +40,6 @@ parameters:
count: 1
path: ../../../Classes/Override/Core12/DatabaseRecordListWithGridelements.php
- -
- message: "#^Method WebVision\\\\Deepltranslate\\\\Core\\\\Override\\\\LocalizationController\\:\\:process\\(\\) has parameter \\$params with no value type specified in iterable type array\\.$#"
- count: 1
- path: ../../../Classes/Override/LocalizationController.php
-
- -
- message: "#^Unsafe access to private constant WebVision\\\\Deepltranslate\\\\Core\\\\Override\\\\LocalizationController\\:\\:ACTION_LOCALIZEDEEPL through static\\:\\:\\.$#"
- count: 3
- path: ../../../Classes/Override/LocalizationController.php
-
- -
- message: "#^Unsafe access to private constant WebVision\\\\Deepltranslate\\\\Core\\\\Override\\\\LocalizationController\\:\\:ACTION_LOCALIZEDEEPL_AUTO through static\\:\\:\\.$#"
- count: 3
- path: ../../../Classes/Override/LocalizationController.php
-
-
message: "#^Method WebVision\\\\Deepltranslate\\\\Core\\\\Utility\\\\DeeplBackendUtility\\:\\:buildBackendRoute\\(\\) has parameter \\$parameters with no value type specified in iterable type array\\.$#"
count: 1
diff --git a/Classes/Event/Listener/ApplyLocalizationModesEventListener.php b/Classes/Event/Listener/ApplyLocalizationModesEventListener.php
new file mode 100644
index 00000000..b7cded6f
--- /dev/null
+++ b/Classes/Event/Listener/ApplyLocalizationModesEventListener.php
@@ -0,0 +1,60 @@
+getMajorVersion();
+ if ($this->allowDeeplTranslate($event)) {
+ $modes[] = new LocalizationMode(
+ identifier: 'deepltranslate',
+ title: $event->getLanguageService()->sL('LLL:EXT:deepltranslate_core/Resources/Private/Language/locallang.xlf:localize.educate.deepltranslateHeader'),
+ description: $event->getLanguageService()->sL('LLL:EXT:deepltranslate_core/Resources/Private/Language/locallang.xlf:localize.educate.deepltranslate'),
+ icon: ($majorVersion === 13 ? 'actions-localize-deepl-13' : 'actions-localize-deepl'),
+ before: [],
+ after: ['translate', 'copy'],
+ );
+ }
+ if ($this->allowDeeplTranslateAuto($event)) {
+ // @todo Consider to drop `deepltranslateauto` mode. Does not make much sense in the current form.
+ $modes[] = new LocalizationMode(
+ identifier: 'deepltranslateauto',
+ title: $event->getLanguageService()->sL('LLL:EXT:deepltranslate_core/Resources/Private/Language/locallang.xlf:localize.educate.deepltranslateHeaderAutodetect'),
+ description: $event->getLanguageService()->sL('LLL:EXT:deepltranslate_core/Resources/Private/Language/locallang.xlf:localize.educate.deepltranslateAuto'),
+ icon: ($majorVersion === 13 ? 'actions-localize-deepl-13' : 'actions-localize-deepl'),
+ before: [],
+ after: ['translate', 'copy', 'deepltranslate'],
+ );
+ }
+ if ($modes !== []) {
+ $event->getModes()->add(...array_values($modes));
+ }
+ }
+
+ private function allowDeeplTranslate(GetLocalizationModesEvent $event): bool
+ {
+ // @todo Prepared for PageTSConfig feature to toggle `deepltranslate`.
+ return true;
+ }
+
+ private function allowDeeplTranslateAuto(GetLocalizationModesEvent $event): bool
+ {
+ // @todo Prepared for PageTSConfig feature to toggle `deepltranslateauto`.
+ return true;
+ }
+}
diff --git a/Classes/Event/Listener/ProcessLocalizationModeEventListener.php b/Classes/Event/Listener/ProcessLocalizationModeEventListener.php
new file mode 100644
index 00000000..2e7c36f3
--- /dev/null
+++ b/Classes/Event/Listener/ProcessLocalizationModeEventListener.php
@@ -0,0 +1,36 @@
+getAction(), ['deepltranslate', 'deepltranslateauto'], true)
+ || !$event->getLocalizationModes()->hasIdentifier($event->getAction())
+ ) {
+ // Not responsible, early return.
+ return;
+ }
+ $cmd = $event->getCmd();
+ foreach ($event->getUidList() as $currentUid) {
+ $cmd['tt_content'][$currentUid] = [
+ // Both modes are handled by the same custom DataHandler command
+ 'deepltranslate' => $event->getDestLanguageId(),
+ ];
+ }
+ $event->setCmd($cmd);
+ }
+}
diff --git a/Classes/Override/LocalizationController.php b/Classes/Override/LocalizationController.php
deleted file mode 100644
index ece15c49..00000000
--- a/Classes/Override/LocalizationController.php
+++ /dev/null
@@ -1,127 +0,0 @@
-pageRenderer = GeneralUtility::makeInstance(PageRenderer::class);
- $this->deeplService = GeneralUtility::makeInstance(DeeplService::class);
- $this->pageRenderer->addInlineLanguageLabelFile('EXT:deepltranslate_core/Resources/Private/Language/locallang.xlf');
- }
-
- /**
- * @param ServerRequestInterface $request
- * @return ResponseInterface
- */
- public function localizeRecords(ServerRequestInterface $request): ResponseInterface
- {
- $params = $request->getQueryParams();
-
- if (!isset($params['pageId'], $params['srcLanguageId'], $params['destLanguageId'], $params['action'], $params['uidList'])) {
- return new JsonResponse(null, 400);
- }
-
- //additional constraint ACTION_LOCALIZEDEEPL
- if (
- $params['action'] !== static::ACTION_COPY
- && $params['action'] !== static::ACTION_LOCALIZE
- && $params['action'] !== static::ACTION_LOCALIZEDEEPL
- && $params['action'] !== static::ACTION_LOCALIZEDEEPL_AUTO
- ) {
- $response = new Response('php://temp', 400, ['Content-Type' => 'application/json; charset=utf-8']);
- $response->getBody()->write('Invalid action "' . $params['action'] . '" called.');
- return $response;
- }
-
- // Filter transmitted but invalid uids
- $params['uidList'] = $this->filterInvalidUids(
- (int)$params['pageId'],
- (int)$params['destLanguageId'],
- $this->getSourceLanguageId($params['srcLanguageId']),
- $params['uidList']
- );
-
- $this->process($params);
-
- return (new JsonResponse())->setPayload([]);
- }
-
- /**
- * Processes the localization actions
- *
- * @param array $params
- */
- protected function process($params): void
- {
- $deeplTranslateActions = [static::ACTION_LOCALIZEDEEPL, static::ACTION_LOCALIZEDEEPL_AUTO];
- $destLanguageId = (int)$params['destLanguageId'];
-
- // Build command map
- $cmd = [
- 'tt_content' => [],
- ];
- if (isset($params['uidList']) && is_array($params['uidList'])) {
- foreach ($params['uidList'] as $currentUid) {
- if (
- $params['action'] === static::ACTION_LOCALIZE
- || $params['action'] === static::ACTION_LOCALIZEDEEPL
- || $params['action'] === static::ACTION_LOCALIZEDEEPL_AUTO
- ) {
- $dataHandlerCommandName = (in_array($params['action'], $deeplTranslateActions, true) ? 'deepltranslate' : 'localize');
- $cmd['tt_content'][$currentUid] = [
- $dataHandlerCommandName => $destLanguageId,
- ];
- } else {
- $cmd['tt_content'][$currentUid] = [
- 'copyToLanguage' => $destLanguageId,
- ];
- }
- }
- }
-
- $dataHandler = GeneralUtility::makeInstance(DataHandler::class);
- $dataHandler->start([], $cmd);
- $dataHandler->process_cmdmap();
- }
-
- /**
- * Return source language ID from source language string
- */
- public function getSourceLanguageId(string $srcLanguage): int
- {
- $langParam = explode('-', $srcLanguage);
- if (count($langParam) > 1) {
- return (int)$langParam[1];
- }
- return (int)$langParam[0];
- }
-}
diff --git a/Configuration/JavaScriptModules.php b/Configuration/JavaScriptModules.php
index 693bd2d0..bfcbd60a 100644
--- a/Configuration/JavaScriptModules.php
+++ b/Configuration/JavaScriptModules.php
@@ -1,9 +1,5 @@
getMajorVersion();
return [
'dependencies' => ['core', 'backend'],
- 'imports' => [
- '@typo3/backend/localization.js' => sprintf('EXT:deepltranslate_core/Resources/Public/JavaScript/localization%s.js', $majorVersion),
- ],
];
diff --git a/Configuration/Services.yaml b/Configuration/Services.yaml
index 79f198b0..be70f8f6 100644
--- a/Configuration/Services.yaml
+++ b/Configuration/Services.yaml
@@ -53,3 +53,17 @@ services:
- name: 'event.listener'
identifier: 'deepltranslate-core/usages'
event: TYPO3\CMS\Backend\Backend\Event\SystemInformationToolbarCollectorEvent
+
+ WebVision\Deepltranslate\Core\Event\Listener\ApplyLocalizationModesEventListener:
+ tags:
+ - name: 'event.listener'
+ identifier: 'deepltranslate-core/deepltranslate-core-localization-modes-determine'
+ event: WebVision\Deepl\Base\Event\GetLocalizationModesEvent
+ after: 'deepl-base/determine-default-typo3-localization-modes'
+
+ WebVision\Deepltranslate\Core\Event\Listener\ProcessLocalizationModeEventListener:
+ tags:
+ - name: 'event.listener'
+ identifier: 'deepltranslate-core/deepltranslate-core-localization-modes-process'
+ event: WebVision\Deepl\Base\Event\LocalizationProcessPrepareDataHandlerCommandMapEvent
+ after: 'deepl-base/process-default-typo3-localization-modes'
diff --git a/Resources/Public/Css/patch-105853.css b/Resources/Public/Css/patch-105853.css
deleted file mode 100644
index 318349f5..00000000
--- a/Resources/Public/Css/patch-105853.css
+++ /dev/null
@@ -1,6 +0,0 @@
-/**
- * Workaround / Patch for core change:
- * 87576: [BUGFIX] Fix overflow of labels in localization mode buttons | https://review.typo3.org/c/Packages/TYPO3.CMS/+/87576
- * Remove in TYPO3 v13.4.3
- */
-.deepl-translate-modal-icon-text-alignment{white-space:normal;text-align:center}
diff --git a/Resources/Public/JavaScript/Settings.js b/Resources/Public/JavaScript/Settings.js
deleted file mode 100644
index 46572ef0..00000000
--- a/Resources/Public/JavaScript/Settings.js
+++ /dev/null
@@ -1,8 +0,0 @@
-define(['jquery'], function() {
- //avoid numeric
- $('.languageAssigned').keypress(function (key) {
- if ((key.charCode > 90 && key.charCode < 97) || (key.charCode < 65 && key.charCode != 45) || key.charCode > 122) {
- return false;
- }
- });
-});
diff --git a/Resources/Public/JavaScript/localization12.js b/Resources/Public/JavaScript/localization12.js
deleted file mode 100644
index b3c3b131..00000000
--- a/Resources/Public/JavaScript/localization12.js
+++ /dev/null
@@ -1,467 +0,0 @@
-import $ from 'jquery';
-import { AjaxResponse } from '@typo3/core/ajax/ajax-response.js';
-import { InputTransformer } from '@typo3/core/ajax/input-transformer.js';
-import AjaxRequest$1 from '@typo3/core/ajax/ajax-request.js';
-import ClientStorage from '@typo3/backend/storage/client.js';
-import { Sizes, States, MarkupIdentifiers } from '@typo3/backend/enum/icon-types.js';
-import 'lit';
-import { SeverityEnum as SeverityEnum$1 } from '@typo3/backend/enum/severity.js';
-import Modal from '@typo3/backend/modal.js';
-import Severity from '@typo3/backend/severity.js';
-import Icons$2 from '@typo3/backend/icons.js';
-
-/*
- * This file is part of the TYPO3 CMS project.
- *
- * It is free software; you can redistribute it and/or modify it under
- * the terms of the GNU General Public License, either version 2
- * of the License, or any later version.
- *
- * For the full copyright and license information, please read the
- * LICENSE.txt file that was distributed with this source code.
- *
- * The TYPO3 project - inspiring people to share!
- */
-class DocumentService{constructor(e=window,t=document){this.windowRef=e,this.documentRef=t;}ready(){return new Promise(((e,t)=>{if("complete"===this.documentRef.readyState)e(this.documentRef);else {const n=setTimeout((()=>{o(),t(this.documentRef);}),3e4),o=()=>{this.windowRef.removeEventListener("load",d),this.documentRef.removeEventListener("DOMContentLoaded",d);},d=()=>{o(),clearTimeout(n),e(this.documentRef);};this.windowRef.addEventListener("load",d),this.documentRef.addEventListener("DOMContentLoaded",d);}}))}}const documentService=new DocumentService;
-
-/*
- * This file is part of the TYPO3 CMS project.
- *
- * It is free software; you can redistribute it and/or modify it under
- * the terms of the GNU General Public License, either version 2
- * of the License, or any later version.
- *
- * For the full copyright and license information, please read the
- * LICENSE.txt file that was distributed with this source code.
- *
- * The TYPO3 project - inspiring people to share!
- */
-var SeverityEnum;!function(n){n[n.notice=-2]="notice",n[n.info=-1]="info",n[n.ok=0]="ok",n[n.warning=1]="warning",n[n.error=2]="error";}(SeverityEnum||(SeverityEnum={}));
-
-/*
- * This file is part of the TYPO3 CMS project.
- *
- * It is free software; you can redistribute it and/or modify it under
- * the terms of the GNU General Public License, either version 2
- * of the License, or any later version.
- *
- * For the full copyright and license information, please read the
- * LICENSE.txt file that was distributed with this source code.
- *
- * The TYPO3 project - inspiring people to share!
- */
-class AjaxRequest{constructor(e){this.queryArguments="",this.url=e,this.abortController=new AbortController;}withQueryArguments(e){const t=this.clone();return t.queryArguments=(""!==t.queryArguments?"&":"")+InputTransformer.toSearchParams(e),t}async get(e={}){const t=await this.send({method:"GET",...e});return new AjaxResponse(t)}async post(e,t={}){const n={body:"string"==typeof e||e instanceof FormData?e:InputTransformer.byHeader(e,t?.headers),cache:"no-cache",method:"POST"},r=await this.send({...n,...t});return new AjaxResponse(r)}async put(e,t={}){const n={body:"string"==typeof e||e instanceof FormData?e:InputTransformer.byHeader(e,t?.headers),cache:"no-cache",method:"PUT"},r=await this.send({...n,...t});return new AjaxResponse(r)}async delete(e={},t={}){const n={cache:"no-cache",method:"DELETE"};"string"==typeof e&&e.length>0||e instanceof FormData?n.body=e:"object"==typeof e&&Object.keys(e).length>0&&(n.body=InputTransformer.byHeader(e,t?.headers));const r=await this.send({...n,...t});return new AjaxResponse(r)}abort(){this.abortController.abort();}clone(){return Object.assign(Object.create(this),this)}async send(e={}){const t=await fetch(this.composeRequestUrl(),this.getMergedOptions(e));if(!t.ok)throw new AjaxResponse(t);return t}composeRequestUrl(){let e=this.url;if("?"===e.charAt(0)&&(e=window.location.origin+window.location.pathname+e),e=new URL(e,window.location.origin).toString(),""!==this.queryArguments){e+=(this.url.includes("?")?"&":"?")+this.queryArguments;}return e}getMergedOptions(e){return {...AjaxRequest.defaultOptions,...e,signal:this.abortController.signal}}}AjaxRequest.defaultOptions={credentials:"same-origin"};
-
-/*
- * This file is part of the TYPO3 CMS project.
- *
- * It is free software; you can redistribute it and/or modify it under
- * the terms of the GNU General Public License, either version 2
- * of the License, or any later version.
- *
- * For the full copyright and license information, please read the
- * LICENSE.txt file that was distributed with this source code.
- *
- * The TYPO3 project - inspiring people to share!
- */
-class Icons{constructor(){this.sizes=Sizes,this.states=States,this.markupIdentifiers=MarkupIdentifiers,this.promiseCache={};}getIcon(e,i,t,n,o){const s=[e,i=i||Sizes.default,t,n=n||States.default,o=o||MarkupIdentifiers.default],r=s.join("_");return this.getIconRegistryCache().then((e=>(ClientStorage.isset("icon_registry_cache_identifier")&&ClientStorage.get("icon_registry_cache_identifier")===e||(ClientStorage.unsetByPrefix("icon_"),ClientStorage.set("icon_registry_cache_identifier",e)),this.fetchFromLocal(r).then(null,(()=>this.fetchFromRemote(s,r))))))}getIconRegistryCache(){const e="icon_registry_cache_identifier";return this.isPromiseCached(e)||this.putInPromiseCache(e,new AjaxRequest$1(TYPO3.settings.ajaxUrls.icons_cache).get().then((async e=>await e.resolve()))),this.getFromPromiseCache(e)}fetchFromRemote(e,i){if(!this.isPromiseCached(i)){const t={icon:JSON.stringify(e)};this.putInPromiseCache(i,new AjaxRequest$1(TYPO3.settings.ajaxUrls.icons).withQueryArguments(t).get().then((async e=>{const t=await e.resolve();return t.includes("t3js-icon")&&t.includes('')&&ClientStorage.set("icon_"+i,t),t})));}return this.getFromPromiseCache(i)}fetchFromLocal(e){return ClientStorage.isset("icon_"+e)?Promise.resolve(ClientStorage.get("icon_"+e)):Promise.reject()}isPromiseCached(e){return void 0!==this.promiseCache[e]}getFromPromiseCache(e){return this.promiseCache[e]}putInPromiseCache(e,i){this.promiseCache[e]=i;}}let iconsObject;iconsObject||(iconsObject=new Icons,TYPO3.Icons=iconsObject);var Icons$1 = iconsObject;
-
-/*
- * This file is part of the TYPO3 CMS project.
- *
- * It is free software; you can redistribute it and/or modify it under
- * the terms of the GNU General Public License, either version 2
- * of the License, or any later version.
- *
- * For the full copyright and license information, please read the
- * LICENSE.txt file that was distributed with this source code.
- *
- * The TYPO3 project - inspiring people to share!
- */
-class Wizard{constructor(){this.setup={slides:[],settings:{},forceSelection:!0,$carousel:null},this.originalSetup=$.extend(!0,{},this.setup);}set(e,t){return this.setup.settings[e]=t,this}addSlide(e,t,s="",i=SeverityEnum$1.info,a){const r={identifier:e,title:t,content:s,severity:i,callback:a};return this.setup.slides.push(r),this}addFinalProcessingSlide(e){return e||(e=()=>{this.dismiss();}),Icons$2.getIcon("spinner-circle-dark",Icons$2.sizes.large,null,null).then((t=>{const s=$("",{class:"text-center"}).append(t);this.addSlide("final-processing-slide",top.TYPO3.lang["wizard.processing.title"],s[0].outerHTML,Severity.info,e);}))}show(){const e=this.generateSlides(),t=this.setup.slides[0],s=Modal.advanced({title:t.title,content:e,severity:t.severity,staticBackdrop:!0,buttons:[{text:top.TYPO3.lang["wizard.button.cancel"],active:!0,btnClass:"btn-default",name:"cancel",trigger:()=>{this.getComponent().trigger("wizard-dismiss");}},{text:top.TYPO3.lang["wizard.button.next"],btnClass:"btn-"+Severity.getCssClass(t.severity),name:"next"}],callback:()=>{this.addProgressBar(),this.initializeEvents(s);}});this.setup.forceSelection&&this.lockNextStep(),this.getComponent().on("wizard-visible",(()=>{this.runSlideCallback(t,this.setup.$carousel.find(".carousel-item").first());})).on("wizard-dismissed",(()=>{this.setup=$.extend(!0,{},this.originalSetup);}));}getComponent(){return null===this.setup.$carousel&&this.generateSlides(),this.setup.$carousel}dismiss(){Modal.dismiss();}lockNextStep(){const e=this.setup.$carousel.closest(".modal").find('button[name="next"]');return e.prop("disabled",!0),e}unlockNextStep(){const e=this.setup.$carousel.closest(".modal").find('button[name="next"]');return e.prop("disabled",!1),e}setForceSelection(e){this.setup.forceSelection=e;}initializeEvents(e){const t=this.setup.$carousel.closest(".modal"),s=t.find(".modal-title"),i=t.find(".modal-footer"),a=i.find('button[name="next"]');a.on("click",(()=>{this.setup.$carousel.carousel("next");})),this.setup.$carousel.on("slide.bs.carousel",(()=>{const e=this.setup.$carousel.data("currentSlide")+1,r=this.setup.$carousel.data("currentIndex")+1;s.text(this.setup.slides[r].title),this.setup.$carousel.data("currentSlide",e),this.setup.$carousel.data("currentIndex",r),e>=this.setup.$carousel.data("realSlideCount")?(t.find(".modal-header .close").remove(),i.slideUp()):i.find(".progress-bar").width(this.setup.$carousel.data("initialStep")*e+"%").text(top.TYPO3.lang["wizard.progress"].replace("{0}",e).replace("{1}",this.setup.$carousel.data("slideCount"))),a.removeClass("btn-"+Severity.getCssClass(this.setup.slides[r-1].severity)).addClass("btn-"+Severity.getCssClass(this.setup.slides[r].severity)),t.removeClass("modal-severity-"+Severity.getCssClass(this.setup.slides[r-1].severity)).addClass("modal-severity-"+Severity.getCssClass(this.setup.slides[r].severity));})).on("slid.bs.carousel",(e=>{const t=this.setup.$carousel.data("currentIndex"),s=this.setup.slides[t];this.runSlideCallback(s,$(e.relatedTarget)),this.setup.forceSelection&&this.lockNextStep();}));const r=this.getComponent();r.on("wizard-dismiss",this.dismiss),e.addEventListener("typo3-modal-hidden",(()=>{r.trigger("wizard-dismissed");})),e.addEventListener("typo3-modal-shown",(()=>{r.trigger("wizard-visible");}));}runSlideCallback(e,t){"function"==typeof e.callback&&e.callback(t,this.setup.settings,e.identifier);}addProgressBar(){const e=this.setup.$carousel.find(".carousel-item").length,t=Math.max(1,e),s=Math.round(100/t),i=this.setup.$carousel.closest(".modal").find(".modal-footer");this.setup.$carousel.data("initialStep",s).data("slideCount",t).data("realSlideCount",e).data("currentIndex",0).data("currentSlide",1),t>1&&i.prepend($("",{class:"progress"}).append($("",{role:"progressbar",class:"progress-bar","aria-valuemin":0,"aria-valuenow":s,"aria-valuemax":100}).width(s+"%").text(top.TYPO3.lang["wizard.progress"].replace("{0}","1").replace("{1}",t))));}generateSlides(){if(null!==this.setup.$carousel)return this.setup.$carousel;let e='
';for(const t of Object.values(this.setup.slides)){let s=t.content;"object"==typeof s&&(s=s.html()),e+='
'+s+"
";}return e+="
",this.setup.$carousel=$(e),this.setup.$carousel.find(".carousel-item").first().addClass("active"),this.setup.$carousel}}let wizardObject;try{window.opener&&window.opener.TYPO3&&window.opener.TYPO3.Wizard&&(wizardObject=window.opener.TYPO3.Wizard),parent&&parent.window.TYPO3&&parent.window.TYPO3.Wizard&&(wizardObject=parent.window.TYPO3.Wizard),top&&top.TYPO3&&top.TYPO3.Wizard&&(wizardObject=top.TYPO3.Wizard);}catch{}wizardObject||(wizardObject=new Wizard,"undefined"!=typeof TYPO3&&(TYPO3.Wizard=wizardObject));var Wizard$1 = wizardObject;
-
-/*
- * This file is part of the TYPO3 CMS project.
- *
- * It is free software; you can redistribute it and/or modify it under
- * the terms of the GNU General Public License, either version 2
- * of the License, or any later version.
- *
- * For the full copyright and license information, please read the
- * LICENSE.txt file that was distributed with this source code.
- *
- * The TYPO3 project - inspiring people to share!
- */
-class Localization {
- constructor() {
- this.triggerButton = '.t3js-localize';
- this.localizationMode = null;
- this.sourceLanguage = null;
- this.records = [];
- documentService.ready().then(() => {
- this.initialize();
- });
- }
- initialize() {
- const me = this;
- Icons$1.getIcon('actions-localize', Icons$1.sizes.large).then((localizeIconMarkup) => {
- Icons$1.getIcon('actions-edit-copy', Icons$1.sizes.large).then((copyIconMarkup) => {
- Icons$1.getIcon('actions-localize-deepl', Icons$1.sizes.large).then((deeplIconMarkup) => {
- $(me.triggerButton).removeClass('disabled');
- $(document).on('click', me.triggerButton, (e) => {
- e.preventDefault();
- const $triggerButton = $(e.currentTarget);
- const actions = [];
- const availableLocalizationModes = [];
- let slideStep1 = '';
- if ($triggerButton.data('allowTranslate')) {
- actions.push('
"),MultiStepWizard.getComponent().on("change",".t3js-language-option",(e=>{MultiStepWizard.set("sourceLanguage",$(e.currentTarget).val()),MultiStepWizard.unlockNextStep()}));const a=$("",{class:"row"});for(const e of c){const t="language"+e.uid,l=$("",{type:"radio",name:"language",id:t,value:e.uid,class:"btn-check t3js-language-option"}),o=$("",{class:"btn btn-default btn-block",for:t}).text(" "+e.title).prepend(e.flagIcon);a.append($("",{class:"col-sm-4"}).append(l).append(o))}e.empty().append(a)})),MultiStepWizard.addSlide("localize-summary",TYPO3.lang["localize.view.summary"],"",SeverityEnum.notice,TYPO3.lang["localize.wizard.step.selectRecords"],(async(e,t)=>{e.empty().html('